自己动手写OpenStack的QoS功能

来源:互联网 发布:漏洞网站源码 编辑:程序博客网 时间:2024/06/05 16:18

http://blog.csdn.net/spch2008/article/details/9279445


本文地址:http://blog.csdn.net/spch2008/article/details/9011321


1. 创建代码ovs_qos_db.py

[python] view plaincopyprint?
  1. ''''' 
  2. Created on 2013-6-3 
  3.  
  4. @author: spch2008 
  5. '''  
  6.   
  7. from sqlalchemy import Column, Integer, String  
  8. from sqlalchemy.orm import exc  
  9. from quantum.db.models_v2 import model_base  
  10.   
  11. class QoSPortBinding(model_base.BASEV2):  
  12.     __tablename__ = 'ovs_qos_port_binding'  
  13.   
  14.     port_id = Column(String(20), primary_key=True)  
  15.       
  16.     qos_id  = Column(String(20), primary_key=True)  
  17.   
  18.     def __init__(self, port_id, qos_id):  
  19.         self.port_id = port_id  
  20.         self.qos_id  = qos_id  
  21.   
  22.     def __repr__(self):  
  23.         return "<QoSPortBinding(%s, %s, %s)>" % (self.port_id, self.qos_id)  

将代码置于/usr/share/pyshared/quantum/plugins/openvswitch# 中


2. 引入该模块

    在/usr/share/pyshared/quantum/plugins/openvswitch#下的ovs_db_v2.py中,导入上述模块 

[python] view plaincopyprint?
  1. from quantum.plugins.openvswitch import ovs_qos_db  

3. 创建软连接


/usr/lib/python2.7/dist-packages/quantum/plugins/openvswitch#   ln -s ../../../../../../share/pyshared/quantum/plugins/openvswitch/ovs_qos_db.py  ovs_qos_db.py


4. 重启quantum-server

    service quantum-server restart


本文地址:http://blog.csdn.net/spch2008/article/details/9279445


起因:OpenStack源代码看有些日子了,于是想找点东西做做。发现NVP有QoS功能,但是是针对Port的,有些复杂,

            就将其简化,做一个针对Interface的QoS功能。针对Interface的QoS只需要几条命令即可,做起来方便简单。

[plain] view plaincopyprint?
  1. ovs-vsctl set interface vif0.0 ingress_policing_rate=1000  
  2. ovs-vsctl set interface vif0.0 ingress_policing_burst=100  
  3. ingress_policing_rate:最大发送速率(单位均为kbps)  
  4. ingress_policing_burst:超过ingress_policing_rate的最大浮动值  

过程:

1.首先通过命令创建QoS条目: 

[plain] view plaincopyprint?
  1. root@nova-network:~# quantum qos-create --name spch2008 --rate 1000 --burst 100  
  2. Created a new ovsqos:  
  3. +-----------+--------------------------------------+  
  4. | Field     | Value                                |  
  5. +-----------+--------------------------------------+  
  6. | burst     | 100                                  |  
  7. | id        | 41d1c686-3298-40bf-a114-b20e7c4e370c |  
  8. | name      | spch2008                             |  
  9. | rate      | 1000                                 |  
  10. | tenant_id | 9b320e2822da4461967232e938d92d18     |  
  11. +-----------+--------------------------------------+  
2.启动虚拟机的时候,将qos参数传入 
[plain] view plaincopyprint?
  1. nova boot --flavor 1 --image 4d3175cf-9d82-44de-862b-f94bd6e71fb7   
  2.           --key_name mykey instance003 --security_groups default   
  3.           --interface_qos 41d1c686-3298-40bf-a114-b20e7c4e370c  

3.查看虚拟机

[plain] view plaincopyprint?
  1. root@nova-compute1:~# ovs-vsctl list Interface  
  2. _uuid               : 2542b505-c895-4e16-9dfc-535c1a922109  
  3. admin_state         : up  
  4. cfm_fault           : []  
  5. cfm_mpid            : []  
  6. cfm_remote_mpids    : []  
  7. duplex              : full  
  8. external_ids        : {attached-mac="fa:16:3e:d8:e1:7e", iface-id="d92f45e9-9c41-424d-9410-2dc5bd82aeca", iface-status=active,   
  9.                        vm-uuid="0062f57a-1fda-444b-a7a5-63dafa8b87d4"}  
  10. ingress_policing_burst: 100  
  11. ingress_policing_rate: 1000  
  12. lacp_current        : []  
  13. link_resets         : 2  
  14. link_speed          : 10000000000  
  15. link_state          : up  
  16. mac                 : []  
  17. mtu                 : 1500  
  18. name                : "qvod92f45e9-9c"  
  19. ofport              : 8  
  20. options             : {}  
  21. other_config        : {}  
  22. statistics          : {collisions=0, rx_bytes=1336, rx_crc_err=0, rx_dropped=0, rx_errors=0, rx_frame_err=0, rx_over_err=0, rx_packets=14,   
  23.                        tx_bytes=0, tx_dropped=0, tx_errors=0, tx_packets=0}  
  24. status              : {driver_name=veth, driver_version="1.0", firmware_version="N/A"}  
  25. type                : ""  


思路:

1. 创建QoS-Rules数据库,写入QoS规则,主键qos_id
2. 创建QoS-Port-Binding数据库,记录port_id 与 qos_id绑定关系。
3. 创建虚拟机时,nova调用Quantum暴露出来的API,将绑定关系写入数据库。
4. ovs-agent通过远程调用函数(参数port_id)向ovs-plugin取得QoS规则。

5. ovs-agent将规则施行于Interface上。


开发环境:

1. 采用OpenStack F版本进行开发

2. 一个控制节点nova-control, 一个网络节点nova-network,一个计算节点nova-compute


在/usr/share/pyshared/quantum/plugins/openvswitch/ 下创建新包extensions,然后将其连接到/usr/lib/python2.7/dist-packages/quantum/plugins/openvswitch下。

在extensions下创建ovsqos.py,同样需要进行软连接。具体可参见Quantum 数据库增加新表 

1. 首先,处理资源属性映射,其实就是对属性进行一些限制。  

[python] view plaincopyprint?
  1. def convert_to_unsigned_int_or_none(val):  
  2.     if val is None:  
  3.         return  
  4.     try:  
  5.         val = int(val)  
  6.         if val < 0:  
  7.             raise ValueError  
  8.     except (ValueError, TypeError):  
  9.         msg = _("'%s' must be a non negative integer.") % val  
  10.         raise qexception.InvalidInput(error_message=msg)  
  11.     return val  
  12.   
  13.   
  14. # Attribute Map  
  15. RESOURCE_ATTRIBUTE_MAP = {  
  16.     'ovsqoss': {  
  17.         'id': {'allow_post'False'allow_put'False,  
  18.                'is_visible'True,  
  19.                'primary_key'True},  
  20.         'name': {'allow_post'True'allow_put'True,  
  21.                  'is_visible'True'default''',  
  22.                  'validate': {'type:string'None}},  
  23.         'rate': {'allow_post'True'allow_put'True,  
  24.                 'is_visible'True'default''0',  
  25.                 'convert_to': convert_to_unsigned_int_or_none},  
  26.         'burst': {'allow_post'True'allow_put'True,  
  27.                 'is_visible'True'default''0',  
  28.                 'convert_to': convert_to_unsigned_int_or_none},  
  29.         'tenant_id': {'allow_post'True'allow_put'False,  
  30.                       'required_by_policy'True,  
  31.                       'validate': {'type:string'None},  
  32.                       'is_visible'True},  
  33.     }  
  34. }  
  convert_to_unsigned_int_or_none将属性值转换成整形。

  RESOURCE_ATTRIBUTE_MAP对属性进行制约; allow_put 是否允许用户进行修改,即update; allow_post是否通过用户传来数值进行填充,比如id,

  此值为false,如果用户提交过来的数据中有id值,则出错,也就是说id由系统进行分配,不由用户指定;is_visible该属性是否对用户可见,若为false,

  用户看不到该值。


2. 同理,qos是port的一个属性,对qos也进行一些限制

[python] view plaincopyprint?
  1. OVSQOS = 'ovsqoss'  
  2. EXTENDED_ATTRIBUTES_2_0 = {  
  3.     'ports': {OVSQOS: {'allow_post'True,  
  4.                                'allow_put'True,  
  5.                                'is_visible'True,  
  6.                                'default': attr.ATTR_NOT_SPECIFIED}}}  

用户通过quantum port-list, port-update等命令对端口进行修改的时候,ovsqos这个属性是否可以修改,对用户可见等。


3. 最重要的一个类

   注意:类名必须与文件同名,且首字母大写。

[python] view plaincopyprint?
  1. class Ovsqos(object):  
  2.  
  3.     @classmethod  
  4.     def get_name(cls):  
  5.         return "ovsqos"  
  6.  
  7.     @classmethod  
  8.     def get_alias(cls):  
  9.         return "ovsqos"  
  10.  
  11.     @classmethod  
  12.     def get_description(cls):  
  13.         return "OVS QoS extension."  
  14.  
  15.     @classmethod  
  16.     def get_namespace(cls):  
  17.         return "http://blog.csdn.net/spch2008"  
  18.  
  19.     @classmethod  
  20.     def get_updated(cls):  
  21.         return "2013-06-05T10:00:00-00:00"  
  22.  
  23.     @classmethod  
  24.     def get_resources(cls):  
  25.         """ Returns Ext Resources """  
  26.         exts = []  
  27.         plugin = manager.QuantumManager.get_plugin()  
  28.         resource_name = 'ovsqos'  
  29.         collection_name = resource_name.replace('_''-') + "s"  
  30.         params = RESOURCE_ATTRIBUTE_MAP.get(resource_name + "s", dict())  
  31.           
  32.         controller = base.create_resource(collection_name,  
  33.                                           resource_name,  
  34.                                           plugin, params, allow_bulk=False)  
  35.   
  36.         ex = extensions.ResourceExtension(collection_name,  
  37.                                           controller)  
  38.         exts.append(ex)  
  39.   
  40.         return exts  
  41.   
  42.     def get_extended_resources(self, version):  
  43.         if version == "2.0":  
  44.             return EXTENDED_ATTRIBUTES_2_0  
  45.         else:  
  46.             return {}  

  • get_extended_resources取得扩展属性,然后实际上报告给了(quantum\api\v2\router.py)中的APIRouter的

                 __init__的ext_mgr.extend_resources("2.0",  attributes.RESOURCE_ATTRIBUTE_MAP)

  • get_resources 取得资源,用于后续创建路由条目
  • get_alias返回一个别名,这个名字很重要。需要在ovs_quantum_plguin.py的OVSQuantumPluginV2属性_supported_extension_aliases

             加入该别名            

[python] view plaincopyprint?
  1. supported_extension_aliases = ["provider""router""ovsqos"]  

4. quantum\extensions\extensions.py文件的最末尾

     def get_extensions_path() 用于取得扩展功能文件,原代码必须使用绝对路径,但是配置文档中给的是相对路径,不一致。

     遂将其改为相对路径,代码如下:   

[python] view plaincopyprint?
  1. def get_extensions_path():  
  2.     #spch  
  3.     paths = ':'.join(quantum.extensions.__path__)  
  4.       
  5.     #get the prefix path  
  6.     prefix = "/".join(quantum.__path__[0].split("/")[:-1])  
  7.         
  8.     if cfg.CONF.api_extensions_path:  
  9.         #split the api_extensions_path by ":"  
  10.         ext_paths = cfg.CONF.api_extensions_path.split(":")  
  11.         #add prefix for each path  
  12.         for i in range(len(ext_paths)):  
  13.             ext_paths[i] = prefix + ext_paths[i]  
  14.           
  15.         ext_paths.append(paths)  
  16.         paths = ":".join(ext_paths)  
  17.       
  18.     return paths  

5. 将扩展功能写入配置文件中,使得OpenStack系统可以加载qos功能

    quantum.conf 中: 

[plain] view plaincopyprint?
  1. api_extensions_path = /quantum/plugins/openvswitch/extensions  

 完整代码如下:

[python] view plaincopyprint?
  1. ''''' 
  2. Created on 2013-6-5 
  3.  
  4. @author: spch2008 
  5. '''  
  6.   
  7.   
  8. from abc import abstractmethod  
  9. from quantum.api.v2 import attributes as attr  
  10. from quantum.api.v2 import base  
  11. from quantum.extensions import extensions  
  12. from quantum.common import exceptions as qexception  
  13. from quantum import manager  
  14. import logging  
  15.   
  16. LOG = logging.getLogger(__name__)  
  17.   
  18.   
  19. def convert_to_unsigned_int_or_none(val):  
  20.     if val is None:  
  21.         return  
  22.     try:  
  23.         val = int(val)  
  24.         if val < 0:  
  25.             raise ValueError  
  26.     except (ValueError, TypeError):  
  27.         msg = _("'%s' must be a non negative integer.") % val  
  28.         raise qexception.InvalidInput(error_message=msg)  
  29.     return val  
  30.   
  31.   
  32. # Attribute Map  
  33. RESOURCE_ATTRIBUTE_MAP = {  
  34.     'ovsqoss': {  
  35.         'id': {'allow_post'False'allow_put'False,  
  36.                'is_visible'True,  
  37.                'primary_key'True},  
  38.         'name': {'allow_post'True'allow_put'True,  
  39.                  'is_visible'True'default''',  
  40.                  'validate': {'type:string'None}},  
  41.         'rate': {'allow_post'True'allow_put'True,  
  42.                 'is_visible'True'default''0',  
  43.                 'convert_to': convert_to_unsigned_int_or_none},  
  44.         'burst': {'allow_post'True'allow_put'True,  
  45.                 'is_visible'True'default''0',  
  46.                 'convert_to': convert_to_unsigned_int_or_none},  
  47.         'tenant_id': {'allow_post'True'allow_put'False,  
  48.                       'required_by_policy'True,  
  49.                       'validate': {'type:string'None},  
  50.                       'is_visible'True},  
  51.     }  
  52. }  
  53.   
  54. OVSQOS = 'ovsqoss'  
  55. EXTENDED_ATTRIBUTES_2_0 = {  
  56.     'ports': {OVSQOS: {'allow_post'True,  
  57.                                'allow_put'True,  
  58.                                'is_visible'True,  
  59.                                'default': attr.ATTR_NOT_SPECIFIED}}}  
  60.   
  61.   
  62. class Ovsqos(object):  
  63.  
  64.     @classmethod  
  65.     def get_name(cls):  
  66.         return "ovsqos"  
  67.  
  68.     @classmethod  
  69.     def get_alias(cls):  
  70.         return "ovsqos"  
  71.  
  72.     @classmethod  
  73.     def get_description(cls):  
  74.         return "OVS QoS extension."  
  75.  
  76.     @classmethod  
  77.     def get_namespace(cls):  
  78.         return "http://blog.csdn.net/spch2008"  
  79.  
  80.     @classmethod  
  81.     def get_updated(cls):  
  82.         return "2013-06-05T10:00:00-00:00"  
  83.  
  84.     @classmethod  
  85.     def get_resources(cls):  
  86.         """ Returns Ext Resources """  
  87.         exts = []  
  88.         plugin = manager.QuantumManager.get_plugin()  
  89.         resource_name = 'ovsqos'  
  90.         collection_name = resource_name.replace('_''-') + "s"  
  91.         params = RESOURCE_ATTRIBUTE_MAP.get(resource_name + "s", dict())  
  92.           
  93.         controller = base.create_resource(collection_name,  
  94.                                           resource_name,  
  95.                                           plugin, params, allow_bulk=False)  
  96.   
  97.         ex = extensions.ResourceExtension(collection_name,  
  98.                                           controller)  
  99.         exts.append(ex)  
  100.   
  101.         return exts  
  102.   
  103.     def get_extended_resources(self, version):  
  104.         if version == "2.0":  
  105.             return EXTENDED_ATTRIBUTES_2_0  
  106.         else:  
  107.             return {}  
  108.   
  109. class OVSPluginBase(object):  
  110.     @abstractmethod  
  111.     def create_ovsqos(self, context, ovsqos):  
  112.         pass  
  113.  
  114.     @abstractmethod  
  115.     def get_ovsqoss(self, context, filters, fields):  
  116.         pass  
  117.  
  118.     @abstractmethod  
  119.     def get_ovsqos(self, context, rule_id, fields):  
  120.         pass  
  121.  
  122.     @abstractmethod  
  123.     def delete_ovsqos(self, context, rule_id):  
  124.         pass  
  125.  
  126.     @abstractmethod  
  127.     def update_ovsqos(self, context, rule_id, ovsqos):  
  128.         pass  




本文地址:http://blog.csdn.net/spch2008/article/details/9281779


创建数据库以及相应的操作:

/usr/share/pyshared/quantum/plugins/openvswitch/ 下创建ovs_qos_db.py,

然后将其连接到/usr/lib/python2.7/dist-packages/quantum/plugins/openvswitch下,可参见Quantum 数据库增加新表 

 

ovs_qos_db.py

[python] view plaincopyprint?
  1. import sqlalchemy as sa  
  2. from sqlalchemy import orm  
  3. from sqlalchemy.orm import exc  
  4.   
  5. from quantum.db import model_base  
  6. from quantum.db import models_v2  
  7.   
  8. from quantum.openstack.common import log as logging  
  9. from quantum.plugins.openvswitch.extensions import ovsqos  
  10.   
  11.   
  12. LOG = logging.getLogger(__name__)  
  13.   
  14. class QualityOfServicePortBinding(model_base.BASEV2):  
  15.       
  16.     __tablename__ = 'ovs_qos_port_bindings'  
  17.       
  18.     port_id = sa.Column(sa.String(255),  
  19.                         primary_key=True)  
  20.     rule_id = sa.Column(sa.String(255))  
  21.   
  22. class QualityOfServiceRule(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):  
  23.   
  24.     __tablename__ = 'ovs_qos_rules'  
  25.       
  26.     name = sa.Column(sa.String(255))  
  27.     rate = sa.Column(sa.Integer)  
  28.     burst = sa.Column(sa.Integer)  
  29.   
  30. class QualityOfServiceDbMixin(ovsqos.OVSPluginBase):  
  31.     
  32.     __native_bulk_support = True  
  33.       
  34.     def create_ovsqos(self, context, ovsqos):  
  35.         qos_rule = ovsqos['ovsqos']  
  36.         with context.session.begin(subtransactions=True):  
  37.             qos = QualityOfServiceRule(  
  38.                       name=qos_rule.get('name'),   
  39.                       rate=qos_rule.get('rate'),  
  40.                       burst=qos_rule.get('burst'),  
  41.                       tenant_id=qos_rule.get('tenant_id'))  
  42.             context.session.add(qos)  
  43.         return self._make_qos_rule_dict(qos)  
  44.       
  45.     def get_ovsqoss(self, context, filters, fields):  
  46.           
  47.         return self._get_collection(context, QualityOfServiceRule,  
  48.                                     self._make_qos_rule_dict,  
  49.                                     filters=filters, fields=fields)  
  50.        
  51.       
  52.     def get_ovsqos(self, context, rule_id, fields=None):  
  53.         return self._make_qos_rule_dict(  
  54.             self._get_ovsqos(context, rule_id), fields)  
  55.   
  56.     def _get_ovsqos(self, context, rule_id):  
  57.         try:  
  58.             return self._get_by_id(context, QualityOfServiceRule, rule_id)  
  59.         except exc.NoResultFound:  
  60.             return None  
  61.           
  62.     def delete_ovsqos(self, context, rule_id):  
  63.         qos = self._get_ovsqos(context, rule_id)  
  64.         with context.session.begin(subtransactions=True):  
  65.             context.session.delete(qos)  
  66.          
  67.     def update_ovsqos(self, context, rule_id, ovsqos):  
  68.         rule = ovsqos['ovsqos']  
  69.         with context.session.begin(subtransactions=True):  
  70.             qos = self._get_ovsqos(context, rule_id)  
  71.             qos.update(rule)  
  72.          
  73.         return self._make_qos_rule_dict(qos)  
  74.           
  75.       
  76.     def _make_qos_rule_dict(self, qos, fields=None):  
  77.         res = {'id': qos.id,  
  78.                'name': qos.name,  
  79.                'rate': qos.rate,  
  80.                'burst': qos.burst,  
  81.                'tenant_id':qos.tenant_id}  
  82.         return self._fields(res, fields)    


数据库很简陋,只有一些基本功能。


数据库相应操作已完成,对OVS-Plugin进行修改。

在quantum\plugins\openvswitch\ovs_quantum_plugin.py中

使OVSQuantumPluginV2继承于上一篇所写的数据库操作类QuanlityOfServiceDbMixin。

[python] view plaincopyprint?
  1. class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,  
  2.                          ovs_qos_db.QualityOfServiceDbMixin,  
  3.                          l3_db.L3_NAT_db_mixin):  

在OVSQuantumPluginV2中,将相应的服务请求转到db类中去处理

[python] view plaincopyprint?
  1. def get_ovsqoss(self, context, filters=None, fields=None):  
  2.     qoss = super(OVSQuantumPluginV2, self).get_ovsqoss(context, filters, fields)  
  3.       
  4.     return qoss  
  5.   
  6.   
  7. def get_ovsqos(self, context, id, fields=None):  
  8.     qos = super(OVSQuantumPluginV2, self).get_ovsqos(context, id, fields)  
  9.       
  10.     return qos  
  11.   
  12.   
  13. def delete_ovsqos(self, context, id):  
  14.       
  15.     result = super(OVSQuantumPluginV2, self).delete_ovsqos(context, id)  
  16.       
  17.     return result  
  18.   
  19.   
  20. def update_ovsqos(self, context, id, ovsqos):  
  21.     result = super(OVSQuantumPluginV2, self).update_ovsqos(context, id, ovsqos)  
  22.       
  23.     return result  
  24.   
  25.   
  26. def create_ovsqos(self, context, ovsqos):  
  27.     qos = super(OVSQuantumPluginV2, self).create_ovsqos(context, ovsqos)  
  28.       
  29.     return qos   

ovs-plugin修改完成后,要改写ovs_agent,用于对openvswitch施行qos规则。

一、创建新类

在计算节点ovs_quantum_agent.py中,增加新类

[python] view plaincopyprint?
  1. class OVSQosAgent(object):  
  2.   
  3.     def __init__(self, context, plugin_rpc, int_br, agent_id):  
  4.         self.context = context  
  5.     self.plugin_rpc = plugin_rpc  
  6.     self.int_br     = int_br  
  7.     self.agent_id   = agent_id  
  8.       
  9.     def treat_qos_added(self, device, qos_rule):  
  10.             
  11.         vif_port = self.int_br.get_vif_port_by_id(device)  
  12.         if not vif_port:  
  13.             LOG.debug("spch_device_not_in")  
  14.             return  
  15.           
  16.         self.int_br.set_interface_qos(vif_port.port_name, qos_rule['rate'], qos_rule['burst'])  
  17.       
  18.       
  19.     def apply_qos_rules(self, devices):  
  20.         if not devices:  
  21.             LOG.debug("spch_devices_is_NULL")  
  22.           
  23.         for device in devices:  
  24.             try:  
  25.                 qos_rule = self.plugin_rpc.get_qos_details(self.context,  
  26.                                                           device,  
  27.                                                            self.agent_id)  
  28.             except Exception:  
  29.                 LOG.debug(_("spch_Unable to get port qos details for device_id = %s" % device))  
  30.             self.treat_qos_added(device, qos_rule)  
  31.               
  32.     def refresh_qos(self, port ):  
  33.     device = port['id']  
  34.     self.apply_qos_rules(device)  

1.  改写ovs_lib,增加qos功能。

quantum\agent\linux\ovs_lib.py中的OVSBridge类中,增加以下两个函数

[python] view plaincopyprint?
  1.    def set_interface_qos(self, interface, rate, burst):  
  2.   
  3.        ingress_policing_rate  = "ingress_policing_rate=%s" % rate  
  4.        ingress_policing_burst = "ingress_policing_burst=%s" % burst  
  5.          
  6.        args = ["set""interface", interface, ingress_policing_rate, ingress_policing_burst]  
  7.   
  8.        self.run_vsctl(args)  
  9.   
  10.    def clear_interface_qos(self, interface):  
  11. ingress_policing_rate  = "ingress_policing_rate=0"  
  12. ingress_policing_burst = "ingress_policing_burst=0"  
  13. args = ["set""interface", interface, ingress_policing_rate, ingress_policing_burst]  
  14.   
  15. self.run_vsctl(args)  

2. 增加远程调用接口,用于向ovs-plugin取得qos规则。

在quantum\agent\rpc.py中

class PluginApi(proxy.RpcProxy):

[python] view plaincopyprint?
  1. def get_qos_details(self, context, device, agent_id):  
  2. urn self.call(context,  
  3.                      self.make_msg('get_qos_details', device=device,  
  4.                                    agent_id=agent_id),  
  5.                      topic=self.topic)  

3. 上述get_qos_details函数中,调用了控制节点的get_qos_details函数,从数据库中取得规则,返回给ovs-agent。

在控制节点的ovs_quantum_plugin.py中

class OVSRpcCallbacks(dhcp_rpc_base.DhcpRpcCallbackMixin):

[python] view plaincopyprint?
  1. def get_qos_details(self, rpc_context, **kwargs):  
  2.     agent_id = kwargs.get('agent_id')  
  3.     device   = kwargs.get('device')  
  4.     LOG.debug("spch_get_device=%s" % device)  
  5.       
  6.     if device:  
  7.         binding = ovs_db_v2.get_port_qos_binding(None, device)  
  8.         if binding:  
  9.             qos = ovs_db_v2.get_port_qos(None, binding.rule_id)  
  10.       
  11.     if qos:  
  12.         return {'rate':qos.rate, 'burst':qos.burst}  
  13.     else:  
  14.         return {'rate':1'burst':1}  


二、 使用

一中,相应的准备工作一切就绪,剩下的部分只是调用OVSQosAgent相应的操作即可。

在OVSQuantumAgent中__init__中,需要持有OVSQosAgent对象。

[python] view plaincopyprint?
  1. self.qos_agent = OVSQosAgent(self.context, self.plugin_rpc, self.int_br, self.agent_id)    


nova启动虚拟机的时候会在br-int(ovs网桥)上创建一个端口,ovs-agent会定期检测,当检测到新端口创建,即会调用treat_devices_added进行处理。

所以,添加qos的操作应该treat_devices_added函数中进行。

[python] view plaincopyprint?
  1. def treat_devices_added(self, devices):  
  2.       resync = False  
  3.     
  4.     self.qos_agent.apply_qos_rules(devices)   
  5.     
  6.   ………………   

  

三、总结

当然,这些实现都很简陋,没有相应的删除操作,只是希望能够掌握开发流程。


这一篇主要介绍quantum client的编写,使完成的功能能够通过命令行进行操作。

quantumclient\quantum\v2_0中增加ovs_qos.py(不要忘记进行软连接)。

[python] view plaincopyprint?
  1. ''''' 
  2. Created on 2013-6-3 
  3.  
  4. @author: spch2008 
  5. '''  
  6.   
  7. import logging  
  8.   
  9. from quantumclient.quantum.v2_0 import CreateCommand  
  10. from quantumclient.quantum.v2_0 import DeleteCommand  
  11. from quantumclient.quantum.v2_0 import ListCommand  
  12. from quantumclient.quantum.v2_0 import ShowCommand  
  13. from quantumclient.quantum.v2_0 import UpdateCommand  
  14.   
  15.   
  16. class CreateQoS(CreateCommand):  
  17.     """Create QoS."""  
  18.   
  19.     resource = 'ovsqos'  
  20.     log = logging.getLogger(__name__ + '.CreateQos')  
  21.   
  22.     def add_known_arguments(self, parser):  
  23.         parser.add_argument(  
  24.             '--name',   
  25.             dest='name', action='store',  
  26.             help='Name of qos')  
  27.         parser.add_argument(  
  28.             '--rate',  
  29.             dest='rate', action='store',  
  30.             help='qos_rate'),  
  31.         parser.add_argument(  
  32.             '--burst',  
  33.             dest='burst',  
  34.             help='qos_burst')  
  35.   
  36.     def args2body(self, parsed_args):  
  37.         body = {'ovsqos': {'name': parsed_args.name,  
  38.                   'rate':  parsed_args.rate,  
  39.                   'burst': parsed_args.burst}, }  
  40.           
  41.         if parsed_args.tenant_id:  
  42.             body['ovsqos'].update({'tenant_id': parsed_args.tenant_id})  
  43.           
  44.         return body  
  45.   
  46.   
  47. class ListQoS(ListCommand):  
  48.     """List QoS."""  
  49.       
  50.     resource = 'ovsqos'  
  51.     log = logging.getLogger(__name__ + '.ListQoS')  
  52.     _formatters = {}  
  53.     list_columns = ['id''name''rate''burst']  
  54.   
  55. class ShowQoS(ShowCommand):  
  56.     """Show QoS."""  
  57.       
  58.     resource = 'ovsqos'  
  59.     log = logging.getLogger(__name__ + '.CreateQos')  
  60.   
  61.   
  62. class DeleteQoS(DeleteCommand):  
  63.     """Delete QoS."""  
  64.       
  65.     log = logging.getLogger(__name__ + '.DeleteQoS')  
  66.     resource = 'ovsqos'  
  67.   
  68.   
  69. class UpdateQoS(UpdateCommand):  
  70.     """Update QoS."""  
  71.       
  72.     log = logging.getLogger(__name__ + '.UpdateQoS')  
  73.     resource = 'ovsqos'  


quantumclient\shell.py中

COMMAND_V2 变量中增加下列命令,导入上述文件中的各个类。

[plain] view plaincopyprint?
  1. 'qos-create': utils.import_class(  
  2.      'quantumclient.quantum.v2_0.ovs_qos.CreateQoS'),  
  3. 'qos-list':utils.import_class(  
  4.      'quantumclient.quantum.v2_0.ovs_qos.ListQoS'),  
  5. 'qos-show':utils.import_class(  
  6.      'quantumclient.quantum.v2_0.ovs_qos.ShowQoS'),  
  7. 'qos-delete':utils.import_class(  
  8.      'quantumclient.quantum.v2_0.ovs_qos.DeleteQoS'),  
  9. 'qos-update':utils.import_class(  
  10.      'quantumclient.quantum.v2_0.ovs_qos.UpdateQoS'),  

quantumclient\v2_0\client.py中

class Client(object):

1. 增加路径,这两个路径直接对应ovs-plugin暴露的API。

    qoss_path = "/ovsqoss"
    qos_path = "/ovsqoss/%s"


2. 增加相应的API处理函数

[python] view plaincopyprint?
  1. @APIParamsCall  
  2. def create_ovsqos(self, body=None):  
  3.     return self.post(self.qoss_path, body=body)  
  4.  
  5. @APIParamsCall  
  6. def list_ovsqoss(self, **_params):  
  7.     return self.get(self.qoss_path, params = _params)  
  8.  
  9. @APIParamsCall  
  10. def show_ovsqos(self, qos_id, **_params):  
  11.     return self.get(self.qos_path % (qos_id), params=_params)  
  12.  
  13. @APIParamsCall  
  14. def delete_ovsqos(self, qos_id):  
  15.     return self.delete(self.qos_path % (qos_id))  
  16.  
  17. @APIParamsCall  
  18. def update_ovsqos(self, qos_id, body=None):  
  19.     return self.put(self.qos_path % (qos_id), body=body)  


前面已经介绍了大部分功能,只剩下启动虚拟机的时候,将qos参数interface_qos(即qos_id)传入,同时在数据库中,

关联端口与qos_id,由于这一部分不是我写的,所以不是很了解,有空的时候在仔细看看。


原创粉丝点击