2019独角兽企业重金招聘Python工程师标准>>>

感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正!
如果转载,请保留作者信息。
博客地址:http://blog.csdn.net/gaoxingnengjisuan
邮箱地址:dong.liu@siat.ac.cn

openstack在创建实例的时候可以将文件和相关的参数注入到实例的镜像中,来完成密码的设定、密钥的添加等动作,而这些动作的完成都是在实例启动之前。这在有些情况下会非常有用,比如修改root密码,注入ssh密钥,对实例的个性化定制等等。

1.相关源码的源码结构

文件和元数据注入是/nova/virt/disk/下的源码文件实现的,我们先来看一下/nova/virt/disk/的源码结构。

/nova/virt/disk/api.py

提供了调整、重新分区和修改磁盘镜像的方法;

包括文件和元数据注入等方法;

磁盘上的实践包括:重定义大小,文件系统建立和文件注入等;

def get_disk_size(path):

获取虚拟磁盘镜像大小;

def extend(image, size):

根据定义的size镜像大小,改变当前镜像的大小;

def can_resize_fs(image, size,use_cow=False):

检测是否可以对文件系统的大小进行重新调整;

class _DiskImage(object):

磁盘文件镜像的操作类;

    def _device_for_path(path):

    从path中获取表示device的路径信息;

    def _reset(self, device):

    为之前挂载的目录进行内部状态的重新设置;

    def errors(self):

    返回所有操作的错误集合;

    def mount(self):

    应用对象属性,实现磁盘镜像的挂载;

    def umount(self):

    从文件系统上卸载挂载点;

    def teardown(self):

    从文件系统上删除磁盘镜像;


def inject_data(image, key=None, net=None, metadata=None, admin_password=None, files=None, partition=None, use_cow=False, mandatory=()):

注入指定的项目到磁盘镜像image;

def setup_container(image,container_dir, use_cow=False):

安装LXC容器;

将会挂载loopback镜像到容器路径,来为容器建立根文件系统;

def teardown_container(container_dir):

这个方法实现了删除容器在根文件系统的挂载;

它将会卸载已经挂载的容器,并删除所有的连接设备;

def clean_lxc_namespace(container_dir):

这个方法实现了清理容器命名空间的根文件系统的挂载;

它将会卸载已经挂载的名称,但是只会留下相关的连接设备;

def inject_data_into_fs(fs,key, net, metadata, admin_password, files, mandatory=()):

注入指定数据到已经挂载的文件系统;

def _inject_files_into_fs(files,fs):

注入文件到文件系统;

def _inject_file_into_fs(fs,path, contents, append=False):

注入指定的文件到指定的文件系统;

def_inject_metadata_into_fs(metadata,fs):

注入元数据到文件系统;

def _setup_selinux_for_keys(fs,sshdir):

获取selinux来宾系统来确认注入key的内容的正确性;

def _inject_key_into_fs(key,fs):

添加指定的公开ssh密钥到root目录下的authorized_keys文件中;

def _inject_net_into_fs(net,fs):

注入文件/etc/network/interfaces(即net)到文件系统fs的根目录;

def _inject_admin_password_into_fs(admin_passwd,fs):

为admin_passwd设置超级用户密码;   

def_set_passwd(username,admin_passwd, passwd_data, shadow_data):

为用户admin_passwd设置密码;


/nova/virt/disk/vfs/api.py

虚拟文件系统实践;

虚拟文件系统API;

class VFS(object):

VFS类定义了一个接口,用来为虚拟磁盘镜像文件系统操作文件;

    defsetup(self):

    执行任务的方法;

    defteardown(self):

    释放在setup方法中初始化的所有的资源;

    defmake_path(self, path):

    建立路径;

    defappend_file(self, path,content):

    添加内容(@content)到@path所标志文件的结尾,

    如果@path所标志文件不存在,则新建立文件;

    def replace_file(self, path,content):

    用@content替换@path所指定文件的内容,

    如果文件不存在,则新建立文件;

    def read_file(self, path):

    返回@path所指定文件的全部内容;

    defhas_file(self, path):

    如果@path指定的文件存在,则返回true值;

    def set_permissions(self, path,mode):

    设置文件权限;

    def set_ownership(self, path,user, group):

    设置文件的用户及用户组;


/nova/virt/disk/vfs/guestfs.py

来宾文件系统访问磁盘镜像文件;

class VFSGuestFS(vfs.VFS):

类 VFSGuestFS继承自类VFS;

类VFSGuestFS实现了VFS模块,这个模块使用了libguestfs API来访问磁盘镜像文件;

    def __init__(self, imgfile,imgfmt='raw', partition=None):

    def setup_os(self):

    def setup_os_static(self):

    def setup_os_inspect(self):

    def setup_os_root(self, root):

    def setup(self):

    def teardown(self):

    def _canonicalize_path(path):

    def make_path(self, path):

    def append_file(self, path,content):

    def replace_file(self, path,content):

    def read_file(self, path):

    def has_file(self, path):

    def set_permissions(self, path,mode):

    def set_ownership(self, path,user, group):


/nova/virt/disk/vfs/localfs.py

本地文件系统访问磁盘镜像文件操作;

classVFSLocalFS(vfs.VFS):

类VFSLocalFS继承自类VFS,这个类实现了VFS模块,

它映射到一个挂载在主机(本地)文件系统上的现有的虚拟根目录;

    def__init__(self, imgfile,imgfmt="raw", partition=None, imgdir=None):

    def setup(self):

    def teardown(self):

    defmake_path(self, path):

    def append_file(self, path,content):

    def replace_file(self, path,content):

    def read_file(self, path):

    def has_file(self, path):

    def set_permissions(self, path,mode):

    def set_ownership(self, path,user, group):


/nova/virt/disk/mount/api.py

支持挂载磁盘镜像到主机文件系统;

支持挂载虚拟镜像文件;

classMount(object):

这个类是标准的挂载操作类,可以被子类重写;

基本的设备操作包括get、map和mount等;

    def instance_for_format(imgfile,mountdir, partition, imgfmt):

    根据镜像类型来判断导入代表不同挂载方式的挂载类;

    如果镜像类型是raw,则导入nova.virt.disk.mount.loop.LoopMount;

    如果镜像是其他类型,则导入nova.virt.disk.mount.nbd.NbdMount;

    def instance_for_device(imgfile,mountdir, partition, device):

    根据设备属性来判断导入代表不同挂载方式的挂载类;

    如果设备属性中包括"loop",则导入nova.virt.disk.mount.loop.LoopMount;

    如果设备属性中不包括"loop",则导入nova.virt.disk.mount.nbd.NbdMount;

    defreset_dev(self):

    重新设置设备路径允许进行卸载操作;

    def get_dev(self):

    设置可用的镜像文件作为块设备在文件系统中;

    def unget_dev(self):

    从文件系统的命名空间释放块设备;

    def map_dev(self):

    映射设备的分区到文件系统的命名空间;

    defunmap_dev(self):

    从文件系统的命名空间删除设备的分区;

    def mnt_dev(self):

    挂载设备到文件系统;

    def unmnt_dev(self):

    从文件系统卸载设备;

    def do_mount(self):

    调用get、map和mnt等操作实现设备的挂载操作;

    def do_umount(self):

    调用unmnt操作实现设备的卸载操作;

    def do_teardown(self):

    调用umntunmapunget操作实现相关资源的卸载及清理工作;

    def _get_dev_retry_helper(self):

    def_inner_get_dev(self):


/nova/virt/disk/mount/loop.py

支持回环设备挂载镜像;

针对raw格式的镜像的回环挂载支持类;

class LoopMount(api.Mount):

针对raw格式的镜像的回环挂载支持类;

LoopMount继承自类Mount

    def _inner_get_dev(self):

    def get_dev(self):

    def unget_dev(self):


/nova/virt/disk/mount/nbd.py

磁盘镜像的qemu-nbd挂载支持类;

class NbdMount(api.Mount):

磁盘镜像的qemu-nbd挂载支持类;

NbdMount继承自类Mount

    def_detect_nbd_devices(self):

    检测nbd设备文件;

    def_find_unused(self,devices):

    def _allocate_nbd(self):

    def _read_pid_file(self,pidfile):

    def _inner_get_dev(self):

    defget_dev(self):

def unget_dev(self):

2.OpenStack Nova文件和元数据注入
openstack在创建实例的时候,可以对实例进行文件注入,注入的内容可为:
key ssh公钥;
network 网络参数;
admin_password 注入超级用户 root 的密码;
metadata 注入元数据meta.js;
在下一篇博客中将会具体来看相关代码的实现;

首先来看各种文件注入的命令行实现:
注入ssh密钥
创建密钥(ssh-keygen),添加密钥对;
nova keypair-add --pub_key.ssh/id_rsa.pub mykey
创建实例的时候注入密钥;
nova boot --key_name mykey --imageid_of_image --flavor 1 name_of_instance
注:id_of_image可以通过nova image-list取得;
注入文件
假如我要注入.vimrc这个文件到新创建的实例中,可以:
nova boot --file /root/.vimrc=/root/.vimrc--image id_of_image --flavor 1 name_of_instance
注:可以注入多个文件(最多5个),只要写多个--file;
注入元数据
可以通过--meta给实例中传入键值对,注入后会写在/meta.js文件里,以类似python字典的方式存储在虚拟机的/meta.js文件中;
nova boot --meta key2=value2 --metakey1=value1 --image id_of_image --flavor 1 name_of_instance
cat /meta.js
{"key2″: “value2″,“key1″: “value1″}

3.文件注入过程中涉及的镜像挂载方式

OpenStack grizzly版本中支持的文件注入执行中镜像的挂载方式有两种:loop和nbd。每种方式对应的实现代码位于nova/nova/virt/disk/mount/目录下,文件名分别为:loop.py和nbd.py。这里以在CENTOS系统上的应用操作,来对这两种文件挂载方式进行一个简单的介绍。

loop方式

loop方式下,镜像以loopdevice的方式挂载到宿主机的某个设备名下,例如:

#losetup–find –show centos-6.2-x86_64.raw

#/dev/loop0

以上命令表示,centos-6.2-x86_64.raw已经被挂载为设备/dev/loop0,可以通过该loop设备来操作镜像文件。

之后,通过kpartx命令,找到loop设备上的可用分区,并分别在宿主机上进行挂载。

注:linux loop device介绍

在Linux中,有一种特殊的块设备叫loop device,这种loop device设备是通过影射操作系统上的正常的文件而形成的虚拟块设备。因为这种设备的存在,就为我们提供了一种创建一个存在于其他文件中的虚拟文件系统的机制.

回环设备( 'loopback device')允许用户以一个普通磁盘文件虚拟一个块设备。设想一个磁盘设备,对它的所有读写操作都将被重定向到读写 一个名为 disk-image 的普通文件而非操作实际磁盘或分区的轨道和扇区。(当然,disk-image 必须存在于一个实际的磁盘上,而这个磁 盘必须比虚拟的磁盘容量更大。)回环设备允许你这样使用一个普通文件。

回环设备的使用与其它任何块设备相同。特别是,你可以在这个设备上创建文件系统并像普通的磁盘一样将它挂载在系统中。这样的一个将全部内容保存在一个普通文件中的文件系统,被称为虚拟文件系统(virtual file system)。

nbd方式

nbd方式下是通过qemu-nbd命令来实现虚拟机镜像的挂载。

首先确保nbd内核模块已经加载:

modprobenbd

此时在/dev目录下应该可以看到nbd的设备:

/dev/nbd0 /dev/nbd10 /dev/nbd12 /dev/nbd14 /dev/nbd2 /dev/nbd4/dev/nbd6 /dev/nbd8

/dev/nbd1/dev/nbd11 /dev/nbd13 /dev/nbd15 /dev/nbd3 /dev/nbd5 /dev/nbd7 /dev/nbd9

#qemu-nbd–connect=/dev/nbd2 /root/temp/centos-6.2-x86_64.raw

#fdisk-l /dev/nbd2

Disk/dev/nbd2: 21.5 GB, 21474836480 bytes

255heads, 63 sectors/track, 2610 cylinders, total 41943040 sectors

Units= sectors of 1 * 512 = 512 bytes

Sectorsize (logical/physical): 512 bytes / 512 bytes

I/Osize (minimum/optimal): 512 bytes / 512 bytes

Diskidentifier: 0x00046def

DeviceBoot Start End Blocks Id System

/dev/nbd2p1* 2048 41943039 20970496 83 Linux

此时已经可以看到镜像文件的分区了,通过将/dev/nbd2p1设备挂载在宿主机上就可以对镜像中的文件进行操作了。

注:NBD简介

NBD(Network Block Device)让你可以将一个远程主机的磁盘空间,当作一个块设备来使用。就像一块硬盘一样.使用它,你可以很方便的将另一台服务器的硬盘空间,增加到本地服务器上。NBD与NFS有所不同.NFS只是提供一个挂载点供客户端使用,客户端无法改变这个挂载点的分区格式。而NBD提供的是一个块设备,客户端可以把这个块设备格式化成各种类型的分区.更便于用户的使用. NBD是一个内核模块,大部分Linux发行版都已包含它。

在/nova/virt/disk/mount/api.py代码文件中,类Mount定义了标准的挂载操作类,在这个类中有两个方法,instance_for_format和instance_for_device,前者实现了通过镜像文件的格式来判断采用哪种挂载方式,后者实现了通过设备属性中是否包括“loop”来判断采用哪种挂载方式,具体来看代码:

[python]  view plain copy print ?
  1. @staticmethod
  2. def instance_for_format(imgfile, mountdir, partition, imgfmt):
  3. LOG.debug(_("Instance for format imgfile=%(imgfile)s "
  4. "mountdir=%(mountdir)s partition=%(partition)s "
  5. "imgfmt=%(imgfmt)s") % locals())
  6. if imgfmt == "raw":
  7. LOG.debug(_("Using LoopMount"))
  8. return importutils.import_object(
  9. "nova.virt.disk.mount.loop.LoopMount",
  10. imgfile, mountdir, partition)
  11. else:
  12. LOG.debug(_("Using NbdMount"))
  13. return importutils.import_object(
  14. "nova.virt.disk.mount.nbd.NbdMount",
  15. imgfile, mountdir, partition)
[python]  view plain copy print ?
  1. @staticmethod
  2. def instance_for_device(imgfile, mountdir, partition, device):
  3. LOG.debug(_("Instance for device imgfile=%(imgfile)s "
  4. "mountdir=%(mountdir)s partition=%(partition)s "
  5. "device=%(device)s") % locals())
  6. if "loop" in device:
  7. LOG.debug(_("Using LoopMount"))
  8. return importutils.import_object(
  9. "nova.virt.disk.mount.loop.LoopMount",
  10. imgfile, mountdir, partition, device)
  11. else:
  12. LOG.debug(_("Using NbdMount"))
  13. return importutils.import_object(
  14. "nova.virt.disk.mount.nbd.NbdMount",
  15. imgfile, mountdir, partition, device)

可见,确定了所应用的挂载方式后,就导入相应的挂载方式实现类。

下一篇博客中将会具体来看文件注入以及采用相应磁盘文件挂载方式和操作的代码实现。

转载于:https://my.oschina.net/tantexian/blog/625965

OpenStack文件注入相关分析(转载)相关推荐

  1. spring-自动加载配置文件\使用属性文件注入

    在上一篇jsf环境搭建的基础上 , 加入spring框架 , 先看下目录结构 src/main/resources 这个source folder 放置web项目所需的主要配置,打包时,会自动打包到W ...

  2. 如何写一个bat批处理自动上传文件到FTP 转载

    如何写一个bat批处理自动上传文件到FTP 转载 2018-05-28 16:34:06 1点赞宁不凡 码龄5年关注单个文件:@echo offecho open 192.168.1.143 & ...

  3. 软件安全之代码注入技术 向目标 PE 文件注入 DLL notepad lpk.dll 远程线程函数 提权函数 OpenProcess VirtualAllocEx

    实验 4 代码注入技术 引言 1.实验说明 代码注入是将用户代码注入到其他进程或者可执行文件中,实现拦截目标进程运行过程的关键信息.改变目标进程或可执行文件原本执行流程等目的 2.实验目的 本实验通过 ...

  4. 木马病毒隐身穿墙术解密之文件注入和反弹连接

    作者: 刘源 比特网 2010-04-01 12:05:08 木马病毒隐身穿墙术解密之文件注入和反弹连接 对于木马病毒当前所使用的隐身和穿墙术,到这篇已经是第三篇了,虽然每篇的篇幅都不是很长,但每篇都 ...

  5. 详解 Spring 3.0 基于 Annotation 的依赖注入实现--转载

    使用 @Repository.@Service.@Controller 和 @Component 将类标识为 Bean Spring 自 2.0 版本开始,陆续引入了一些注解用于简化 Spring 的 ...

  6. SetDll把Dll文件注入到.exe应用程序中

    setdll.exe 下载地址:http://download.csdn.net/detail/u013147600/8649009点击打开链接 1.将下载好的setdll.exe 和.exe应用程序 ...

  7. CocoStudio 1.3和1.4.1导入Flash文件注意事项(转载并有修改)

    转载自URL:http://www.cocoachina.com/bbs/read.php?tid=169621 在手机游戏火热之前,世界上最大的游戏平台应该是flash游戏了.Adobe公司提供了一 ...

  8. python去重txt文本_Python 文件去重(转载)

    原博文 2020-02-14 13:20 − Python实现的txt文件去重功能示例 更新时间:2018年07月07日 09:00:36 作者:人饭子 我要评论 这篇文章主要介绍了Python实现的 ...

  9. /bin/bash^M: bad interpreter: 没有那个文件或目录--转载

    运行脚本时出现了这样一个错误,打开之后并没有找到所谓的^M,查了之后才知道原来是文件格式的问题,也就是linux和windows之间的不完全兼容... 具体细节不管,如果验证: vim test.sh ...

最新文章

  1. logstash导入数据到Elasticsearch踩过的坑详解
  2. 【scala】集和映射
  3. 【theano-windows】学习笔记十一——theano中与神经网络相关函数
  4. OSPF第十章:OSPF 一
  5. Fedora 18在ASUS N6系列电脑上以太网卡驱动的安装
  6. 列表的修改,复制,遍历,嵌套和查询
  7. 配置的代理服务器未响应 电脑连不上网_手机、电脑为什么连不上网(断网)?...
  8. Android 四大组件学习之BroadcastReceiver三
  9. 错误: 找不到或无法加载主类 Main
  10. Firebug 入门指南
  11. flutter 文字颜色渐变
  12. 20155313 杨瀚 《网络对抗技术》实验九 Web安全基础
  13. RPL-UDP的cooja仿真过程
  14. 在线电影订票系统 - 数据库建模
  15. 阿里云发布首款云电脑“无影”,价格仅传统电脑的一半
  16. kubernete编排技术五:DaemonSet
  17. swagger首页空白
  18. 计算机教师结构化方式面试,市计算机:17名学生通过全国教师资格证结构化面试...
  19. matlab踩坑 自带surf 函数找不了 surf 作为函数执行
  20. linux中的df和du命令

热门文章

  1. 写一个ArrayList类的动态代理类
  2. 妙用终截者密码锁防***注入Explorer
  3. opengl深度缓冲获得的深度图精度太低_深度学习行人重识别ReID最新综述与展望...
  4. mysql while 游标_mysql 游标 loop while 的使用
  5. 程序员的岗位方向和所需技能都有哪些?
  6. python迭代器生成器 学会再缩短一半开发效率 看看大牛是怎么写的
  7. 那个计算机应用没有广告,为什么别人的电脑没有什么广告,而你的电脑一大堆呢?答案在这里...
  8. /proc/diskstats各字段解析
  9. 简单分析MySQL 一则慢日志监控误报问题
  10. 一文搞懂栈(stack)、堆(heap)、单片机裸机内存管理malloc