+
+ created_items = created_items or {}
+ try:
+ # Check vm exists, we can call delete_vm to clean created_items
+ if vm_id:
+ res_name = self._get_resource_name_from_resource_id(vm_id)
+ vm = self.conn_compute.virtual_machines.get(self.resource_group, res_name)
+
+ # Shuts down the virtual machine and releases the compute resources
+ # vm_stop = self.conn_compute.virtual_machines.power_off(self.resource_group, resName)
+ # vm_stop.wait()
+
+ vm_delete = self.conn_compute.virtual_machines.delete(self.resource_group, res_name)
+ vm_delete.wait()
+ self.logger.debug('deleted VM name: %s', res_name)
+
+ # Delete OS Disk
+ os_disk_name = vm.storage_profile.os_disk.name
+ self.logger.debug('delete OS DISK: %s', os_disk_name)
+ async_disk_delete = self.conn_compute.disks.delete(self.resource_group, os_disk_name)
+ async_disk_delete.wait()
+ # os disks are created always with the machine
+ self.logger.debug('deleted OS DISK name: %s', os_disk_name)
+
+ for data_disk in vm.storage_profile.data_disks:
+ self.logger.debug('delete data_disk: %s', data_disk.name)
+ async_disk_delete = self.conn_compute.disks.delete(self.resource_group, data_disk.name)
+ async_disk_delete.wait()
+ self._markdel_created_item(data_disk.managed_disk.id, created_items)
+ self.logger.debug('deleted OS DISK name: %s', data_disk.name)
+
+ # After deleting VM, it is necessary to delete NIC, because if is not deleted delete_network
+ # does not work because Azure says that is in use the subnet
+ network_interfaces = vm.network_profile.network_interfaces
+
+ for network_interface in network_interfaces:
+
+ nic_name = self._get_resource_name_from_resource_id(network_interface.id)
+ nic_data = self.conn_vnet.network_interfaces.get(
+ self.resource_group,
+ nic_name)
+
+ public_ip_name = None
+ exist_public_ip = nic_data.ip_configurations[0].public_ip_address
+ if exist_public_ip:
+ public_ip_id = nic_data.ip_configurations[0].public_ip_address.id
+
+ # Delete public_ip
+ public_ip_name = self._get_resource_name_from_resource_id(public_ip_id)
+
+ # Public ip must be deleted afterwards of nic that is attached
+
+ self.logger.debug('delete NIC name: %s', nic_name)
+ nic_delete = self.conn_vnet.network_interfaces.delete(self.resource_group, nic_name)
+ nic_delete.wait()
+ self._markdel_created_item(network_interface.id, created_items)
+ self.logger.debug('deleted NIC name: %s', nic_name)
+
+ # Delete list of public ips
+ if public_ip_name:
+ self.logger.debug('delete PUBLIC IP - ' + public_ip_name)
+ ip_delete = self.conn_vnet.public_ip_addresses.delete(self.resource_group, public_ip_name)
+ ip_delete.wait()
+ self._markdel_created_item(public_ip_id, created_items)
+
+ # Delete created items
+ self._delete_created_items(created_items)
+
+ except CloudError as e:
+ if e.error.error and "notfound" in e.error.error.lower():
+ raise vimconn.VimConnNotFoundException("No vm instance found '{}'".format(vm_id))
+ else:
+ self._format_vimconn_exception(e)
+ except Exception as e:
+ self._format_vimconn_exception(e)
+
+ def _markdel_created_item(self, item_id, created_items):
+ if item_id in created_items:
+ created_items[item_id] = False
+
+ def _delete_created_items(self, created_items):
+ """ Delete created_items elements that have not been deleted with the virtual machine
+ Created_items may not be deleted correctly with the created machine if the
+ virtual machine fails creating or in other cases of error
+ """
+ self.logger.debug("Created items: %s", created_items)
+ # Must delete in order first nics, then public_ips
+ # As dictionaries don't preserve order, first get items to be deleted then delete them
+ nics_to_delete = []
+ publics_ip_to_delete = []
+ disks_to_delete = []
+ for item_id, v in created_items.items():
+ if not v: # skip already deleted
+ continue
+
+ # self.logger.debug("Must delete item id: %s", item_id)
+
+ # Obtain type, supported nic, disk or public ip
+ parsed_id = azure_tools.parse_resource_id(item_id)
+ resource_type = parsed_id.get("resource_type")
+ name = parsed_id.get("name")
+
+ if resource_type == "networkInterfaces":
+ nics_to_delete.append(name)
+ elif resource_type == "publicIPAddresses":
+ publics_ip_to_delete.append(name)
+ elif resource_type == "disks":
+ disks_to_delete.append(name)
+
+ # Now delete
+ for item_name in nics_to_delete:
+ try:
+ self.logger.debug("deleting nic name %s:", item_name)
+ nic_delete = self.conn_vnet.network_interfaces.delete(self.resource_group, item_name)
+ nic_delete.wait()
+ self.logger.debug("deleted nic name %s:", item_name)
+ except Exception as e:
+ self.logger.error("Error deleting item: {}: {}".format(type(e).__name__, e))
+
+ for item_name in publics_ip_to_delete:
+ try:
+ self.logger.debug("deleting public ip name %s:", item_name)
+ ip_delete = self.conn_vnet.public_ip_addresses.delete(self.resource_group, name)
+ ip_delete.wait()
+ self.logger.debug("deleted public ip name %s:", item_name)
+ except Exception as e:
+ self.logger.error("Error deleting item: {}: {}".format(type(e).__name__, e))
+
+ for item_name in disks_to_delete:
+ try:
+ self.logger.debug("deleting data disk name %s:", name)
+ async_disk_delete = self.conn_compute.disks.delete(self.resource_group, item_name)
+ async_disk_delete.wait()
+ self.logger.debug("deleted data disk name %s:", name)
+ except Exception as e:
+ self.logger.error("Error deleting item: {}: {}".format(type(e).__name__, e))
+
+ def action_vminstance(self, vm_id, action_dict, created_items={}):
+ """Send and action over a VM instance from VIM
+ Returns the vm_id if the action was successfully sent to the VIM
+ """
+
+ self.logger.debug("Action over VM '%s': %s", vm_id, str(action_dict))
+ try:
+ self._reload_connection()
+ resName = self._get_resource_name_from_resource_id(vm_id)
+ if "start" in action_dict:
+ self.conn_compute.virtual_machines.start(self.resource_group, resName)
+ elif "stop" in action_dict or "shutdown" in action_dict or "shutoff" in action_dict:
+ self.conn_compute.virtual_machines.power_off(self.resource_group, resName)
+ elif "terminate" in action_dict:
+ self.conn_compute.virtual_machines.delete(self.resource_group, resName)
+ elif "reboot" in action_dict:
+ self.conn_compute.virtual_machines.restart(self.resource_group, resName)
+ return None
+ except CloudError as e:
+ if e.error.error and "notfound" in e.error.error.lower():
+ raise vimconn.VimConnNotFoundException("No vm found '{}'".format(vm_id))
+ else:
+ self._format_vimconn_exception(e)
+ except Exception as e:
+ self._format_vimconn_exception(e)
+
+ def delete_flavor(self, flavor_id):
+ raise vimconn.VimConnAuthException("It is not possible to delete a FLAVOR in AZURE")
+
+ def delete_tenant(self, tenant_id,):
+ raise vimconn.VimConnAuthException("It is not possible to delete a TENANT in AZURE")
+
+ def delete_image(self, image_id):
+ raise vimconn.VimConnAuthException("It is not possible to delete a IMAGE in AZURE")