def ListInstances(self, resource_group_name: Optional[str] = None ) -> Dict[str, compute.AZVirtualMachine]: """List instances in an Azure subscription / resource group. Args: resource_group_name (str): Optional. The resource group name to list instances from. If none specified, then all instances in the Azure subscription will be listed. Returns: Dict[str, AZVirtualMachine]: Dictionary mapping instance names (str) to their respective AZVirtualMachine object. """ instances = {} # type: Dict[str, compute.AZVirtualMachine] az_vm_client = self.compute_client.virtual_machines if not resource_group_name: responses = common.ExecuteRequest(az_vm_client, 'list_all') else: responses = common.ExecuteRequest( az_vm_client, 'list', {'resource_group_name': resource_group_name}) for response in responses: for instance in response: instances[instance.name] = compute.AZVirtualMachine( self, instance.id, instance.name, instance.location, zones=instance.zones) return instances
# pylint: disable=line-too-long with mock.patch( 'libcloudforensics.providers.azure.internal.common.GetCredentials' ) as mock_creds: mock_creds.return_value = ('fake-subscription-id', mock.Mock()) with mock.patch( 'libcloudforensics.providers.azure.internal.account.AZAccount._GetOrCreateResourceGroup' ) as mock_resource: # pylint: enable=line-too-long mock_resource.return_value = 'fake-resource-group' FAKE_ACCOUNT = account.AZAccount('fake-resource-group', default_region='fake-region') FAKE_INSTANCE = compute.AZVirtualMachine( FAKE_ACCOUNT, '/a/b/c/fake-resource-group/fake-vm-name', 'fake-vm-name', 'fake-region', ['fake-zone']) FAKE_DISK = compute.AZDisk(FAKE_ACCOUNT, '/a/b/c/fake-resource-group/fake-disk-name', 'fake-disk-name', 'fake-region', ['fake-zone']) FAKE_BOOT_DISK = compute.AZDisk( FAKE_ACCOUNT, '/a/b/c/fake-resource-group/fake-boot-disk-name', 'fake-boot-disk-name', 'fake-region', ['fake-zone']) FAKE_SNAPSHOT = compute.AZSnapshot( FAKE_ACCOUNT, '/a/b/c/fake-resource-group/fake_snapshot_name', 'fake_snapshot_name', 'fake-region', FAKE_DISK) MOCK_INSTANCE = mock.Mock(id='/a/b/c/fake-resource-group/fake-vm-name',
def GetOrCreateAnalysisVm( self, vm_name: str, boot_disk_size: int, cpu_cores: int, memory_in_mb: int, ssh_public_key: str, region: Optional[str] = None, packages: Optional[List[str]] = None, tags: Optional[Dict[str, str]] = None ) -> Tuple[compute.AZVirtualMachine, bool]: """Get or create a new virtual machine for analysis purposes. Args: vm_name (str): The instance name tag of the virtual machine. boot_disk_size (int): The size of the analysis VM boot volume (in GB). cpu_cores (int): Number of CPU cores for the analysis VM. memory_in_mb (int): The memory size (in MB) for the analysis VM. ssh_public_key (str): A SSH public key data to associate with the VM. This must be provided as otherwise the VM will not be accessible. region (str): Optional. The region in which to create the vm. If not provided, the vm will be created in the default_region associated to the AZAccount object. packages (List[str]): Optional. List of packages to install in the VM. tags (Dict[str, str]): Optional. A dictionary of tags to add to the instance, for example {'TicketID': 'xxx'}. An entry for the instance name is added by default. Returns: Tuple[AWSInstance, bool]: A tuple with an AZVirtualMachine object and a boolean indicating if the virtual machine was created (True) or reused (False). Raises: RuntimeError: If the virtual machine cannot be found or created. """ # Re-use instance if it already exists, or create a new one. try: instance = self.GetInstance(vm_name) if instance: created = False return instance, created except RuntimeError: pass # Validate SSH public key format try: sshpubkeys.SSHKey(ssh_public_key, strict=True).parse() except sshpubkeys.InvalidKeyError as exception: raise RuntimeError('The provided public SSH key is invalid: ' '{0:s}'.format(str(exception))) instance_type = self._GetInstanceType(cpu_cores, memory_in_mb) startup_script = utils.ReadStartupScript() if packages: startup_script = startup_script.replace('${packages[@]}', ' '.join( packages)) if not region: region = self.default_region creation_data = { 'location': region, 'properties': { 'hardwareProfile': {'vmSize': instance_type}, 'storageProfile': { 'imageReference': { 'sku': '18.04-LTS', 'publisher': 'Canonical', 'version': 'latest', 'offer': 'UbuntuServer'} }, 'osDisk': { 'caching': 'ReadWrite', 'managedDisk': {'storageAccountType': 'Standard_LRS'}, 'name': 'os-disk-{0:s}'.format(vm_name), 'diskSizeGb': boot_disk_size, 'createOption': models.DiskCreateOption.from_image }, 'osProfile': { 'adminUsername': '******', 'computerName': vm_name, # Azure requires the startup script to be sent as a b64 string 'customData': base64.b64encode( str.encode(startup_script)).decode('utf-8'), 'linuxConfiguration': { 'ssh': { 'publicKeys': [{ 'path': '/home/AzureUser/.ssh/authorized_keys', 'keyData': ssh_public_key}] } } }, 'networkProfile': { 'networkInterfaces': [ {'id': self._CreateNetworkInterfaceForVM(vm_name, region)} ] } } } # type: Dict[str, Any] if tags: creation_data['tags'] = tags try: request = self.compute_client.virtual_machines.create_or_update( self.default_resource_group_name, vm_name, creation_data ) while not request.done(): sleep(5) # Wait 5 seconds before checking disk status again vm = request.result() except azure_exceptions.CloudError as exception: raise RuntimeError('Could not create instance {0:s}: {1:s}'.format( vm_name, str(exception))) instance = compute.AZVirtualMachine(self, vm.id, vm.name, vm.location, zones=vm.zones) created = True return instance, created