def testGenerateDiskName(self): """Test that disk names are correclty generated. The disk name must comply with the following RegEx: ^[\\w]{1,80}$ i.e., it must be between 1 and 80 chars and be within [a-zA-Z0-9]. """ disk_name = common.GenerateDiskName(FAKE_SNAPSHOT) self.assertEqual('fake_snapshot_name_f4c186ac_copy', disk_name) disk_name = common.GenerateDiskName(FAKE_SNAPSHOT, disk_name_prefix='prefix') self.assertEqual('prefix_fake_snapshot_name_f4c186ac_copy', disk_name)
def CreateDiskFromSnapshotURI( self, snapshot: 'AZComputeSnapshot', snapshot_uri: str, region: Optional[str] = None, disk_name: Optional[str] = None, disk_name_prefix: Optional[str] = None, disk_type: str = 'Standard_LRS') -> 'AZComputeDisk': """Create a new disk based on a SAS snapshot URI. This is useful if e.g. one wants to make a copy of a disk in a separate Azure account. This method will create a temporary Azure Storage account within the destination account, import the snapshot from a downloadable link (the source account needs to share the snapshot through a SAS link) and then create a disk from the VHD file saved in storage. The Azure storage account is then deleted. Args: snapshot (AZComputeSnapshot): Source snapshot to use. snapshot_uri (str): The URI of the snapshot to copy. region (str): Optional. The region in which to create the disk. If not provided, the disk will be created in the default_region associated to the AZAccount object. disk_name (str): Optional. String to use as new disk name. disk_name_prefix (str): Optional. String to prefix the disk name with. disk_type (str): Optional. The sku name for the disk to create. Can be Standard_LRS, Premium_LRS, StandardSSD_LRS, or UltraSSD_LRS. Default is Standard_LRS. Returns: AZComputeDisk: Azure Compute Disk. Raises: RuntimeError: If the disk could not be created. """ if not region: region = self.az_account.default_region # Create a temporary Azure account storage to import the snapshot storage_account_name = hashlib.sha1( snapshot.resource_id.encode('utf-8')).hexdigest()[:23] storage_account_url = 'https://{0:s}.blob.core.windows.net'.format( storage_account_name) # pylint: disable=line-too-long storage_account_id, storage_account_access_key = self.az_account.storage.CreateStorageAccount( storage_account_name, region=region) # pylint: enable=line-too-long blob_service_client = blob.BlobServiceClient( account_url=storage_account_url, credential=storage_account_access_key) # Create a container within the Storage to receive the imported snapshot container_name = storage_account_name + '-container' snapshot_vhd_name = snapshot.name + '.vhd' container_client = blob_service_client.get_container_client( container_name) try: logger.info('Creating blob container {0:s}'.format(container_name)) container_client.create_container() logger.info('Blob container {0:s} successfully created'.format( container_name)) except exceptions.ResourceExistsError: # The container already exists, so we can re-use it logger.warning( 'Reusing existing container: {0:s}'.format(container_name)) # Download the snapshot from the URI to the storage copied_blob = blob_service_client.get_blob_client( container_name, snapshot_vhd_name) logger.info( 'Importing snapshot to container from URI {0:s}. ' 'Depending on the size of the snapshot, this process is going ' 'to take a while.'.format(snapshot_uri)) copied_blob.start_copy_from_url(snapshot_uri) copy_status = copied_blob.get_blob_properties().copy.status while copy_status != 'success': sleep( 5 ) # Wait for the vhd to be imported in the Azure storage container copy_status = copied_blob.get_blob_properties().copy.status if copy_status in ('aborted', 'failed'): raise RuntimeError('Could not import the snapshot from URI ' '{0:s}'.format(snapshot_uri)) logger.debug( 'Importing snapshot from URI {0:s}'.format(snapshot_uri)) logger.info('Snapshot successfully imported from URI {0:s}'.format( snapshot_uri)) if not disk_name: disk_name = common.GenerateDiskName( snapshot, disk_name_prefix=disk_name_prefix) # Create a new disk from the imported snapshot creation_data = { 'location': region, 'creation_data': { 'source_uri': copied_blob.url, 'storage_account_id': storage_account_id, 'create_option': models.DiskCreateOption.import_enum }, 'sku': { 'name': disk_type } } try: logger.info('Creating disk: {0:s}'.format(disk_name)) request = self.compute_client.disks.create_or_update( self.az_account.default_resource_group_name, disk_name, creation_data) while not request.done(): sleep(5) # Wait 5 seconds before checking disk status again disk = request.result() logger.info('Disk {0:s} successfully created'.format(disk_name)) except azure_exceptions.CloudError as exception: raise RuntimeError( 'Could not create disk from URI {0:s}: {1:s}'.format( snapshot_uri, str(exception))) # Cleanup the temporary account storage self.az_account.storage.DeleteStorageAccount(storage_account_name) return AZComputeDisk(self.az_account, disk.id, disk.name, disk.location, disk.zones)
def CreateDiskFromSnapshot( self, snapshot: 'AZComputeSnapshot', region: Optional[str] = None, disk_name: Optional[str] = None, disk_name_prefix: Optional[str] = None, disk_type: str = 'Standard_LRS') -> 'AZComputeDisk': """Create a new disk based on a Snapshot. Args: snapshot (AZComputeSnapshot): Snapshot to use. region (str): Optional. The region in which to create the disk. If not provided, the disk will be created in the default_region associated to the AZAccount object. disk_name (str): Optional. String to use as new disk name. disk_name_prefix (str): Optional. String to prefix the disk name with. disk_type (str): Optional. The sku name for the disk to create. Can be Standard_LRS, Premium_LRS, StandardSSD_LRS, or UltraSSD_LRS. The default value is Standard_LRS. Returns: AZComputeDisk: Azure Compute Disk. Raises: RuntimeError: If the disk could not be created. """ if not disk_name: disk_name = common.GenerateDiskName( snapshot, disk_name_prefix=disk_name_prefix) if not region: region = self.az_account.default_region creation_data = { 'location': region, 'creation_data': { 'sourceResourceId': snapshot.resource_id, 'create_option': models.DiskCreateOption.copy }, 'sku': { 'name': disk_type } } try: logger.info('Creating disk: {0:s}'.format(disk_name)) request = self.compute_client.disks.create_or_update( self.az_account.default_resource_group_name, disk_name, creation_data) while not request.done(): sleep(5) # Wait 5 seconds before checking disk status again disk = request.result() logger.info('Disk {0:s} successfully created'.format(disk_name)) except azure_exceptions.CloudError as exception: raise RuntimeError( 'Could not create disk from snapshot {0:s}: {1:s}'.format( snapshot.resource_id, str(exception))) return AZComputeDisk(self.az_account, disk.id, disk.name, disk.location, disk.zones)