张梁+罗宇
摘 要:本文致力于为openstack设计一个可以设定虚拟机实例定时运行功能的插件。该插件是基于openstack的horizon组件的功能拓展,用户可以像以往使用horizon的dashboard的功能一样去使用它。用户通过这个组件可以设定每一天虚拟机运行的起止时间,以及每周需要哪几天运行的周期循环时间。整个插件的设计完全遵循Django的设计原则。
关键词:openstack;虚拟机定时任务;horizon dashboard;Django
Design and implement the instance timing running based on openstack
Zhang Liang1, Luo Yu2
(1. School of Computer,Nation University of Defense Technology,Changsha 410073,China;2. School of Computer,Nation University of Defense Technology,Changsha 410073,China)
Abstract:This paper contribute to design a plugin for openstack to implement the function of setting the time of some instance's running.The plugin is designed based on horizon dashboard,the users can operate it the same as them use dashboard.User not only could set the time of start and suspend of some instance easily by it,but also choose day of the week as he want.The designing model follow the principle of Django complete.
Key words: openstack;setting instance timing running;horizon dashboard;Django
0引言
由于云计算技术所具有的资源调配灵活,节约硬件、人员、管理成本,对于计算资源的高利用率,数据可靠性高,平台管理的高度集约性等众多突出优势,如今不仅仅是提供公有云服务的大型云服务企业,还是搭建私有云供自身使用的政企科研教学单位都对其趋之如骛。
而openstack则是为企事业单位提供云平台的一个绝佳选择,这主要得益于openstack是完全开源的项目,有诸如RedHat、HP、IBM、Rackspace、Citrix、Intel、Cisco等众多科技领头企业的鼎力支持,在技术得到保障的同时又不必担心代码会被某个独家企业所垄断而陷入付费的桎梏。
openstack简介。整个openstack的架构是一个典型的分布结构。openstack主要由Nova,glance,Swift,keystone,horizon,cinder, neutron ,heat等组件构成。其中Nova负责对所建虚拟机整个生命周期的管理例如从虚拟机创建,虚拟机的调度分配,控制虚拟机的运行,快照的生成,卷的管理等,主要起到了云控制器的作用,本课题也要与Nova提供的API服务打交道。glance组件则是对于镜像存储的管理。Swift提供对象存储系统。cinder提供块存储。keystone为云主机Nova,镜像管理glance,对象存储Swift和界面horizon提供认证服务,主要工作内容包括对用户信息管理(包括用户,租户基本信息),项目project的管理。登陆认证,用户权限管理。本课题的开发内容就涉及到用户身份认证以及虚拟机认证令牌的申请获取。horizon则是则是为终端用户(云平台管理员和普通用户)提供使用云平台的界面。本课题的交互界面开发也是完全基于horizon组件的。neutron则是为虚拟机分配网络。heat则是提供对于虚拟机实例上的软件的简单的部署、配置管理功能。
普通用户对于openstack的功能使用一般都会通过horizon组件提供的dashboard(如图1)界面去获得,dashboard就充当了openstack提供给普通用户的UI。从dashboard中可以找到一些对于openstack的基本操作,如创建虚拟机,编辑虚拟机,启动、停止虚拟机,给虚拟机做快照等等,但是缺乏定时运行虚拟机的功能。在虚拟机的实际应用中,具体某个实例的运行时段是跟使用虚拟机人员的工作作息时间或者虚拟机的使用计费时段密切相关,例如说某人早上8点开始上班需要启动若干虚拟机,等到下午6点下班后对其的使用就结束了,但是第二天还得接着当天的工作继续进行——也就是说当天的工作现场还得继续保留以待第二天继续使用,事实上这里还有另外一个优点,由于虚拟机启动时间受制于本地磁盘性能(如果是远程启动更要受制于带宽限制),如果实例较大往往需要较长的等待时间,所以使用者可以提前设置虚拟机启动,使用者进入工作现场时候就直接能够使用,这样是用户体验得到明显改善。云平台下的某些租用计费方式一般是按量、按时计费——也就说是按照使用虚拟资源的多少以及占用计算存储资源时长来计费的。企业个人在某些时段可能就不需要使用虚拟机,这个时候选择将其停止,运行实例退出内存,运行现场保留到磁盘中腾出了运行资源也退出了计费状态。
图(1)
从以上列举分析的案例可以看出,为openstack设计开发虚拟机定时任务功能很有实际意义,本文就是着力详细解析决基于openstack虚拟机定时任务的完整方案。
1软件需求分析
1.1人机交互需求
openstack本身的交互方式的架构为典型的B/S架构。用户通过浏览器访问horizon组件内置的web服务器,web服务器提供的一个访问界面被称作dashboard,dashboard提供了各种对于openstack的操作,这些操作大致分类为:对于镜像的操作,对于虚拟机的操作,对于卷的操作,网络的设置,域及用户权限的设置。显然,为了交互的一致性、跟便捷性,新增的“虚拟机定时任务”功能应该放在与对虚拟机操作的按钮列表栏(如图2所示)。为了在点击设置定时任务按钮后,将会弹出一个时间设置页面(如图3所示),让用户通过点击下拉列表去设置启、停的时间。对于“星期几”运行的设置,由于星期是全排列的复选组合方式,所以设置选取“星期几”的时候则使用复选框。为了保持风格的一致性,使用的对话框、下拉列表与复选框均与dashboard使用的一致
图(2)
图(3)
1.2数据传输的需求
web前端的用户数据主要有四类:(1)用户ID信息以及所属于工程及域。(2)虚拟机实例的信息,主要包括实例ID号,空间大小,系统类型等。(3)用户输入的启动时间信息,主要包括启动以及停止实例的时(24小时制)、分,以及星期一至星期天复选项等信息。(4)确认信息的数据传输,按下确认按钮后的信息的的传输。
1.3数据存储的需求
web前端的用户数据传输到服务器后台之后,一些重要的数据如登陆用户信息、使用虚拟机实例的信息、用户定时信息、用户操作日志、组件出错信息都要被存储。
1.4业务功能需求
本组件要完成的功能主要有:(1)虚拟机运行任务的定时。(2)定时任务到点后对于启动或者停止虚拟机脚本的触发。(3)启动、停止虚拟机脚本。
2技术实现方案
从上一部分需求分析的结论我们可以将整个软件的分为“人机交互模块”跟“任务处理模块”,“人机交互模块”主要提供人机交互UI界面跟界面上数据的传递,而“任务处理模块”则是接收处理从web前端传递来的数据,完成业务逻辑。
2.1人机交互模块的技术实现
openstack是由horizon组件来提供一个命名为dashboard的基于网页交互界面。整个dashboard是在Django框架下设计开发的,很显然新增的业务功能必须在同样的框架下开发。Django本身推崇“MTC模式”,在所谓“MTC模式”中M(model)代表数据据访问部分,通过Django的数据库层处理 ;T(template)选择数据并决定怎样呈现的部分,通过视图和模板来处理 ;C(control)控制部分通过Django框架本身的URL配置和对Python方法的调用来处理 。其中“C”是Django框架本身提供的机制来处理,而Django的重点就在于模型,模板和视图。
2.1.1设置页面的按钮设计
dashboard本身就是在MTC模式下高度面向对象化设计的,且采取自顶向下的设计风格。从继承关系看分为:Dashboard → PanelGroup → Panel这样三层关系。Horizon中现有的dashboard有4个,分别是project ——普通用户登陆后看到的项目面板;admin ——管理登陆后可见,左侧的管理员面板;settings ——右上角的设置面板,里面可设置语言,时区,更改密码;router(配置文件中将profile_support打开可见),ciso nexus 1000v的管理面板。每一个dashboard都是django中的一个app,django中的app可以理解成对业务逻辑模块化的一种手段,里面可以包含自己独有的url设定,模板,和业务逻辑代码。每个dashboard下定义了一系列的PanelGroup,虚拟机管理对应到界面上就是一个PanelGroup(Manage Compute), 而这个PanelGroup里面有一系列的子panel(例如:Overview, Instances, Volumes…)。而我们要新增的虚拟机定时任务的启动按钮就是要放在这个Instances这个子panel上面。如图4所示,在instances这个panel上面就出现了诸如解除浮动IP的绑定、编辑云主机、编辑安全组、控制台、查看日志、停止云主机等选项,设置虚拟机定时任务时间按钮置于最下方。要往panel上添加按钮必须在horizon/openstack_dashboard/dashboards/project/instances目录下的tables.py文件里添加一个类,我们命名它为SetTime类,由于这个按钮是一个链接性质的,这个类必须从tables.LinkAction继承,SetTime类必须具有指代名(name),详细名(verbose_name,用于显示时候的名称),以及url(用于标示这个按钮的位置)三个必须的私有属性。对于name这个属性我们可以赋予settime(可阅读性好)。verbose_name赋予Set Instance Lanuch Time,这个名称将会显示在instance的panel上。URL则被赋予“horizon:project:instances:settime”。还有一个链接指示函数,通常命名为get_link_url(),这个函数是告诉Django去寻找并解析这个url的路径值,作用就是找到“Set Instance Lanuch Time”按钮指向的页面。还必须在同文件中一个Meta类中注册SetTime这个按钮,将其写进row_actions这个元组当中去,这样这个按钮的图标才能被显示出。
2.1.2设置对话框的设计
接着要设计出按钮触发的设计时间的对话框。对话框必须有起止的时间,星期数,确定的按钮。如图6所示。Django遵循MTC设计模式,视图的内容(被称为context)均由模板来修饰。对话框就是一个典型的视图,要设计这个视图首先必须有一个视图类(这里我们命名为:SetTimeView),这个类当中有几个必须的私有属性,一个呗命名为from_class,它必须去继承一个设计好的视图。另一个属性则是模板名字template_name,这个私有属性获得模板的路径。另外还有个被命名为success_url的属性,它的作用当你点击上文提到的“确定”按钮时候服务器就会去根据success_url的值去寻找视图。除了以上三个必须的私有属性外还必须有一个获取模板所修饰的对象——上下文——context的函数,这个函数主要作用就是获取模板修饰的上下文。
接下来就是设计下拉条(设置时间),复选框(设计星期)跟确认按钮这些UI组件。首先必须在找到horizon/openstack_dashboard/dashboards/project/instances这个文件夹,进入forms.py文件,下拉列表选用ChoiceField插件,只需在ChoiceField属性内填充一个label为欲设计的下拉列表的标题名称,以及窗口名字的设置class为‘set time即可,其他可以使用默认参数。例如设计哪个小时启动的下拉列表,LaunchHour = forms. ChoiceField(label=_("hour"),widget=fields.SelectWidget(attrs={'class'=:'set time'},data_attrs=('size','display-name'),transform=_image_choice_title))。同法设置其他时间选取下拉列表。再来设计星期几的复选框,复选框使用MultipleChoiceField插件
,在其choice参数赋予子选项所组成的元组,如choices=list_choices, list_choices = (('1', Monday),('2','Tuesday'),('3','Wednesday'),('4','Thursday'),('5','Friday'),('6','Saturday') ,('7','Sunday'))。用request.REQUEST.getlist函数去取的选中的值。最后还要设计一个HTML文件。由于horizon高度模块化的设计,视图函数与HTML文件是分离的,这样视图函数就会比较灵活能随时替换以及修改,这里需要在HTML文件设计一下任务时间弹出设置框网页的网页标题,显示方式,以及一个“确认”按钮即可。到此整个组件的网页的UI部分设计完毕。
2.2数据传输模式
在这里要处理的数据传输主要是前段的用户数据传输到后端处理。当前段用户数据设定完成后,按下“确定”按钮会触发一个post函数方法将数据打包经由HTTP协议发送至后端,后端的get方法会得到这些数据并交由相应的模块处理
2.3后台业务逻辑处理
图(4)
后台的业务流程如图4所示。用户前端网页的数据传给定时器,定时器设置自身的数据设置计时,时间到点后去触发启动/停止脚本,与此同时数据库还会将用户的数据(用户ID,每个ID下对应的实例,定时信息)以及操作的行为记录下来。
2.3.1定时器的设计说
openstack目前只能安装在Linux内核系列的系统上,在常见的Linux内核系统(如Ubuntu,RedHat,centos,federal等)一般都有一个非常实用的定时组件叫crontab。crontab可以较为方便、稳定、准确的实现定时任务执行。使用crontab分为两步:1、只需将诸如“* * * * * something.py”的文本写入一个文件,其中五个*符号顺序依次代表分钟(0-59)、小时(0-23)、日期(1-31)、月份(1-12)、星期几(0-6),最后面的something.py文件代表要去执行的命令或者程序(可以使多条命令或者程序),当然对时间的设置其实有相当大的灵活性,比如可以进行几个小时或者分钟的间隔设置,可以指定某段时间执行,本文在此就不详细叙述。2、执行crontab something.py文件定时任务即可生效。这里还有一个问题,就是这个crontab文件由谁,如何去产生,其实完全可以把这个任务交给之前的SetTimeForm类里去编码执行,这个类的作用原本是设计弹出设置时间的页面,在这个类里有个handle()函数,这个函数起到两个非常重要的作用,一是向其他文件构共享出用户设置的时间变量,起到通信作用。二是向需要生成crontab文件注入启动/停止的时间周期以及到时间点需要执行的脚本。
2.3.2启动/停止脚本
现在来现对于虚拟机实例的启动/停止(这里的停止是将其整个虚拟机运行现场保存至硬盘,在虚拟机监视器看来并没有真的停止它),要自己通过代码去控制一个虚拟机的启动/停止有两种途径,一种是通过openstack官方给出API函数接口去实现,使用的方法是:首先必须使用你的证书来认证来获取authentication token。证书包含了用户名、密码和tenant(项目)。而这个证书则可以通过curl+租户名+用户名+密码+本机ip地址去获得(具体格式参考openstack官网)。token允许你不需要再次认证就能和其他的service endpoints交互。Tokens通常只有24小时的生命期,当token过期后,你将会收到一个401(未被授权的)响应,这时候必须重新请求一个token。利用这个token就可以去使用openstack的服务,停止虚拟机的命令如下:nova suspend --flavor 2 --key_name oskey --image ea3ffba1-065e-483f-bfe2-c84184ee76be(这串字符为image的id)。第二种方法是通过novaclient提供的命令行工具去执行命令。具体做法如下:从openstack本身提供的novaclient.v1_1模块import一个client包创建并且初始化一个nt=client.Client("用户名","密码","站点IP地址"),调用nt的servers的属性方法nt.servers.suspend("虚拟机实例的ID")即可。同上理,执行这个命令暂时借用超级管理员身份。
这里要注意一个问题,对于虚拟机运行时间的设置的用户的身份一般都是普通用户,而普通用户很可能(取决于该用户所属于租户所赋予的角色权利,但是普通用户往往权限较低)是不能直接去使用某些服务,为了统一、简洁的解决这个问题,在启动/停止脚本中暂时借用admin身份去使用某些服务
3总结
本文致力于为openstack设计一个虚拟机定时任务组件,本组件基于horizon项目,完全遵循Django的设计开发模式,能轻易满足具备openstack使用经验用户的习惯。设计完毕后通过在自己实验室openstack的部署环境下试用测试,运行稳定未发现BUG。