// deleteInstances deletes a virtual machine and all of the resources that // it owns, and any corresponding network security rules. func deleteInstance( inst *azureInstance, computeClient compute.ManagementClient, networkClient network.ManagementClient, storageClient internalazurestorage.Client, ) error { vmName := string(inst.Id()) vmClient := compute.VirtualMachinesClient{computeClient} nicClient := network.InterfacesClient{networkClient} nsgClient := network.SecurityGroupsClient{networkClient} securityRuleClient := network.SecurityRulesClient{networkClient} publicIPClient := network.PublicIPAddressesClient{networkClient} logger.Debugf("deleting instance %q", vmName) logger.Debugf("- deleting virtual machine") deleteResult, err := vmClient.Delete(inst.env.resourceGroup, vmName) if err != nil { if deleteResult.Response == nil || deleteResult.StatusCode != http.StatusNotFound { return errors.Annotate(err, "deleting virtual machine") } } // Delete the VM's OS disk VHD. logger.Debugf("- deleting OS VHD") blobClient := storageClient.GetBlobService() if _, err := blobClient.DeleteBlobIfExists(osDiskVHDContainer, vmName); err != nil { return errors.Annotate(err, "deleting OS VHD") } // Delete network security rules that refer to the VM. logger.Debugf("- deleting security rules") if err := deleteInstanceNetworkSecurityRules( inst.env.resourceGroup, inst.Id(), nsgClient, securityRuleClient, ); err != nil { return errors.Annotate(err, "deleting network security rules") } // Detach public IPs from NICs. This must be done before public // IPs can be deleted. In the future, VMs may not necessarily // have a public IP, so we don't use the presence of a public // IP to indicate the existence of an instance. logger.Debugf("- detaching public IP addresses") for _, nic := range inst.networkInterfaces { if nic.Properties.IPConfigurations == nil { continue } var detached bool for i, ipConfiguration := range *nic.Properties.IPConfigurations { if ipConfiguration.Properties.PublicIPAddress == nil { continue } ipConfiguration.Properties.PublicIPAddress = nil (*nic.Properties.IPConfigurations)[i] = ipConfiguration detached = true } if detached { if _, err := nicClient.CreateOrUpdate( inst.env.resourceGroup, to.String(nic.Name), nic, ); err != nil { return errors.Annotate(err, "detaching public IP addresses") } } } // Delete public IPs. logger.Debugf("- deleting public IPs") for _, pip := range inst.publicIPAddresses { pipName := to.String(pip.Name) logger.Tracef("deleting public IP %q", pipName) result, err := publicIPClient.Delete(inst.env.resourceGroup, pipName) if err != nil { if result.Response == nil || result.StatusCode != http.StatusNotFound { return errors.Annotate(err, "deleting public IP") } } } // Delete NICs. // // NOTE(axw) this *must* be deleted last, or we risk leaking resources. logger.Debugf("- deleting network interfaces") for _, nic := range inst.networkInterfaces { nicName := to.String(nic.Name) logger.Tracef("deleting NIC %q", nicName) result, err := nicClient.Delete(inst.env.resourceGroup, nicName) if err != nil { if result.Response == nil || result.StatusCode != http.StatusNotFound { return errors.Annotate(err, "deleting NIC") } } } return nil }
// deleteVirtualMachine deletes a virtual machine and all of the resources that // it owns, and any corresponding network security rules. func (env *azureEnviron) deleteVirtualMachine( instId instance.Id, maybeStorageClient internalazurestorage.Client, networkInterfaces []network.Interface, publicIPAddresses []network.PublicIPAddress, ) error { vmClient := compute.VirtualMachinesClient{env.compute} nicClient := network.InterfacesClient{env.network} nsgClient := network.SecurityGroupsClient{env.network} securityRuleClient := network.SecurityRulesClient{env.network} pipClient := network.PublicIPAddressesClient{env.network} deploymentsClient := resources.DeploymentsClient{env.resources} vmName := string(instId) logger.Debugf("- deleting virtual machine (%s)", vmName) if err := deleteResource(env.callAPI, vmClient, env.resourceGroup, vmName); err != nil { if !errors.IsNotFound(err) { return errors.Annotate(err, "deleting virtual machine") } } if maybeStorageClient != nil { logger.Debugf("- deleting OS VHD (%s)", vmName) blobClient := maybeStorageClient.GetBlobService() if _, err := blobClient.DeleteBlobIfExists(osDiskVHDContainer, vmName, nil); err != nil { return errors.Annotate(err, "deleting OS VHD") } } logger.Debugf("- deleting security rules (%s)", vmName) if err := deleteInstanceNetworkSecurityRules( env.resourceGroup, instId, nsgClient, securityRuleClient, env.callAPI, ); err != nil { return errors.Annotate(err, "deleting network security rules") } logger.Debugf("- deleting network interfaces (%s)", vmName) for _, nic := range networkInterfaces { nicName := to.String(nic.Name) logger.Tracef("deleting NIC %q", nicName) if err := deleteResource(env.callAPI, nicClient, env.resourceGroup, nicName); err != nil { if !errors.IsNotFound(err) { return errors.Annotate(err, "deleting NIC") } } } logger.Debugf("- deleting public IPs (%s)", vmName) for _, pip := range publicIPAddresses { pipName := to.String(pip.Name) logger.Tracef("deleting public IP %q", pipName) if err := deleteResource(env.callAPI, pipClient, env.resourceGroup, pipName); err != nil { if !errors.IsNotFound(err) { return errors.Annotate(err, "deleting public IP") } } } // The deployment must be deleted last, or we risk leaking resources. logger.Debugf("- deleting deployment (%s)", vmName) if err := deleteResource(env.callAPI, deploymentsClient, env.resourceGroup, vmName); err != nil { if !errors.IsNotFound(err) { return errors.Annotate(err, "deleting deployment") } } return nil }