libvirt的file injection

来源:互联网 发布:mac虚拟机玩天龙八部 编辑:程序博客网 时间:2024/06/08 15:23
在E:\nova\nova\virt\libvirt\driver.py 中的_create_and_inject_local_root 检查是否需要进行injectiondef _create_and_inject_local_root(self, context, instance,                                      booted_from_volume, suffix, disk_images,                                      injection_info, fallback_from_host):        # File injection only if needed#判断是否要进行injection        need_inject = (not configdrive.required_by(instance) and                       injection_info is not None and                       CONF.libvirt.inject_partition != -2)        # NOTE(ndipanov): Even if disk_mapping was passed in, which        # currently happens only on rescue - we still don't want to        # create a base image.        if not booted_from_volume:#执行injection 操作            if need_inject:                self._inject_data(backend, instance, injection_info)        elif need_inject:            LOG.warning('File injection into a boot from volume '                        'instance is not supported', instance=instance)我们看看这里的CONF.libvirt.inject_partition为啥不能等于-2源码路径为:E:\nova\nova\conf\libvirt.py    cfg.IntOpt('inject_partition',               default=-2,               min=-2,               help="""Possible values:* -2 => disable the injection of data.* -1 => find the root partition with the file system to mount with libguestfs*  0 => The image is not partitioned* >0 => The number of the partition to use for the injection可以看到-2就表示禁止injection在实际运行的机器上通过cat /etc/nova/nova-computer.conf可以返现这个参数一般情况下是被设置成-1的这样就我们看看_inject_data的实现    def _inject_data(self, disk, instance, injection_info):        """Injects data in a disk image        Helper used for injecting data in a disk image file system.        :param disk: The disk we're injecting into (an Image object)        :param instance: The instance we're injecting into        :param injection_info: Injection info        """        # Handles the partition need to be used.        LOG.debug('Checking root disk injection %(info)s',                  info=str(injection_info), instance=instance)        target_partition = None#找到要inject data的硬盘路径        if not instance.kernel_id:            target_partition = CONF.libvirt.inject_partition            if target_partition == 0:                target_partition = None        if CONF.libvirt.virt_type == 'lxc':            target_partition = None        # Handles the key injection.#处理key injection的case,我们的case中这个值为none        if CONF.libvirt.inject_key and instance.get('key_data'):            key = str(instance.key_data)        else:            key = None        # Handles the admin password injection.#处理key injection的case,我们的case中这个值为none        if not CONF.libvirt.inject_password:            admin_pass = None        else:            admin_pass = injection_info.admin_pass        # Handles the network injection.#处理key injection的case,我们的case中这个值为none        net = netutils.get_injected_network_template(            injection_info.network_info,            libvirt_virt_type=CONF.libvirt.virt_type)        # Handles the metadata injection        metadata = instance.get('metadata')#可以看到可以执行injection的有key/net/metadata/admin_pass        if any((key, net, metadata, admin_pass, injection_info.files)):            LOG.debug('Injecting %(info)s', info=str(injection_info),                      instance=instance)            img_id = instance.image_ref            try:#调用具体的驱动来执行injection 动作                disk_api.inject_data(disk.get_model(self._conn),                                     key, net, metadata, admin_pass,                                     injection_info.files,                                     partition=target_partition,                                     mandatory=('files',))            except Exception as e:                with excutils.save_and_reraise_exception():                    LOG.error('Error injecting data into image '                              '%(img_id)s (%(e)s)',                              {'img_id': img_id, 'e': e},                              instance=instance)E:\nova\nova\virt\disk\api.pydef inject_data(image, key=None, net=None, metadata=None, admin_password=None,                files=None, partition=None, mandatory=()):       items = {'image': image, 'key': key, 'net': net, 'metadata': metadata,             'files': files, 'partition': partition}    LOG.debug("Inject data image=%(image)s key=%(key)s net=%(net)s "              "metadata=%(metadata)s admin_password=<SANITIZED> "              "files=%(files)s partition=%(partition)s", items)    try:#可以看到执行injection的是虚拟文件系统fs,这里首先得到fs后,再执行setup        fs = vfs.VFS.instance_for_image(image, partition)        fs.setup()    except Exception as e:        # If a mandatory item is passed to this function,        # then reraise the exception to indicate the error.        for inject in mandatory:            inject_val = items[inject]            if inject_val:                raise        LOG.warning('Ignoring error injecting data into image %(image)s '                    '(%(e)s)', {'image': image, 'e': e})        return False    try:#执行这个fs的injection        return inject_data_into_fs(fs, key, net, metadata, admin_password,                                   files, mandatory)    finally:        fs.teardown()我们以guestfs的fs为例E:\nova\nova\virt\disk\vfs\guestfs.py    def setup(self, mount=True):        LOG.debug("Setting up appliance for %(image)s",                  {'image': self.image})        try:#得到guestfs的handle,以后对guestfs操作都是通过这个handle来完成            self.handle = tpool.Proxy(                guestfs.GuestFS(python_return_dict=False,                                close_on_exit=False))        except TypeError as e:            if ('close_on_exit' in six.text_type(e) or                'python_return_dict' in six.text_type(e)):                # NOTE(russellb) In case we're not using a version of                # libguestfs new enough to support parameters close_on_exit                # and python_return_dict which were added in libguestfs 1.20.                self.handle = tpool.Proxy(guestfs.GuestFS())            else:                raise        try:#这里会根据image是local image还是rbd image 来设置不同的参数,但是都会调用add_drive_opts 将image作为一个driver添加到appliance            if isinstance(self.image, imgmodel.LocalImage):                self.handle.add_drive_opts(self.image.path,                                           format=self.image.format)            elif isinstance(self.image, imgmodel.RBDImage):                self.handle.add_drive_opts("%s/%s" % (self.image.pool,                                                      self.image.name),                                           protocol="rbd",                                           format=imgmodel.FORMAT_RAW,                                           server=self.image.servers,                                           username=self.image.user,                                           secret=self.image.password)            else:                raise exception.UnsupportedImageModel(                    self.image.__class__.__name__)#运行这个appliance            self.handle.launch()#这里的mount 为true            if mount:                self.setup_os()                self.handle.aug_init("/", 0)                self.mount = True        except RuntimeError as e:            # explicitly teardown instead of implicit close()            # to prevent orphaned VMs in cases when an implicit            # close() is not enough            self.teardown()            raise exception.NovaException(                _("Error mounting %(image)s with libguestfs (%(e)s)") %                {'image': self.image, 'e': e})        except Exception:            # explicitly teardown instead of implicit close()            # to prevent orphaned VMs in cases when an implicit            # close() is not enough            self.teardown()            raise前面都是injection前的准备工作,最后的injection是在E:\nova\nova\virt\disk\api.pydef inject_data_into_fs(fs, key, net, metadata, admin_password, files,    #可以看到这个函数对不同的injection有不同的处理函数,这里以文件为例,    items = {'key': key, 'net': net, 'metadata': metadata,             'admin_password': admin_password, 'files': files}    functions = {        'key': _inject_key_into_fs,        'net': _inject_net_into_fs,        'metadata': _inject_metadata_into_fs,        'admin_password': _inject_admin_password_into_fs,        'files': _inject_files_into_fs,    }    status = True    for inject, inject_val in items.items():        if inject_val:            try:#以文件injection为例的话,最终是调用_inject_files_into_fs                inject_func = functions[inject]                inject_func(inject_val, fs)            except Exception as e:                if inject in mandatory:                    raise                LOG.warning('Ignoring error injecting %(inject)s into '                            'image (%(e)s)', {'inject': inject, 'e': e})                status = False    return statusdef _inject_files_into_fs(files, fs):    for (path, contents) in files:        # NOTE(wangpan): Ensure the parent dir of injecting file exists        parent_dir = os.path.dirname(path)        if (len(parent_dir) > 0 and parent_dir != "/"                and not fs.has_file(parent_dir)):#设定路径            fs.make_path(parent_dir)#设定为root 用户            fs.set_ownership(parent_dir, "root", "root")#设置权限为744            fs.set_permissions(parent_dir, 0o744)#调用_inject_file_into_fs        _inject_file_into_fs(fs, path, contents)def _inject_file_into_fs(fs, path, contents, append=False):    LOG.debug("Inject file fs=%(fs)s path=%(path)s append=%(append)s",              {'fs': fs, 'path': path, 'append': append})    if append:        fs.append_file(path, contents)    else:        fs.replace_file(path, contents)_inject_file_into_fs 文件找那个的append 为false,最后执行fs.replace_file 原来所谓的文件injection就是调用虚拟文件系统的fs.replace_file来讲形参contents写到形参path 表示的路径中.    def replace_file(self, path, content):        LOG.debug("Replace file path=%s", path)        path = self._canonicalize_path(path)        self.handle.write(path, content)可见如前面所说,最后还是通过handler调用guestfs的writer函数来执行injection

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 卧室锁打不开了怎么办 锁舌头回不去怎么办 房门锁打不开怎么办 门锁松动怎么办 木门锁打不开怎么办 门锁保险打不开怎么办 球形门锁打不开怎么办 门锁里外打不开怎么办 圆形门锁打不开怎么办 门锁反锁打不开怎么办 防盗门锁开不开怎么办 门锁钥匙打不开怎么办 家用门锁打不开怎么办 球形锁打不开了怎么办 反锁了门打不开怎么办 大门锁打不开怎么办 锁头打不开了怎么办 普通门锁锁不上怎么办 门锁很难开怎么办 室内锁打不开了怎么办 保险锁打不开怎么办 防盗门副锁不退怎么办 门锁坏了怎么办 木门锁槽坏了怎么办 房门锁芯坏了怎么办 锁轴坏了怎么办 柜子锁被撬坏了怎么办 八宝粥打不开怎么办 摩托车碟刹响怎么办 门打不开怎么办有钥匙 密码锁打不开了怎么办 防盗门没有门铃怎么办 木门变形关不上怎么办 门变形关不上怎么办 防盗门下坠了怎么办 防盗门下沉怎么办 防盗门瓢了怎么办 门锁不灵活怎么办 厕所门锁打不开怎么办 防盗锁锁芯坏了怎么办 自如锁没电了怎么办