Beispiel #1
0
    def test_create_configdrive_vfat(self):
        CONF.set_override('config_drive_format', 'vfat')
        imagefile = None
        try:
            self.mox.StubOutWithMock(utils, 'mkfs')
            self.mox.StubOutWithMock(utils, 'execute')
            self.mox.StubOutWithMock(utils, 'trycmd')

            utils.mkfs('vfat', mox.IgnoreArg(),
                       label='config-2').AndReturn(None)
            utils.trycmd('mount',
                         '-o',
                         mox.IgnoreArg(),
                         mox.IgnoreArg(),
                         mox.IgnoreArg(),
                         run_as_root=True).AndReturn((None, None))
            utils.execute('umount', mox.IgnoreArg(),
                          run_as_root=True).AndReturn(None)

            self.mox.ReplayAll()

            with configdrive.ConfigDriveBuilder(FakeInstanceMD()) as c:
                (fd, imagefile) = tempfile.mkstemp(prefix='cd_vfat_')
                os.close(fd)
                c.make_drive(imagefile)

            # NOTE(mikal): we can't check for a VFAT output here because the
            # filesystem creation stuff has been mocked out because it
            # requires root permissions

        finally:
            if imagefile:
                fileutils.delete_if_exists(imagefile)
Beispiel #2
0
    def test_create_configdrive_iso(self):
        CONF.set_override('config_drive_format', 'iso9660')
        imagefile = None

        try:
            self.mox.StubOutWithMock(utils, 'execute')

            utils.execute('genisoimage',
                          '-o',
                          mox.IgnoreArg(),
                          '-ldots',
                          '-allow-lowercase',
                          '-allow-multidot',
                          '-l',
                          '-publisher',
                          mox.IgnoreArg(),
                          '-quiet',
                          '-J',
                          '-r',
                          '-V',
                          'config-2',
                          mox.IgnoreArg(),
                          attempts=1,
                          run_as_root=False).AndReturn(None)

            self.mox.ReplayAll()

            with configdrive.ConfigDriveBuilder(FakeInstanceMD()) as c:
                (fd, imagefile) = tempfile.mkstemp(prefix='cd_iso_')
                os.close(fd)
                c.make_drive(imagefile)

        finally:
            if imagefile:
                fileutils.delete_if_exists(imagefile)
    def test_create_configdrive_iso(self, mock_execute):
        CONF.set_override('config_drive_format', 'iso9660')
        imagefile = None

        try:
            with configdrive.ConfigDriveBuilder(FakeInstanceMD()) as c:
                (fd, imagefile) = tempfile.mkstemp(prefix='cd_iso_')
                os.close(fd)
                c.make_drive(imagefile)

            mock_execute.assert_called_once_with('genisoimage',
                                                 '-o',
                                                 mock.ANY,
                                                 '-ldots',
                                                 '-allow-lowercase',
                                                 '-allow-multidot',
                                                 '-l',
                                                 '-publisher',
                                                 mock.ANY,
                                                 '-quiet',
                                                 '-J',
                                                 '-r',
                                                 '-V',
                                                 'config-2',
                                                 mock.ANY,
                                                 attempts=1,
                                                 run_as_root=False)
        finally:
            if imagefile:
                fileutils.delete_if_exists(imagefile)
    def _generate_configdrive(self, instance, node, network_info,
                              extra_md=None, files=None):
        """Generate a config drive.

        :param instance: The instance object.
        :param node: The node object.
        :param network_info: Instance network information.
        :param extra_md: Optional, extra metadata to be added to the
                         configdrive.
        :param files: Optional, a list of paths to files to be added to
                      the configdrive.

        """
        if not extra_md:
            extra_md = {}

        i_meta = instance_metadata.InstanceMetadata(instance,
            content=files, extra_md=extra_md, network_info=network_info)

        with tempfile.NamedTemporaryFile() as uncompressed:
            with configdrive.ConfigDriveBuilder(instance_md=i_meta) as cdb:
                cdb.make_drive(uncompressed.name)

            with tempfile.NamedTemporaryFile() as compressed:
                # compress config drive
                with gzip.GzipFile(fileobj=compressed, mode='wb') as gzipped:
                    uncompressed.seek(0)
                    shutil.copyfileobj(uncompressed, gzipped)

                # base64 encode config drive
                compressed.seek(0)
                return base64.b64encode(compressed.read())
def _create_config_drive(context, instance_path, instance, injected_files,
                         network_info, admin_password):
    if CONF.config_drive_format != 'iso9660':
        raise exception.ConfigDriveUnsupportedFormat(
            format=CONF.config_drive_format)

    LOG.debug('Using config drive', instance=instance)

    extra_md = {}
    if admin_password:
        extra_md['admin_pass'] = admin_password

    inst_md = instance_metadata.InstanceMetadata(instance,
                                                 content=injected_files,
                                                 extra_md=extra_md,
                                                 network_info=network_info,
                                                 request_context=context)

    configdrive_iso = os.path.join(instance_path, 'cfgdrive.iso')
    LOG.debug('Creating config drive at %s',
              configdrive_iso,
              instance=instance)
    with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
        cdb.make_drive(configdrive_iso)

    return configdrive_iso
Beispiel #6
0
    def _create_config_drive(self, instance, injected_files, admin_password):
        if CONF.config_drive_format != 'iso9660':
            vmutils.HyperVException(
                _('Invalid config_drive_format "%s"') %
                CONF.config_drive_format)

        LOG.info(_('Using config drive for instance: %s'), instance=instance)

        extra_md = {}
        if admin_password and CONF.config_drive_inject_password:
            extra_md['admin_pass'] = admin_password

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md)

        instance_path = self._pathutils.get_instance_path(instance['name'])
        configdrive_path_iso = os.path.join(instance_path, 'configdrive.iso')
        LOG.info(_('Creating config drive at %(path)s'),
                 {'path': configdrive_path_iso},
                 instance=instance)

        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            try:
                cdb.make_drive(configdrive_path_iso)
            except exception.ProcessExecutionError, e:
                LOG.error(_('Creating config drive failed with error: %s'),
                          e,
                          instance=instance)
                raise
Beispiel #7
0
    def _setup_spawn_config_drive_mocks(self, use_cdrom):
        instance_metadata.InstanceMetadata(mox.IgnoreArg(),
                                           content=mox.IsA(list),
                                           extra_md=mox.IsA(dict))

        m = fake.PathUtils.get_instance_dir(mox.IsA(str))
        m.AndReturn(self._test_instance_dir)

        cdb = self._mox.CreateMockAnything()
        m = configdrive.ConfigDriveBuilder(instance_md=mox.IgnoreArg())
        m.AndReturn(cdb)
        # __enter__ and __exit__ are required by "with"
        cdb.__enter__().AndReturn(cdb)
        cdb.make_drive(mox.IsA(str))
        cdb.__exit__(None, None, None).AndReturn(None)

        if not use_cdrom:
            utils.execute(CONF.hyperv.qemu_img_cmd,
                          'convert',
                          '-f',
                          'raw',
                          '-O',
                          'vpc',
                          mox.IsA(str),
                          mox.IsA(str),
                          attempts=1)
            fake.PathUtils.remove(mox.IsA(str))

        m = vmutils.VMUtils.attach_ide_drive(mox.IsA(str), mox.IsA(str),
                                             mox.IsA(int), mox.IsA(int),
                                             mox.IsA(str))
        m.WithSideEffects(self._add_disk)
Beispiel #8
0
    def test_create_configdrive_iso(self):
        imagefile = None

        try:
            self.mox.StubOutWithMock(utils, 'execute')

            utils.execute('genisoimage', '-o', mox.IgnoreArg(), '-ldots',
                          '-allow-lowercase', '-allow-multidot', '-l',
                          '-publisher', mox.IgnoreArg(), '-quiet', '-J', '-r',
                          '-V', 'config-2', mox.IgnoreArg(), attempts=1,
                          run_as_root=False).AndReturn(None)

            self.mox.ReplayAll()

            c = configdrive.ConfigDriveBuilder()
            c._add_file('this/is/a/path/hello', 'This is some content')
            (fd, imagefile) = tempfile.mkstemp(prefix='cd_iso_')
            os.close(fd)
            c._make_iso9660(imagefile)
            c.cleanup()

            # Check cleanup
            self.assertFalse(os.path.exists(c.tempdir))

        finally:
            if imagefile:
                utils.delete_if_exists(imagefile)
Beispiel #9
0
    def test_create_configdrive_vfat(self, mock_trycmd, mock_execute,
                                     mock_mkfs):
        CONF.set_override('config_drive_format', 'vfat')
        imagefile = None
        try:
            with configdrive.ConfigDriveBuilder(FakeInstanceMD()) as c:
                (fd, imagefile) = tempfile.mkstemp(prefix='cd_vfat_')
                os.close(fd)
                c.make_drive(imagefile)

            mock_mkfs.assert_called_once_with('vfat',
                                              mock.ANY,
                                              label='config-2')
            mock_trycmd.assert_called_once_with('mount',
                                                '-o',
                                                mock.ANY,
                                                mock.ANY,
                                                mock.ANY,
                                                run_as_root=True)
            mock_execute.assert_called_once_with('umount',
                                                 mock.ANY,
                                                 run_as_root=True)
            # NOTE(mikal): we can't check for a VFAT output here because the
            # filesystem creation stuff has been mocked out because it
            # requires root permissions

        finally:
            if imagefile:
                fileutils.delete_if_exists(imagefile)
Beispiel #10
0
    def configure_container_configdrive(self, container_config, instance,
                                        injected_files):
        LOG.debug('Creating LXD config drive')
        if CONF.config_drive_format not in ('fs', None):
            msg = (_('Invalid config drive format: %s')
                   % CONF.config_drive_format)
            raise exception.InstancePowerOnFailure(reason=msg)

        LOG.info(_LI('Using config drive for instance'), instance=instance)
        extra_md = {}

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md)
        name = instance.name
        try:
            with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
                container_configdrive = (
                    self.container_dir.get_container_configdrive(name)
                )
                cdb.make_drive(container_configdrive)
                container_config = self.configure_disk_path(container_config,
                                                            'configdrive',
                                                            instance)
        except Exception as e:
            with excutils.save_and_reraise_exception():
                LOG.error(_LE('Creating config drive failed with error: %s'),
                          e, instance=instance)

        return container_config
Beispiel #11
0
    def _create_cfg_dr_iso(self,
                           instance,
                           injected_files,
                           network_info,
                           admin_pass=None):
        """Creates an ISO file that contains the injected files.

        Used for config drive.

        :param instance: The VM instance from OpenStack.
        :param injected_files: A list of file paths that will be injected into
                               the ISO.
        :param network_info: The network_info from the nova spawn method.
        :param admin_pass: Optional password to inject for the VM.
        :return iso_path: The path to the ISO
        :return file_name: The file name for the ISO
        """
        LOG.info("Creating config drive.", instance=instance)
        extra_md = {}
        if admin_pass is not None:
            extra_md['admin_pass'] = admin_pass

        # Sanitize the vifs for the network config
        network_info = self._sanitize_network_info(network_info)

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md,
                                                     network_info=network_info)

        if not os.path.exists(_VOPT_TMPDIR):
            os.mkdir(_VOPT_TMPDIR)

        file_name = pvm_util.sanitize_file_name_for_api(
            instance.name,
            prefix='cfg_',
            suffix='.iso',
            max_len=pvm_const.MaxLen.VOPT_NAME)
        iso_path = os.path.join(_VOPT_TMPDIR, file_name)
        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            LOG.info("Config drive ISO being built in %s.",
                     iso_path,
                     instance=instance)

            # There may be an OSError exception when create the config drive.
            # If so, retry the operation before raising.
            @retrying.retry(
                retry_on_exception=lambda exc: isinstance(exc, OSError),
                stop_max_attempt_number=2)
            def _make_cfg_drive(iso_path):
                cdb.make_drive(iso_path)

            try:
                _make_cfg_drive(iso_path)
                return iso_path, file_name
            except OSError:
                with excutils.save_and_reraise_exception(logger=LOG):
                    LOG.exception("Config drive ISO could not be built",
                                  instance=instance)
Beispiel #12
0
 def _create_ext4_ploop(self, calls):
     imagefile = None
     with mock.patch.object(utils, 'execute', return_value=('', '')) as ex:
         with configdrive.ConfigDriveBuilder(FakeInstanceMD()) as c:
             imagefile = "/tmp/cd_ext4_" + str(uuid.uuid4())[:8]
             c.make_drive(imagefile, image_type='ploop')
             ex.assert_has_calls(calls)
     return imagefile
Beispiel #13
0
    def _create_cfg_dr_iso(self,
                           instance,
                           injected_files,
                           network_info,
                           iso_path,
                           admin_pass=None):
        """Creates an ISO file that contains the injected files.

        Used for config drive.

        :param instance: The VM instance from OpenStack.
        :param injected_files: A list of file paths that will be injected into
                               the ISO.
        :param network_info: The network_info from the nova spawn method.
        :param iso_path: The absolute file path for the new ISO
        :param admin_pass: Optional password to inject for the VM.
        """
        LOG.info("Creating config drive.", instance=instance)
        extra_md = {}
        if admin_pass is not None:
            extra_md['admin_pass'] = admin_pass

        # Sanitize the vifs for the network config
        network_info = self._sanitize_network_info(network_info)

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md,
                                                     network_info=network_info)

        # fix instance uuid to match uuid assigned to VM
        inst_md.uuid = vm.get_pvm_uuid(instance).lower()

        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            LOG.info("Config drive ISO building to path %(iso_path)s.",
                     {'iso_path': iso_path},
                     instance=instance)

            # In case, if there's an OSError related failure while
            # creating config drive, retry make drive operation.

            def _retry_on_oserror(exc):
                return isinstance(exc, OSError)

            @retrying.retry(retry_on_exception=_retry_on_oserror,
                            stop_max_attempt_number=2)
            def _make_cfg_drive(iso_path):
                cdb.make_drive(iso_path)

            try:
                _make_cfg_drive(iso_path)
            except OSError:
                with excutils.save_and_reraise_exception(logger=LOG):
                    # If we get here, that means there's an exception during
                    # second attempt, log the same and fail the deploy
                    # operation.
                    LOG.exception("Config drive ISO could not be built.",
                                  instance=instance)
Beispiel #14
0
    def _create_config_drive(self,
                             context,
                             instance,
                             injected_files,
                             admin_password,
                             network_info,
                             rescue=False):
        if CONF.config_drive_format != 'iso9660':
            raise exception.ConfigDriveUnsupportedFormat(
                format=CONF.config_drive_format)

        LOG.info('Using config drive for instance', instance=instance)

        extra_md = {}
        if admin_password and CONF.hyperv.config_drive_inject_password:
            extra_md['admin_pass'] = admin_password

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md,
                                                     network_info=network_info,
                                                     request_context=context)

        configdrive_path_iso = self._pathutils.get_configdrive_path(
            instance.name, constants.DVD_FORMAT, rescue=rescue)
        LOG.info('Creating config drive at %(path)s',
                 {'path': configdrive_path_iso},
                 instance=instance)

        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            try:
                cdb.make_drive(configdrive_path_iso)
            except processutils.ProcessExecutionError as e:
                with excutils.save_and_reraise_exception():
                    LOG.error('Creating config drive failed with '
                              'error: %s',
                              e,
                              instance=instance)

        if not CONF.hyperv.config_drive_cdrom:
            configdrive_path = self._pathutils.get_configdrive_path(
                instance.name, constants.DISK_FORMAT_VHD, rescue=rescue)
            utils.execute(CONF.hyperv.qemu_img_cmd,
                          'convert',
                          '-f',
                          'raw',
                          '-O',
                          'vpc',
                          configdrive_path_iso,
                          configdrive_path,
                          attempts=1)
            self._pathutils.remove(configdrive_path_iso)
        else:
            configdrive_path = configdrive_path_iso

        return configdrive_path
Beispiel #15
0
    def _create_cfg_dr_iso(self,
                           instance,
                           injected_files,
                           network_info,
                           admin_pass=None):
        """Creates an ISO file that contains the injected files.

        Used for config drive.

        :param instance: The VM instance from OpenStack.
        :param injected_files: A list of file paths that will be injected into
                               the ISO.
        :param network_info: The network_info from the nova spawn method.
        :param admin_pass: Optional password to inject for the VM.
        :return iso_path: The path to the ISO
        :return file_name: The file name for the ISO
        """
        LOG.info(_LI("Creating config drive for instance: %s"),
                 instance.name,
                 instance=instance)
        extra_md = {}
        if admin_pass is not None:
            extra_md['admin_pass'] = admin_pass

        # Sanitize the vifs for the network config
        network_info = self._sanitize_network_info(network_info)

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md,
                                                     network_info=network_info)

        # Make sure the path exists.
        im_path = CONF.powervm.image_meta_local_path
        if not os.path.exists(im_path):
            os.mkdir(im_path)

        file_name = pvm_util.sanitize_file_name_for_api(
            instance.name,
            prefix=CFG_DRV_PREFIX,
            suffix=CFG_DRV_SUFFIX,
            max_len=pvm_const.MaxLen.VOPT_NAME)
        iso_path = os.path.join(im_path, file_name)
        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            LOG.info(_LI("Config drive ISO being built for instance %(inst)s "
                         "building to path %(iso_path)s."), {
                             'inst': instance.name,
                             'iso_path': iso_path
                         },
                     instance=instance)
            cdb.make_drive(iso_path)
            return iso_path, file_name
Beispiel #16
0
    def _create_config_drive(self, instance, injected_files, admin_password):
        if CONF.config_drive_format != 'iso9660':
            vmutils.HyperVException(
                _('Invalid config_drive_format "%s"') %
                CONF.config_drive_format)

        LOG.info(_('Using config drive for instance: %s'), instance=instance)

        extra_md = {}
        if admin_password and CONF.hyperv.config_drive_inject_password:
            extra_md['admin_pass'] = admin_password

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md)

        instance_path = self._pathutils.get_instance_dir(instance['name'])
        configdrive_path_iso = os.path.join(instance_path, 'configdrive.iso')
        LOG.info(_('Creating config drive at %(path)s'),
                 {'path': configdrive_path_iso},
                 instance=instance)

        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            try:
                cdb.make_drive(configdrive_path_iso)
            except processutils.ProcessExecutionError as e:
                with excutils.save_and_reraise_exception():
                    LOG.error(_('Creating config drive failed with error: %s'),
                              e,
                              instance=instance)

        if not CONF.hyperv.config_drive_cdrom:
            drive_type = constants.IDE_DISK
            configdrive_path = os.path.join(instance_path, 'configdrive.vhd')
            utils.execute(CONF.hyperv.qemu_img_cmd,
                          'convert',
                          '-f',
                          'raw',
                          '-O',
                          'vpc',
                          configdrive_path_iso,
                          configdrive_path,
                          attempts=1)
            self._pathutils.remove(configdrive_path_iso)
        else:
            drive_type = constants.IDE_DVD
            configdrive_path = configdrive_path_iso

        self._vmutils.attach_ide_drive(instance['name'], configdrive_path, 1,
                                       0, drive_type)
Beispiel #17
0
    def _create_config_drive(self, instance, injected_files, admin_password,
                             network_info):
        if CONF.config_drive_format != 'iso9660':
            raise vmutils.UnsupportedConfigDriveFormatException(
                _('Invalid config_drive_format "%s"') %
                CONF.config_drive_format)

        LOG.info(_LI('Using config drive for instance'), instance=instance)

        extra_md = {}
        if admin_password and CONF.hyperv.config_drive_inject_password:
            extra_md['admin_pass'] = admin_password

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md,
                                                     network_info=network_info)

        instance_path = self._pathutils.get_instance_dir(instance.name)
        configdrive_path_iso = os.path.join(instance_path, 'configdrive.iso')
        LOG.info(_LI('Creating config drive at %(path)s'),
                 {'path': configdrive_path_iso},
                 instance=instance)

        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            try:
                cdb.make_drive(configdrive_path_iso)
            except processutils.ProcessExecutionError as e:
                with excutils.save_and_reraise_exception():
                    LOG.error(_LE('Creating config drive failed with '
                                  'error: %s'),
                              e,
                              instance=instance)

        if not CONF.hyperv.config_drive_cdrom:
            configdrive_path = os.path.join(instance_path, 'configdrive.vhd')
            utils.execute(CONF.hyperv.qemu_img_cmd,
                          'convert',
                          '-f',
                          'raw',
                          '-O',
                          'vpc',
                          configdrive_path_iso,
                          configdrive_path,
                          attempts=1)
            self._pathutils.remove(configdrive_path_iso)
        else:
            configdrive_path = configdrive_path_iso

        return configdrive_path
Beispiel #18
0
    def _create_cfg_dr_iso(self,
                           instance,
                           injected_files,
                           network_info,
                           iso_path,
                           admin_pass=None):
        """Creates an ISO file that contains the injected files.

        Used for config drive.

        :param instance: The VM instance from OpenStack.
        :param injected_files: A list of file paths that will be injected into
                               the ISO.
        :param network_info: The network_info from the nova spawn method.
        :param iso_path: The absolute file path for the new ISO
        :param admin_pass: Optional password to inject for the VM.
        """
        LOG.info("Creating config drive.", instance=instance)
        extra_md = {}
        if admin_pass is not None:
            extra_md['admin_pass'] = admin_pass

        # Sanitize the vifs for the network config
        network_info = self._sanitize_network_info(network_info)

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md,
                                                     network_info=network_info)

        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            LOG.info("Config drive ISO being built in %s.",
                     iso_path,
                     instance=instance)

            # There may be an OSError exception when create the config drive.
            # If so, retry the operation before raising.
            @retrying.retry(
                retry_on_exception=lambda exc: isinstance(exc, OSError),
                stop_max_attempt_number=2)
            def _make_cfg_drive(iso_path):
                cdb.make_drive(iso_path)

            try:
                _make_cfg_drive(iso_path)
            except OSError:
                with excutils.save_and_reraise_exception(logger=LOG):
                    LOG.exception("Config drive ISO could not be built",
                                  instance=instance)
Beispiel #19
0
    def _create_config_drive(self, instance, injected_files, admin_password):
        if CONF.config_drive_format != 'iso9660':
            vmutils.HyperVException(
                _('Invalid config_drive_format "%s"') %
                CONF.config_drive_format)

        LOG.info(_('Using config drive'), instance=instance)
        extra_md = {}
        if admin_password and CONF.config_drive_inject_password:
            extra_md['admin_pass'] = admin_password

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md)

        instance_path = self._vmutils.get_instance_path(instance['name'])
        configdrive_path_iso = os.path.join(instance_path, 'configdrive.iso')
        LOG.info(_('Creating config drive at %(path)s'),
                 {'path': configdrive_path_iso},
                 instance=instance)

        cdb = configdrive.ConfigDriveBuilder(instance_md=inst_md)
        try:
            cdb.make_drive(configdrive_path_iso)
        finally:
            cdb.cleanup()

        if not CONF.config_drive_cdrom:
            drive_type = constants.IDE_DISK
            configdrive_path = os.path.join(instance_path, 'configdrive.vhd')
            utils.execute(CONF.qemu_img_cmd,
                          'convert',
                          '-f',
                          'raw',
                          '-O',
                          'vpc',
                          configdrive_path_iso,
                          configdrive_path,
                          attempts=1)
            os.remove(configdrive_path_iso)
        else:
            drive_type = constants.IDE_DVD
            configdrive_path = configdrive_path_iso

        self._attach_ide_drive(instance['name'], configdrive_path, 1, 0,
                               drive_type)
Beispiel #20
0
    def test_create_configdrive_vfat(self):
        imagefile = None
        try:
            self.mox.StubOutWithMock(virtutils, 'mkfs')
            self.mox.StubOutWithMock(utils, 'execute')
            self.mox.StubOutWithMock(utils, 'trycmd')

            virtutils.mkfs('vfat', mox.IgnoreArg(),
                           label='config-2').AndReturn(None)
            utils.trycmd('mount',
                         '-o',
                         'loop',
                         mox.IgnoreArg(),
                         mox.IgnoreArg(),
                         run_as_root=True).AndReturn((None, None))
            utils.trycmd('chown',
                         mox.IgnoreArg(),
                         mox.IgnoreArg(),
                         run_as_root=True).AndReturn((None, None))
            utils.execute('umount', mox.IgnoreArg(),
                          run_as_root=True).AndReturn(None)

            self.mox.ReplayAll()

            c = configdrive.ConfigDriveBuilder()
            c._add_file('this/is/a/path/hello', 'This is some content')
            (fd, imagefile) = tempfile.mkstemp(prefix='cd_vfat_')
            os.close(fd)
            c._make_vfat(imagefile)
            c.cleanup()

            # Check cleanup
            self.assertFalse(os.path.exists(c.tempdir))

            # NOTE(mikal): we can't check for a VFAT output here because the
            # filesystem creation stuff has been mocked out because it
            # requires root permissions

        finally:
            if imagefile:
                utils.delete_if_exists(imagefile)
Beispiel #21
0
    def _create_cfg_dr_iso(self,
                           instance,
                           injected_files,
                           network_info,
                           admin_pass=None):
        """Creates an ISO file that contains the injected files.

        Used for config drive.

        :param instance: The VM instance from OpenStack.
        :param injected_files: A list of file paths that will be injected into
                               the ISO.
        :param network_info: The network_info from the nova spawn method.
        :param admin_pass: Optional password to inject for the VM.
        :return iso_path: The path to the ISO
        :return file_name: The file name for the ISO
        """
        LOG.info("Creating config drive.", instance=instance)
        extra_md = {}
        if admin_pass is not None:
            extra_md['admin_pass'] = admin_pass

        # Sanitize the vifs for the network config
        network_info = self._sanitize_network_info(network_info)

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md,
                                                     network_info=network_info)

        # Make sure the path exists.
        im_path = CONF.powervm.image_meta_local_path
        if not os.path.exists(im_path):
            os.mkdir(im_path)

        file_name = pvm_util.sanitize_file_name_for_api(
            instance.name,
            prefix=CFG_DRV_PREFIX,
            suffix=CFG_DRV_SUFFIX,
            max_len=pvm_const.MaxLen.VOPT_NAME)
        iso_path = os.path.join(im_path, file_name)
        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            LOG.info("Config drive ISO building to path %(iso_path)s.",
                     {'iso_path': iso_path},
                     instance=instance)

            # In case, if there's an OSError related failure while
            # creating config drive, retry make drive operation.

            def _retry_on_oserror(exc):
                return isinstance(exc, OSError)

            @retrying.retry(retry_on_exception=_retry_on_oserror,
                            stop_max_attempt_number=2)
            def _make_cfg_drive(iso_path):
                cdb.make_drive(iso_path)

            try:
                _make_cfg_drive(iso_path)
                return iso_path, file_name
            except OSError:
                with excutils.save_and_reraise_exception(logger=LOG):
                    # If we get here, that means there's an exception during
                    # second attempt, log the same and fail the deploy
                    # operation.
                    LOG.exception("Config drive ISO could not be built.",
                                  instance=instance)
Beispiel #22
0
    def _add_configdrive(self, context, instance,
                         injected_files, admin_password, network_info):
        """Create configdrive for the instance."""
        if CONF.config_drive_format != 'iso9660':
            raise exception.ConfigDriveUnsupportedFormat(
                format=CONF.config_drive_format)

        container = self.client.containers.get(instance.name)
        container_id_map = container.config[
            'volatile.last_state.idmap'].split(',')
        storage_id = container_id_map[2].split(':')[1]

        extra_md = {}
        if admin_password:
            extra_md['admin_pass'] = admin_password

        inst_md = instance_metadata.InstanceMetadata(
            instance, content=injected_files, extra_md=extra_md,
            network_info=network_info, request_context=context)

        iso_path = os.path.join(
            common.InstanceAttributes(instance).instance_dir,
            'configdrive.iso')

        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            try:
                cdb.make_drive(iso_path)
            except processutils.ProcessExecutionError as e:
                with excutils.save_and_reraise_exception():
                    LOG.error('Creating config drive failed with '
                              'error: %s',
                              e, instance=instance)

        configdrive_dir = os.path.join(
            nova.conf.CONF.instances_path, instance.name, 'configdrive')
        if not os.path.exists(configdrive_dir):
            fileutils.ensure_tree(configdrive_dir)

        with utils.tempdir() as tmpdir:
            mounted = False
            try:
                _, err = utils.execute('mount',
                                       '-o',
                                       'loop,uid=%d,gid=%d' % (os.getuid(),
                                                               os.getgid()),
                                       iso_path, tmpdir,
                                       run_as_root=True)
                mounted = True

                # Copy and adjust the files from the ISO so that we
                # dont have the ISO mounted during the life cycle of the
                # instance and the directory can be removed once the instance
                # is terminated
                for ent in os.listdir(tmpdir):
                    shutil.copytree(os.path.join(tmpdir, ent),
                                    os.path.join(configdrive_dir, ent))
                    utils.execute('chmod', '-R', '775', configdrive_dir,
                                  run_as_root=True)
                    utils.execute('chown', '-R', storage_id, configdrive_dir,
                                  run_as_root=True)
            finally:
                if mounted:
                    utils.execute('umount', tmpdir, run_as_root=True)

        return configdrive_dir
Beispiel #23
0
    def _add_driver_fields(self,
                           node,
                           instance,
                           image_meta,
                           flavor,
                           admin_pass=None,
                           files=None,
                           network_info=None,
                           preserve_ephemeral=None):
        icli = client_wrapper.IronicClientWrapper()
        patch = patcher.create(node).get_deploy_patch(instance, image_meta,
                                                      flavor,
                                                      preserve_ephemeral)

        # Associate the node with an instance
        patch.append({
            'path': '/instance_uuid',
            'op': 'add',
            'value': instance['uuid']
        })

        if configdrive.required_by(instance):
            LOG.info(_('Using config drive'), instance=instance)
            extra_md = {}
            if admin_pass:
                extra_md['admin_pass'] = admin_pass

            inst_md = instance_metadata.InstanceMetadata(
                instance,
                content=files,
                extra_md=extra_md,
                network_info=network_info)

            fd, configdrive_path = tempfile.mkstemp()
            os.close(fd)

            with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
                try:
                    cdb.make_drive(configdrive_path)
                except processutils.ProcessExecutionError as e:
                    with excutils.save_and_reraise_exception():
                        LOG.error(_('Creating config drive failed '
                                    'with error: %s'),
                                  e,
                                  instance=instance)
            # gzip the configdrive.
            with open(configdrive_path, "rb") as configdrive_fh:
                configdrive_payload = base64.b64encode(
                    zlib.compress(configdrive_fh.read()))
            os.remove(configdrive_path)
            patch.append({
                'path': '/instance_info/config_drive',
                'op': 'add',
                'value': configdrive_payload
            })

        try:
            icli.call('node.update', node.uuid, patch)
        except ironic_exception.BadRequest:
            msg = (_("Failed to add deploy parameters on node %(node)s "
                     "when provisioning the instance %(instance)s") % {
                         'node': node.uuid,
                         'instance': instance['uuid']
                     })
            LOG.error(msg)
            raise exception.InstanceDeployFailure(msg)
Beispiel #24
0
    def _add_configdrive(self, instance, injected_files):
        """Configure the config drive for the container

        :param instance: nova instance object
        :param injected_files: instance injected files
        """
        LOG.debug('add_configdrive called for instance', instance=instance)

        extra_md = {}
        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md)
        # Create the ISO image so we can inject the contents of the ISO
        # into the container
        iso_path = os.path.join(self.instance_dir, 'configdirve.iso')
        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            try:
                cdb.make_drive(iso_path)
            except Exception as e:
                with excutils.save_and_reraise_exception():
                    LOG.error(_LE('Creating config drive failed with error: '
                                  '%s'),
                              e,
                              instance=instance)

        # Copy the metadata info from the ISO into the container
        configdrive_dir = \
            self.container_dir.get_container_configdrive(instance.name)
        with utils.tempdir() as tmpdir:
            mounted = False
            try:
                _, err = utils.execute('mount',
                                       '-o',
                                       'loop,uid=%d,gid=%d' %
                                       (os.getuid(), os.getgid()),
                                       iso_path,
                                       tmpdir,
                                       run_as_root=True)
                mounted = True

                # Copy and adjust the files from the ISO so that we
                # dont have the ISO mounted during the life cycle of the
                # instance and the directory can be removed once the instance
                # is terminated
                for ent in os.listdir(tmpdir):
                    shutil.copytree(os.path.join(tmpdir, ent),
                                    os.path.join(configdrive_dir, ent))
                utils.execute('chmod',
                              '-R',
                              '775',
                              configdrive_dir,
                              run_as_root=True)
                utils.execute('chown',
                              '-R',
                              '%s:%s' %
                              (self._uid_map('/etc/subuid').rstrip(),
                               self._uid_map('/etc/subgid').rstrip()),
                              configdrive_dir,
                              run_as_root=True)
            finally:
                if mounted:
                    utils.execute('umount', tmpdir, run_as_root=True)
Beispiel #25
0
    def _add_configdrive(self, context, instance,
                         injected_files, admin_password, network_info):
        """Create configdrive for the instance."""
        if CONF.config_drive_format != 'iso9660':
            raise exception.ConfigDriveUnsupportedFormat(
                format=CONF.config_drive_format)

        container = self.client.containers.get(instance.name)
        storage_id = 0
        """
        Determine UID shift used for container uid mapping
        Sample JSON config from LXD
        {
            "volatile.apply_template": "create",
            ...
            "volatile.last_state.idmap": "[
                {
                \"Isuid\":true,
                \"Isgid\":false,
                \"Hostid\":100000,
                \"Nsid\":0,
                \"Maprange\":65536
                },
                {
                \"Isuid\":false,
                \"Isgid\":true,
                \"Hostid\":100000,
                \"Nsid\":0,
                \"Maprange\":65536
                }] ",
            "volatile.tap5fd6808a-7b.name": "eth0"
        }
        """
        container_id_map = json.loads(
            container.config['volatile.last_state.idmap'])
        uid_map = filter(lambda id_map: id_map.get("Isuid"), container_id_map)
        if uid_map:
            storage_id = uid_map[0].get("Hostid", 0)
        else:
            # privileged containers does not have uid/gid mapping
            # LXD API return nothing
            pass

        extra_md = {}
        if admin_password:
            extra_md['admin_pass'] = admin_password

        inst_md = instance_metadata.InstanceMetadata(
            instance, content=injected_files, extra_md=extra_md,
            network_info=network_info, request_context=context)

        iso_path = os.path.join(
            common.InstanceAttributes(instance).instance_dir,
            'configdrive.iso')

        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            try:
                cdb.make_drive(iso_path)
            except processutils.ProcessExecutionError as e:
                with excutils.save_and_reraise_exception():
                    LOG.error('Creating config drive failed with '
                              'error: %s',
                              e, instance=instance)

        configdrive_dir = os.path.join(
            nova.conf.CONF.instances_path, instance.name, 'configdrive')
        if not os.path.exists(configdrive_dir):
            fileutils.ensure_tree(configdrive_dir)

        with utils.tempdir() as tmpdir:
            mounted = False
            try:
                _, err = utils.execute('mount',
                                       '-o',
                                       'loop,uid=%d,gid=%d' % (os.getuid(),
                                                               os.getgid()),
                                       iso_path, tmpdir,
                                       run_as_root=True)
                mounted = True

                # Copy and adjust the files from the ISO so that we
                # dont have the ISO mounted during the life cycle of the
                # instance and the directory can be removed once the instance
                # is terminated
                for ent in os.listdir(tmpdir):
                    shutil.copytree(os.path.join(tmpdir, ent),
                                    os.path.join(configdrive_dir, ent))

                utils.execute('chmod', '-R', '775', configdrive_dir,
                              run_as_root=True)
                utils.execute('chown', '-R',
                              '%s:%s' % (storage_id, storage_id),
                              configdrive_dir, run_as_root=True)
            finally:
                if mounted:
                    utils.execute('umount', tmpdir, run_as_root=True)

        return configdrive_dir