通過neutron的extension新增restful介面和程式碼跨版本遷移
阿新 • • 發佈:2019-01-29
公司最初開發用的openstack版本是Kilo版,在neutron中開發的extension遷移到最新的Newton版本中就不適用了,需要做一些調整。
原先開發的內容是要實現虛實結合,即在程式碼層面實現物理機和虛擬機器通訊,大體思路就是增加neutron的extension來新增一個restful
介面,通過呼叫介面來控制SDN交換機與各個節點間建立vxlan的tunnel,然後用另一個微服務管理物理機的註冊和刪除等等步驟,下面
來記錄下怎樣寫extension和遷移的問題。
一、編寫neutron的extension
1.在neutron/extensions程式碼目錄下有許多neutron自帶的extension,可以借鑑這些entension來寫自己的extension,
比如在apitest.py中有如下程式碼:
在這段程式碼中主要就兩點:(1)RESOURCE_ATTRIBUTE_MAP字典是對新擴充套件的屬性的定義。字典第一層的key為RESOURCE_NAME + 's',其實就是檔名加上一個 ‘s'。第二層的 keys ’id‘, ’name‘, ’tenant_id‘ , ‘address’就是這個擴充套件的三個屬性。第三層的 keys 在 neutron/api/v2/attributes.py 中一百多行有比較詳細的解釋,大家可以多翻原始碼。
(2)Apitest類的名稱與包含這個類的檔名字母必須一樣,只是類名首字母大寫。具體原因可以參考 neutron/api/extensions.py 中 ExtensionManager 的_load_all_extensions_from_path 方法的實現。Apitest這個類必須繼承 neutron/api/extensions.py 這個檔案中的一個類:ExtensionDescriptor,不然過不了N版neutron程式碼neutron/api/extensions.py檔案中ExtensionManager類中_check_extension方法中return isinstance(extension, ExtensionDescriptor)驗證這關。
2.這個檔案到這就算寫完了,然後把檔案放到neutron/extensions/下,接下來去寫個操作neutron資料庫的py檔案,為restful介面用。
比如檔名為apitest_db.py,內容如下:
具體內容根據自己公司的業務邏輯來寫就好了,這個檔案寫好後放到neutron/db/下,下一步來配置下restful介面,在/etc/neutron/policy.json檔案里加入以下內容:
3.然後編輯neutron/plugins/ml2/plugin.py,新增from neutron.db import apitest_db,Ml2Plugin增加父類apitest_db.Apitest_db_mixin,Ml2Plugin的_supported_extension_aliases 屬性增加元素apitest。
如下圖:
token取到後就可以呼叫新新增的介面了:
5.如果需要修改neutron資料庫請看這篇文章點選開啟連結,這個問題到這就完成了。
二、再說說從K版遷移到N版的問題,我遇到的問題就兩點。
1. apitest.py檔案裡的class Apitest原先是繼承的object,在K版是可以的,但是在N版就必須繼承extensions.ExtensionDescriptor了,原因上文已經說明了。
2. apitest_db.py檔案中from oslo_utils import uuidutils程式碼是被替換後的程式碼,替換前為from neutron.openstack.common import uuidutils,這個也是在K版可以,在N版不行,這個問題原先的報錯只是這樣:ImportError: Plugin 'ml2' not found.
原先開發的內容是要實現虛實結合,即在程式碼層面實現物理機和虛擬機器通訊,大體思路就是增加neutron的extension來新增一個restful
介面,通過呼叫介面來控制SDN交換機與各個節點間建立vxlan的tunnel,然後用另一個微服務管理物理機的註冊和刪除等等步驟,下面
來記錄下怎樣寫extension和遷移的問題。
一、編寫neutron的extension
1.在neutron/extensions程式碼目錄下有許多neutron自帶的extension,可以借鑑這些entension來寫自己的extension,
比如在apitest.py中有如下程式碼:
from neutron.api import extensions from neutron.api.v2 import attributes as attr from neutron.api.v2 import base from neutron import manager # Attribute Map RESOURCE_NAME = 'apitest' RESOURCE_ATTRIBUTE_MAP = { RESOURCE_NAME + 's': { 'id': {'allow_post': False, 'allow_put': False, 'validate': {'type:uuid': None}, 'is_visible': True}, 'name': {'allow_post': True, 'allow_put': True, 'validate': {'type:string': None}, 'default': '', 'is_visible': True}, 'tenant_id': {'allow_post': True, 'allow_put': False, 'is_visible': False}, 'address': {'allow_post': True, 'allow_put': False, 'default': attr.ATTR_NOT_SPECIFIED, 'validate': {'type:ip_address_or_none': None}, 'is_visible': True} }, } class Apitest(extensions.ExtensionDescriptor): """Agent management extension.""" @classmethod def get_name(cls): return "apitest" @classmethod def get_alias(cls): return "apitest" @classmethod def get_description(cls): return "The centec switch extension." @classmethod def get_namespace(cls): return "http://docs.openstack.org/ext/agent/api/v2.0" @classmethod def get_updated(cls): return "2016-05-09T10:00:00-00:00" @classmethod def get_resources(cls): """Returns Ext Resources.""" my_plurals = [(key, key[:-1]) for key in RESOURCE_ATTRIBUTE_MAP.keys()] attr.PLURALS.update(dict(my_plurals)) plugin = manager.NeutronManager.get_plugin() params = RESOURCE_ATTRIBUTE_MAP.get(RESOURCE_NAME + 's') controller = base.create_resource(RESOURCE_NAME + 's', RESOURCE_NAME, plugin, params ) ex = extensions.ResourceExtension(RESOURCE_NAME + 's', controller) return [ex] def get_extended_resources(self, version): if version == "2.0": return RESOURCE_ATTRIBUTE_MAP else: return {}
在這段程式碼中主要就兩點:(1)RESOURCE_ATTRIBUTE_MAP字典是對新擴充套件的屬性的定義。字典第一層的key為RESOURCE_NAME + 's',其實就是檔名加上一個 ‘s'。第二層的 keys ’id‘, ’name‘, ’tenant_id‘ , ‘address’就是這個擴充套件的三個屬性。第三層的 keys 在 neutron/api/v2/attributes.py 中一百多行有比較詳細的解釋,大家可以多翻原始碼。
(2)Apitest類的名稱與包含這個類的檔名字母必須一樣,只是類名首字母大寫。具體原因可以參考 neutron/api/extensions.py 中 ExtensionManager 的_load_all_extensions_from_path 方法的實現。Apitest這個類必須繼承 neutron/api/extensions.py 這個檔案中的一個類:ExtensionDescriptor,不然過不了N版neutron程式碼neutron/api/extensions.py檔案中ExtensionManager類中_check_extension方法中return isinstance(extension, ExtensionDescriptor)驗證這關。
2.這個檔案到這就算寫完了,然後把檔案放到neutron/extensions/下,接下來去寫個操作neutron資料庫的py檔案,為restful介面用。
比如檔名為apitest_db.py,內容如下:
import sqlalchemy as sa from neutron import context as rpc_context from neutron.db import model_base from neutron.db import models_v2 from neutron.extensions import apitest as ext_sw from oslo_utils import uuidutils class Apitest(model_base.BASEV2, models_v2.HasId): name = sa.Column(sa.String(255)) address = sa.Column(sa.String(64)) tunnel_type = sa.Column(sa.String(32)) description = sa.Column(sa.String(255)) class Apitest_db_mixin(ext_sw.CentecSWBase): def __init__(self): pass def create_apitest(self, context, apitest): pass def tunnel_sync(self): pass
具體內容根據自己公司的業務邏輯來寫就好了,這個檔案寫好後放到neutron/db/下,下一步來配置下restful介面,在/etc/neutron/policy.json檔案里加入以下內容:
"update_apitest": "rule:admin_only",
"delete_apitest": "rule:admin_only",
"get_apitest": "rule:admin_only",
3.然後編輯neutron/plugins/ml2/plugin.py,新增from neutron.db import apitest_db,Ml2Plugin增加父類apitest_db.Apitest_db_mixin,Ml2Plugin的_supported_extension_aliases 屬性增加元素apitest。
4.最後重啟neutron-server就行了,因為我是用kolla部署的openstack單節點測試環境,所以直接重啟neutron-server的映象就行了,重啟前tail下日誌沒有報錯就可以訪問新加的restful介面了,介面名大家也看出來了,就是apitest,不過呼叫前先需要取下keystone的token
curl -X POST -d '{"auth": {"passwordCredentials": {"username": "admin", "password": "password"}, "tenantName": "admin"}}' -H "Content-type: application/json" http://127.0.0.1:5000/v2.0/tokens | python -m json.tool
如下圖:
token取到後就可以呼叫新新增的介面了:
curl "http://127.0.0.1:9696/v2.0/apitest" -H 'X-Auth-Token:9e1c09b8fd1d43d19465cfb45ebe999d' -H 'content-type:applicatin/json' -X POST -d '{"apitest":{"name":"sdn1_switch","address":"10.2.3.254","tunnel_type":"vxlan"}}'
5.如果需要修改neutron資料庫請看這篇文章點選開啟連結,這個問題到這就完成了。
二、再說說從K版遷移到N版的問題,我遇到的問題就兩點。
1. apitest.py檔案裡的class Apitest原先是繼承的object,在K版是可以的,但是在N版就必須繼承extensions.ExtensionDescriptor了,原因上文已經說明了。
2. apitest_db.py檔案中from oslo_utils import uuidutils程式碼是被替換後的程式碼,替換前為from neutron.openstack.common import uuidutils,這個也是在K版可以,在N版不行,這個問題原先的報錯只是這樣:ImportError: Plugin 'ml2' not found.
除錯了半天才知道真正的錯誤被多層的try except吃掉了,沒有打印出來,現在解決完畢!