forked from Azure/aks-engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
deletevm.go
122 lines (105 loc) · 4.39 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
118
119
120
121
122
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
package operations
import (
"context"
"fmt"
"github.com/Azure/aks-engine/pkg/armhelpers"
"github.com/Azure/aks-engine/pkg/armhelpers/utils"
azStorage "github.com/Azure/azure-sdk-for-go/storage"
"github.com/pkg/errors"
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.AKSEngineClient, logger *log.Entry, subscriptionID, resourceGroup, name string) error {
ctx, cancel := context.WithTimeout(context.Background(), armhelpers.DefaultARMOperationTimeout)
defer cancel()
logger.Infof("fetching VM: %s/%s", resourceGroup, name)
vm, err := az.GetVirtualMachine(ctx, 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 errors.New("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)
logger.Infof("waiting for vm deletion: %s/%s", resourceGroup, name)
if err = az.DeleteVirtualMachine(ctx, resourceGroup, name); err != nil {
return err
}
if len(nicName) > 0 {
logger.Infof("deleting nic: %s/%s", resourceGroup, nicName)
logger.Infof("waiting for nic deletion: %s/%s", resourceGroup, nicName)
if err = az.DeleteNetworkInterface(ctx, resourceGroup, nicName); err != nil {
return err
}
}
if vhd != nil {
var accountName, vhdContainer, vhdBlob string
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)
var as armhelpers.AKSStorageClient
as, err = az.GetStorageClient(ctx, resourceGroup, accountName)
if err != nil {
return err
}
logger.Infof("deleting blob: %s/%s", vhdContainer, vhdBlob)
if err = as.DeleteBlob(vhdContainer, vhdBlob, &azStorage.DeleteBlobOptions{}); 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)
if err = az.DeleteManagedDisk(ctx, resourceGroup, *osDiskName); err != nil {
return err
}
}
}
if vm.Identity != nil && vm.Identity.PrincipalID != 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)
for vmRoleAssignmentsPage, err := az.ListRoleAssignmentsForPrincipal(ctx, scope, *vm.Identity.PrincipalID); vmRoleAssignmentsPage.NotDone(); err = vmRoleAssignmentsPage.Next() {
if err != nil {
logger.Errorf("failed to list role assignments: %s/%s: %s", scope, *vm.Identity.PrincipalID, err)
return err
}
for _, roleAssignment := range vmRoleAssignmentsPage.Values() {
logger.Infof("deleting role assignment: %s", *roleAssignment.ID)
_, deleteRoleAssignmentErr := az.DeleteRoleAssignmentByID(ctx, *roleAssignment.ID)
if deleteRoleAssignmentErr != nil {
logger.Errorf("failed to delete role assignment: %s: %s", *roleAssignment.ID, deleteRoleAssignmentErr.Error())
return deleteRoleAssignmentErr
}
}
}
}
return nil
}