博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
libvirt的file injection
阅读量:4214 次
发布时间:2019-05-26

本文共 10056 字,大约阅读时间需要 33 分钟。

在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=
" "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

转载地址:http://urjmi.baihongyu.com/

你可能感兴趣的文章
CentOS6.4配置Hadoop-2.6.0集群配置安装指南(经过实战演练)【张振华.Jack】
查看>>
【屌丝程序的口才逆袭演讲稿50篇】第二篇:专注的力量 [张振华.Jack]
查看>>
【屌丝程序的口才逆袭演讲稿50篇】第三篇:我的舍与得的2014[张振华.Jack]
查看>>
【屌丝程序的口才逆袭演讲稿50篇】第五篇:不要给自己找任何借口【张振华.Jack】
查看>>
【屌丝程序的口才逆袭演讲稿50篇】第七篇:请留意我们身边的风景 【张振华.Jack】
查看>>
【屌丝程序的口才逆袭演讲稿50篇】第八篇:坚持的力量 【张振华.Jack】
查看>>
【屌丝程序的口才逆袭演讲稿50篇】第九篇:春节那些事-过年回家不需要理由【张振华.Jack】
查看>>
【屌丝程序的口才逆袭演讲稿50篇】第十篇:程序员们请看看外面的世界吧【张振华.Jack】
查看>>
【屌丝程序的口才逆袭演讲稿50篇】第十一篇:马云乌镇40分钟演讲实录【张振华.Jack】
查看>>
Java并发编程从入门到精通 张振华.Jack --我的书
查看>>
【屌丝程序的口才逆袭演讲稿50篇】第十二篇:世界上最快的捷径【张振华.Jack】
查看>>
Android中Java代码和XML布局效率问题
查看>>
android TextView属性大全(转)
查看>>
Conclusion for Resource Management
查看>>
Conclusion for Constructors,Destructors,and Assignment Operators
查看>>
Conclusion for Accustoming Yourself to C++
查看>>
面试题1:赋值运算函数(offer)
查看>>
面试题15:在O(1)时间删除链表结点
查看>>
面试题16:调整数组顺序使奇数位于偶数前面
查看>>
面试题17:链表中倒数第k个结点(offer)
查看>>