第一次任务完成经历的总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/albertjone/article/details/83713389

第一次任务完成经历的总结:

任务简介:

为Openstack的组件cloudkitty添加一个计费通知feature的子功能,通知发送功能。具体的要求是,提供4个邮件接口和一个短信接口给上游调用,并将上游传入的data分为四类渲染成指定的html并通过邮件发送api发送给客户,同时把一类data通过短信api发送给客户。
虽然这只是一个小小的功能但是花了1个礼拜(5个工作日完成了这个活)。

阅读准备:

首先先介绍下cloudkitty,cloudkitty是openstack项目的一个计费作为服务(Rating as a service)的项目。cloudkitty在以下四个层面高度组件话:

  • input data sources (collectors)
  • rating policies (rating pipeline)
  • output storage (storage)
  • output file format (writers, used to generate reports)

这次任务做的便是第三四层级的活。

任务抽象

简单任务抽象的缘由:

之前自己有写过一些程序,面向对象的编程思想也了解,但是从来都没有仔细的去思考过在实际的编码过程中更好地使用面向对象的思维方式来解决问题。在这次任务的一开始,我都没有考虑过用面向对象的方法去解决这个问题,但是项目使用的是stevedore来动态加载服务的,为了使整体更加的协调,同时为了与调度服务解耦,所以通知发送服务所以必须用类来封装方法。

抽象对我造成的挑战:

由于从通知方式出发去抽象的话,两种方式需要的接口数不一样,所以父类写接口不合适,所以我就想从发送的邮件内容来设置父类盒子类,父类实现发送邮件和短信的方法,子类直接调用就行。虽然这样实现了复用,但是调度程者得去初始化很多子类的实例,并要知道对应的子类是否需要发送短信。后来找了超哥聊了下,发现从方式的角度去抽象才是最好的。对于不需要使用的内容短信发送可以进行空实现,在父类中定义接口,调用者以下便可以看明白。
第一次使用python中的接口实现方式,这里记录下:

@six.add_metaclass(abc.ABCMeta)
class NotifierService(object):
    def __init__(self):
        pass
        @abc.abstractmethod
    def notify_user_arrearing_lightly(self):
        """send normal user arrearing notification in less than pridict_day

        days.
        """

    @abc.abstractmethod
    def notify_admin_arrearing_lightly(self):
        """send admin all arrearing users in less than pridict_day days with

        email.
        """

    @abc.abstractmethod
    def notify_admin_arrearing_strongly(self):
        """send admin all arrearing users in less than 30days with email."""

    @abc.abstractmethod
    def notify_admin_releasing_strongly(self):
        """send admin all resource releasing users in less than

        ( max_day - float_variable ) days.
    

其他的就不写了。

stevedore之坑:

这个对象自动加载的包,会把对象初始化的报错信息给吃掉并且不会向外部调用抛异常,并把这个异常写入到日志中。这个即便是单步调试也无法定位问题。直到在超哥的帮助下逐个排除问题后,最后翻查日志的时候发现问题的。开发陌生项目的时候,有日志一定要关注,这样可以少走很多弯路,特别是使用一些库的时候。

oslo_config库之坑:

第一次使用这个库,看了下官方的文档就了解了下一些options的类型和demo却没有发现必须要将自己定义的Options注册到conf中才能使用其中的配置值,这里举个例子:

notification_opts = [
    cfg.StrOpt('origin',
               help='SMS and Email api origin'),
    cfg.ListOpt('emails',
                help='Emails of administrator of platform'), ]

CONF = cfg.CONF
CONF.register_opts(notification_opts, 'notification')

在定义完option后必须要通过register_opts方法将options注册到conf对象中。

经验分享:

这次的部署是使用kolla-ansible的方式来进行的,所以所有的服务都跑在容器里面。如果想要测试的话,就得将代码更新到容器中,然后再重启容器服务才能才能够工作。但是这样操作的话非常麻烦,下面分享几个方便的小技巧:

修改容器启动命令,让工作远离重启:

玩过kolla-ansible的朋友都知道:每一个用kolla-ansible启动的容器在“/etc/kolla/容器名下”都会有一个config.json的文件。这个文件名中的command键值存放了容器中服务的启动命令,一旦这个命令启动的进程挂了,容器便会重启,这里我们改为sleep 111111111111111111 让其一直休眠。这样容器便不会挂了。

git更新代码:

当代码改动变得非常多而杂的时候手动更新代码便不再合适了。所以我们要借助工具来完成代码的更新,git是我们的首选,因为镜像中是使用pip安装的包,所以文件目录结构和项目的文件目录结构基本没什么变化。可以使用以下命令操作:

1.
#如果你修改的不再stage中
git diff  > patch
#如果在stage中
git diff  --cached > patch

git diff  branchname --cached > patch
2.将patch文件scp到部署机上
scp patch remote:/root

3.使用docker cp指令将patch复制到容器中
docker cp patch cloudkitty_api:/root

4.用git初始化项目的部署目录,并将当前的代码提交个patch,这步操作需要设置下邮箱
docker exec -u root -it cloudkitty bash
cd /var/lib/kolla/venv/lib/python2.7/site-packages/cloudkitty
git init 
git add .
git config --global user.email "hi@openstack.com"
git commit -m 'init'

5.在这里如果path中有requirements和setup.cfg文件请把他们删除掉,因为安装文件中不存在这些东西。
docker exec -u root -it cloudkitty bash
cd /var/lib/kolla/venv/lib/python2.7/site-packages/
git apply /root/patch
展开阅读全文

没有更多推荐了,返回首页