Implementation of Tacker NFV MANO API
Introduce new Tacker REST API endpoints 'vnfd' and 'vnf' based on NFV MANO in 'vnfm' extension. Existing 'device' and'device_template' endpoints will be retained for backward compatibility. Change-Id: I9dffd4bee25b1f49aea7478f2bd779cf0f6dfb49 Implements: blueprint tacker-api-mano
This commit is contained in:
parent
2c4e277b9d
commit
f8bc9cc05c
@ -1,4 +1,4 @@
|
||||
[DEFAULT]
|
||||
test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 OS_LOG_CAPTURE=1 ${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./tacker/tests/unit} $LISTOPT $IDOPTION
|
||||
test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 OS_LOG_CAPTURE=1 ${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./tacker/tests/unit/vm} $LISTOPT $IDOPTION
|
||||
test_id_option=--load-list $IDFILE
|
||||
test_list_option=--list
|
||||
|
279
doc/source/devref/mano_api.rst
Normal file
279
doc/source/devref/mano_api.rst
Normal file
@ -0,0 +1,279 @@
|
||||
************************
|
||||
Tacker MANO API Overview
|
||||
************************
|
||||
|
||||
Tacker MANO API introduces new REST API end-points based on ETSI NFV MANO
|
||||
standards [1]. The two new resources introduced are 'vnfd' and 'vnf' for
|
||||
describing the 'vnfm' extension. The resources request and response formats are
|
||||
described in below sections.
|
||||
|
||||
API versions
|
||||
============
|
||||
|
||||
Lists information for Tacker API version.
|
||||
|
||||
**GET /**
|
||||
|
||||
List API versions - Lists information about all Networking API versions.
|
||||
|
||||
::
|
||||
|
||||
|
||||
Response:
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"status": "CURRENT",
|
||||
"id": "v1.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://10.18.160.13:8888/v1.0",
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Vnfds
|
||||
=====
|
||||
|
||||
**GET /v1.0/vnfds**
|
||||
|
||||
List vnfds - List vnfds stored in the VNF catalog.
|
||||
|
||||
::
|
||||
|
||||
Response:
|
||||
{
|
||||
"vnfds": [
|
||||
{
|
||||
"service_types": [
|
||||
{
|
||||
"service_type": "vnfd",
|
||||
"id": "378b774d-89f5-4634-9c65-9c49ed6f00ce"
|
||||
}
|
||||
],
|
||||
"description": "OpenWRT with services",
|
||||
"tenant_id": "4dd6c1d7b6c94af980ca886495bcfed0",
|
||||
"mgmt_driver": "openwrt",
|
||||
"infra_driver": "heat",
|
||||
"attributes": {
|
||||
"vnfd": "template_name: OpenWRT\r\ndescription:
|
||||
template_description <sample_vnfd_template>"
|
||||
},
|
||||
"id": "247b045e-d64f-4ae0-a3b4-8441b9e5892c",
|
||||
"name": "openwrt_services"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**GET /v1.0/vnfds/{vnfd_id}**
|
||||
|
||||
Show vnfd - Show information for a specified vnfd id.
|
||||
|
||||
::
|
||||
|
||||
Response:
|
||||
{
|
||||
"vnfd": {
|
||||
"service_types": [
|
||||
{
|
||||
"service_type": "vnfd",
|
||||
"id": "378b774d-89f5-4634-9c65-9c49ed6f00ce"
|
||||
}
|
||||
],
|
||||
"description": "OpenWRT with services",
|
||||
"tenant_id": "4dd6c1d7b6c94af980ca886495bcfed0",
|
||||
"mgmt_driver": "openwrt",
|
||||
"infra_driver": "heat",
|
||||
"attributes": {
|
||||
"vnfd": "template_name: OpenWRT\r\ndescription:
|
||||
template_description <sample_vnfd_template>"
|
||||
},
|
||||
"id": "247b045e-d64f-4ae0-a3b4-8441b9e5892c",
|
||||
"name": "openwrt_services"
|
||||
}
|
||||
}
|
||||
|
||||
**POST /v1.0/vnfds**
|
||||
|
||||
Create vnfd - Create a vnfd entry based on the vnfd template.
|
||||
|
||||
::
|
||||
|
||||
Request:
|
||||
{"auth": {"tenantName": "admin", "passwordCredentials": {"username": "admin",
|
||||
"password": "devstack"}}, "vnfd": {"attributes": {"vnfd": "template_name:
|
||||
OpenWRT \r\ndescription: OpenWRT router\r\n\r\nservice_properties:\r\n Id:
|
||||
sample-vnfd\r\n vendor: tacker\r\n version: 1\r\n\r\nvdus:\r\n vdu1:\r\n
|
||||
id: vdu1\r\n vm_image: cirros-0.3.2-x86_64-uec\r\n instance_type:
|
||||
m1.tiny\r\n\r\n network_interfaces:\r\n management:\r\n network:
|
||||
net_mgmt\r\n management: true\r\n pkt_in:\r\n network:
|
||||
net0\r\n pkt_out:\r\n network: net1\r\n\r\n placement_policy:
|
||||
\r\n availability_zone: nova\r\n\r\n auto-scaling: noop\r\n
|
||||
monitoring_policy: noop\r\n failure_policy: noop\r\n\r\n config:\r\n
|
||||
param0: key0\r\n param1: key1"}, "service_types": [{"service_type":
|
||||
"vnfd"}], "mgmt_driver": "noop", "infra_driver": "heat"}}
|
||||
|
||||
::
|
||||
|
||||
Response:
|
||||
{
|
||||
"vnfd": {
|
||||
"service_types": [
|
||||
{
|
||||
"service_type": "vnfd",
|
||||
"id": "336fe422-9fba-47c7-87fb-d48475c3e0ce"
|
||||
}
|
||||
],
|
||||
"description": "OpenWRT router",
|
||||
"tenant_id": "4dd6c1d7b6c94af980ca886495bcfed0",
|
||||
"mgmt_driver": "noop",
|
||||
"infra_driver": "heat",
|
||||
"attributes": {
|
||||
"vnfd": "template_name: OpenWRT \r\ndescription:
|
||||
template_description <sample_vnfd_template>"
|
||||
},
|
||||
"id": "ab10a543-22ee-43af-a441-05a9d32a57da",
|
||||
"name": "OpenWRT"
|
||||
}
|
||||
}
|
||||
|
||||
**DELETE /v1.0/vnfds/{vnfd_id}**
|
||||
|
||||
Delete vnfd - Deletes a specified vnfd_id from the VNF catalog.
|
||||
|
||||
This operation does not accept a request body and does not return a response
|
||||
body.
|
||||
|
||||
Vnfs
|
||||
====
|
||||
|
||||
**GET /v1.0/vnfs**
|
||||
|
||||
List vnfs - Lists instantiated vnfs in VNF Manager
|
||||
|
||||
::
|
||||
|
||||
Response:
|
||||
{
|
||||
"vnfs": [
|
||||
{
|
||||
"status": "ACTIVE",
|
||||
"name": "open_wrt",
|
||||
"tenant_id": "4dd6c1d7b6c94af980ca886495bcfed0",
|
||||
"instance_id": "f7c93726-fb8d-4036-8349-2e82f196e8f6",
|
||||
"mgmt_url": "{\"vdu1\": \"192.168.120.3\"}",
|
||||
"attributes": {
|
||||
"service_type": "firewall",
|
||||
"param_values": "",
|
||||
"heat_template": "description: sample_template_description
|
||||
type: OS::Nova::Server\n",
|
||||
"monitoring_policy": "noop",
|
||||
"failure_policy": "noop"
|
||||
},
|
||||
"id": "c9b4f5a5-d304-473a-a57e-b665b1f9eb8f",
|
||||
"description": "OpenWRT with services"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**GET /v1.0/vnfs/{vnf_id}**
|
||||
|
||||
Show vnf - Show information for a specified vnf_id.
|
||||
|
||||
::
|
||||
|
||||
Response:
|
||||
{
|
||||
"vnf": [
|
||||
{
|
||||
"status": "ACTIVE",
|
||||
"name": "open_wrt",
|
||||
"tenant_id": "4dd6c1d7b6c94af980ca886495bcfed0",
|
||||
"instance_id": "f7c93726-fb8d-4036-8349-2e82f196e8f6",
|
||||
"mgmt_url": "{\"vdu1\": \"192.168.120.3\"}",
|
||||
"attributes": {
|
||||
"service_type": "firewall",
|
||||
"param_values": "",
|
||||
"heat_template": "description: OpenWRT with services\n
|
||||
sample_template_description type: OS::Nova::Server\n",
|
||||
"monitoring_policy": "noop", "failure_policy": "noop"
|
||||
},
|
||||
"id": "c9b4f5a5-d304-473a-a57e-b665b1f9eb8f",
|
||||
"description": "OpenWRT with services"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**POST /v1.0/vnfs**
|
||||
|
||||
Create vnf - Create a vnf based on the vnfd template id.
|
||||
|
||||
::
|
||||
|
||||
Request:
|
||||
{"auth": {"tenantName": "admin", "passwordCredentials": {"username": "admin",
|
||||
"password": "devstack"}}, "vnf":
|
||||
{"vnfd_id": "d770ddd7-6014-4191-92d8-a2cd7a6cecd8"}}
|
||||
|
||||
::
|
||||
|
||||
Response:
|
||||
{
|
||||
"vnf": {
|
||||
"status": "PENDING_CREATE",
|
||||
"name": "",
|
||||
"tenant_id": "4dd6c1d7b6c94af980ca886495bcfed0",
|
||||
"description": "OpenWRT with services",
|
||||
"instance_id": "4f0d6222-afa0-4f02-8e19-69e7e4fd7edc",
|
||||
"mgmt_url": null,
|
||||
"attributes": {
|
||||
"service_type": "firewall",
|
||||
"heat_template": "description: OpenWRT with services\n
|
||||
<sample_heat_template> type: OS::Nova::Server\n",
|
||||
"monitoring_policy": "noop",
|
||||
"failure_policy": "noop"
|
||||
},
|
||||
"id": "e3158513-92f4-4587-b949-70ad0bcbb2dd",
|
||||
"vnfd_id": "247b045e-d64f-4ae0-a3b4-8441b9e5892c"
|
||||
}
|
||||
}
|
||||
|
||||
**PUT /v1.0/vnfs/{vnf_id}**
|
||||
|
||||
Update vnf - Update a vnf based on user config file or data.
|
||||
|
||||
::
|
||||
|
||||
Request:
|
||||
{"auth": {"tenantName": "admin", "passwordCredentials": {"username": "admin",
|
||||
"password": "devstack"}}, "vnf": {"attributes": {"config": "vdus:\n vdu1:
|
||||
<sample_vdu_config> \n\n"}}}
|
||||
|
||||
::
|
||||
|
||||
Response:
|
||||
{
|
||||
"vnf": {
|
||||
"status": "PENDING_UPDATE",
|
||||
"name": "",
|
||||
"tenant_id": "4dd6c1d7b6c94af980ca886495bcfed0",
|
||||
"instance_id": "4f0d6222-afa0-4f02-8e19-69e7e4fd7edc",
|
||||
"mgmt_url": "{\"vdu1\": \"192.168.120.4\"}",
|
||||
"attributes": {
|
||||
"service_type": "firewall",
|
||||
"monitoring_policy": "noop",
|
||||
"config": "vdus:\n vdu1:\n config: {<sample_vdu_config>
|
||||
type: OS::Nova::Server\n",
|
||||
"failure_policy": "noop"
|
||||
},
|
||||
"id": "e3158513-92f4-4587-b949-70ad0bcbb2dd",
|
||||
"description": "OpenWRT with services"
|
||||
}
|
||||
}
|
||||
|
||||
**DELETE /v1.0/vnfs/{vnf_id}**
|
||||
|
||||
Delete vnf - Deletes a specified vnf_id from the VNF list.
|
@ -61,7 +61,7 @@ lock_path = $state_path/lock
|
||||
#
|
||||
# service_plugins =
|
||||
# Example: service_plugins = router,firewall,lbaas,vpnaas,metering
|
||||
service_plugins = tacker.vm.plugin.ServiceVMPlugin
|
||||
service_plugins = tacker.vm.plugin.VNFMPlugin
|
||||
|
||||
# Paste configuration file
|
||||
# api_paste_config = api-paste.ini
|
||||
|
@ -18,6 +18,7 @@ netaddr>=0.7.12
|
||||
#python-tackerclient>=2.3.4,<3
|
||||
SQLAlchemy<1.1.0,>=0.9.7
|
||||
WebOb>=1.2.3
|
||||
python-heatclient>=0.3.0
|
||||
python-keystoneclient>=1.1.0
|
||||
alembic>=0.7.2
|
||||
six>=1.9.0
|
||||
|
@ -43,7 +43,7 @@ console_scripts =
|
||||
tacker-rootwrap = oslo.rootwrap.cmd:main
|
||||
tacker.service_plugins =
|
||||
dummy = tacker.tests.unit.dummy_plugin:DummyServicePlugin
|
||||
servicevm = tacker.vm.plugin.ServiceVMPlugin
|
||||
vnfm = tacker.vm.plugin:VNFMPlugin
|
||||
tacker.openstack.common.cache.backends =
|
||||
memory = tacker.openstack.common.cache._backends.memory:MemoryBackend
|
||||
tacker.servicevm.device.drivers =
|
||||
|
@ -40,6 +40,8 @@ core_opts = [
|
||||
help=_("The API paste config file to use")),
|
||||
cfg.StrOpt('api_extensions_path', default="",
|
||||
help=_("The path for API extensions")),
|
||||
cfg.ListOpt('service_plugins', default=[],
|
||||
help=_("The service plugins Tacker will use")),
|
||||
cfg.StrOpt('policy_file', default="policy.json",
|
||||
help=_("The policy file to use")),
|
||||
cfg.StrOpt('auth_strategy', default='keystone',
|
||||
|
@ -32,7 +32,7 @@ from tacker.db import api as qdbapi
|
||||
from tacker.db import db_base
|
||||
from tacker.db import model_base
|
||||
from tacker.db import models_v1
|
||||
from tacker.extensions import servicevm
|
||||
from tacker.extensions import vnfm
|
||||
from tacker import manager
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common import uuidutils
|
||||
@ -265,8 +265,7 @@ class ServiceContextEntry(dict):
|
||||
})
|
||||
|
||||
|
||||
class ServiceResourcePluginDb(servicevm.ServiceVMPluginBase,
|
||||
db_base.CommonDbMixin):
|
||||
class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
||||
|
||||
@property
|
||||
def _core_plugin(self):
|
||||
@ -278,20 +277,20 @@ class ServiceResourcePluginDb(servicevm.ServiceVMPluginBase,
|
||||
|
||||
def __init__(self):
|
||||
qdbapi.register_models()
|
||||
super(ServiceResourcePluginDb, self).__init__()
|
||||
super(VNFMPluginDb, self).__init__()
|
||||
|
||||
def _get_resource(self, context, model, id):
|
||||
try:
|
||||
return self._get_by_id(context, model, id)
|
||||
except orm_exc.NoResultFound:
|
||||
if issubclass(model, DeviceTemplate):
|
||||
raise servicevm.DeviceTemplateNotFound(device_tempalte_id=id)
|
||||
raise vnfm.DeviceTemplateNotFound(device_tempalte_id=id)
|
||||
elif issubclass(model, ServiceType):
|
||||
raise servicevm.ServiceTypeNotFound(service_type_id=id)
|
||||
raise vnfm.ServiceTypeNotFound(service_type_id=id)
|
||||
elif issubclass(model, ServiceInstance):
|
||||
raise servicevm.ServiceInstanceNotFound(service_instance_id=id)
|
||||
raise vnfm.ServiceInstanceNotFound(service_instance_id=id)
|
||||
if issubclass(model, Device):
|
||||
raise servicevm.DeviceNotFound(device_id=id)
|
||||
raise vnfm.DeviceNotFound(device_id=id)
|
||||
else:
|
||||
raise
|
||||
|
||||
@ -390,13 +389,13 @@ class ServiceResourcePluginDb(servicevm.ServiceVMPluginBase,
|
||||
|
||||
if (not attributes.is_attr_set(infra_driver)):
|
||||
LOG.debug(_('hosting device driver unspecified'))
|
||||
raise servicevm.InfraDriverNotSpecified()
|
||||
raise vnfm.InfraDriverNotSpecified()
|
||||
if (not attributes.is_attr_set(mgmt_driver)):
|
||||
LOG.debug(_('mgmt driver unspecified'))
|
||||
raise servicevm.MGMTDriverNotSpecified()
|
||||
raise vnfm.MGMTDriverNotSpecified()
|
||||
if (not attributes.is_attr_set(service_types)):
|
||||
LOG.debug(_('service types unspecified'))
|
||||
raise servicevm.SeviceTypesNotSpecified()
|
||||
raise vnfm.SeviceTypesNotSpecified()
|
||||
|
||||
with context.session.begin(subtransactions=True):
|
||||
template_id = str(uuid.uuid4())
|
||||
@ -444,7 +443,7 @@ class ServiceResourcePluginDb(servicevm.ServiceVMPluginBase,
|
||||
devices_db = context.session.query(Device).filter_by(
|
||||
template_id=device_template_id).first()
|
||||
if devices_db is not None:
|
||||
raise servicevm.DeviceTemplateInUse(
|
||||
raise vnfm.DeviceTemplateInUse(
|
||||
device_template_id=device_template_id)
|
||||
|
||||
context.session.query(ServiceType).filter_by(
|
||||
@ -597,9 +596,9 @@ class ServiceResourcePluginDb(servicevm.ServiceVMPluginBase,
|
||||
filter(Device.status.in_(current_statuses)).
|
||||
with_lockmode('update').one())
|
||||
except orm_exc.NoResultFound:
|
||||
raise servicevm.DeviceNotFound(device_id=device_id)
|
||||
raise vnfm.DeviceNotFound(device_id=device_id)
|
||||
if device_db.status == constants.PENDING_UPDATE:
|
||||
raise servicevm.DeviceInUse(device_id=device_id)
|
||||
raise vnfm.DeviceInUse(device_id=device_id)
|
||||
device_db.update({'status': new_status})
|
||||
return device_db
|
||||
|
||||
@ -633,7 +632,7 @@ class ServiceResourcePluginDb(servicevm.ServiceVMPluginBase,
|
||||
binding_db = (context.session.query(ServiceDeviceBinding).
|
||||
filter_by(device_id=device_id).first())
|
||||
if binding_db is not None:
|
||||
raise servicevm.DeviceInUse(device_id=device_id)
|
||||
raise vnfm.DeviceInUse(device_id=device_id)
|
||||
device_db = self._get_device_db(
|
||||
context, device_id, _ACTIVE_UPDATE_ERROR_DEAD,
|
||||
constants.PENDING_DELETE)
|
||||
@ -851,7 +850,7 @@ class ServiceResourcePluginDb(servicevm.ServiceVMPluginBase,
|
||||
with_lockmode('update').one())
|
||||
|
||||
if service_instance.managed_by_user != managed_by_user:
|
||||
raise servicevm.ServiceInstanceNotManagedByUser(
|
||||
raise vnfm.ServiceInstanceNotManagedByUser(
|
||||
service_instance_id=service_instance_id)
|
||||
|
||||
service_instance.status = constants.PENDING_DELETE
|
||||
@ -864,7 +863,7 @@ class ServiceResourcePluginDb(servicevm.ServiceVMPluginBase,
|
||||
assert binding_db
|
||||
# check only. _post method will delete it.
|
||||
if len(binding_db) > 1:
|
||||
raise servicevm.ServiceInstanceInUse(
|
||||
raise vnfm.ServiceInstanceInUse(
|
||||
service_instance_id=service_instance_id)
|
||||
|
||||
def _delete_service_instance_post(self, context, service_instance_id):
|
||||
@ -930,3 +929,18 @@ class ServiceResourcePluginDb(servicevm.ServiceVMPluginBase,
|
||||
return self._get_collection(
|
||||
context, ServiceInstance, self._make_service_instance_dict,
|
||||
filters=filters, fields=fields)
|
||||
|
||||
def get_vnfs(self, context, filters=None, fields=None):
|
||||
return self.get_devices(context, filters, fields)
|
||||
|
||||
def get_vnf(self, context, vnf_id, fields=None):
|
||||
return self.get_device(context, vnf_id, fields)
|
||||
|
||||
def delete_vnfd(self, context, vnfd_id):
|
||||
self.delete_device_template(context, vnfd_id)
|
||||
|
||||
def get_vnfd(self, context, vnfd_id, fields=None):
|
||||
return self.get_device_template(context, vnfd_id, fields)
|
||||
|
||||
def get_vnfds(self, context, filters=None, fields=None):
|
||||
return self.get_device_templates(context, filters, fields)
|
@ -1,11 +1,6 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
#
|
||||
# Copyright 2013, 2014 Intel Corporation.
|
||||
# Copyright 2013, 2014 Isaku Yamahata <isaku.yamahata at intel com>
|
||||
# <isaku.yamahata at gmail com>
|
||||
# Copyright 2015 Intel Corporation..
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
@ -17,8 +12,6 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# @author: Isaku Yamahata, Intel Corporation.
|
||||
|
||||
import abc
|
||||
|
||||
@ -30,7 +23,7 @@ from tacker.api.v1 import resource_helper
|
||||
from tacker.common import exceptions
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.plugins.common import constants
|
||||
from tacker.services.service_base import ServicePluginBase
|
||||
from tacker.services.service_base import NFVPluginBase
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -163,9 +156,137 @@ def _validate_service_context_list(data, valid_values=None):
|
||||
attr.validators['type:service_type_list'] = _validate_service_type_list
|
||||
attr.validators['type:service_context_list'] = _validate_service_context_list
|
||||
|
||||
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
|
||||
'vnfds': {
|
||||
'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': None},
|
||||
'required_by_policy': True,
|
||||
'is_visible': True,
|
||||
},
|
||||
'name': {
|
||||
'allow_post': True,
|
||||
'allow_put': True,
|
||||
'validate': {'type:string': None},
|
||||
'is_visible': True,
|
||||
'default': '',
|
||||
},
|
||||
'description': {
|
||||
'allow_post': True,
|
||||
'allow_put': True,
|
||||
'validate': {'type:string': None},
|
||||
'is_visible': True,
|
||||
'default': '',
|
||||
},
|
||||
'service_types': {
|
||||
'allow_post': True,
|
||||
'allow_put': False,
|
||||
'convert_to': attr.convert_to_list,
|
||||
'validate': {'type:service_type_list': None},
|
||||
'is_visible': True,
|
||||
'default': attr.ATTR_NOT_SPECIFIED,
|
||||
},
|
||||
'infra_driver': {
|
||||
'allow_post': True,
|
||||
'allow_put': False,
|
||||
'validate': {'type:string': None},
|
||||
'is_visible': True,
|
||||
'default': attr.ATTR_NOT_SPECIFIED,
|
||||
},
|
||||
'mgmt_driver': {
|
||||
'allow_post': True,
|
||||
'allow_put': False,
|
||||
'validate': {'type:string': None},
|
||||
'is_visible': True,
|
||||
'default': attr.ATTR_NOT_SPECIFIED,
|
||||
},
|
||||
'attributes': {
|
||||
'allow_post': True,
|
||||
'allow_put': False,
|
||||
'convert_to': attr.convert_none_to_empty_dict,
|
||||
'validate': {'type:dict_or_nodata': None},
|
||||
'is_visible': True,
|
||||
'default': None,
|
||||
},
|
||||
},
|
||||
|
||||
'vnfs': {
|
||||
'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': None},
|
||||
'required_by_policy': True,
|
||||
'is_visible': True
|
||||
},
|
||||
'vnfd_id': {
|
||||
'allow_post': True,
|
||||
'allow_put': False,
|
||||
'validate': {'type:uuid': None},
|
||||
'is_visible': True,
|
||||
},
|
||||
'name': {
|
||||
'allow_post': True,
|
||||
'allow_put': True,
|
||||
'validate': {'type:string': None},
|
||||
'is_visible': True,
|
||||
'default': '',
|
||||
},
|
||||
'description': {
|
||||
'allow_post': True,
|
||||
'allow_put': True,
|
||||
'validate': {'type:string': None},
|
||||
'is_visible': True,
|
||||
'default': '',
|
||||
},
|
||||
'instance_id': {
|
||||
'allow_post': False,
|
||||
'allow_put': False,
|
||||
'validate': {'type:string': None},
|
||||
'is_visible': True,
|
||||
},
|
||||
'mgmt_url': {
|
||||
'allow_post': False,
|
||||
'allow_put': False,
|
||||
'validate': {'type:string': None},
|
||||
'is_visible': True,
|
||||
},
|
||||
'attributes': {
|
||||
'allow_post': True,
|
||||
'allow_put': True,
|
||||
'validate': {'type:dict_or_none': None},
|
||||
'is_visible': True,
|
||||
'default': {},
|
||||
},
|
||||
'service_contexts': {
|
||||
'allow_post': True,
|
||||
'allow_put': False,
|
||||
'validate': {'type:service_context_list': None},
|
||||
'is_visible': True,
|
||||
'default': [],
|
||||
},
|
||||
'status': {
|
||||
'allow_post': False,
|
||||
'allow_put': False,
|
||||
'is_visible': True,
|
||||
},
|
||||
},
|
||||
|
||||
'device_templates': {
|
||||
'id': {
|
||||
'allow_post': False,
|
||||
@ -288,109 +409,31 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
'is_visible': True,
|
||||
'default': [],
|
||||
},
|
||||
'services': {
|
||||
'allow_post': False,
|
||||
'allow_put': False,
|
||||
'validate': {'type:uuid': None},
|
||||
'is_visible': True,
|
||||
},
|
||||
'status': {
|
||||
'allow_post': False,
|
||||
'allow_put': False,
|
||||
'is_visible': True,
|
||||
},
|
||||
},
|
||||
|
||||
# 'service_instances': {
|
||||
# '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': None},
|
||||
# 'required_by_policy': True,
|
||||
# 'is_visible': True
|
||||
# },
|
||||
# 'name': {
|
||||
# 'allow_post': True,
|
||||
# 'allow_put': True,
|
||||
# 'validate': {'type:string': None},
|
||||
# 'is_visible': True,
|
||||
# },
|
||||
# 'service_type_id': {
|
||||
# 'allow_post': True,
|
||||
# 'allow_put': False,
|
||||
# 'validate': {'type:uuid': None},
|
||||
# 'is_visible': True,
|
||||
# },
|
||||
# 'service_table_id': {
|
||||
# 'allow_post': True,
|
||||
# 'allow_put': False,
|
||||
# 'validate': {'type:string': None},
|
||||
# 'is_visible': True,
|
||||
# },
|
||||
# 'mgmt_driver': {
|
||||
# 'allow_post': True,
|
||||
# 'allow_put': False,
|
||||
# 'validate': {'type:string': None},
|
||||
# 'is_visible': True,
|
||||
# },
|
||||
# 'mgmt_url': {
|
||||
# 'allow_post': True,
|
||||
# 'allow_put': False,
|
||||
# 'validate': {'type:string': None},
|
||||
# 'is_visible': True,
|
||||
# },
|
||||
# 'service_contexts': {
|
||||
# 'allow_post': True,
|
||||
# 'allow_put': False,
|
||||
# 'validate': {'type:service_context_list': None},
|
||||
# 'is_visible': True,
|
||||
# },
|
||||
# 'devices': {
|
||||
# 'allow_post': True,
|
||||
# 'allow_put': False,
|
||||
# 'validate': {'type:uuid_list': None},
|
||||
# 'convert_to': attr.convert_to_list,
|
||||
# 'is_visible': True,
|
||||
# },
|
||||
# 'status': {
|
||||
# 'allow_post': False,
|
||||
# 'allow_put': False,
|
||||
# 'is_visible': True,
|
||||
# },
|
||||
# 'kwargs': {
|
||||
# 'allow_post': True,
|
||||
# 'allow_put': True,
|
||||
# 'validate': {'type:dict_or_none': None},
|
||||
# 'is_visible': True,
|
||||
# 'default': {},
|
||||
# },
|
||||
# },
|
||||
}
|
||||
|
||||
|
||||
class Servicevm(extensions.ExtensionDescriptor):
|
||||
class Vnfm(extensions.ExtensionDescriptor):
|
||||
@classmethod
|
||||
def get_name(cls):
|
||||
return 'Service VM'
|
||||
return 'VNFM'
|
||||
|
||||
@classmethod
|
||||
def get_alias(cls):
|
||||
return 'servicevm'
|
||||
return 'VNF Manager'
|
||||
|
||||
@classmethod
|
||||
def get_description(cls):
|
||||
return "Extension for ServiceVM service"
|
||||
return "Extension for VNF Manager"
|
||||
|
||||
@classmethod
|
||||
def get_namespace(cls):
|
||||
return 'http://wiki.openstack.org/Tacker/ServiceVM'
|
||||
return 'http://wiki.openstack.org/Tacker'
|
||||
|
||||
@classmethod
|
||||
def get_updated(cls):
|
||||
@ -401,23 +444,19 @@ class Servicevm(extensions.ExtensionDescriptor):
|
||||
special_mappings = {}
|
||||
plural_mappings = resource_helper.build_plural_mappings(
|
||||
special_mappings, RESOURCE_ATTRIBUTE_MAP)
|
||||
plural_mappings['devices'] = 'device'
|
||||
plural_mappings['service_types'] = 'service_type'
|
||||
plural_mappings['service_contexts'] = 'service_context'
|
||||
plural_mappings['services'] = 'service'
|
||||
attr.PLURALS.update(plural_mappings)
|
||||
action_map = {'device': {'attach_interface': 'PUT',
|
||||
'detach_interface': 'PUT'}}
|
||||
return resource_helper.build_resource_info(
|
||||
plural_mappings, RESOURCE_ATTRIBUTE_MAP, constants.SERVICEVM,
|
||||
translate_name=True, action_map=action_map)
|
||||
plural_mappings, RESOURCE_ATTRIBUTE_MAP, constants.VNFM,
|
||||
translate_name=True)
|
||||
|
||||
@classmethod
|
||||
def get_plugin_interface(cls):
|
||||
return ServiceVMPluginBase
|
||||
return VNFMPluginBase
|
||||
|
||||
def update_attributes_map(self, attributes):
|
||||
super(Servicevm, self).update_attributes_map(
|
||||
super(Vnfm, self).update_attributes_map(
|
||||
attributes, extension_attrs_map=RESOURCE_ATTRIBUTE_MAP)
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
@ -426,16 +465,52 @@ class Servicevm(extensions.ExtensionDescriptor):
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class ServiceVMPluginBase(ServicePluginBase):
|
||||
|
||||
class VNFMPluginBase(NFVPluginBase):
|
||||
def get_plugin_name(self):
|
||||
return constants.SERVICEVM
|
||||
return constants.VNFM
|
||||
|
||||
def get_plugin_type(self):
|
||||
return constants.SERVICEVM
|
||||
return constants.VNFM
|
||||
|
||||
def get_plugin_description(self):
|
||||
return 'Service VM plugin'
|
||||
return 'Tacker VNF Manager plugin'
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_vnfd(self, context, vnfd):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def delete_vnfd(self, context, vnfd_id):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_vnfd(self, context, vnfd_id, fields=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_vnfds(self, context, filters=None, fields=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_vnfs(self, context, filters=None, fields=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_vnf(self, context, vnf_id, fields=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_vnf(self, context, vnf):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def update_vnf(
|
||||
self, context, vnf_id, vnf):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def delete_vnf(self, context, vnf_id):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_device_template(self, context, device_template):
|
||||
@ -473,24 +548,3 @@ class ServiceVMPluginBase(ServicePluginBase):
|
||||
@abc.abstractmethod
|
||||
def delete_device(self, context, device_id):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def attach_interface(self, context, id, port_id):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def detach_interface(self, contexct, id, port_id):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_service_instances(self, context, filters=None, fields=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_service_instance(self, context, service_instance_id, fields=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def update_service_instance(self, context, service_instance_id,
|
||||
service_instance):
|
||||
pass
|
@ -107,8 +107,7 @@ class TackerManager(object):
|
||||
Starts from the core plugin and checks if it supports
|
||||
advanced services then loads classes provided in configuration.
|
||||
"""
|
||||
# plugin_providers = cfg.CONF.service_plugins
|
||||
plugin_providers = ['tacker.vm.plugin.ServiceVMPlugin']
|
||||
plugin_providers = cfg.CONF.service_plugins
|
||||
LOG.debug(_("Loading service plugins: %s"), plugin_providers)
|
||||
for provider in plugin_providers:
|
||||
if provider == '':
|
||||
|
@ -18,18 +18,12 @@
|
||||
# service type constants:
|
||||
CORE = "CORE"
|
||||
DUMMY = "DUMMY"
|
||||
SERVICEVM = "SERVICEVM"
|
||||
|
||||
#maps extension alias to service type
|
||||
EXT_TO_SERVICE_MAPPING = {
|
||||
'dummy': DUMMY,
|
||||
'servicevm': SERVICEVM,
|
||||
}
|
||||
VNFM = "VNFM"
|
||||
|
||||
COMMON_PREFIXES = {
|
||||
CORE: "",
|
||||
DUMMY: "/dummy_svc",
|
||||
SERVICEVM: "",
|
||||
VNFM: "",
|
||||
}
|
||||
|
||||
# Service operation status constants
|
||||
|
@ -27,7 +27,7 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class ServicePluginBase(extensions.PluginInterface):
|
||||
class NFVPluginBase(extensions.PluginInterface):
|
||||
"""Define base interface for any Advanced Service plugin."""
|
||||
supported_extension_aliases = []
|
||||
|
||||
|
@ -30,7 +30,7 @@ class VnfTestJSON(base.BaseTackerTest):
|
||||
toscal_str = open(yaml_file).read()
|
||||
data['tosca'] = toscal_str
|
||||
toscal = data['tosca']
|
||||
tosca_arg = {'vnfd': {'vnfd': toscal}}
|
||||
tosca_arg = {'vnfd': {'attributes': {'vnfd': toscal}}}
|
||||
vnfd_instance = self.client.create_vnfd(body=tosca_arg)
|
||||
self.assertIsNotNone(vnfd_instance)
|
||||
|
||||
|
49
tacker/tests/unit/db/base.py
Normal file
49
tacker/tests/unit/db/base.py
Normal file
@ -0,0 +1,49 @@
|
||||
# Copyright 2015 Brocade Communications System, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import fixtures
|
||||
import testtools
|
||||
|
||||
from tacker.db import api as db_api
|
||||
from tacker.db import model_base
|
||||
|
||||
|
||||
class SqlFixture(fixtures.Fixture):
|
||||
|
||||
# flag to indicate that the models have been loaded
|
||||
_TABLES_ESTABLISHED = False
|
||||
|
||||
def setUp(self):
|
||||
super(SqlFixture, self).setUp()
|
||||
# Register all data models
|
||||
engine = db_api.get_engine()
|
||||
if not SqlFixture._TABLES_ESTABLISHED:
|
||||
model_base.BASE.metadata.create_all(engine)
|
||||
SqlFixture._TABLES_ESTABLISHED = True
|
||||
|
||||
def clear_tables():
|
||||
with engine.begin() as conn:
|
||||
for table in reversed(
|
||||
model_base.BASE.metadata.sorted_tables):
|
||||
conn.execute(table.delete())
|
||||
|
||||
self.addCleanup(clear_tables)
|
||||
|
||||
|
||||
class SqlTestCase(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(SqlTestCase, self).setUp()
|
||||
self.useFixture(SqlFixture())
|
60
tacker/tests/unit/db/utils.py
Normal file
60
tacker/tests/unit/db/utils.py
Normal file
@ -0,0 +1,60 @@
|
||||
# Copyright 2015 Brocade Communications System, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
def get_dummy_vnfd_obj():
|
||||
return {u'vnfd': {u'service_types': [{u'service_type': u'vnfd'}],
|
||||
'name': 'dummy_vnfd', 'tenant_id':
|
||||
u'ad7ebc56538745a08ef7c5e97f8bd437', u'mgmt_driver': u'noop',
|
||||
u'infra_driver': u'fake_driver', u'attributes': {u'vnfd':
|
||||
u'template_name: OpenWRT'
|
||||
u' \r\ndescription: OpenWRT router'
|
||||
u'\r\n\r\nservice_properties:\r\n'
|
||||
u' Id: sample-vnfd\r\n vendor:'
|
||||
u' tacker\r\n version: '
|
||||
u'1\r\n\r\nvdus:'
|
||||
u'\r\n vdu1:\r\n id: vdu1\r\n'
|
||||
u' vm_image:'
|
||||
u' cirros-0.3.2-x86_64-uec\r\n'
|
||||
u' instance_type: m1.tiny\r\n\r\n'
|
||||
u' network_interfaces:\r\n'
|
||||
u' management:\r\n'
|
||||
u' network: net_mgmt\r\n'
|
||||
u' management: true\r\n'
|
||||
u' pkt_in:\r\n network:'
|
||||
u' net0\r\n pkt_out:\r\n'
|
||||
u' network: net1\r\n\r\n'
|
||||
u' placement_policy:\r\n'
|
||||
u' availability_zone: nova\r\n'
|
||||
u'\r'
|
||||
u'\n auto-scaling: noop\r\n'
|
||||
u' monitoring_policy: noop\r\n'
|
||||
u' failure_policy: noop\r\n\r\n'
|
||||
u' config:\r\n param0: key0'
|
||||
u'\r\n param1: key1'},
|
||||
'description': 'dummy_vnfd_description'},
|
||||
u'auth': {u'tenantName': u'admin', u'passwordCredentials': {
|
||||
u'username': u'admin', u'password': u'devstack'}}}
|
||||
|
||||
|
||||
def get_dummy_vnf_obj():
|
||||
return {'vnf': {'description': 'dummy_vnf_description', 'tenant_id':
|
||||
u'ad7ebc56538745a08ef7c5e97f8bd437', 'name': 'dummy_vnf',
|
||||
'service_contexts': [], 'attributes': {}}}
|
||||
|
||||
|
||||
def get_dummy_vnf_config_obj():
|
||||
return {'vnf': {u'attributes': {u'config': {'vdus': {'vdu1': {
|
||||
'config': {'firewall': 'dummy_firewall_values'}}}}}}}
|
0
tacker/tests/unit/vm/__init__.py
Normal file
0
tacker/tests/unit/vm/__init__.py
Normal file
162
tacker/tests/unit/vm/test_plugin.py
Normal file
162
tacker/tests/unit/vm/test_plugin.py
Normal file
@ -0,0 +1,162 @@
|
||||
# Copyright 2015 Brocade Communications System, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
import uuid
|
||||
|
||||
from tacker import context
|
||||
from tacker.db.vm import vm_db
|
||||
from tacker.tests.unit.db import base as db_base
|
||||
from tacker.tests.unit.db import utils
|
||||
from tacker.vm import plugin
|
||||
|
||||
|
||||
class FakeDriverManager(mock.Mock):
|
||||
def invoke(self, *args, **kwargs):
|
||||
if 'create' in args:
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
class FakeDeviceStatus(mock.Mock):
|
||||
pass
|
||||
|
||||
|
||||
class FakeGreenPool(mock.Mock):
|
||||
pass
|
||||
|
||||
|
||||
class TestVNFMPlugin(db_base.SqlTestCase):
|
||||
def setUp(self):
|
||||
super(TestVNFMPlugin, self).setUp()
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
self.context = context.get_admin_context()
|
||||
self._mock_device_manager()
|
||||
self._mock_device_status()
|
||||
self._mock_green_pool()
|
||||
self.vnfm_plugin = plugin.VNFMPlugin()
|
||||
|
||||
def _mock_device_manager(self):
|
||||
self._device_manager = mock.Mock(wraps=FakeDriverManager())
|
||||
self._device_manager.__contains__ = mock.Mock(
|
||||
return_value=True)
|
||||
fake_device_manager = mock.Mock()
|
||||
fake_device_manager.return_value = self._device_manager
|
||||
self._mock(
|
||||
'tacker.common.driver_manager.DriverManager', fake_device_manager)
|
||||
|
||||
def _mock_device_status(self):
|
||||
self._device_status = mock.Mock(wraps=FakeDeviceStatus())
|
||||
fake_device_status = mock.Mock()
|
||||
fake_device_status.return_value = self._device_status
|
||||
self._mock(
|
||||
'tacker.vm.monitor.DeviceStatus', fake_device_status)
|
||||
|
||||
def _mock_green_pool(self):
|
||||
self._pool = mock.Mock(wraps=FakeGreenPool())
|
||||
fake_green_pool = mock.Mock()
|
||||
fake_green_pool.return_value = self._pool
|
||||
self._mock(
|
||||
'eventlet.GreenPool', fake_green_pool)
|
||||
|
||||
def _mock(self, target, new=mock.DEFAULT):
|
||||
patcher = mock.patch(target, new)
|
||||
return patcher.start()
|
||||
|
||||
def _insert_dummy_device_template(self):
|
||||
session = self.context.session
|
||||
device_template = vm_db.DeviceTemplate(
|
||||
id='eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
tenant_id='ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
name='fake_template',
|
||||
description='fake_template_description',
|
||||
infra_driver='fake_driver',
|
||||
mgmt_driver='fake_mgmt_driver')
|
||||
session.add(device_template)
|
||||
session.flush()
|
||||
return device_template
|
||||
|
||||
def _insert_dummy_device(self):
|
||||
session = self.context.session
|
||||
device_db = vm_db.Device(id='6261579e-d6f3-49ad-8bc3-a9cb974778ff',
|
||||
tenant_id='ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
name='fake_device',
|
||||
description='fake_device_description',
|
||||
instance_id=
|
||||
'da85ea1a-4ec4-4201-bbb2-8d9249eca7ec',
|
||||
template_id=
|
||||
'eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
status='ACTIVE')
|
||||
session.add(device_db)
|
||||
session.flush()
|
||||
return device_db
|
||||
|
||||
def test_create_vnfd(self):
|
||||
vnfd_obj = utils.get_dummy_vnfd_obj()
|
||||
result = self.vnfm_plugin.create_vnfd(self.context, vnfd_obj)
|
||||
self.assertIsNotNone(result)
|
||||
self.assertIn('id', result)
|
||||
self.assertIn('service_types', result)
|
||||
self.assertIn('attributes', result)
|
||||
self._device_manager.invoke.assert_called_once_with(mock.ANY,
|
||||
mock.ANY,
|
||||
plugin=mock.ANY,
|
||||
context=mock.ANY,
|
||||
device_template=
|
||||
mock.ANY)
|
||||
|
||||
def test_create_vnf(self):
|
||||
device_template_obj = self._insert_dummy_device_template()
|
||||
vnf_obj = utils.get_dummy_vnf_obj()
|
||||
vnf_obj['vnf']['vnfd_id'] = device_template_obj['id']
|
||||
result = self.vnfm_plugin.create_vnf(self.context, vnf_obj)
|
||||
self.assertIsNotNone(result)
|
||||
self.assertIn('id', result)
|
||||
self.assertIn('instance_id', result)
|
||||
self.assertIn('status', result)
|
||||
self.assertIn('attributes', result)
|
||||
self.assertIn('mgmt_url', result)
|
||||
self._device_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
||||
plugin=mock.ANY,
|
||||
context=mock.ANY,
|
||||
device=mock.ANY)
|
||||
self._pool.spawn_n.assert_called_once_with(mock.ANY)
|
||||
|
||||
def test_delete_vnf(self):
|
||||
self._insert_dummy_device_template()
|
||||
dummy_device_obj = self._insert_dummy_device()
|
||||
self.vnfm_plugin.delete_vnf(self.context, dummy_device_obj[
|
||||
'id'])
|
||||
self._device_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
||||
plugin=mock.ANY,
|
||||
context=mock.ANY,
|
||||
device_id=mock.ANY)
|
||||
self._device_status.delete_hosting_device.assert_called_with(mock.ANY)
|
||||
self._pool.spawn_n.assert_called_once_with(mock.ANY, mock.ANY,
|
||||
mock.ANY)
|
||||
|
||||
def test_update_vnf(self):
|
||||
self._insert_dummy_device_template()
|
||||
dummy_device_obj = self._insert_dummy_device()
|
||||
vnf_config_obj = utils.get_dummy_vnf_config_obj()
|
||||
result = self.vnfm_plugin.update_vnf(self.context, dummy_device_obj[
|
||||
'id'], vnf_config_obj)
|
||||
self.assertIsNotNone(result)
|
||||
self.assertEqual(dummy_device_obj['id'], result['id'])
|
||||
self.assertIn('instance_id', result)
|
||||
self.assertIn('status', result)
|
||||
self.assertIn('attributes', result)
|
||||
self.assertIn('mgmt_url', result)
|
||||
self._pool.spawn_n.assert_called_once_with(mock.ANY, mock.ANY,
|
||||
mock.ANY)
|
@ -31,7 +31,7 @@ from keystoneclient.v2_0 import client as ks_client
|
||||
from oslo_config import cfg
|
||||
|
||||
from tacker.common import log
|
||||
from tacker.extensions import servicevm
|
||||
from tacker.extensions import vnfm
|
||||
from tacker.openstack.common import jsonutils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.vm.drivers import abstract_driver
|
||||
@ -119,13 +119,13 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver):
|
||||
self._update_params(value, paramvalues[key], False)
|
||||
else:
|
||||
LOG.debug('Key missing Value: %s', key)
|
||||
raise servicevm.InputValuesMissing()
|
||||
raise vnfm.InputValuesMissing()
|
||||
elif 'get_input' in value:
|
||||
if value['get_input'] in paramvalues:
|
||||
original[key] = paramvalues[value['get_input']]
|
||||
else:
|
||||
LOG.debug('Key missing Value: %s', key)
|
||||
raise servicevm.InputValuesMissing()
|
||||
raise vnfm.InputValuesMissing()
|
||||
else:
|
||||
self._update_params(value, paramvalues, True)
|
||||
|
||||
@ -172,12 +172,12 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver):
|
||||
LOG.debug('param_vattrs_yaml', param_vattrs_dict)
|
||||
except Exception as e:
|
||||
LOG.debug("Not Well Formed: %s", str(e))
|
||||
raise servicevm.ParamYAMLNotWellFormed(
|
||||
raise vnfm.ParamYAMLNotWellFormed(
|
||||
error_msg_details=str(e))
|
||||
else:
|
||||
self._update_params(vnfd_dict, param_vattrs_dict)
|
||||
else:
|
||||
raise servicevm.ParamYAMLInputMissing()
|
||||
raise vnfm.ParamYAMLInputMissing()
|
||||
|
||||
KEY_LIST = (('description', 'description'),
|
||||
)
|
||||
@ -231,7 +231,7 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver):
|
||||
'user_data_format']
|
||||
properties['user_data'] = vdu_dict['user_data']
|
||||
elif 'user_data' in vdu_dict or 'user_data_format' in vdu_dict:
|
||||
raise servicevm.UserDataFormatNotFound()
|
||||
raise vnfm.UserDataFormatNotFound()
|
||||
if ('placement_policy' in vdu_dict and
|
||||
'availability_zone' in vdu_dict['placement_policy']):
|
||||
properties['availability_zone'] = vdu_dict[
|
||||
@ -449,7 +449,7 @@ class HeatClient:
|
||||
return self.stacks.create(**fields)
|
||||
except heatException.HTTPException:
|
||||
type_, value, tb = sys.exc_info()
|
||||
raise servicevm.HeatClientException(msg=value)
|
||||
raise vnfm.HeatClientException(msg=value)
|
||||
|
||||
def delete(self, stack_id):
|
||||
try:
|
||||
|
@ -31,7 +31,7 @@ from tacker.common import driver_manager
|
||||
from tacker import context as t_context
|
||||
from tacker.db.vm import proxy_db # noqa
|
||||
from tacker.db.vm import vm_db
|
||||
from tacker.extensions import servicevm
|
||||
from tacker.extensions import vnfm
|
||||
from tacker.openstack.common import excutils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.plugins.common import constants
|
||||
@ -41,7 +41,7 @@ from tacker.vm import monitor
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ServiceVMMgmtMixin(object):
|
||||
class VNFMMgmtMixin(object):
|
||||
OPTS = [
|
||||
cfg.MultiStrOpt(
|
||||
'mgmt_driver', default=[],
|
||||
@ -52,7 +52,7 @@ class ServiceVMMgmtMixin(object):
|
||||
cfg.CONF.register_opts(OPTS, 'servicevm')
|
||||
|
||||
def __init__(self):
|
||||
super(ServiceVMMgmtMixin, self).__init__()
|
||||
super(VNFMMgmtMixin, self).__init__()
|
||||
self._mgmt_manager = driver_manager.DriverManager(
|
||||
'tacker.servicevm.mgmt.drivers', cfg.CONF.servicevm.mgmt_driver)
|
||||
|
||||
@ -152,7 +152,7 @@ class ServiceVMMgmtMixin(object):
|
||||
service_instance=service_instance_dict, kwargs=kwargs)
|
||||
|
||||
|
||||
class ServiceVMPlugin(vm_db.ServiceResourcePluginDb, ServiceVMMgmtMixin):
|
||||
class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
|
||||
"""ServiceVMPlugin which supports ServiceVM framework
|
||||
"""
|
||||
OPTS = [
|
||||
@ -161,10 +161,10 @@ class ServiceVMPlugin(vm_db.ServiceResourcePluginDb, ServiceVMMgmtMixin):
|
||||
help=_('Hosting device drivers servicevm plugin will use')),
|
||||
]
|
||||
cfg.CONF.register_opts(OPTS, 'servicevm')
|
||||
supported_extension_aliases = ['servicevm']
|
||||
supported_extension_aliases = ['vnfm']
|
||||
|
||||
def __init__(self):
|
||||
super(ServiceVMPlugin, self).__init__()
|
||||
super(VNFMPlugin, self).__init__()
|
||||
self._pool = eventlet.GreenPool()
|
||||
self._device_manager = driver_manager.DriverManager(
|
||||
'tacker.servicevm.device.drivers',
|
||||
@ -184,18 +184,18 @@ class ServiceVMPlugin(vm_db.ServiceResourcePluginDb, ServiceVMMgmtMixin):
|
||||
infra_driver = template.get('infra_driver')
|
||||
if not attributes.is_attr_set(infra_driver):
|
||||
LOG.debug(_('hosting device driver must be specified'))
|
||||
raise servicevm.InfraDriverNotSpecified()
|
||||
raise vnfm.InfraDriverNotSpecified()
|
||||
if infra_driver not in self._device_manager:
|
||||
LOG.debug(_('unknown hosting device driver '
|
||||
'%(infra_driver)s in %(drivers)s'),
|
||||
{'infra_driver': infra_driver,
|
||||
'drivers': cfg.CONF.servicevm.infra_driver})
|
||||
raise servicevm.InvalidInfraDriver(infra_driver=infra_driver)
|
||||
raise vnfm.InvalidInfraDriver(infra_driver=infra_driver)
|
||||
|
||||
service_types = template.get('service_types')
|
||||
if not attributes.is_attr_set(service_types):
|
||||
LOG.debug(_('service type must be specified'))
|
||||
raise servicevm.ServiceTypesNotSpecified()
|
||||
raise vnfm.ServiceTypesNotSpecified()
|
||||
for service_type in service_types:
|
||||
# TODO(yamahata):
|
||||
# framework doesn't know what services are valid for now.
|
||||
@ -206,7 +206,7 @@ class ServiceVMPlugin(vm_db.ServiceResourcePluginDb, ServiceVMMgmtMixin):
|
||||
infra_driver, 'create_device_template_pre', plugin=self,
|
||||
context=context, device_template=device_template)
|
||||
|
||||
return super(ServiceVMPlugin, self).create_device_template(
|
||||
return super(VNFMPlugin, self).create_device_template(
|
||||
context, device_template)
|
||||
|
||||
###########################################################################
|
||||
@ -258,7 +258,7 @@ class ServiceVMPlugin(vm_db.ServiceResourcePluginDb, ServiceVMMgmtMixin):
|
||||
self._device_manager.invoke(
|
||||
driver_name, 'create_wait', plugin=self, context=context,
|
||||
device_dict=device_dict, device_id=instance_id)
|
||||
except servicevm.DeviceCreateWaitFailed:
|
||||
except vnfm.DeviceCreateWaitFailed:
|
||||
instance_id = None
|
||||
del device_dict['instance_id']
|
||||
|
||||
@ -415,27 +415,6 @@ class ServiceVMPlugin(vm_db.ServiceResourcePluginDb, ServiceVMMgmtMixin):
|
||||
self._delete_device_post(context, device_id, None)
|
||||
self.spawn_n(self._delete_device_wait, context, device_dict)
|
||||
|
||||
def _do_interface(self, context, device_id, port_id, action):
|
||||
device_dict = self._update_device_pre(context, device_id)
|
||||
driver_name = self._infra_driver_name(device_dict)
|
||||
instance_id = self._instance_id(device_dict)
|
||||
|
||||
try:
|
||||
self._device_manager.invoke(driver_name, action, plugin=self,
|
||||
context=context, device_id=instance_id)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
device_dict['status'] = constants.ERROR
|
||||
self._update_device_post(context, device_id, constants.ERROR)
|
||||
|
||||
self._update_device_post(context, device_dict['id'], constants.ACTIVE)
|
||||
|
||||
def attach_interface(self, context, id, port_id):
|
||||
return self._do_interface(context, id, port_id, 'attach_interface')
|
||||
|
||||
def detach_interface(self, context, id, port_id):
|
||||
return self._do_interface(context, id, port_id, 'dettach_interface')
|
||||
|
||||
###########################################################################
|
||||
# logical service instance
|
||||
#
|
||||
@ -473,7 +452,7 @@ class ServiceVMPlugin(vm_db.ServiceResourcePluginDb, ServiceVMMgmtMixin):
|
||||
|
||||
def _create_service_instance_db(self, context, device_id,
|
||||
service_instance_param, managed_by_user):
|
||||
return super(ServiceVMPlugin, self)._create_service_instance(
|
||||
return super(VNFMPlugin, self)._create_service_instance(
|
||||
context, device_id, service_instance_param, managed_by_user)
|
||||
|
||||
def _create_service_instance_by_type(
|
||||
@ -683,3 +662,24 @@ class ServiceVMPlugin(vm_db.ServiceResourcePluginDb, ServiceVMMgmtMixin):
|
||||
self.spawn_n(
|
||||
self._delete_service_instance_wait, context, device,
|
||||
service_instance, {}, None, None)
|
||||
|
||||
def create_vnf(self, context, vnf):
|
||||
vnf['device'] = vnf.pop('vnf')
|
||||
vnf_attributes = vnf['device']
|
||||
vnf_attributes['template_id'] = vnf_attributes.pop('vnfd_id')
|
||||
vnf_dict = self.create_device(context, vnf)
|
||||
vnf_dict['vnfd_id'] = vnf_dict.pop('template_id')
|
||||
return vnf_dict
|
||||
|
||||
def update_vnf(
|
||||
self, context, vnf_id, vnf):
|
||||
vnf['device'] = vnf.pop('vnf')
|
||||
return self.update_device(context, vnf_id, vnf)
|
||||
|
||||
def delete_vnf(self, context, vnf_id):
|
||||
self.delete_device(context, vnf_id)
|
||||
|
||||
def create_vnfd(self, context, vnfd):
|
||||
vnfd['device_template'] = vnfd.pop('vnfd')
|
||||
new_dict = self.create_device_template(context, vnfd)
|
||||
return new_dict
|
4
tox.ini
4
tox.ini
@ -2,7 +2,7 @@
|
||||
# TODO(yamahata): enable tests of py26, py27, py33, py34.
|
||||
# Those unit tests are temporalily disabled until its stabilization
|
||||
#envlist = py26,py27,py33,py34,pep8
|
||||
envlist = pep8
|
||||
envlist = pep8,py27
|
||||
minversion = 1.6
|
||||
skipsdist = True
|
||||
|
||||
@ -10,8 +10,6 @@ skipsdist = True
|
||||
# disable unit tests for now until stabilization
|
||||
[testenv:py26]
|
||||
commands = bash -c "echo do nothing for py26 for now. enable after stablized"
|
||||
[testenv:py27]
|
||||
commands = bash -c "echo do nothing for py27 for now. enable after stablized"
|
||||
[testenv:py33]
|
||||
commands = bash -c "echo do nothing for py33 for now. enable after stablized"
|
||||
[testenv:py34]
|
||||
|
Loading…
Reference in New Issue
Block a user