openstack 扩展开发最佳实践之计算节点高可用
前言:注意是扩展开发,这个词是我杜撰的,大概意思是指基于openstack的rest api做的一些开发,用于辅助相关功能,而不是直接改动openstack内的代码,怎么修改添加openstack各个组件的代码不在此文章内容内。
首先,千万,千万,千万不要用Openstack提供的SDK,原因如下。
一,SDK的相关文档并不健全。
二,版本不够统一,即兼容的问题。
所以不要使用openstack的SDK而是自己查阅openstack的API文档,通过requests库发http请求要比SDK灵活并便捷得多的方式。但是难过的地方在于开头,这也是本章的主要内容。为了使内容更加贴近现实,我们要做的需求是Openstack计算节点的高可用,主题内容如下:
一:解决思路
二:查询相关API
三:组织代码
四:总结
(一)解决思路
其实openstack计算节点高可用的方案应该是不同的厂商有不同解决方案,这里不具体分析各个方案,二是针对笔者自己实现的一个方案的实现讲解。
一,怎样确定计算节点挂了
二,怎样将计算节点上的虚拟机迁移到现存可用的计算节点
三,迁移之后是否应该采取相关措施
笔者的对应的解决方案如下,
一:通过openstack自身机制监控,即计算节点不可用时,不会上报状态,控制节点会将该计算节点的状态state设置为down,为down的就判定该计算节点不可用。
二:通过evacuate API将不可用的计算节点上的虚拟机迁移到可用的计算节点,共享存储肯定是必须的。
三:通过将该不可用计算节点status设置为disable,以达到隔离效果,即该计算节点即使又好了,也不会将新的虚拟机调度到该计算节点,除非人为干预。
注:这里没有考虑网络环境。
(二)查询相关API
一:所有计算节点可用状态:/os-services
二:查询指定计算节点上的虚拟机:/servers/detail
三:evacuate实例:/servers/<server-id>/action
四:disable阶段节点:/os-services/disable
主要就是上面这些API了。
(三)组织代码
1.首先是认证获取token,获取各个endpoint。
2.统一封装HTTP请求过程。
3.然后为每个对应的API封装一个函数。
4.将整个需求的逻辑独立与封装的函数及类。
相对应的代码如下
1.这里新建一个baseInfo的类作为基类,用于获取token及相应的endpoint
class baseInfo(object): """init the info of all compute, and get the token for access the api""" def __init__(self): confFile = sys.argv[1] headers = {} headers["Content-Type"] = "application/json" self.cf = ConfigParser() self.cf.read(confFile) self.conf = self.getConf() self.headers = headers self.catalog, self.token = self.getToken() self.url = [url for url in self.catalog if url["name"] == "nova"] self.url = self.url[0]["endpoints"][0]["publicURL"] def getConf(self): try: conf = { "url": self.cf.get("ser","OS_AUTH_URL"), "uname" : self.cf.get("ser","OS_USERNAME"), "passwd" : self.cf.get("ser","OS_PASSWORD"), "tname" : self.cf.get("ser","OS_TENANT_NAME"), "interval" : self.cf.get("ser","INTERVAL")} except Exception as e: logging.critical("加载配置文件失败") logging.critical(e) sys.exit(1) return conf def getToken(self): headers = self.headers url = self.conf["url"] + "/tokens" data = '{"auth": {"tenantName": "%s", "passwordCredentials": {"username": "%s", "password": "%s"}}}' data = data % (self.conf["tname"], self.conf["uname"], self.conf["passwd"]) try: logging.debug("开始获取Token") ret = requests.post(url, data=data, headers=headers) logging.debug("request url:%s" % ret.url) ret = ret.json() except Exception as e: msg = "获取Token失败 data:%s headers:%s" % (data, headers) logging.critical(msg) logging.critical(e) catalog = ret["access"]["serviceCatalog"] token = ret["access"]["token"]["id"] return catalog, token
2.将每个交互API的HTTP请求独立出来,所谓DRY吧,不要重复你自己,这样的好处自然是不用重复写代码,再者就是在一个统一的地方对所有调用了的,统一包装或修改。
def getResp(self, suffix, method, data=None, headers=None, params=None, isjson=True): """return the result of requests""" url = self.url + suffix if headers == None: headers = self.headers.copy() headers["X-Auth-Token"] = self.token req = getattr(requests, method) try: ret = req(url, data=data, headers=headers, params=params, verify=False) logging.debug("request url:%s" % ret.url) except Exception as e: msg = "%s访问%s失败 data:%s headers:%s" % (method, suffix, data, headers) logging.critical(msg) logging.critical(e) sys.exit(1) if ret.status_code == 401: logging.warning("Token 过期,重新获取Token") self.catalog, self.token = self.getToken() headers["X-Auth-Token"] = self.token logging.debug("request headers:%s" % ret.request.headers) ret = req(url, data=data, headers=headers) if isjson: ret = ret.json() return ret
3.封装每个API作为函数,函数是第一公民嘛。
... def chkNode(self): """get the compute list service down""" suffix = "/os-services" ret = self.getResp(suffix, "get") ret = ret["services"] cmpAll = [host["host"] for host in ret if host["binary"] == "nova-compute"] cmpDown = [host["host"] for host in ret if host["state"] != "up" and host["binary"] == "nova-compute"] return cmpDown, cmpAll def chkSerFromNode(self): """get the server list from failed node""" suffix = "/servers/detail" params = {"all_tenants":1} ret = self.getResp(suffix, "get", params=params) ret = ret["servers"] serDown = [ser["id"] for ser in ret if ser["OS-EXT-SRV-ATTR:host"] in self.cmpDown] self.serDown.extend(serDown) def evacuate(self, serID): """evacuate the server""" suffix = "/servers/%s/action" % serID data = '{"evacuate": {"onSharedStorage": "True"}}' ret = self.getResp(suffix, "post", data=data, isjson=False) return ret.ok ...
4.逻辑独立出来,不要做太多事情。
def main(): if len(sys.argv) > 1 and os.path.isfile(sys.argv[1]): ch = check() fen = fence() recov = recover() while True: interval = ch.conf["interval"] try: interval = int(interval) except Exception as e: msg = "时间间隔设置有误 interval:%s" % interval logging.critical(msg) logging.critical(e) sys.exit(1) cmd = "pcs status|grep 'Current DC'|grep `hostname`" p = sp.Popen(cmd, shell=True, stdout=DEVNULL, stderr=sp.STDOUT) vip = p.wait() if not vip: ch.check() logging.info("失败的计算节点%s" %ch.cmpDown) fen.fence(ch.cmpDown) logging.info("失败的计算节点下面的server %s" %ch.serDown) recov.recover(ch.serDown) time.sleep(interval) else: print "配置文件不存在"
(四)总结
不要用SDK,rest API的文档足够健全。
至于完整项目可参考我的Github。
https://github.com/youerning/UserPyScript
相关链接:
Openstack API:https://developer.openstack.org/api-guide/quick-start/index.html
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
SQL Server 数据恢复到指点时间点(完整恢复)
SQL Server 数据恢复到指点时间点(完整恢复) 说到数据库恢复,其实我们一般最常见的有两种,一种就是简单恢复,通过备份的bak文件直接恢复数据库,缺点就是有可能数据丢失。另外一种就是通过备份的数据+事务日志还原数据。但是后者还原的话我们需要保证事务日志的完整性。我们今天就主要介绍的是第二种,所有的操作过程我们使用的是SSMS进行操作的。 注:使用第二种方法还原数据的时候需要注意的问题:1、要准备好之前的完整备份的数据,2、备份全新的事务日志。3、通过完整备份的数据进行完整还原。4、通过备份的全新的事务日志进行指定时间点的数据还原。 我们首先创建一个测试数据库---DB2,然后创建一个表info 定义字段信息 我们插入数据 select*frominfo insertintoinfo(idcode,age)values('zs',18) insertintoinfo(idcode,age)values('ls',20) insertintoinfo(idcode,age)values('gwl',27) 接下来我们备份数据,备份路劲D:\DB_BACKUP 右击数据库---任务-...
- 下一篇
CentOS7下利用cobbler部署CentOS
1)安装epel源和cobbler [root@cobbler~]#yum-yinstallhttp://mirrors.163.com/centos/7/extras/x86_64/Packages/epel-release-7-9.noarch.rpm [root@cobbler~]#yuminstallcobblercobbler-webdhcptftp-serverpykickstarthttpdxinetd-y [root@cobbler~]#systemctlstartxinetd.service [root@cobbler~]#systemctlenablexinetd.service [root@cobbler~]#systemctlstarthttpd [root@cobbler~]#systemctlenablehttpd Createdsymlinkfrom/etc/systemd/system/multi-user.target.wants/httpd.serviceto/usr/lib/systemd/system/httpd.service. [root@c...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Mario游戏-低调大师作品
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- 2048小游戏-低调大师作品
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker使用Oracle官方镜像安装(12C,18C,19C)