OpenstackNeutron扩展实现细节1目的本文已QOS为例子,记录通过Neutron的扩展机制扩展网络服务所注意的细节,帮助后续的开发人员快速上手2Neutron的架构Neutron分为三个部分:neutron-client,neutron-server,网络服务代理。Neturon-client提供两种接口,Shell命令行与开发SDK;内部完成REST请求的封装、发送,应答的处理。Neutron-server处理来自client的请求,根据请求的路径调用相应的插件进行处理,配置信息存储导数据库,调度选择目标代理,并将网络配置发送给相应的代理Agent是网络服务直接提供的部分,不同的网络服务由不同的代理完成,比如二层网络的配置由Openvswitch-agent完成。L3-agent完成路由的配置,dhcp-agent完成dnsmasq的配置,lbass-agent完成各种硬件或软件的负载均衡的配置3Neutron的代码的修改Neutron代码主要是要增加常量定义neutron\plugins\common\constants.pyQOS=QOSEXT_TO_SERVICE_MAPPING={'dummy':DUMMY,'lbaas':LOADBALANCER,'lbaasv2':LOADBALANCERV2,'fwaas':FIREWALL,'vpnaas':VPN,'metering':METERING,'qos':QOS,'router':L3_ROUTER_NAT}4Neutron的Server部分4.1扩展的Rest接口定义4.1.1资源的属性定义表资源的属性定义表格式如下,定义了Rest接口提供了配置的资源类型,对资源进行操作的属性要求;RESOURCE_ATTRIBUTE_MAP的key为每一种资源名的复数形式,Value为该资源的scheme描述。RESOURCE_ATTRIBUTE_MAP={'qos_rules':{'id':{'allow_post':False,'allow_put':False,'validate':{'type:uuid':None},'is_visible':True,'primary_key':True},'tenant_id':{'allow_post':True,'allow_put':False,'validate':{'type:string':attr.TENANT_ID_MAX_LEN},'required_by_policy':True,'is_visible':True},'network_id':{'allow_post':True,'allow_put':False,'validate':{'type:uuid':None},'is_visible':True},'port_id':{'allow_post':True,'allow_put':False,'validate':{'type:uuid':None},'is_visible':True},'max_kbps':{'allow_post':True,'allow_put':True,'is_visible':True,'convert_to':convert_to_unsigned_int_or_none},'max_burst_kbps':{'allow_post':True,'allow_put':True,'is_visible':True,'convert_to':convert_to_unsigned_int_or_none},}}REST接口有post,put,get,delete四种方法,post为创建资源,put为修改某个资源,get为获取某个资源,delete为删除某个资源资源的每个属性都定义了一些约束:allow_posTrue:创建时可以指定;False:创建时不能指定allow_putTrue:可以修改;False:不允许修改validate:验证值的合法性,可以验证最大长度,数据类型,或者是枚举值is_visible:是否可见,list资源时属性值是否可以返回4.1.2扩展的描述该文件的路径为$包名/extensions/qos.pyclassQos(extensions.ExtensionDescriptor):@classmethoddefget_name(cls):returnQOSservice@classmethoddefget_alias(cls):returnqos@classmethoddefget_description(cls):returnExtensionforQOSservice@classmethoddefget_namespace(cls):return@classmethoddefget_updated(cls):return2015-04-07T10:00:00-00:00@classmethoddefget_resources(cls):special_mappings={}plural_mappings=resource_helper.build_plural_mappings(special_mappings,RESOURCE_ATTRIBUTE_MAP)attr.PLURALS.update(plural_mappings)returnresource_helper.build_resource_info(plural_mappings,RESOURCE_ATTRIBUTE_MAP,constants.QOS)@classmethoddefget_plugin_interface(cls):returnQOSPluginBasedefupdate_attributes_map(self,attributes):super(Qos,self).update_attributes_map(attributes,extension_attrs_map=RESOURCE_ATTRIBUTE_MAP)defget_extended_resources(self,version):ifversion==2.0:returnRESOURCE_ATTRIBUTE_MAPelse:return{}扩展的描述需要从extensions.ExtensionDescriptor继承,get_name,get_description,get_namespace,get_updated四个函数返回的内容,是在调用neutronext-showqos命令时显示的内容。defget_resources(cls):special_mappings={}plural_mappings=resource_helper.build_plural_mappings(special_mappings,RESOURCE_ATTRIBUTE_MAP)attr.PLURALS.update(plural_mappings)returnresource_helper.build_resource_info(plural_mappings,RESOURCE_ATTRIBUTE_MAP,constants.QOS)4.1.3插件接口的定义插件的接口必须从ServicePluginBase继承,get_plugin_name,get_plugin_type,get_plugin_description必须实现,为插件的基础信息。@six.add_metaclass(abc.ABCMeta)classQOSPluginBase(ServicePluginBase):defget_plugin_name(self):returnconstants.QOSdefget_plugin_type(self):returnconstants.QOSdefget_plugin_description(self):return'qosserviceplugin'@abc.abstractmethoddefget_qos_rules(self,context,filters=None,fields=None):pass@abc.abstractmethoddefget_qos_rule(self,context,id,fields=None):pass@abc.abstractmethoddefcreate_qos_rule(self,context,qos_rule):qos_rule={'qos_rule':{'network_id':'uuid','port_id':'uuid','max_kbps':10,'max_burst_kbps':10}}pass@abc.abstractmethoddefupdate_qos_rule(self,context,id,qos_rule):pass@abc.abstractmethoddefdelete_qos_rule(self,context,id):pass必须为每个资源定义5个接口,分别为:#list资源的接口defget_资源复数名(self,context,filters=None,fields=None)#show单个资源的接口defget_资源单数名(self,context,id,fields=None):#create单个资源的接口defcreate_资源单数名(self,context,data):#update单个资源的接口defupdate_资源单数名(self,context,id,data):#delete单个资源的接口defdelete_资源单数名(self,context,id):4.1.4插件的数据库实现4.1.4.1定义数据库模型类classQosRule(model_base.BASEV2,models_v2.HasId,models_v2.HasTenant):__tablename__='qos_rules'__table_args__=(sa.schema.UniqueConstraint('port_id',name='uniq_qos_rule_port'),)network_id=sa.Column(sa.String(36),nullable=False)port_id=sa.Column(sa.String(36),nullable=False)max_kbps=sa.Column(sa.Integer)max_burst_kbps=sa.Column(sa.Integer)4.1.4.2插件数据库操作类需要多重继承插件接口类与base_db.CommonDbMixinclassQOSPluginDB(QOSPluginBase,base_db.CommonDbMixin):def_make_qos_dict(self,qos,fields=None):res={'id':qos['id'],'tenant_id':qos['tenant_id'],'network_id':qos['network_id'],'port_id':qos['port_id'],'max_kbps':qos['max_kbps'],'max_burst_kbps':qos['max_burst_kbps']}returnself._fields(res,fields)def_get_qos(self,context,id):try:returnself._get_by_id(context,QosRule,id)exceptexc.NoResultFound:raiseQosNotFound(Qos_id=id)defcreate_qos_rule(self,context,qos_rule):tenant