forked from Azure/acs-engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
deletevm.go
117 lines (98 loc) · 4.04 KB
/
deletevm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package operations
import (
"fmt"
"github.com/Azure/acs-engine/pkg/armhelpers"
"github.com/Azure/acs-engine/pkg/armhelpers/utils"
log "github.com/sirupsen/logrus"
)
const (
// AADRoleResourceGroupScopeTemplate is a template for a roleDefinition scope
AADRoleResourceGroupScopeTemplate = "/subscriptions/%s/resourceGroups/%s"
)
// CleanDeleteVirtualMachine deletes a VM and any associated OS disk
func CleanDeleteVirtualMachine(az armhelpers.ACSEngineClient, logger *log.Entry, subscriptionID, resourceGroup, name string) error {
logger.Infof("fetching VM: %s/%s", resourceGroup, name)
vm, err := az.GetVirtualMachine(resourceGroup, name)
if err != nil {
logger.Errorf("failed to get VM: %s/%s: %s", resourceGroup, name, err.Error())
return err
}
vhd := vm.VirtualMachineProperties.StorageProfile.OsDisk.Vhd
managedDisk := vm.VirtualMachineProperties.StorageProfile.OsDisk.ManagedDisk
if vhd == nil && managedDisk == nil {
logger.Errorf("failed to get a valid os disk URI for VM: %s/%s", resourceGroup, name)
return fmt.Errorf("os disk does not have a VHD URI")
}
osDiskName := vm.VirtualMachineProperties.StorageProfile.OsDisk.Name
var nicName string
nicID := (*vm.VirtualMachineProperties.NetworkProfile.NetworkInterfaces)[0].ID
if nicID == nil {
logger.Warnf("NIC ID is not set for VM (%s/%s)", resourceGroup, name)
} else {
nicName, err = utils.ResourceName(*nicID)
if err != nil {
return err
}
logger.Infof("found nic name for VM (%s/%s): %s", resourceGroup, name, nicName)
}
logger.Infof("deleting VM: %s/%s", resourceGroup, name)
_, deleteErrChan := az.DeleteVirtualMachine(resourceGroup, name, nil)
logger.Infof("waiting for vm deletion: %s/%s", resourceGroup, name)
if err := <-deleteErrChan; err != nil {
return err
}
if len(nicName) > 0 {
logger.Infof("deleting nic: %s/%s", resourceGroup, nicName)
_, nicErrChan := az.DeleteNetworkInterface(resourceGroup, nicName, nil)
logger.Infof("waiting for nic deletion: %s/%s", resourceGroup, nicName)
if nicErr := <-nicErrChan; nicErr != nil {
return nicErr
}
}
if vhd != nil {
accountName, vhdContainer, vhdBlob, err := utils.SplitBlobURI(*vhd.URI)
if err != nil {
return err
}
logger.Infof("found os disk storage reference: %s %s %s", accountName, vhdContainer, vhdBlob)
as, err := az.GetStorageClient(resourceGroup, accountName)
if err != nil {
return err
}
logger.Infof("deleting blob: %s/%s", vhdContainer, vhdBlob)
if err = as.DeleteBlob(vhdContainer, vhdBlob); err != nil {
return err
}
} else if managedDisk != nil {
if osDiskName == nil {
logger.Warnf("osDisk is not set for VM %s/%s", resourceGroup, name)
} else {
logger.Infof("deleting managed disk: %s/%s", resourceGroup, *osDiskName)
_, diskErrChan := az.DeleteManagedDisk(resourceGroup, *osDiskName, nil)
if err := <-diskErrChan; err != nil {
return err
}
}
}
if vm.Identity != nil {
// Role assignments are not deleted if the VM is destroyed, so we must cleanup ourselves!
// The role assignments should only be relevant if managed identities are used,
// but always cleaning them up is easier than adding rule based logic here and there.
scope := fmt.Sprintf(AADRoleResourceGroupScopeTemplate, subscriptionID, resourceGroup)
logger.Infof("fetching roleAssignments: %s with principal %s", scope, *vm.Identity.PrincipalID)
vmRoleAssignments, listRoleAssingmentsError := az.ListRoleAssignmentsForPrincipal(scope, *vm.Identity.PrincipalID)
if listRoleAssingmentsError != nil {
logger.Errorf("failed to list role assignments: %s/%s: %s", scope, *vm.Identity.PrincipalID, listRoleAssingmentsError.Error())
return listRoleAssingmentsError
}
for _, roleAssignment := range *vmRoleAssignments.Value {
logger.Infof("deleting role assignment: %s", *roleAssignment.ID)
_, deleteRoleAssignmentErr := az.DeleteRoleAssignmentByID(*roleAssignment.ID)
if deleteRoleAssignmentErr != nil {
logger.Errorf("failed to delete role assignment: %s: %s", *roleAssignment.ID, deleteRoleAssignmentErr.Error())
return deleteRoleAssignmentErr
}
}
}
return nil
}