def commit(self): """Write to the disk.""" LOG.debug("Committing partitions to disk.") cmd_args = ['mklabel', self._disk_label] # NOTE(lucasagomes): Lead in with 1MiB to allow room for the # partition table itself. start = 1 for num, part in self.get_partitions(): end = start + part['size'] cmd_args.extend(['mkpart', part['type'], part['fs_type'], str(start), str(end)]) if part['boot_flag']: cmd_args.extend(['set', str(num), part['boot_flag'], 'on']) if part['extra_flags']: for flag in part['extra_flags']: cmd_args.extend(['set', str(num), flag, 'on']) start = end self._exec(*cmd_args) try: utils.wait_for_disk_to_become_available(self._device) except exception.IronicException as e: raise exception.InstanceDeployFailure( _('Disk partitioning failed on device %(device)s. ' 'Error: %(error)s') % {'device': self._device, 'error': e})
def test_wait_for_disk_to_become_available(self, mock_exc): mock_exc.return_value = ('', '') utils.wait_for_disk_to_become_available('fake-dev') fuser_cmd = ['fuser', 'fake-dev'] fuser_call = mock.call(*fuser_cmd, run_as_root=True, check_exit_code=[0, 1]) self.assertEqual(1, mock_exc.call_count) mock_exc.assert_has_calls([fuser_call])
def destroy_disk_metadata(dev, node_uuid): """Destroy metadata structures on node's disk. Ensure that node's disk magic strings are wiped without zeroing the entire drive. To do this we use the wipefs tool from util-linux. :param dev: Path for the device to work on. :param node_uuid: Node's uuid. Used for logging. """ # NOTE(NobodyCam): This is needed to work around bug: # https://bugs.launchpad.net/ironic/+bug/1317647 LOG.debug("Start destroy disk metadata for node %(node)s.", {'node': node_uuid}) try: utils.execute('wipefs', '--force', '--all', dev, run_as_root=True, use_standard_locale=True) except processutils.ProcessExecutionError as e: with excutils.save_and_reraise_exception() as ctxt: # NOTE(zhenguo): Check if --force option is supported for wipefs, # if not, we should try without it. if '--force' in str(e): ctxt.reraise = False utils.execute('wipefs', '--all', dev, run_as_root=True, use_standard_locale=True) utils.execute('sgdisk', '-Z', dev, run_as_root=True, use_standard_locale=True) try: utils.wait_for_disk_to_become_available(dev) except exception.IronicException as e: raise exception.InstanceDeployFailure( _('Destroying metadata failed on device %(device)s. ' 'Error: %(error)s') % { 'device': dev, 'error': e }) LOG.info( "Disk metadata on %(dev)s successfully destroyed for node " "%(node)s", { 'dev': dev, 'node': node_uuid })
def test_wait_for_disk_to_become_available_dev_becomes_avail_busybox( self, mock_exc): # Test that initially device is not available but then becomes # available. This version has the 'busybox' version of 'fuser' values # for stdout and stderr. # The 'busybox' version does not have a leading space character in # stdout. Also nothing is output to stderr. mock_exc.side_effect = [('1234 5895', ''), ('', '')] utils.wait_for_disk_to_become_available('fake-dev') fuser_cmd = ['fuser', 'fake-dev'] fuser_call = mock.call(*fuser_cmd, run_as_root=True, check_exit_code=[0, 1]) self.assertEqual(2, mock_exc.call_count) mock_exc.assert_has_calls([fuser_call, fuser_call])
def test_wait_for_disk_to_become_available_dev_becomes_avail_psmisc( self, mock_exc): # Test that initially device is not available but then becomes # available. This version has the 'psmisc' version of 'fuser' values # for stdout and stderr. CONF.disk_partitioner.check_device_interval = .01 CONF.disk_partitioner.check_device_max_retries = 2 # The 'psmisc' version has a leading space character in stdout. The # filename is output to stderr mock_exc.side_effect = [(' 1234 ', 'fake-dev: '), ('', '')] utils.wait_for_disk_to_become_available('fake-dev') fuser_cmd = ['fuser', 'fake-dev'] fuser_call = mock.call(*fuser_cmd, run_as_root=True, check_exit_code=[0, 1]) self.assertEqual(2, mock_exc.call_count) mock_exc.assert_has_calls([fuser_call, fuser_call])