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

时间: 2024-08-01 10:28:05

openstack 扩展开发最佳实践之计算节点高可用的相关文章

openstack 扩展开发最佳实践之云主机监控查询

前言:此功能代码不代表笔者代码正常水平...真的只是为了实现而实现,很多硬代码加不优雅的地方.就让我自己先吐槽一下吧,首先是代码每次会去拿token而不是用horizon缓存的token,没有将js,css优雅的放进horizon,以及panel的名字都没改,最后就是前端布局不好看(这个真的是当下能力之外的了). 首先说说需求,在horizon有这么一个页面,可以查看本项目的虚拟机的一些基本的性能指标,比如cpu使用率,内存使用率,磁盘io,网络io等. 怎么实现呢? 数据获取: 方案一,自己造

OpenStack企业级开发最佳实践

培训目标: OpenStack云平台技术是开源云计算技术中的主流技术,已得到大量主流商业厂商和研究机构的大力支持.在未来的几年中,OpenStack会对云计算以及IT领域产生极大的影响. 本课程从OpenStack云平台的发展历程.体系架构.关键技术.主要应用领域以及相应的发展策略.课程通过丰富的技术知识与应用案例的分享,以及对OpenStack云平台浅显易懂的讲解分析,引导学员对 OpenStack技术有一个更为清晰.准确的理解和认识. 课程对OpenStack的各个组件进行详细的讲解,让学员

[1.30] 保持的力量:接口开发最佳实践

神啊,求你赐给我平静的心,去接受我无法改变的事:赐给我勇气,去做我能改变的事:赐给我智慧,去分辨两者的不同. --平静之祷 1.30.1 论保持的力量 追到一个心仪的女生不难,难于如何保持和培养一份真挚的感情:获得一时的财富也不难,难于如何长久保持收益:创业的公司很容易博得一时媒体的关注以及某次天使的投资,但难于如何排除各种障碍.充分利用各方资源发展成中企业及至上市公司. 同样,提供一时的接口很容易,但当我们需要不断为接口提供升级,以及当我们维护提供一整套接口时,面临的困难和问题会越来越大.所以

Hadoop MapReduce开发最佳实践(上篇)

body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI",Tahoma,Helvetica,Sans-Serif,"Microsoft YaHei", Georgia,Helvetica,Arial,sans-serif,宋体, PMingLiU,serif; font-size: 10.5pt; line-height: 1.5;}

Android开发最佳实践---Futurice之见

原文链接:https://github.com/futurice/android-best-practices 本文是Futurice公司的Android开发人员总结的最佳实践,遵循这些准则可以避免重复制造轮子.如果你对iOS或者WindowsPhone开发感兴趣,那么也请看看iOS最佳实践和Windows客户端开发最佳实践. 第一版翻译自:http://blog.csdn.net/asce1885 Android开发技术日新月异, Github上也有较大更新, 故对原文有增删 CSDN的mar

[转]Android开发最佳实践

——欢迎转载,请注明出处 http://blog.csdn.net/asce1885 ,未经本人同意请勿用于商业用途,谢谢—— 原文链接:https://github.com/futurice/android-best-practices 本文是Futurice公司的Android开发人员总结的最佳实践,遵循这些准则可以避免重复制造轮子.如果你对iOS或者Windows Phone开发感兴趣,那么也请看看iOS最佳实践和Windows客户端开发最佳实践. 概要 使用Gradle和推荐的工程结构

【微信公众平台开发最佳实践】正品!包邮!半价!双12特惠,仅此一天,微信开发必备,请尽快购买!

[正品!五折!包邮!] #史上最低价,错过等明年!# 微信开发必备宝典 <微信公众平台开发最佳实践>双12盛典, 定价69,现价34.5元, 点此购买

移动端WEB前端开发最佳实践

移动端WEB前端开发最佳实践 Safari,Android Browser,Chrome都是以WebKit为核心的 移动设备和PC之间的页面现实存在差异(Safari中定义了viewport) 在移动设备和桌面端WEB前端开发中,事件绑定存在差异(移动触点) 页面控件设计存差异(点触不灵敏,虚拟键盘弹出框) 移动设备的网络带宽普遍比PC慢,移动页面要设置更简洁 PC页面兼容移动设备 使用流式布局 借助CSS Media queries(媒体查询)技术 使用合适的图片显示兼容方案 保持页面简洁,不

Android企业级应用程序开发完整训练:精通Android商业级开发最佳实践的24堂课

从企业级商业实战的角度入手,24小时内通过23个动手实战案例,循序渐进的对Android商业级别的应用程序开发要点各个击破,依托于在多年的Android(6款完整的硬件产品和超过20款应用软件)开发和企业级培训经验(超过150期的次Android的企业内训和公开课),旨在在实务的基础之上帮助你完成任何复杂程序的高质量Android应用程序开发,让Android开发跟上想象的速度.最后,通过ActivityManagerService揭秘Android应用程序一切行为背后的核心根源,让你从此开发应