OSC support for VNF package APIs

Added support vnf package create command and their unit test cases.

Please see the results here:
http://paste.openstack.org/show/775422/

Change-Id: Idf59847aaf33e360dae696eae819d217ae63570f
Implements: bp tosca-csar-mgmt-driver
This commit is contained in:
Shubham Potale 2019-04-25 11:29:25 +05:30 committed by dharmendra kushwaha
parent 0edfda9171
commit 9940682bc8
14 changed files with 572 additions and 22 deletions

View File

@ -3,6 +3,7 @@ Babel==2.3.4
cliff==2.8.0 cliff==2.8.0
cmd2==0.8.0 cmd2==0.8.0
coverage==4.0 coverage==4.0
ddt==1.0.1
debtcollector==1.2.0 debtcollector==1.2.0
decorator==3.4.0 decorator==3.4.0
deprecation==1.0 deprecation==1.0
@ -49,6 +50,7 @@ python-subunit==1.0.0
pytz==2013.6 pytz==2013.6
PyYAML==3.12 PyYAML==3.12
requests==2.14.2 requests==2.14.2
requests-mock==1.2.0
requestsexceptions==1.2.0 requestsexceptions==1.2.0
rfc3986==0.3.1 rfc3986==0.3.1
simplejson==3.5.1 simplejson==3.5.1

View File

@ -80,6 +80,7 @@ openstack.tackerclient.v1 =
vnf_classifier_show = tackerclient.osc.v1.nfvo.vnffg:ShowFC vnf_classifier_show = tackerclient.osc.v1.nfvo.vnffg:ShowFC
vnf_chain_list = tackerclient.osc.v1.nfvo.vnffg:ListSFC vnf_chain_list = tackerclient.osc.v1.nfvo.vnffg:ListSFC
vnf_chain_show = tackerclient.osc.v1.nfvo.vnffg:ShowSFC vnf_chain_show = tackerclient.osc.v1.nfvo.vnffg:ShowSFC
vnf_package_create = tackerclient.osc.v1.vnfpkgm.vnf_package:CreateVnfPackage
[build_releasenotes] [build_releasenotes]

View File

View File

@ -0,0 +1,71 @@
# Copyright (C) 2019 NTT DATA
# 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 logging
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import utils
from tackerclient.i18n import _
from tackerclient.osc import sdk_utils
LOG = logging.getLogger(__name__)
_mixed_case_fields = ('onboardingState', 'operationalState',
'usageState', 'userDefinedData')
def _get_columns(item):
column_map = {
'_links': 'Links',
'onboardingState': 'Onboarding State',
'operationalState': 'Operational State',
'usageState': 'Usage State',
'userDefinedData': 'User Defined Data',
'id': 'ID'
}
return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
class CreateVnfPackage(command.ShowOne):
_description = _("Create a new VNF Package")
def get_parser(self, prog_name):
LOG.debug('get_parser(%s)', prog_name)
parser = super(CreateVnfPackage, self).get_parser(prog_name)
parser.add_argument(
'--user-data',
metavar='<key=value>',
action=parseractions.KeyValueAction,
help=_('User defined data for the VNF package '
'(repeat option to set multiple user defined data)'),
)
return parser
def args2body(self, parsed_args):
body = {}
if parsed_args.user_data:
body["userDefinedData"] = parsed_args.user_data
return body
def take_action(self, parsed_args):
client = self.app.client_manager.tackerclient
vnf_package = client.create_vnf_package(self.args2body(parsed_args))
display_columns, columns = _get_columns(vnf_package)
data = utils.get_item_properties(
sdk_utils.DictModel(vnf_package),
columns, mixed_case_fields=_mixed_case_fields)
return (display_columns, data)

View File

View File

@ -0,0 +1,48 @@
# Copyright (C) 2019 NTT DATA
# 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
from requests_mock.contrib import fixture as requests_mock_fixture
import testtools
class FixturedTestCase(testtools.TestCase):
client_fixture_class = None
def setUp(self):
super(FixturedTestCase, self).setUp()
self.app = mock.MagicMock()
if self.client_fixture_class:
self.requests_mock = self.useFixture(requests_mock_fixture.
Fixture())
fix = self.client_fixture_class(self.requests_mock)
self.cs = self.useFixture(fix).client
def check_parser(self, cmd, args, verify_args):
cmd_parser = cmd.get_parser('check_parser')
try:
parsed_args = cmd_parser.parse_args(args)
except SystemExit:
raise ParserException
for av in verify_args:
attr, value = av
if attr:
self.assertIn(attr, parsed_args)
self.assertEqual(getattr(parsed_args, attr), value)
return parsed_args
class ParserException(Exception):
pass

View File

@ -0,0 +1,60 @@
# Copyright 2019 NTT DATA
#
# 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
from keystoneauth1 import fixture
from keystoneauth1 import loading
from keystoneauth1 import session
from tackerclient.v1_0 import client as proxy_client
IDENTITY_URL = 'http://identityserver:5000/v3'
TACKER_URL = 'http://nfv-orchestration'
class ClientFixture(fixtures.Fixture):
def __init__(self, requests_mock, identity_url=IDENTITY_URL):
super(ClientFixture, self).__init__()
self.identity_url = identity_url
self.client = None
self.token = fixture.V2Token()
self.token.set_scope()
self.requests_mock = requests_mock
self.discovery = fixture.V2Discovery(href=self.identity_url)
s = self.token.add_service('nfv-orchestration')
s.add_endpoint(TACKER_URL)
def setUp(self):
super(ClientFixture, self).setUp()
auth_url = '%s/tokens' % self.identity_url
headers = {'X-Content-Type': 'application/json'}
self.requests_mock.post(auth_url, json=self.token, headers=headers)
self.requests_mock.get(self.identity_url, json=self.discovery,
headers=headers)
self.client = self.new_client()
def new_client(self):
self.session = session.Session()
loader = loading.get_plugin_loader('password')
self.session.auth = loader.load_from_options(
auth_url=self.identity_url, username='xx', password='xx')
return proxy_client.Client(service_type='nfv-orchestration',
interface='public',
endpoint_type='public',
region_name='RegionOne',
auth_url=self.identity_url,
token=self.token.token_id,
endpoint_url=TACKER_URL)

View File

@ -0,0 +1,70 @@
# Copyright (C) 2019 NTT DATA
# 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 ddt
import mock
from tackerclient.osc.v1.vnfpkgm import vnf_package
from tackerclient.tests.unit.osc import base
from tackerclient.tests.unit.osc.v1.fixture_data import client
from tackerclient.tests.unit.osc.v1 import vnf_package_fakes
class TestVnfPackage(base.FixturedTestCase):
client_fixture_class = client.ClientFixture
def setUp(self):
super(TestVnfPackage, self).setUp()
self.url = client.TACKER_URL
self.app = mock.Mock()
self.app_args = mock.Mock()
self.client_manager = self.cs
self.app.client_manager.tackerclient = self.client_manager
@ddt.ddt
class TestCreateVnfPackage(TestVnfPackage):
columns = ('ID', 'Links', 'Onboarding State', 'Operational State',
'Usage State', 'User Defined Data')
def setUp(self):
super(TestCreateVnfPackage, self).setUp()
self.create_vnf_package = vnf_package.CreateVnfPackage(
self.app, self.app_args, cmd_name='vnf package create')
@ddt.data((["--user-data", 'Test_key=Test_value'],
[('user_data', {'Test_key': 'Test_value'})]),
([], []))
@ddt.unpack
def test_take_action(self, arglist, verifylist):
# command param
parsed_args = self.check_parser(self.create_vnf_package, arglist,
verifylist)
header = {'content-type': 'application/json'}
if arglist:
json = vnf_package_fakes.vnf_package_obj(
attrs={'userDefinedData': {'Test_key': 'Test_value'}})
else:
json = vnf_package_fakes.vnf_package_obj()
self.requests_mock.register_uri(
'POST', self.url + '/vnfpkgm/v1/vnf_packages',
json=json, headers=header)
columns, data = (self.create_vnf_package.take_action(parsed_args))
self.assertEqual(self.columns, columns)
self.assertItemsEqual(vnf_package_fakes.get_vnf_package_data(json),
data)

View File

@ -0,0 +1,58 @@
# Copyright (C) 2019 NTT DATA
# 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 vnf_package_obj(attrs=None):
"""Create a fake vnf package.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeVnfPackage dict
"""
attrs = attrs or {}
# Set default attributes.
fake_vnf_package = {"id": "60a6ac16-b50d-4e92-964b-b3cf98c7cf5c",
"_links": {"self": {"href": "string"},
"vnfd": {"href": "string"},
"packageContent": {"href": "string"}
},
"onboardingState": "CREATED",
"operationalState": "DISABLED",
"usageState": "NOT_IN_USE",
"userDefinedData": None}
# Overwrite default attributes.
fake_vnf_package.update(attrs)
return fake_vnf_package
def get_vnf_package_data(vnf_package=None):
"""Get the vnf package data from a FakeVnfPackage dict object.
:param vnf_package:
A FakeVnfPackage dict object
:return:
A tuple which may include the following values:
(u"packageContent='{'href': 'string'}', self='{'href': 'string'}',
vnfd='{'href': 'string'}'", '60a6ac16-b50d-4e92-964b-b3cf98c7cf5c',
'CREATED', 'DISABLED', 'NOT_IN_USE', u"Test_key='Test_value'")
"""
data_list = []
if vnf_package is not None:
for x in sorted(vnf_package.keys()):
data_list.append(vnf_package[x])
return tuple(data_list)

View File

@ -192,9 +192,9 @@ class CLITestV10Base(testtools.TestCase):
def setUp(self, plurals={}): def setUp(self, plurals={}):
"""Prepare the test environment.""" """Prepare the test environment."""
super(CLITestV10Base, self).setUp() super(CLITestV10Base, self).setUp()
client.Client.EXTED_PLURALS.update(constants.PLURALS) client.LegacyClient.EXTED_PLURALS.update(constants.PLURALS)
client.Client.EXTED_PLURALS.update(plurals) client.LegacyClient.EXTED_PLURALS.update(plurals)
self.metadata = {'plurals': client.Client.EXTED_PLURALS, self.metadata = {'plurals': client.LegacyClient.EXTED_PLURALS,
'xmlns': constants.XML_NS_V10, 'xmlns': constants.XML_NS_V10,
constants.EXT_NS: {'prefix': constants.EXT_NS: {'prefix':
'http://xxxx.yy.com'}} 'http://xxxx.yy.com'}}
@ -207,7 +207,8 @@ class CLITestV10Base(testtools.TestCase):
self.useFixture(fixtures.MonkeyPatch( self.useFixture(fixtures.MonkeyPatch(
'tackerclient.tacker.v1_0.find_resourceid_by_id', 'tackerclient.tacker.v1_0.find_resourceid_by_id',
self._find_resourceid)) self._find_resourceid))
self.client = client.Client(token=TOKEN, endpoint_url=self.endurl) self.client = client.LegacyClient(token=TOKEN,
endpoint_url=self.endurl)
@mock.patch.object(TackerCommand, 'get_client') @mock.patch.object(TackerCommand, 'get_client')
def _test_create_resource(self, resource, cmd, def _test_create_resource(self, resource, cmd,
@ -685,7 +686,7 @@ class ClientV1TestJson(CLITestV10Base):
error = self.assertRaises(exceptions.TackerClientException, error = self.assertRaises(exceptions.TackerClientException,
self.client.do_request, 'PUT', '/test', self.client.do_request, 'PUT', '/test',
body='', params=params) body='', params=params)
self.assertEqual("An error", str(error)) self.assertEqual("400-tackerFault", str(error))
class CLITestV10ExceptionHandler(CLITestV10Base): class CLITestV10ExceptionHandler(CLITestV10Base):
@ -779,11 +780,11 @@ class CLITestV10ExceptionHandler(CLITestV10Base):
error_content = {'message': 'This is an error message'} error_content = {'message': 'This is an error message'}
self._test_exception_handler_v10( self._test_exception_handler_v10(
exceptions.TackerClientException, 500, exceptions.TackerClientException, 500,
expected_msg='This is an error message', expected_msg='500-tackerFault',
error_content=error_content) error_content=error_content)
def test_exception_handler_v10_error_dict_not_contain_message(self): def test_exception_handler_v10_error_dict_not_contain_message(self):
error_content = {'error': 'This is an error message'} error_content = 'tackerFault'
expected_msg = '%s-%s' % (500, error_content) expected_msg = '%s-%s' % (500, error_content)
self._test_exception_handler_v10( self._test_exception_handler_v10(
exceptions.TackerClientException, 500, exceptions.TackerClientException, 500,

View File

@ -31,6 +31,18 @@ from tackerclient.i18n import _
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
DEFAULT_DESC_LENGTH = 25 DEFAULT_DESC_LENGTH = 25
DEFAULT_ERROR_REASON_LENGTH = 100 DEFAULT_ERROR_REASON_LENGTH = 100
STATUS_CODE_MAP = {
400: "badRequest",
401: "unauthorized",
403: "forbidden",
404: "itemNotFound",
405: "badMethod",
409: "conflictingRequest",
413: "overLimit",
415: "badMediaType",
429: "overLimit",
501: "notImplemented",
503: "serviceUnavailable"}
def exception_handler_v10(status_code, error_content): def exception_handler_v10(status_code, error_content):
@ -45,6 +57,9 @@ def exception_handler_v10(status_code, error_content):
error_dict = None error_dict = None
if isinstance(error_content, dict): if isinstance(error_content, dict):
error_dict = error_content.get('TackerError') error_dict = error_content.get('TackerError')
if not error_dict:
error_content = error_content.get(STATUS_CODE_MAP.get(status_code),
'tackerFault')
# Find real error type # Find real error type
bad_tacker_error_flag = False bad_tacker_error_flag = False
if error_dict: if error_dict:
@ -141,17 +156,6 @@ class ClientBase(object):
:param session: Keystone client auth session to use. (optional) :param session: Keystone client auth session to use. (optional)
:param auth: Keystone auth plugin to use. (optional) :param auth: Keystone auth plugin to use. (optional)
Example::
from tackerclient.v1_0 import client
tacker = client.Client(username=USER,
password=PASS,
tenant_name=TENANT_NAME,
auth_url=KEYSTONE_URL)
nets = tacker.list_networks()
...
""" """
# API has no way to report plurals, so we have to hard code them # API has no way to report plurals, so we have to hard code them
@ -182,15 +186,19 @@ class ClientBase(object):
# Raise the appropriate exception # Raise the appropriate exception
exception_handler_v10(status_code, des_error_body) exception_handler_v10(status_code, des_error_body)
def do_request(self, method, action, body=None, headers=None, params=None): def build_action(self, action):
# Add format and tenant_id
action += ".%s" % self.format action += ".%s" % self.format
action = self.action_prefix + action action = self.action_prefix + action
return action
def do_request(self, method, action, body=None, headers=None, params=None):
action = self.build_action(action)
# Add format and tenant_id
if type(params) is dict and params: if type(params) is dict and params:
params = utils.safe_encode_dict(params) params = utils.safe_encode_dict(params)
action += '?' + urlparse.urlencode(params, doseq=1) action += '?' + urlparse.urlencode(params, doseq=1)
if body: if body or body == {}:
body = self.serialize(body) body = self.serialize(body)
resp, replybody = self.httpclient.do_request( resp, replybody = self.httpclient.do_request(
@ -329,7 +337,7 @@ class ClientBase(object):
break break
class Client(ClientBase): class LegacyClient(ClientBase):
extensions_path = "/extensions" extensions_path = "/extensions"
extension_path = "/extensions/%s" extension_path = "/extensions/%s"
@ -708,3 +716,232 @@ class Client(ClientBase):
@APIParamsCall @APIParamsCall
def delete_clustermember(self, clustermember): def delete_clustermember(self, clustermember):
return self.delete(self.cluster_member_path % clustermember) return self.delete(self.cluster_member_path % clustermember)
class VnfPackageClient(ClientBase):
"""Client for vnfpackage APIs.
Purpose of this class is to create required request url for vnfpackage
APIs.
"""
vnfpackages_path = '/vnfpkgm/v1/vnf_packages'
def build_action(self, action):
return action
@APIParamsCall
def create_vnf_package(self, body):
return self.post(self.vnfpackages_path, body=body)
class Client(object):
"""Unified interface to interact with multiple applications of tacker service.
This class is a single entry point to interact with legacy tacker apis and
vnf packages apis.
Example::
from tackerclient.v1_0 import client
tacker = client.Client(username=USER,
password=PASS,
tenant_name=TENANT_NAME,
auth_url=KEYSTONE_URL)
vnf_package = tacker.create_vnf_package(...)
nsd = tacker.create_nsd(...)
"""
def __init__(self, **kwargs):
self.vnf_package_client = VnfPackageClient(**kwargs)
self.legacy_client = LegacyClient(**kwargs)
# LegacyClient methods
def list_extensions(self, **_params):
return self.legacy_client.list_extensions(**_params)
def show_extension(self, ext_alias, **_params):
"""Fetch a list of all exts on server side."""
return self.legacy_client.show_extension(ext_alias, **_params)
def list_vnfds(self, retrieve_all=True, **_params):
return self.legacy_client.list_vnfds(retrieve_all=retrieve_all,
**_params)
def show_vnfd(self, vnfd, **_params):
return self.legacy_client.show_vnfd(vnfd, **_params)
def create_vnfd(self, body):
return self.legacy_client.create_vnfd(body)
def delete_vnfd(self, vnfd):
return self.legacy_client.delete_vnfd(vnfd)
def list_vnfs(self, retrieve_all=True, **_params):
return self.legacy_client.list_vnfs(retrieve_all=retrieve_all,
**_params)
def show_vnf(self, vnf, **_params):
return self.legacy_client.show_vnf(vnf, **_params)
def create_vnf(self, body):
return self.legacy_client.create_vnf(body)
def delete_vnf(self, vnf, body=None):
return self.legacy_client.delete_vnf(vnf, body=body)
def update_vnf(self, vnf, body):
return self.legacy_client.update_vnf(vnf, body)
def list_vnf_resources(self, vnf, retrieve_all=True, **_params):
return self.legacy_client.list_vnf_resources(
vnf, retrieve_all=retrieve_all, **_params)
def scale_vnf(self, vnf, body=None):
return self.legacy_client.scale_vnf(vnf, body=body)
def show_vim(self, vim, **_params):
return self.legacy_client.show_vim(vim, **_params)
def create_vim(self, body):
return self.legacy_client.create_vim(body)
def delete_vim(self, vim):
return self.legacy_client.delete_vim(vim)
def update_vim(self, vim, body):
return self.legacy_client.update_vim(vim, body)
def list_vims(self, retrieve_all=True, **_params):
return self.legacy_client.list_vims(retrieve_all=retrieve_all,
**_params)
def list_events(self, retrieve_all=True, **_params):
return self.legacy_client.list_events(retrieve_all=retrieve_all,
**_params)
def list_vnf_events(self, retrieve_all=True, **_params):
return self.legacy_client.list_vnf_events(
retrieve_all=retrieve_all, **_params)
def list_vnfd_events(self, retrieve_all=True, **_params):
return self.legacy_client.list_vnfd_events(
retrieve_all=retrieve_all, **_params)
def list_vim_events(self, retrieve_all=True, **_params):
return self.legacy_client.list_vim_events(
retrieve_all=retrieve_all, **_params)
def show_event(self, event_id, **_params):
return self.legacy_client.show_event(event_id, **_params)
def create_vnffgd(self, body):
return self.legacy_client.create_vnffgd(body)
def list_vnffgds(self, retrieve_all=True, **_params):
return self.legacy_client.list_vnffgds(retrieve_all=retrieve_all,
**_params)
def show_vnffgd(self, vnffgd, **_params):
return self.legacy_client.show_vnffgd(vnffgd, **_params)
def delete_vnffgd(self, vnffgd):
return self.legacy_client.delete_vnffgd(vnffgd)
def list_vnffgs(self, retrieve_all=True, **_params):
return self.legacy_client.list_vnffgs(retrieve_all=retrieve_all,
**_params)
def show_vnffg(self, vnffg, **_params):
return self.legacy_client.show_vnffg(vnffg, **_params)
def create_vnffg(self, body):
return self.legacy_client.create_vnffg(body)
def delete_vnffg(self, vnffg):
return self.legacy_client.delete_vnffg(vnffg)
def update_vnffg(self, vnffg, body):
return self.legacy_client.update_vnffg(vnffg, body)
def list_sfcs(self, retrieve_all=True, **_params):
return self.legacy_client.list_sfcs(retrieve_all=retrieve_all,
**_params)
def show_sfc(self, chain, **_params):
return self.legacy_client.show_sfc(chain, **_params)
def list_nfps(self, retrieve_all=True, **_params):
return self.legacy_client.list_nfps(retrieve_all=retrieve_all,
**_params)
def show_nfp(self, nfp, **_params):
return self.legacy_client.show_nfp(nfp, **_params)
def list_classifiers(self, retrieve_all=True, **_params):
return self.legacy_client.list_classifiers(
retrieve_all=retrieve_all, **_params)
def show_classifier(self, classifier, **_params):
return self.legacy_client.show_classifier(classifier, **_params)
def list_nsds(self, retrieve_all=True, **_params):
return self.legacy_client.list_nsds(retrieve_all=retrieve_all,
**_params)
def show_nsd(self, nsd, **_params):
return self.legacy_client.show_nsd(nsd, **_params)
def create_nsd(self, body):
return self.legacy_client.create_nsd(body)
def delete_nsd(self, nsd):
return self.legacy_client.delete_nsd(nsd)
def list_nss(self, retrieve_all=True, **_params):
return self.legacy_client.list_nss(retrieve_all=retrieve_all,
**_params)
def show_ns(self, ns, **_params):
return self.legacy_client.show_ns(ns, **_params)
def create_ns(self, body):
return self.legacy_client.create_ns(body)
def delete_ns(self, ns):
return self.legacy_client.delete_ns(ns)
def create_cluster(self, body=None):
return self.legacy_client.create_cluster(body=body)
def list_clusters(self, retrieve_all=True, **_params):
return self.legacy_client.list_clusters(retrieve_all=retrieve_all,
**_params)
def show_cluster(self, cluster, **_params):
return self.legacy_client.show_cluster(cluster, **_params)
def delete_cluster(self, cluster):
return self.legacy_client.delete_cluster(cluster)
def create_clustermember(self, body=None):
return self.legacy_client.create_clustermember(body=body)
def list_clustermembers(self, retrieve_all=True, **_params):
return self.legacy_client.list_clustermembers(
retrieve_all=retrieve_all, **_params)
def show_clustermember(self, clustermember, **_params):
return self.legacy_client.show_clustermember(clustermember,
**_params)
def delete_clustermember(self, clustermember):
return self.legacy_client.delete_clustermember(clustermember)
# VnfPackageClient methods
def create_vnf_package(self, body):
return self.vnf_package_client.create_vnf_package(body)

View File

@ -4,8 +4,10 @@
hacking>=1.1.0,<1.2.0 # Apache-2.0 hacking>=1.1.0,<1.2.0 # Apache-2.0
coverage!=4.4,>=4.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0
ddt>=1.0.1 # MIT
fixtures>=3.0.0 # Apache-2.0/BSD fixtures>=3.0.0 # Apache-2.0/BSD
python-subunit>=1.0.0 # Apache-2.0/BSD python-subunit>=1.0.0 # Apache-2.0/BSD
requests-mock>=1.2.0 # Apache-2.0
stestr>=2.0.0 # Apache-2.0 stestr>=2.0.0 # Apache-2.0
testtools>=2.2.0 # MIT testtools>=2.2.0 # MIT
mock>=2.0.0 # BSD mock>=2.0.0 # BSD