本文地址:http://blog.csdn.net/spch2008/article/details/9281947
在/usr/share/pyshared/quantum/plugins/openvswitch/ 下创建新包extensions,然后将其连接到/usr/lib/python2.7/dist-packages/quantum/plugins/openvswitch下。
在extensions下创建ovsqos.py,同样需要进行软连接。具体可参见Quantum 数据库增加新表
1. 首先,处理资源属性映射,其实就是对属性进行一些限制。
def convert_to_unsigned_int_or_none(val): if val is None: return try: val = int(val) if val < 0: raise ValueError except (ValueError, TypeError): msg = _("'%s' must be a non negative integer.") % val raise qexception.InvalidInput(error_message=msg) return val # Attribute Map RESOURCE_ATTRIBUTE_MAP = { 'ovsqoss': { 'id': {'allow_post': False, 'allow_put': False, 'is_visible': True, 'primary_key': True}, 'name': {'allow_post': True, 'allow_put': True, 'is_visible': True, 'default': '', 'validate': {'type:string': None}}, 'rate': {'allow_post': True, 'allow_put': True, 'is_visible': True, 'default': '0', 'convert_to': convert_to_unsigned_int_or_none}, 'burst': {'allow_post': True, 'allow_put': True, 'is_visible': True, 'default': '0', 'convert_to': convert_to_unsigned_int_or_none}, 'tenant_id': {'allow_post': True, 'allow_put': False, 'required_by_policy': True, 'validate': {'type:string': None}, 'is_visible': True}, } }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也进行一些限制
OVSQOS = 'ovsqoss' EXTENDED_ATTRIBUTES_2_0 = { 'ports': {OVSQOS: {'allow_post': True, 'allow_put': True, 'is_visible': True, 'default': attr.ATTR_NOT_SPECIFIED}}}
3. 最重要的一个类
注意:类名必须与文件同名,且首字母大写。
class Ovsqos(object): @classmethod def get_name(cls): return "ovsqos" @classmethod def get_alias(cls): return "ovsqos" @classmethod def get_description(cls): return "OVS QoS extension." @classmethod def get_namespace(cls): return "http://blog.csdn.net/spch2008" @classmethod def get_updated(cls): return "2013-06-05T10:00:00-00:00" @classmethod def get_resources(cls): """ Returns Ext Resources """ exts = [] plugin = manager.QuantumManager.get_plugin() resource_name = 'ovsqos' collection_name = resource_name.replace('_', '-') + "s" params = RESOURCE_ATTRIBUTE_MAP.get(resource_name + "s", dict()) controller = base.create_resource(collection_name, resource_name, plugin, params, allow_bulk=False) ex = extensions.ResourceExtension(collection_name, controller) exts.append(ex) return exts def get_extended_resources(self, version): if version == "2.0": return EXTENDED_ATTRIBUTES_2_0 else: return {}
__init__的ext_mgr.extend_resources("2.0", attributes.RESOURCE_ATTRIBUTE_MAP)
加入该别名
supported_extension_aliases = ["provider", "router", "ovsqos"]
4. quantum\extensions\extensions.py文件的最末尾
def get_extensions_path() 用于取得扩展功能文件,原代码必须使用绝对路径,但是配置文档中给的是相对路径,不一致。
遂将其改为相对路径,代码如下:
def get_extensions_path(): #spch paths = ':'.join(quantum.extensions.__path__) #get the prefix path prefix = "/".join(quantum.__path__[0].split("/")[:-1]) if cfg.CONF.api_extensions_path: #split the api_extensions_path by ":" ext_paths = cfg.CONF.api_extensions_path.split(":") #add prefix for each path for i in range(len(ext_paths)): ext_paths[i] = prefix + ext_paths[i] ext_paths.append(paths) paths = ":".join(ext_paths) return paths
quantum.conf 中:
api_extensions_path = /quantum/plugins/openvswitch/extensions
完整代码如下:
''' Created on 2013-6-5 @author: spch2008 ''' from abc import abstractmethod from quantum.api.v2 import attributes as attr from quantum.api.v2 import base from quantum.extensions import extensions from quantum.common import exceptions as qexception from quantum import manager import logging LOG = logging.getLogger(__name__) def convert_to_unsigned_int_or_none(val): if val is None: return try: val = int(val) if val < 0: raise ValueError except (ValueError, TypeError): msg = _("'%s' must be a non negative integer.") % val raise qexception.InvalidInput(error_message=msg) return val # Attribute Map RESOURCE_ATTRIBUTE_MAP = { 'ovsqoss': { 'id': {'allow_post': False, 'allow_put': False, 'is_visible': True, 'primary_key': True}, 'name': {'allow_post': True, 'allow_put': True, 'is_visible': True, 'default': '', 'validate': {'type:string': None}}, 'rate': {'allow_post': True, 'allow_put': True, 'is_visible': True, 'default': '0', 'convert_to': convert_to_unsigned_int_or_none}, 'burst': {'allow_post': True, 'allow_put': True, 'is_visible': True, 'default': '0', 'convert_to': convert_to_unsigned_int_or_none}, 'tenant_id': {'allow_post': True, 'allow_put': False, 'required_by_policy': True, 'validate': {'type:string': None}, 'is_visible': True}, } } OVSQOS = 'ovsqoss' EXTENDED_ATTRIBUTES_2_0 = { 'ports': {OVSQOS: {'allow_post': True, 'allow_put': True, 'is_visible': True, 'default': attr.ATTR_NOT_SPECIFIED}}} class Ovsqos(object): @classmethod def get_name(cls): return "ovsqos" @classmethod def get_alias(cls): return "ovsqos" @classmethod def get_description(cls): return "OVS QoS extension." @classmethod def get_namespace(cls): return "http://blog.csdn.net/spch2008" @classmethod def get_updated(cls): return "2013-06-05T10:00:00-00:00" @classmethod def get_resources(cls): """ Returns Ext Resources """ exts = [] plugin = manager.QuantumManager.get_plugin() resource_name = 'ovsqos' collection_name = resource_name.replace('_', '-') + "s" params = RESOURCE_ATTRIBUTE_MAP.get(resource_name + "s", dict()) controller = base.create_resource(collection_name, resource_name, plugin, params, allow_bulk=False) ex = extensions.ResourceExtension(collection_name, controller) exts.append(ex) return exts def get_extended_resources(self, version): if version == "2.0": return EXTENDED_ATTRIBUTES_2_0 else: return {} class OVSPluginBase(object): @abstractmethod def create_ovsqos(self, context, ovsqos): pass @abstractmethod def get_ovsqoss(self, context, filters, fields): pass @abstractmethod def get_ovsqos(self, context, rule_id, fields): pass @abstractmethod def delete_ovsqos(self, context, rule_id): pass @abstractmethod def update_ovsqos(self, context, rule_id, ovsqos): pass