def test_resize_image_resize(self, mock_link, mock_identify, mock_exists, mock_execute, mock_copyfile): images.resize('/a/b/c/hash', 8) mock_link.assert_not_called() mock_execute.assert_called_with( 'qemu-img resize /a/b/c/hash.qcow2.8G 8G', shell=True) mock_copyfile.assert_called_with('/a/b/c/hash.qcow2', '/a/b/c/hash.qcow2.8G')
def test_resize_image_resize(self, mock_link, mock_identify, mock_exists, mock_execute): images.resize(None, '/a/b/c/hash', 8) mock_link.assert_not_called() mock_execute.assert_has_calls([ mock.call(None, 'cp /a/b/c/hash.qcow2 /a/b/c/hash.qcow2.8G'), mock.call(None, 'qemu-img resize /a/b/c/hash.qcow2.8G 8G') ])
def create(self, lock=None): db.update_instance_state(self.db_entry['uuid'], 'creating') # Ensure we have state on disk if not os.path.exists(self.instance_path): logutil.debug( [self], 'Creating instance storage at %s' % self.instance_path) os.makedirs(self.instance_path) # Generate a config drive with util.RecordedOperation('make config drive', self): self._make_config_drive(os.path.join( self.instance_path, self.db_entry['block_devices']['devices'][1]['path'])) # Prepare disks if not self.db_entry['block_devices']['finalized']: modified_disks = [] for disk in self.db_entry['block_devices']['devices']: if disk.get('base'): img = images.Image(disk['base']) hashed_image_path = img.get([lock], self) with util.RecordedOperation('detect cdrom images', self): try: cd = pycdlib.PyCdlib() cd.open(hashed_image_path) disk['present_as'] = 'cdrom' except Exception: pass if disk.get('present_as', 'cdrom') == 'cdrom': # There is no point in resizing or COW'ing a cdrom disk['path'] = disk['path'].replace('.qcow2', '.raw') disk['type'] = 'raw' disk['snapshot_ignores'] = True try: os.link(hashed_image_path, disk['path']) except OSError: # Different filesystems util.execute( [lock], 'cp %s %s' % (hashed_image_path, disk['path'])) # Due to limitations in some installers, cdroms are always on IDE disk['device'] = 'hd%s' % disk['device'][-1] disk['bus'] = 'ide' else: with util.RecordedOperation('resize image', self): resized_image_path = images.resize( [lock], hashed_image_path, disk['size']) if config.parsed.get('DISK_FORMAT') == 'qcow': with util.RecordedOperation('create copy on write layer', self): images.create_cow( [lock], resized_image_path, disk['path']) # Record the backing store for modern libvirts disk['backing'] = ('<backingStore type=\'file\'>\n' ' <format type=\'qcow2\'/>\n' ' <source file=\'%s\'/>\n' ' </backingStore>' % resized_image_path) elif config.parsed.get('DISK_FORMAT') == 'qcow_flat': with util.RecordedOperation('create flat layer', self): images.create_flat( [lock], resized_image_path, disk['path']) elif config.parsed.get('DISK_FORMAT') == 'flat': with util.RecordedOperation('create raw disk', self): images.create_raw( [lock], resized_image_path, disk['path']) else: raise Exception('Unknown disk format') elif not os.path.exists(disk['path']): util.execute(None, 'qemu-img create -f qcow2 %s %sG' % (disk['path'], disk['size'])) modified_disks.append(disk) self.db_entry['block_devices']['devices'] = modified_disks self.db_entry['block_devices']['finalized'] = True db.persist_block_devices( self.db_entry['uuid'], self.db_entry['block_devices']) # Create the actual instance with util.RecordedOperation('create domain XML', self): self._create_domain_xml() # Sometimes on Ubuntu 20.04 we need to wait for port binding to work. # Revisiting this is tracked by issue 320 on github. with util.RecordedOperation('create domain', self): if not self.power_on(): attempts = 0 while not self.power_on() and attempts < 100: logutil.warning( [self], 'Instance required an additional attempt to power on') time.sleep(5) attempts += 1 if self.is_powered_on(): logutil.info([self], 'Instance now powered on') else: logutil.info([self], 'Instance failed to power on') db.update_instance_state(self.db_entry['uuid'], 'created')
def create(self, lock=None): # Ensure we have state on disk if not os.path.exists(self.instance_path): LOG.debug('%s: Creating instance storage at %s' % (self, self.instance_path)) os.makedirs(self.instance_path) # Generate a config drive with util.RecordedOperation('make config drive', self) as _: self._make_config_drive( os.path.join( self.instance_path, self.db_entry['block_devices']['devices'][1]['path'])) # Prepare disks if not self.db_entry['block_devices']['finalized']: modified_disks = [] for disk in self.db_entry['block_devices']['devices']: if disk.get('base'): with util.RecordedOperation('fetch image', self) as _: image_url = images.resolve(disk['base']) hashed_image_path, info, image_dirty, resp = \ images.requires_fetch(image_url) if image_dirty: hashed_image_path = images.fetch(hashed_image_path, info, resp, lock=lock) else: hashed_image_path = '%s.v%03d' % ( hashed_image_path, info['version']) try: cd = pycdlib.PyCdlib() cd.open(hashed_image_path) disk['present_as'] = 'cdrom' except Exception: pass if disk.get('present_as', 'cdrom') == 'cdrom': # There is no point in resizing or COW'ing a cdrom disk['path'] = disk['path'].replace('.qcow2', '.raw') disk['type'] = 'raw' disk['snapshot_ignores'] = True try: os.link(hashed_image_path, disk['path']) except OSError: # Different filesystems if lock: lock.refresh() shutil.copyfile(hashed_image_path, disk['path']) if lock: lock.refresh() # Due to limitations in some installers, cdroms are always on IDE disk['device'] = 'hd%s' % disk['device'][-1] disk['bus'] = 'ide' else: with util.RecordedOperation('transcode image', self) as _: if lock: lock.refresh() images.transcode(hashed_image_path) with util.RecordedOperation('resize image', self) as _: if lock: lock.refresh() resized_image_path = images.resize( hashed_image_path, disk['size']) with util.RecordedOperation( 'create copy on write layer', self) as _: if lock: lock.refresh images.create_cow(resized_image_path, disk['path']) elif not os.path.exists(disk['path']): processutils.execute('qemu-img create -f qcow2 %s %sG' % (disk['path'], disk['size']), shell=True) modified_disks.append(disk) self.db_entry['block_devices']['devices'] = modified_disks self.db_entry['block_devices']['finalized'] = True db.persist_block_devices(self.db_entry['uuid'], self.db_entry['block_devices']) # Create the actual instance with util.RecordedOperation('create domain XML', self) as _: self._create_domain_xml() with util.RecordedOperation('create domain', self) as _: self.power_on() db.update_instance_state(self.db_entry['uuid'], 'created')
def test_resize_image_link(self, mock_link, mock_identify, mock_exists, mock_execute, mock_copyfile): images.resize('/a/b/c/hash', 8) mock_link.assert_called_with('/a/b/c/hash', '/a/b/c/hash.qcow2.8G') mock_execute.assert_not_called() mock_copyfile.assert_not_called()
def test_resize_image_noop(self, mock_link, mock_identify, mock_exists, mock_execute): images.resize(None, '/a/b/c/hash', 8) mock_link.assert_not_called() mock_execute.assert_not_called()