写给未出世的儿子<3>

2012-06-28 20:57:03

前几天给你起好了名字,爸爸决定了就叫“王余羲”了!

而且你 人民毕宏博士 伯伯也觉得这名字挺好,既然毕博士都觉得不错,那就它了!
关于名字的意义,这个问题等你长大后肯定会有一些小姑娘好奇的问你的,
那我先说下标准答案以备你判断哪个小姑娘比较聪明,最起码知道“羲”的解释也是挺聪明的小姑娘了!
王:这个不解释!
余:1.首先这是你的辈分,你排到“余”字辈;2.其次“余”字的含义是“饱足, 足食得饱;余,饶也。——《说文》
羲:根据隶定字形解释。会意。从羊,从“禾戈”,从丂。“羊”本指羊或羊群,引申指“羊群跟人走”、“羊顺从人意”。“禾戈”表示“庄稼像军队方阵那样排列整齐”(参见本百科中“栽”、“戠”等类似结构字的分析)。“丂”指“经历风雨”。“禾戈”与“丂”联合起来表示“排列整齐的庄稼在风雨中成长”。“羊”与“禾戈丂”联合起来表示“风雨中的庄稼顺着人意生长”。本义:春夏季节庄稼顺着人意生长。而你又是夏天出生的。
所以整体解释起来就是,爸爸妈妈希望你能 在衣食无忧的家庭 不惧风雨 一切皆如人意的顺利成长
风雨由爸爸妈妈替你尽力遮挡,但有些事情爸爸妈妈也是无能为力的,比如追女朋友、中考、高考、考研、考博等等,这些事情基本上只能靠你自己的努力了,当然追女朋友这个事情可能不是努力就能搞定的,你也不要太过执着了。另外虽然爸爸把追女朋友放在了各种考试之前,意思就是媳妇儿比考试重要,因为这个人关系到你的终身幸福,考不好可以复读甚至放弃,但是媳妇儿可必须有。不过你自己也得分清特定时期的主次关系,考上大学之前肯定是升学考试重要,可以喜欢小姑娘,但不能影响了考试,就像爸爸在上篇写给你的文章里面写的那样。
另外爸爸准备后天也就这周六(6月30号)回老家看你和妈妈,陪妈妈一起等待宝宝你的出生,爸爸的假期只有7天,也就是从7月2号到7月8号,爸爸9号就要上班了,希望宝宝你能给点力,在31号到5号这几天出世,这样爸爸就能陪你几天再回杭州上班,不然你出生的那天可能就见不到爸爸了。

 

偷偷的告诉你啊,爸爸已经开始给你物色媳妇儿了,等爸爸看到哪家小姑娘长得不错、有潜力的给你定个娃娃亲啥的,哈哈,等你长大了就偷着乐吧!
不过你媳妇这会儿还不知道有没有出生呢,我估计十有八九还没!除非你也跟老爸一样找个比你大好几岁的媳妇。

 

哎,都晚上9点多了,爸爸昨天晚上睡觉前还想着晚上能抽空练会儿字呢,爸爸好久没有写字了,写的都不成样子了,看来今天不行了。儿子长大要好好写字,虽然不流行写情书了,但是如果能写一手好字,小姑娘也会喜欢的。

写给未出世的儿子<2>

2012-06-16 10:59:55

今天爸爸坐汽车去东阳,去给爸爸的姑父送电脑,爸爸的姑父你该叫什么?爸爸也不知道,⊙﹏⊙b汗,是姑姥爷吗?
路上很无聊,就给你说会儿话吧。
爸爸这几天都在给你想名字呢,不过还是没想好,想了一个,王余曦,因为按照老家的辈分,你排在余字辈。不知道这个名字你喜不喜欢,爸爸感觉太普通了,不够响亮,还得再想一个。其实也就是把余字替换成别的字而已。爸爸给你取余字的意思是为了让你不要忘本,要记住自己的老家以及老家的亲人,他们可都是很勤劳善良的好人,你长大以后也要做这样的人。
还有爸爸还想说的是关于爸爸的人生观,爸爸希望自己可以生活的比较洒脱快乐,虽然没有完全做到,至少我有
追求的目标。人生的很多时候,目标比结果更有意义,比如说高考,追女朋友,赚钱买房等等。
爸爸想活的洒脱快乐,不知道到目前为止算不算做到了,我想应该还不算吧,原因有很多,比如要赚钱,买房,养活你和妈妈,还有之前爱感情方面的一些事情,当然不是和你妈妈的问题,哪个男生还能没暗恋过几个女生呢。
不过爸爸希望你的人生能实现这个目标,做人洒脱快乐一些,凡事不要太计较得失,快乐痛苦都是一辈子,何苦为难自己呢!但是我不是说做人可以没有追求,爸爸的网名aspirer你可以查下词典看看是什么意思。追求必须得有,不然人生就没有目标,就会浑浑噩噩,也就不会有挑战,不会有成就感,也就不会被别人尊重。
人生的不同阶段肯定会有不同的追求,这很明显,小时候,你的追求可能是很多玩具,很多好吃的零食,没有老师和爸妈的管教,自由自在。但更多的情况是同一个阶段你的追求跟爸妈老师期望的追求可能不一样,尤其是当你还不懂事的时候,这时候爸妈总是希望你能听我们的话,为什么呢?因为你还小,不知道你的这个人生阶段应该追求什么,至少是各种追求应该有主次之分,爸爸妈妈老师的教导就是让你在目前的人生阶段分清主次,为你以后的人生有更多更好的机会追求自己想要的东西,比如物质生活,女朋友等等。
你要时刻记住一点,爸爸妈妈做任何决定都是为你好。
好了,爸爸快到了,先聊到这吧。宝宝在妈妈肚子里要乖乖的,过几天顺利出生,爸爸回老家看你和妈妈。

写给未出世的儿子<1>

2012-06-04 14:17:07

没有打草稿,信手涂鸦,望你见谅

虽然经常带你去医院检查,但直到前天上午10点之前我都不知道你是男宝宝还是女宝宝
你都已经8个月啦!医院的彩超里都可以看到你的小脸和小JJ啦!
其实以前我老感觉你是个女宝宝的,可是你妈妈说你是男宝宝,看来还是女人的直觉比较准!
说实话爸爸也不是感觉是女宝宝,而是希望最好是个女宝宝,因为不用有太多压力,爸爸想偷懒、不想赚钱太累呢,嘿嘿
不过听说你是男宝宝,你的爷爷奶奶很开心啊!毕竟老人们传宗接代的思想观念还是很重的,尤其是在农村老家那边
还有一个原因是爸爸觉得男孩子容易不听话,爸爸小时候就是一个超级气人精,基本每天都惹你爷爷奶奶生气,每次都挨你爷爷的打,幸亏爸爸后来懂事了,不然估计现在爸爸还不知道能不能有现在的出息呢
所以爸爸很担心你生下来是否也会像爸爸小时候一样不听话、爱调皮捣蛋,现在爸爸可发愁怎么教育你了
希望你能继承爸爸的优点,爱学习,有上进心,不怕吃苦。。。其实爸爸还是有很多优点的,虽然当年爸爸追的那些除了你妈妈之外的阿姨都不喜欢爸爸,嘿嘿
另外爸爸还在给你起名字,你妈妈之前给你起了一个两个字的“王曦”,爸爸觉得两个字的不给力,还是想起三个字的,因为爸爸的名字就是两个字,刚上小学时的爸爸把名字都拆成了三个,哈哈,多有创意啊,因为爸爸看人家的名字都是三个字,太羡慕了
这次就写到这吧

KVM in OpenStack

图裂请查看原文!

原文地址:http://aspirer2004.blog.163.com/blog/static/1067647201531452142289/

本文结构及部分内容参考了:http://files.meetup.com/10602292/kvm%20features.pdf海云捷迅–Dexin(Mark) Wu)

本文主要介绍KVM(QEMU)在OpenStack开源云平台中的地位、作用、用途,以及目前各种功能的应用情况,最后介绍了一些常见场景的具体使用方式和流程。 目录结构如下:

  1. KVM介绍
  2. KVM与QEMU及libvirt三者的关系
  3. KVM子系统在OpenStack中的应用
    • Cpu
    • Memory
    • Storage
    • Network
    • others
  4. OpenStack应用实例分析
    • 创建云主机
    • 挂载云硬盘
    • 修改云主机规格
    • 在线迁移云主机

KVM简单介绍

KVM是Kernel-based Virtual Machine的简称,一套X86平台CPU架构下的完全虚拟化解决方案,它依赖Intel-VT或者AMD-V硬件辅助虚拟化技术[1],同时支持EPT和AMD NPT内存虚拟化技术[2],以提升CPU和内存的虚拟化性能[3]。 06年10月以色列qumranet公司发布,2.6.20加入内核主干(充分利用Linux内核既有代码),08年qumranet被redhat收购,之后由redhat主导开发。 kvm提供可动态加载的内核模块kvm.ko,以及支持具体的CPU厂商的kvm_intel.ko或kvm_amd.ko。 提供与内核交互的途径(/dev/kvm)、管理内核中虚拟机数据结构、状态信息、捕获并处理虚拟机遇到的特殊指令等,不模拟具体的设备。 简化版架构图如下:

2015年04月14日 - aspirer - Aspirers blog

2015年04月14日 - aspirer - Aspirers blog

从上图中可以看出,KVM主要是负责kernel-mode部分。

KVM与QEMU的关系

既然KVM不负责具体的虚拟机运行必须的硬件如BIOS、磁盘、IO设备、PCI设备等,那么就得依靠其他软件来实现,目前来说,实现这部分硬件模拟功能的软件就是QEMU。 QEMU:quick emulate简写而成,一个开源的硬件设备模拟软件,比KVM历史更早,优点是可以模拟多种架构和设备[4],不足在于原始的qemu是不支持硬件加速的,所以效率比较低。 qemu本身不依赖kvm,没有kvm,qemu照样可以做到配合kvm可以做的任何事(只是性能很差,这一点可以从Android设备模拟的时候体验到),qemu本身就不是为kvm而生的。 kvm出现后,为了专门支持kvm,形成了qemu-kvm,目前qemu已经原生支持kvm,也就是不需要做任何改动就可以配合kvm使用(当然还有专门支持Xen而形成了qemu-xen),KVM与QEMU二者在内核态和用户态互相配合,极大的提升了虚拟化性能,二者目前来说是一个整体,打个比方来解释二者的关系:QEMU是普通发动机汽车,KVM+QEMU就是喷气式发动机汽车!

2015年04月14日 - aspirer - Aspirers blog

QEMU和libvirt的关系

目前要直接使用QEMU,只能用命令行方式运行,没有相关API提供,使用不方便,很多在线命令,如热插拔磁盘、网卡等,是需要交互式执行的,显然是不适合大规模环境下应用,要记住那么多的参数也是一件及其痛苦的事情[5]。

2015年04月14日 - aspirer - Aspirers blog

为了解决这一问题,也为了形成统一的管理接口层,libvirt诞生了,最初libvirt是为了解决qemu-xen遇到的上述管理问题,但由redhat主导开发的libvirt的目标远不止于此。 libvirt[6],顾名思义,是lib+virt的意思,虚拟化软件库,专门提供各种虚拟化平台的统一接口,支持很多虚拟化软件如:qemu、xen、virtual box,lxc等等。 原生C开发,提供各种绑定语言接口,C#、python、Java、ruby等,各大开源云计算平台几乎都是用libvirt作为底层虚拟化软件接口层提供服务。 libvirt使用更加人性化的xml格式配置来定义虚拟机各种参数信息,libvirt会解析这些xml配置,并最终转化为qemu的命令行参数,并在用户执行启动虚拟机命令时把qemu进程拉起来(用xml中的各种参数)。

2015年04月14日 - aspirer - Aspirers blog

KVM子系统在OpenStack中的应用

在此我们不再区分KVM和QEMU,认为他们是一个整体,统称为KVM。 KVM在OpenStack中应用的整体架构图如下:
2015年04月14日 - aspirer - Aspirers blog

CPU子系统

  • 可以使用host-model、host-passthrough两种模式
  • 每个vm都是一个用户态的qemu进程
  • 每个vcpu都是一个用户态的隶属于qemu进程的线程
  • 可以通过cgroup或者其他Linux工具对qemu进程执行各种资源限制操作(qemu默认就提供cgroup支持)
  • 支持vcpu绑定到特定范围的pcpu,防止vm影响宿主机进程(vcpu_pin_set配置项指定)
  • 支持设置vcpu的weight、period、quota,网易云利用该特性还开发了ecu功能,可以保障每个vcpu的计算能力
  • 单个vm的vcpu绑定设置、vcpu拓扑结构设置、vNUMA等功能正在开发中(qemu和libvirt已经支持),网易云利用拓扑结构设置,支持了超过2核的windows云主机
  • vcpu热插拔功能还没有开发计划(qemu和libvirt已经支持,但不够稳定)

MEMORY子系统

  • 支持设置内存复用比例(overcommit,通过配置项ram_allocation_ratio)
  • 支持内存预留(预留内存无法分配给vm,通过配置项reserved_host_memory_mb)
  • vm内存映射到qemu进程地址空间,qemu利用malloc和mmap分配内存
  • vm内存支持各种Linux内核的内存交互、合并、压缩等特性
  • vm支持内存大页(2M)(OpenStack开发中) 、透明大页特性
  • vm气泡方式(balloon)内存复用(qemu和libvirt已经支持,OpenStack未支持)
  • 内存热插(qemu已支持,libvirt和OpenStack未支持)

STORAGE子系统

  • 前端(vm内部驱动)支持IDE、SCSI、virtio、virtio-scsi,OpenStack默认使用virtio方式,也可以配置其他方式(镜像设置属性:hw_disk_bus=ide, hw_scsi_model=virtio-scsi)
  • 后端(qemu进程)支持的文件镜像格式包括raw、qcow2、vmdk、qed、vdi、vpc、vhdx等(通过glance上传镜像时可以指定镜像格式,也可以配置nova实际创建云主机的时候使用的格式libvirt_images_type、use_cow_images)
  • qemu支持的存储后端包括file、iscsi、host、ceph、sheepdog、glusterfs等
  • 后端磁盘缓存模式支持none、directsync、writeback、writethrough、nosafe
  • 支持IO限速功能(qemu内部实现和cgroup实现两种方式,支持限制读写bps和iops,新版支持burst模式),网易云硬盘使用的是cgroup方式,OpenStack支持单个vm的IO限速,可以在云主机规格里增加限制条件,但还不支持集群级别的限速
2015年04月14日 - aspirer - Aspirers blog
2015年04月14日 - aspirer - Aspirers blog

NETWORK子系统

  • 前端支持多种网卡类型包括virtio、i82551、i82557b、i82559er、ne2k_pci、ne2k_isa、pcnet、rtl8139、e1000等,可以通过镜像属性hw_vif_model选择网卡型号
  • 后端支持bridge、socket、tap、vhost-net、sriov、vhost-user等网络设备
  • 支持多队列virtio网卡
2015年04月14日 - aspirer - Aspirers blog

OTHERS

  • 显卡设备:支持cirrus、std vga、vmware、qxl等显卡,也可以设置为none不配置显卡设备,OpenStack默认使用std vga显卡,也通过镜像属性设置其他设备:hw_video_model=qxl,还可以设置显存容量:hw_video_ram
  • 串口设备:qemu-guest-agent(镜像属性里可以控制是否启用:hw_qemu_guest_agent=yes/no)、pty、文件
  • 图形终端:VNC、spice
  • 输入输出设备:usb、ps2

OpenStack应用实例分析

OpenStack用到的KVM管理操作功能

主要有启动、关机、暂停、休眠、恢复、唤醒、磁盘冷热插拔、网卡冷热插拔、快照、VNC、在线迁移等

创建云主机

2015年04月14日 - aspirer - Aspirers blog

挂载云硬盘

2015年04月14日 - aspirer - Aspirers blog

修改云主机规格

2015年04月14日 - aspirer - Aspirers blog

在线迁移云主机

2015年04月14日 - aspirer - Aspirers blog

参考资料:

[1] X86虚拟化: http://zh.wikipedia.org/wiki/X86虚拟化 [2] AMD NPT/Intel EPT简介: http://blog.pchome.net/article/458429.html [3] Extending KVM with new Intel ? Virtualization technology: http://www.linux-kvm.org/wiki/images/c/c7/KvmForum2008$kdf2008_11.pdf [4] http://zh.wikipedia.org/wiki/QEMU, http://blog.chinaunix.net/uid-25714487-id-3560065.html [5] http://linux.die.net/man/1/qemu-kvm, [6] http://www.xuebuyuan.com/930444.html,

其他资料:

《系统虚拟化——原理与实现》 《KVM虚拟化技术:实战与原理解》 《云计算与OpenStack(虚拟机Nova篇)》 http://www.linux-kvm.org/ http://wiki.qemu.org/ http://libvirt.org/ http://docs.openstack.org/

公有云IaaS服务功能对比

原文地址:http://aspirer2004.blog.163.com/blog/static/1067647201521934533215/

云主机
功能 阿里云 青云 UStack Ucloud AWS Rackspace Google
生命周期管理
(创建、删除、列表、详情、修改规格、重启、启动、停止、重命名)
y y y y y
y
系统盘快照 y y y y y
y
VNC y y y y ?
?
public key注入及数量 n? y y
y
y
支持镜像数量 很多
用户帮助文档 很详细 详细 一般 一般 很详细
很详细
用户操作tips指引 y y y y y
查看控制台输出 n n y n y
y
云主机状态检查 y n n n y
n
开放API y y y y y
y
API SDK y y n n y
y
监控报警 一般 一般 一般
一般
本地镜像启动云主机 y n n y? y
n
云硬盘启动云主机 y y y n y
y
本地实例存储盘 y n n n n?
n
配额管理 y y y y y
y
报警通知人员管理 y y y y y
y
离线迁移 n n n n n
n
资源使用量报表(使用时长、费用等) y y y y y
y
资源利用率报表(cpu、mem、disk等维度) y y y y y
y
资源及配额概览(cpu、内存等资源的使用量及配额) y y y y y
y
服务健康状态显示(AZ、Region等级别、网络状态监控、故障记录等) n y n n y
y
资源回收站 n y n n n
n
计费相关(账单报表、余额等信息) y y y y y
y
欠费资源处理 y y y y y
y
计划任务支持 n n n n y
y
工单支持 y y y y y
y
账户锁(控制台、API,锁定后无法执行操作) n y n n n?
n
操作日志 y y y y y
y
子账户(子账户共享主账户配额、余额等资源,受控于主账户) n y y n n
y
镜像重置(镜像替换修复) y y n y n
n
镜像弃用或替换(排序、过滤等,API级别支持) y y y y y
y
镜像共享(跨租户) n n n n n
n
多语言用户界面支持 n y y n 部分页面
y
云主机分组管理功能(instance group) n n n n y
y
创建时启动脚本支持(startup scripts) n y n n y
y
云主机故障自动重启 n n n n n
y
节点维护时自动迁移云主机
y
从已有云主机复制出相同的云主机 n n n n y
y
云主机模板 n n n n y
y
云主机自动伸缩 y n n n y
y
高级特性(内存复用、QoS、HA、在线迁移、内核热升级。。。)
QoS、
内核热升级
QoS
QoS
QoS、
在线迁移、
内核热升级
QoS
云网络
功能 阿里 青云 UStack Ucloud AWS Rackspace Google
私有网 N Y Y Y Y
Y
私有网接入 VPN 需额外公网IP
虚拟机转发
需额外公网IP
虚拟机转发
VPN
VPN
机房内网 Y Y Y Y Y (经典网络)
N
外网 IP Y Y Y Y Y
Y
端口转发 [1] N Y Y N N
Y
DHCP N Y Y Y Y
Y
DNS N P (内网CNAME) N N Y
Y
流量监控 Y Y Y Y Y
Y
虚拟路由器 N Y Y Y P [2]
P [2]
防火墙 P [3] Y Y (安全组) Y (安全组) Y
Y
带宽限制 Y Y Y Y Y
Y
计费 Y Y Y Y Y
Y
负载均衡 (L4/L7) Y Y N Y Y
Y
API P [4] Y Y Y Y
Y
CDN Y Y N Y Y
Y

[1] 端口转发可以通过 L4 负载均衡实现
[2] AWS 和 Google 可为子网分配私有和公网网关,允许用户修改路由设置,但同一个网关不能直接设置为连通多个子网
[3] 拥有无法配置,工作机制不明的云盾
[4] 没有单独提供网络 API,主要是主机 API

云硬盘

Ucloud不支持云硬盘

功能 阿里云 青云 UStack Ucloud AWS Rackspace Google
生命周期管理(创建/删除/改名) 支持 支持 支持 / 支持
支持(普通,SSD)
挂载/卸载云硬盘 支持 支持 支持
支持
支持,
还支持挂载模式,可读写还是只读
重新初始化磁盘 支持 不支持 不支持
不支持
不支持
磁盘监控 支持 支持 支持
支持
支持
创建/删除快照 支持 支持 支持
支持
支持
利用快照会滚磁盘 支持 不支持 不支持
不支持
不支持
从快照创建云硬盘 不支持 支持 支持
支持
支持
从快照创建自定义镜像 支持 支持 不支持
支持
不支持,但支持从快照启动云主机
跨区拷贝快照 不支持 不支持 不支持
支持
不支持,但支持快照在各可用域共享
设置快照为public/private 不支持 不支持 不支持
支持
不支持
共享快照给其他用户 不支持 不支持 不支持
支持
不支持
共享卷给其他用户 不支持 不支持 不支持
不支持
不支持
多区域 支持 支持 支持
支持
不支持
多可用域 支持 不支持 不支持
支持
支持
API,SDK,用户手册 支持 支持 支持
支持
支持
云硬盘扩容 不支持 支持 支持
不支持
不支持,通过快照间接实现
云硬盘QoS 创建云硬盘时设置默认qos,
不提供修改qos api
支持,创建时指定大小,不提供api
支持,设置默认大小
DNS

注:Aliyun、Ustack、Ucloud不提供DNS相关服务。

功能 青云 AWS Google
内网域名自动分配 Y [1] Y N
公网域名自动分配 N Y N
外部域名托管 N Y Y
API N Y Y
资源别名 [2] N Y [3] N
别名状态监控 N Y N

1 分配后可自由修改。
2 添加域名纪录时,可将其作为别名指定给现有的资源,如云主机、RDS等。
3 仅支持 ELB、CloudFront、S3 website endpoint、现有DNS记录 四种类型。

qemu guest agent常见问题

原文地址:http://aspirer2004.blog.163.com/blog/static/1067647201502715020494/

请教kvm-monitor问题
8 封邮件

njupt_student <njupt_student#njupt.edu.cn> 2015年1月23日 下午10:33
收件人:aspirer2004 <aspirer2004#gmail.com>
您好!
       我是一名在校学生,看到您在Github上写的kvm-monitor代码,感觉非常好,很精妙,但是由于我刚刚接触Qemu Guest Agent ,对Qemu Guest Agent不是太懂,想请教您几个问题,非常感谢您在百忙之中,能够回答我的问题:
      1、在utils.py 文件中,有这样几行代码
util_opts = [
cfg.StrOpt(‘instances_path’,
default=’/var/lib/nova/instances/’,
help=’Where instances are stored on disk’),
cfg.StrOpt(‘config_path’,
default=’/etc/nvs_monitor/’,
help=’Where the conf files of nvs monitor are stored on disk’),
cfg.StrOpt(‘monitor_setting_file_name’,
default=’monitor-metrics.xml’,
help=’The file name of monitor metrics setting’),
cfg.StrOpt(‘info_file_name’,
default=’info’,
help=’The file name of instance info’),
]
           我想问一些 info_file_name 是什么文件,我在/var/lib/nova/instances/ 目录下实例的文件是
qemu guest agent blacklist - aspirer - Aspirers blog
           不知道您说的是哪个文件?这几个文件我都试过了,都出错了。
       2、在data_stat.py文件中,def load_temp(self),def save_temp(self)两个函数的作用是什么,我不是很清楚。如果我只想监控磁盘的利用率,还需要使用这两个函数吗?
祝您身体健康,工作顺利!
  
                        谢谢!


ME <aspirer2004#gmail.com> 2015年1月26日 上午9:33
收件人:njupt_student <njupt_student#njupt.edu.cn>
多谢关注,首先说明下,这个项目是供参考用的,里面很多内容都是我们自己的私有云才需要的,比如你提到的info_file_name这个文件,就是我们自己增加的,并非nova里面就有的,作用是为了和监控数据存储分析服务器交互,让服务器知道推过来的数据是有哪些属性,便于后续展示。

其次磁盘的利用率是空间还是IO利用率?如果是空间应该不用,只要把当前的使用空间与总空间比较一下就知道空间利用率了,如果是IO利用率,可能需要用到temp文件。
temp文件的作用是保存上一个监控数据获取时间点的数据,用来和下一个时间点获取的监控数据比较,从而计算出一个推送间隔周期内,虚拟机的某些监控维度的统计信息,简言之,只有需要累积后处理的才需要用到temp,如果是获取某个时间点某个监控维度的实时数据则不需要。
在 2015年1月23日 下午10:33,njupt_student <njupt_student#njupt.edu.cn>写道:

[引用文字已隐藏]

njupt_student <njupt_student#njupt.edu.cn> 2015年1月26日 上午10:56
收件人:aspirer2004 <aspirer2004#gmail.com>
非常感谢您能在百忙之中回复我的邮件,我只是想监控某个时刻磁盘空间的利用率,看来是不需要temp文件的。
我现在还有个问题想请教您一下:
 qemu guest agent blacklist - aspirer - Aspirers blog
我在测试物理机和虚拟机通信的时候,发现有一些服务不能使用,我不知道为什么会这样,您以前遇到这种情况没有?是因为libvirt的版本太低了吗?
我的物理机上的libvirt版本为:
 qemu guest agent blacklist - aspirer - Aspirers blog
我查看了libvirt的日志文件:
qemu guest agent blacklist - aspirer - Aspirers blog
我的虚拟机中的qemu-ga已经开启了。
请您帮我分析一下错误的原因,非常感谢!
祝您身体健康,工作顺利!

发件人: ME
发送时间: 2015-01-26 09:33
收件人: njupt_student
主题: Re: 请教kvm-monitor问题
[引用文字已隐藏]

ME <aspirer2004#gmail.com> 2015年1月26日 下午1:11
收件人:njupt_student <njupt_student#njupt.edu.cn>
你也在guest-info结果里面看到了,这些命令都被disable了(enabled:false),应该是qemu-ga这个程序给disable了,

root#host-16:/var/log# qemu-ga –help
Usage: qemu-ga [-m <method> -p <path>] [<options>]
QEMU Guest Agent 1.6.1
  -m, –method      transport method: one of unix-listen, virtio-serial, or
                    isa-serial (virtio-serial is the default)
  ……
  -d, –daemonize   become a daemon
  -b, –blacklist   comma-separated list of RPCs to disable (no spaces, “?”
                    to list available RPCs)
  -h, –help        display this help and exit
你可以ps看下qemu-ga程序跑起来的参数是不是有-b,我这边没有,所以都是enabled:

root#host-16:/var/log# ps -ef |grep qemu-ga
root      2284     1  0 Jan13 ?        00:02:56 /usr/sbin/qemu-ga –daemonize -m virtio-serial -p /dev/virtio-ports/org.qemu.guest_agent.0
在 2015年1月26日 上午10:56,njupt_student <njupt_student#njupt.edu.cn>写道:

[引用文字已隐藏]

njupt_student <njupt_student#njupt.edu.cn> 2015年1月26日 下午8:03
收件人:aspirer2004 <aspirer2004#gmail.com>
非常感谢,我按照您的方法,确实发现了问题,就是虚拟机中有-b参数,这6个命令确实被关闭了。
我试了好多办法都不能开启这几个命令,请问您知道怎么开启这几个命令吗?谢谢啦!
祝您身体健康,工作顺利!

发件人: ME
发送时间: 2015-01-26 13:11
收件人: njupt_student
主题: Re: Re: 请教kvm-monitor问题
[引用文字已隐藏]

ME <aspirer2004#gmail.com> 2015年1月27日 上午10:42
收件人:njupt_student <njupt_student#njupt.edu.cn>
把–blacklist 这个参数包括后面的具体命令去掉就好了,这样手工启动试下:

$ /usr/sbin/qemu-ga –daemonize -m virtio-serial -p /dev/virtio-ports/org.qemu.guest_agent.0
如果可以使用了,修改一下initd启动脚本就好了,应该是在/etc/init.d/qemu-guest-agent这个脚本里面有–blacklist这些参数,删掉就好了,或者其他地方有配置,应该也可以从这个脚本里面看出端倪(比如配置文件的路径等),找到地方删掉就好了,一般都是在/etc的子目录下,想省事可以:
$ grep -r blacklist /etc/
如果结果比较多,可以再加一个grep命令,如:
$ grep -r blacklist /etc/ | grep guest
在 2015年1月26日 下午8:03,njupt_student <njupt_student#njupt.edu.cn>写道:

[引用文字已隐藏]

njupt_student <njupt_student#njupt.edu.cn> 2015年1月27日 上午11:43
收件人:aspirer2004 <aspirer2004#gmail.com>
真的非常感谢您,我已经解决了,正如你所说的那样,在/etc/sysconfig/qemu-ga文件里确实有–blocklist参数,把那几个命令禁止掉了。
我把它删除了,就好了,太感谢您了,您真的太牛了。
以后如果有机会去杭州工作,一定请您吃饭,感谢您这几天对我的帮助。
祝您身体健康,工作顺利!
小弟 njupt_student

发件人: ME
发送时间: 2015-01-27 10:42
[引用文字已隐藏]
[引用文字已隐藏]

ME <aspirer2004#gmail.com> 2015年1月27日 下午1:41
收件人:njupt_student <njupt_student#njupt.edu.cn>
不用客气

nova并发问题定位思路

原文地址:http://aspirer2004.blog.163.com/blog/static/1067647201411119615820/

1. 问题症状

    QA测试重复挂卸载网卡场景过程中,多次挂卸载后,发现网卡挂载成功,nova-compute日志无异常,但却无法卸载,nova-compute日志中有异常输出:

并且nova list看不到挂载的网卡,但是nova interface-list $UUID可以看到挂载的网卡:
nova并发问题定位思路 - aspirer - Aspirers blog
nova并发问题定位思路 - aspirer - Aspirers blog
    初步判断问题不是必现的,因为挂载网卡属于常规操作,经常用到,如果是必现问题,应该很容易被发现。
2. 问题难点
    经过简单的定位之后,发现要分析问题的原因,有以下几点困难:
  1. 代码不熟悉,之前没看过这部分代码,这也是使用开源软件最常遇到的困难
  2. 问题比较难重现出来,如果找不到重现场景,就很难分析出具体原因,更不要说解决问题了,即使搞出来一个解决方法,也没办法验证是否真正解决了问题
  3. 网卡挂卸载属于与neutron组件交互的功能,对neutron组件实现细节不熟悉,不清楚是否属于neutron本身的问题还是属于nova的问题
3. 分析问题
    虽说分析起来有一些困难,但是问题总归还是要解决掉,否则一旦用户使用过程中发现这个问题,短时间内面临时间压力的情况下,会更难静下心来找到问题原因并解决掉。
针对上述几个困难,简单的在稿纸上罗列了对应的解决方法:
  1. 阅读代码分析代码流程,先把代码吃透,分析出的代码流程可以根据日志中的内容来进行正确性验证
  2. 在阅读代码的基础上,思考问题可能出现的场景,整理出所有可能的场景,记录下来,以便进行问题重现
  3. 先把nova部分代码搞清楚,确认是不是nova这边的问题,如果确认不是,再分析neutron组件
3.1 阅读代码
    代码没看过不是问题,一个几十上百万行代码的开源软件,一般都不太可能把所有代码都分析一遍,最多也就是把关键流程搞清楚,后续遇到具体问题再具体分析(当然也不排除有些牛人+闲人,一天到晚的没事做在分析代码流程),这样既能快速了解代码的大致框架,也节省出来时间去做二次开发。
    既然要分析代码,总要先找到入口,确定从哪里下手,这最终还是得根据问题症状来确定,症状有两点,一是挂载网卡后nova list看不到,nova interface-list可以看到,二是卸载的时候报错,port未挂载。
    首先分析第一个症状的代码流程,发现nova list看到的网卡信息是调用的nova api,从nova数据库中取到的,具体是在instance_info_cache表中,而nova interface-list则是直接调用的neutron api,从neutron数据库中获取的。分析到这里得出两种可能,一是nova这边挂载网卡失败,没有把网卡信息保存到数据库中,但是没有通知neutron清理残留现场(或者通知了neutron但是清理失败了),二是挂载成功了,nova没有把网卡信息写入数据库(可能是没写,也可能是数据库、网络等抽风导致写入失败),不管怎样,还有第二个症状没有分析,先把这两种场景记录下来再说。
    继续分析第二个症状的代码流程,卸载网卡失败,查看错误TRACE日志发现是因为nova数据库中instance_info_cache表中没有这个网卡信息导致的,分析到这里,发现和症状1应该是同样的原因,所以可以暂时不考虑症状2,全力分析症状1的出现场景和原因。
3.2 分析场景
    既然决定分析症状1,那就把刚刚整理的可能的场景拿出来认真想一想。
    第一种场景是nova挂载失败,如果真的是这种情况,那么日志里面一般都会有错误信息输出,因为一般人写代码通常都会把一些错误、警告等信息打印到日志里面,当然也不排除有些人不喜欢打日志,不过nova是python语言开发的,即使你不打印日志,如果遇到没有捕获的异常,也会有错误TRACE输出的,除非遇到变态码农,把所有的异常都捕获掉并且不打印任何日志,我相信OpenStack这么大的社区,这么多的大牛,是不能忍受这样的码农和代码存在的,所以去搜索日志中的ERROR、WARN、TRACE,发现除了卸载时的错误,还有一些其他告警之外,没有任何异常日志输出,当然这并不能说nova挂载网卡一定是成功的,还需要继续跟进日志,一步一步的跟着代码和日志进行逐行日志分析,确认是否有代码中已经处理但是又没有特殊级别日志输出的异常逻辑流程,经过分析,发现挂载过程没有异常,也没有走到异常流程,这里还做了一件事,就是把本次挂载流程的所有日志挑选出来,和某次确认是正常挂载的挑选出来的日志进行对比(注意挑选方式要保持一致,比如grep request id,port-id等),对比工具有很多,notepad++、beyondcompare、vimdiff等文本对比工具都可以,主要是为了对比是否有多余或者缺少的日志输出,多余和缺少的部分很有可能就是走到了异常逻辑流程。总之,挂载流程基本确认是正常的,这个结论也符合偶现问题这个前提,否则就极有可能是必现问题了。
    接着考虑第二种场景,挂载成功了,但是nova没有把网卡信息写入数据库,要确认是否是这个场景,通过分析代码,看到更新数据库之前会打印日志,把更新的网卡信息打印到日志里面,既然有日志就好办多了,首先就是搜索日志中对应记录:

搜索到日志,并且是在挂载流程过程中打印的,说明挂载过程是正常尝试更新了数据库的(至于是不是后面的更新数据库操作失败了,暂时不清楚,不过没有看到错误日志,基本可以断定是成功的)。
    既然有更新进去,那就看下数据库里面有没有,经过检查,发现数据库里面确实没有新挂载的网卡,那就有两种可能,一是没更新成功,这个可能性很小,二是更新成功了,但是后来被其他操作清理掉了。
    重点看下第二个可能性概率比较高的问题,既然每次更新都有日志,那肯定还是搜索日志,搜索发现:

有很多很多的这个日志,并且时间间隔都很规律,1分钟左右,再检查update_instance_cache_with_nw_info的代码流程,发现nova-compute有个定时任务在刷新info_cache:

继续搜索日志,看下什么时候把挂载的网卡清理掉的(根据QA提供截图中的两个网卡id来过滤):

发现日志太多太多了,定时任务每分钟都会更新这个info cache,需要再考虑另外的方法来过滤。既然上面已经在日志中找到了挂载过程中的更新记录,那么要把信息更新回去,必然在这个时间点之后做更新操作才行,并且剩下的网卡应该是现在可以看到的那个,于是在日志里面根据网卡id从上面那个更新成功时间点2014-12-04 14:17:07.359向后排查,发现短时间内并未找到更新信息。
    仔细查看了上面更新成功的日志和QA截图后,发现QA其实还挂卸载过另外一张网卡,导致两张网卡的ip和id都不一样,截图是老的,目前是新的(ip最后2位分别是12、11),既然知道了问题所在,那就更换网卡id继续搜索,果然就在后面没几行,就看到了一条日志:

注意看两条日志的时间点:2014-12-04 14:17:07.359(挂载网卡操作),2014-12-04 14:17:07.612(定时任务操作),相隔不到300ms,既然如此相近,那么就极有可能是并发问题,联系到问题不是必现,而且是两个不同操作在分别执行,并发问题的可能性就更大了。
3.3 确定场景
    怀疑是并发问题的话,就需要找到并发点,从哪里下手呢?当然是以更新到数据库中info cache信息的数据来源为切入点,因为是定时任务更新在后,并且是定时任务把数据库中信息更新丢了一部分,那么就以定时任务的数据来源为主要分析点,肯定是数据来源有问题,才导致更新后丢失了部分网卡信息。
    分析代码发现,定时任务会先从数据库查询出来当前的info cache信息,并且一步一步的传到最终的更新数据库操作方法里面,这个过程如此漫长肯定不是原子的,那么就必须要加锁才能解决并发问题,经过仔细寻找确认,整个流程都没有加锁,再回头分析一下挂载网卡流程,发现整个流程也没有加锁,这就更进一步说明了并发问题的可能性。
    并发问题的场景一般都是多个操作穿插交互执行,本来应该是串行执行的操作被打乱之后就会导致各种意想不到的问题,那么就模拟思考当时的场景,还是以定时任务的数据来源为切入点,来源有三种情况,一是在挂载操作之前从nova数据库中查询到info cache信息,二是在挂载操作过程中,三是在挂载完成之后,经过分析挂载流程代码,发现info cache是在挂载完成的最后一步才更新到数据库的,那么前两种情况其实就属于同一种情况了,都是在数据库中的info cache没有更新之前,就被定时任务拿到了,这个可能性很大,因为挂载流程比较漫长,很有可能被每分钟就执行一次的定时任务给乱入掉,如果定时任务拿到的是旧的info cache数据(也即脏数据),并且恰好在挂载操作执行成功之后紧接着就再次刷新数据库中的info cache,那么就会出现QA所说的症状。
    画个流程示意图来确定一下二者的流程是否有重复,并且确认下有哪些时间点可以被乱入:
nova并发问题定位思路 - aspirer - Aspirers blog
    发现有很长一段操作都可能被乱入…
4. 重现问题
    既然分析出了可能性很高的场景,就得去动手验证是否真的是这样的原因。如果一个问题不能被重现,那么你就不能断定你的分析过程是否正确,也就没办法确定解决方法是否正确,一切也都停留在假设上面,所以说重现问题比解决问题重要,能大概率重现的问题都是能被解决掉的,怕的就是无规律低概率重现的问题。
    重现并发问题,一个基本的原则就是加延时,在两个操作的任意代码位置增加sleep代码,并且是任意时间长度,如果可以导致乱序执行,那就说明代码存在并发可能性。既然是定时任务冲掉了挂载网卡后的info cache信息,那么就在定时任务里面增加延时,让他先到后执行(强制他被挂载操作乱入掉),这样应该就能出现后续的刷掉正确info cache的问题。
    直接改代码加延时:

上面的判断里面的uuid,是之后会被执行挂载网卡操作的虚拟机的uuid。重启nova-compute服务之后,等待定时任务执行到虚拟机61c1159c-3999-4bd5-9029-1757a55bce3d,日志会打印出”xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx————————-xxxxxxxxxxxxx”,看到之后这条日志后,执行挂载网卡操作,挂载成功后,执行nova list和nova interface-list,可以看到一切正常,再等半分钟左右,看到日志里面打印出”yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy————————-xxxxxxxxxxxxx”,再次执行nova list和nova interface-list,发现与QA同样的症状,执行卸载网卡操作,报同样的port未挂载错误,查看nova数据库instance_info_cache表,网卡少了一块,问题重现!
5. 解决问题
   找到问题原因并重现确认后,就可以考虑解决问题的方法了,既然是用的开源软件,那么就可以考虑社区上游代码中是否已经修复了这个bug,搜索bug记录中info cache关键字(注意要选择所有状态的bug,包括已修复的,否则已修复的bug会搜索不到),果然找到了一个同样的标记为已修复的问题:https://bugs.launchpad.net/nova/+bug/1326183,看了问题出现场景和TRACE log,确认是相同的问题,然后再看提交的patch:https://review.openstack.org/#/c/97662,nova/network/neutronv2/api.py文件中发现确实有对这部分代码加锁了,貌似是修复了这个问题,你以为到此就结束了吗?
    NO!还没有,为啥呢?因为仔细分析过这个修复patch,发现他们还是没有解决定时任务数据源不准确问题,也即没有对数据来源加锁,更新info cache所用的数据仍然可能是脏数据,要确认是否修复正确,只需要把重现代码加入到上游代码里面进行测试验证就行了(这里也可以看出,找出问题的必现场景是多么重要),试过之后发现,问题依然存在,社区修复方法有问题。
    既然知道他们的修复方法有问题,并且知道问题出在哪里,那就自己动手修复吧。加锁之后再重新获取一次数据库中的最新的info cache信息,然后再依据这个信息从neutron同步最新数据到nova数据库中即可解决这个并发问题,也就是保证拿到的数据都是最新的就好了。提交给社区:https://review.openstack.org/#/c/139900
    我们自己的代码比较老了,但只要稍作改动就可以实现类似的锁和网卡info cache信息获取的原子性,这里不再列出具体改动。
6. 思路总结
    总结一下思路:
  1. 确认问题症状
  2. 分析代码流程
  3. 根据日志输出检查分析过程的正确性
  4. 思考问题出现场景,并根据日志进行验证
  5. 再次回到代码,模拟代码执行过程,验证问题场景
  6. 整理可能的场景(可以使用画图、草稿纸上列出等方式),根据场景可能性的高低进行顺序,先尝试重现高概率的场景
  7. 根据代码流程和要重现的场景,思考重现辅助代码,对于并发问题来说,加延时是最简单有效的手段
  8. 重现出来之后,去社区搜索是否已经有类似bug,是否已经解决
  9. 如果已经解决,还需要分析并验证社区方法是否真正的修复了问题,毕竟社区虽然有很多牛人,也不一定会每个bug都找到重现方法,并一一验证patch正确性
  10. 如果验证ok,那问题解决,万事大吉
  11. 如果验证问题依旧存在,那就得想办法自己动手解决了
  12. 既然找到了问题的根因,那解决方法就有很多种,即便你不知道如何解决,也可以把必现条件反馈给社区,请社区牛人帮忙进行解决
    之前也处理过nova中另外一个并发问题,处理流程也是十分类似的,所以觉得这个流程是比较通用的,整理出来分享给大家,希望能对大家解决bug有所帮助。

docker in lxc试验

docker in kvm

首先尝试在debian7 wheezy kvm虚拟机中安装运行docker,试验可以成功,步骤如下:

  1. 添加wheezy-backports源,升级内核到3.14以上的bpo版本(为了支持aufs文件系统),源里有2个版本,选择linux-image-3.16-0.bpo.3-amd64
  2. 之后执行curl -sSL https://get.docker.com/ | sh,即可自动安装部署好docker服务
执行完毕会输出hello-world镜像的运行结果:
docker in lxc in kvm
继续在之前的基础上试验在kvm中安装libvirt-lxc,之后再在lxc中安装docker,试验失败,步骤如下:
  1. 安装libvirt,apt-get install libvirt0 libvirt-bin python-libvirt,注意使用wheezy-backports源中的版本,目前的版本是:
  2. 拷贝一个lxc镜像到kvm虚拟机中(云网络联调环境有一个debian7-amd64的lxc镜像)
  3. mount镜像到/mnt目录(modprobe nbd;qemu-nbd -c /dev/nbd0;mount /dev/nbd0 /mnt)
  4. 增加bridge设备,brctl addbr br0,然后修改/etc/network/interfaces文件:
  5. 重启kvm虚拟机(注意:请先为kvm虚拟机提前设置密码,防止网桥配置错误导致无法ssh登录kvm虚拟机,有密码可以通过vnc登录)
  6. 编写lxc虚拟机的xml文件,示例如下:
  7. 在kvm虚拟机中启动lxc虚拟机,virsh命令如下:
  8. lxc虚拟机启动,由于没有给lxc虚拟机配置ip和dhcp服务,lxc虚拟机会自动把kvm虚拟机的bridge的ip拿到,此时你用ssh登录kvm虚拟机的私有网ip,会直接登录到lxc内部,这一点不影响我们的测试
  9. 登录到lxc内部,执行curl -sSL https://get.docker.com/ | sh,会发现docker守护进程由于没有网桥设备无法正常运行,改成无网络模式docker -d -b none运行后正常
  10. 执行docker run –rm hello-world进行测试,报错:
  11. 增加–privileged参数,报另外的错误:

docker in lxc on host

改为在lxc虚拟机里面安装docker进行实验,也即lxc直接运行在物理宿主机上,而不是kvm中,宿主机内核版本是3.10.45。
步骤为:
  1. 在nova中使用debian7-amd64-lxc镜像创建lxc虚拟机
  2. lxc虚拟机中执行curl -sSL https://get.docker.com/ | sh
实验失败,错误与上面的docker in lxc in kvm一样。
问题未解决,抛砖引玉,请明白人指点迷津啊!~

nova文件注入流程分析

API支持说明

OpenStack Nova创建云主机API支持personality参数,用来把用户文件注入到新创建的云主机内部,该参数由两个部分组成,文件的目标路径和文件内容,比如用户想把

abc

efg

这个文件注入到云主机内部的 /etc/path/to/file 路径下,则参数可以设置为:

“personality”: [{“path”: “/etc/vm_monitor/info”, “contents”: “ZXhwb3J0IE9TX1VTRVJOQdJ…T05fTkFNRT1SZWdpb25Ud28K”}]

其中文件内容是需要经过base64转码的,可以支持同时注入多个不同路径的文件,在目标路径不存在的情况下会新创建整个路径和文件,在目标文件存在的情况下,会覆盖已有内容。 API说明页面

另外需要说明的是:key、密码、网络配置等文件的注入有专门的API参数支持,不虽然最终的注入逻辑是基本相同的,但是API参数却不是这个personality。

从本地镜像文件启动时文件注入功能实现介绍

nova文件注入序列图(简化版)如下:

nova文件注入流程分析 - aspirer - Aspirers blog

 

文字描述

  • 首先Nova api接受请求拿到base64编码后的文件内容,
  • 之后通过MQ转发到Nova scheduler进行计算节点的调度选择,
  • 选好节点后,把请求转发到相应计算节点,由Nova compute解码文件内容,
  • 之后根据本节点是否部署了libguestfs模块来决定文件注入的driver,
  • 如果安装了,使用libguestfs对应的guestfs driver来执行文件注入过程,
  • 否则选择localfs driver作为注入方法。

guestfs

关于guestfs介绍可以参考guestfs-python, 它是基于libguestfs开发的Python库,其最大好处就是可以不mount镜像就可以操作镜像内部文件系统里面的文件,支持read,write,writeappend,stat,mkdirp等基本文件读写操作。

libguestfs是一个C库,可以参考libguestfs,可以看出这是个功能非常强大的虚拟机镜像访问修改工具,其不足主要有两点,一是速度比较慢,二是有些系统上没有软件包,需要编译安装(redhat系列都支持,因为libguestfs是redhat主导开发的)

localfs

localfs driver则是完全依赖宿主机各种工具软件来实现的文件注入(loop或者nbd,如果是raw格式镜像使用loop设备,其它格式则使用nbd设备),这里以qcow2+nbd方式作为示例进行说明,这种情况下文件注入流程主要用到了如下几个软件:

  • nbd内核模块:用来加载nbd设备,供挂载镜像使用
  • qemu-nbd:一个qemu开源项目提供的nbd设备挂载小工具,可以把各种格式的镜像(比如qcow2等)文件挂载到nbd设备上,支持基于远程的nbd协议,可以把远程的镜像挂载到本地nbd设备上
  • kpartx:一个Linux下常用的分区工具
  • mount,mkdir,tee:这些软件不解释了

主要流程就是:

  1. 先把镜像准备好(从glance下载到计算节点,之后用qemu-img软件生成qcow2镜像及cow部分),
  2. 然后用qemu-nbd工具挂载镜像到找到的空闲nbd设备上,
  3. 之后用kpartx工具找到系统分区会把该分区映射到/dev/mapper下,名称为nbd0p1,0为刚刚挂载到的空闲nbd设备编号,
  4. 之后把/dev/mapper/nbd0p1 mount到宿主机的一个临时目录下,
  5. 最后就可以像操作本地文件一样操作虚拟机镜像里面的文件了。

需要注意的一点是,windows镜像的文件系统格式一般都是ntfs,如果要在宿主机上mount Windows分区,需要安装ntfs-3g软件,并且由于Windows vista及之后系统,都有一个保留分区,kpartx分区后,Nova默认选择注入到第一个分区,对于Windows系统镜像来说就是保留分区,而不是真正的系统分区,这一点需要注意,要么做镜像的时候,去掉保留分区,要么修改Nova代码,对Windows镜像特殊处理。

从云硬盘启动云主机时文件注入功能遇到的问题

上面的流程都是基于镜像文件已经保存到计算节点上这个前提下的,而从云硬盘启动的云主机,则没有镜像文件(是远程挂载过来的),虽说也是有一个mapper设备,但是在Nova代码流程里,挂载云硬盘是在文件注入流程之后才执行的,换句话说,注入文件的过程中,云硬盘还没有存在在计算节点上。Nova代码里也有明确说明,从云硬盘启动的云主机是不支持文件注入的,包括personality,key,password,net等。 简而言之,从云硬盘启动的云主机不支持文件注入!

解决方法

  1. 使用userdata配合cloud-init实现文件注入,用户现在是用的personality参数,需要修改为使用userdata参数, 好处:官方推荐,使用广泛,稳定可靠, 不足:需要cloud-init配合,增加一个维护项目。
  2. 使用user_data配合自研的脚本加上nas服务,实现类似cloud-init的功能, 好处:自己增加的脚本和自己开发的nas服务,可控程度高, 不足:所有功能都需要自己开发,比较耗时耗力,而且某些需求nas并不能满足,比如控制启动顺序等。
  3. 修改Nova代码,把personality在系统内部转换成user_data,之后再配合上面的两种方法来实现对用户透明的修改, 好处:对用户透明,不影响api, 不足:nova代码属于开源项目,如果有改动比较难融入上游代码,后期维护成本高。
  4. 使用qemu-guest-agent来实现文件注入,nova已经支持文件注入的api了,只不过libvirt driver没有实现具体的注入逻辑(Xen api driver支持了),如果我们通过qemu-guest-agent来完善libvirt driver的具体注入过程,是可以实现任意文件的注入的,但是一个问题是,要用户改变注入流程和接口,目前是创建云主机api参数传入,如果采用该方法,则需要云主机完全启动后,再调用nova文件注入api来实现文件注入,某些应用可能会遇到问题,比如配置文件还没有注入的时候就已经启动了,导致启动失败。

综合考虑推荐使用方法1,成熟方案且使用广泛。

需要注意的是,不论使用上面哪种方法,都不支持把已有的没有安装cloud-init或者没有打开user_data配置的云主机,转换成云硬盘系统盘,来恢复出一台支持文件注入的云主机。

扩展nova api UT编写注意事项

扩展nova api时最大困难就是UT的修改,nova api的UT比较全面,主要涉及到如下几个方面的验证:
1)api response:你的扩展后的api的返回内容,这个就是涉及到的代码改动
2)api sample:api说明文档,或者说示例,这个部分在nova/doc目录下,比如

nova/doc/api_samples/all_extensions/extensions-get-resp.json

3)api template:api模板,主要用来正则匹配上面两个方面的值是否一致,忽略掉易变内容,这部分在nova/nova/tests目录下,比如

nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl

如果你扩展了某个,那么nova的UT就会验证这个api上面三个部分的内容是否匹配,任意两个不匹配单元测试都会不通过。
验证分为两个部分,一部分是对扩展本身的验证,比如调用获取扩展api插件能不能获取到新增的这个api插件,另一部分是对新增的api插件的响应做的验证,验证新增api返回结果是否与sample和template中的匹配。
具体例子说明:
我扩展了server detail接口(GET http://IP:PORT/v2/TENANT_ID/servers/UUID),
之前返回的是:
{
“server”: {
“status”: “ACTIVE”,
“updated”: “2014-10-15T01:32:16Z”,
“hostId”: “1ca9490db6fa17273f48b94d5824a021ed07a4f94112fe80da1216cb”,
……
“accessIPv6”: “”,
“progress”: 0,
“OS-EXT-STS:power_state”: 1,
“config_drive”: “”,
}
}
扩展后
{
“server”: {
“status”: “ACTIVE”,
“updated”: “2014-10-15T01:32:16Z”,
“hostId”: “1ca9490db6fa17273f48b94d5824a021ed07a4f94112fe80da1216cb”,
……
“accessIPv6”: “”,
“progress”: 0,
“OS-EXT-STS:power_state”: 1,
“config_drive”: “”,
“vncPass”: “abc123EDF”  # 增加了这个属性,管理员可见
}
}
这个时候你就要保证api sample和api template两个部分的文档里面也有这个新增的vncPass属性,并且要保证响应和sample经过template规则后二者能匹配通过,
另外因为这个接口是管理员可见,普通用户不可见,所以某些sample和template是不用改动的,要找到哪些不需要改动的需要具体看下sample和template文件的内容,看看之前只有管理员可见的属性是否在这些文件里面,如果有,那就要增加vncPass这个,没有则不用。
具体来说要改掉的文件主要位于api_samples目录下,因为是管理员可见,所以子目录为

OS-EXT-SRV-ATTR:

api sample:
doc/api_samples/OS-EXT-SRV-ATTR/server-get-resp.json
doc/api_samples/OS-EXT-SRV-ATTR/servers-detail-resp.json
api template:
nova/tests/integrated/api_samples/OS-EXT-SRV-ATTR/server-get-resp.json.tpl
nova/tests/integrated/api_samples/OS-EXT-SRV-ATTR/servers-detail-resp.json.tpl
改动的内容也比较简单,OS-EXT-SRV-ATTR这个目录下的文件只要把vncPass属性加上就好了,比如”vncPass”: null,表示返回的是内容为空,
如果响应是易变的字符串,可以用%s来匹配。
另外我还扩展了一个server action的api(POST  ‘http://IP:PORT/v2/TENANT_ID/servers/UUID/action’ -X -d ‘{“changeVNCPassword”: {“vncPass”: “123456”, “oldPass”: “654321”}}’),
新增的文件:nova/api/openstack/compute/contrib/change_vnc_password.py,内容就不列出来了,
要改掉的文件主要位于api_samples目录下,因为是测试扩展本身的,所以位于all_extensions子目录下:
api sample:
doc/api_samples/all_extensions/extensions-get-resp.json
doc/api_samples/all_extensions/extensions-get-resp.xml
doc/api_samples/all_extensions/server-get-resp.json
doc/api_samples/all_extensions/servers-details-resp.json
api template:
nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
nova/tests/integrated/api_samples/all_extensions/server-get-resp.json.tpl
nova/tests/integrated/api_samples/all_extensions/servers-details-resp.json.tpl
extensions目录下表示是验证扩展本身的sample或者template,需要根据xml或者JSON类型来添加,比如JSON的:
{
“alias”: “change-vnc-password”,
“description”: “%(text)s”,
“links”: [],
“name”: “ChangeVncPassword”,
“namespace”: “http://docs.openstack.org/compute/ext/change-vnc-password/api/v1.1“,
“updated”: “%(timestamp)s”
}
xml的:
<extension alias=”change-vnc-password” updated=”2014-10-31T00:00:00+00:00″ namespace=”http://docs.openstack.org/compute/ext/change-vnc-password/api/v1.1” name=”ChangeVncPassword”>
 <description>Change vnc password for a given server, need hard reboot to enable.</description>
</extension>
如果还有UT错误,可以根据UT错误TRACE具体分析下,比如错误是:
Traceback (most recent call last):
  File “nova/tests/integrated/test_api_samples.py”, line 972, in test_detail
    self._verify_response(‘servers-detail-resp’, subs, response, 200)
  File “nova/tests/integrated/api_samples_test_base.py”, line 243, in _verify_response
    response_data, “Response”)
  File “nova/tests/integrated/api_samples_test_base.py”, line 137, in _compare_result
    result_str)
  File “nova/tests/integrated/api_samples_test_base.py”, line 171, in _compare_result
    raise NoMatch(‘\n’.join(error))
那么应该是servers-detail-resp.xml/json的api sample和或者api template缺少了你新增的属性,可以根据与你新增的属性同类的属性搜索一下相关目录的文件,比如你新增了一个newattr属性,与之前的oldattr属性是一个权限和api返回的,那么所有有oldattr的sample和template文件都应该有newattr。
或者你可以ipdb设置断点,用python -m testtools.run nova.tests.integrated.test_api_samples.ExtendedServerAttributesXmlTest.test_detail执行单个用例进行调试(如果执行单个用例报NoSuchOptError: no such option: consoleauth_manager,注释掉这行File “nova/tests/integrated/integrated_helpers.py”, line 89, in setUp
    self.consoleauth = self.start_service(‘consoleauth’)就可以了),就可以看到具体是哪个文件缺少了你新增的属性, File “nova/tests/integrated/api_samples_test_base.py”, line 243, in _verify_response,基本都是用这个方法来验证一致性的,里面有self._get_template(name),self._get_sample(name),这两个方法,可以手工调用这两个方法来确定具体是哪个template或者sample文件有问题。