Compare commits
108 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbc71552f2 | ||
|
|
1cf8ceb72e | ||
|
|
a6a2fa0975 | ||
|
|
b40c5930d5 | ||
|
|
69009d6dad | ||
|
|
3b99b49852 | ||
|
|
3f7cc06aff | ||
|
|
d90dac82ca | ||
|
|
64e41e103d | ||
|
|
6944ea0405 | ||
|
|
592f7d22b3 | ||
|
|
0373528ff3 | ||
|
|
1e613792fd | ||
|
|
ef1585a024 | ||
|
|
f673cea49c | ||
|
|
fb1c3cd273 | ||
|
|
10711d5b47 | ||
|
|
0d941634ae | ||
|
|
7617b71841 | ||
|
|
33b1d3f20b | ||
|
|
2b3b1792d5 | ||
|
|
b45904f7a1 | ||
|
|
d26d358145 | ||
|
|
8a5679c4b0 | ||
|
|
bdba1b1384 | ||
|
|
ca132cbb3b | ||
|
|
10f286989d | ||
|
|
71312260d1 | ||
|
|
2a62ba447b | ||
|
|
edf203acb8 | ||
|
|
e3f0d522ba | ||
|
|
65a5198d73 | ||
|
|
f499e93fcf | ||
|
|
19d7cadd8e | ||
|
|
62832b010c | ||
|
|
7cbdfabc75 | ||
|
|
6cf2973c49 | ||
|
|
98a6ea328a | ||
|
|
f160afac6a | ||
|
|
66c9b13212 | ||
|
|
6c78395976 | ||
|
|
c2e86d3145 | ||
|
|
c3d69c8e22 | ||
|
|
d763fedc3c | ||
|
|
f01c05a268 | ||
|
|
45ebce43cb | ||
|
|
36b52a14a2 | ||
|
|
d810074cda | ||
|
|
e6e54b7f33 | ||
|
|
cb66556390 | ||
|
|
1612e2227c | ||
|
|
495ccbd2aa | ||
|
|
d8a6fa279a | ||
|
|
a624948cc8 | ||
|
|
f8e1d00eb8 | ||
|
|
95733d9eb4 | ||
|
|
3b60ab1aaa | ||
|
|
48d458d290 | ||
|
|
32ad7f33b6 | ||
|
|
f1eef18974 | ||
|
|
23f34cdf1a | ||
|
|
78b0876baf | ||
|
|
f6848f0f31 | ||
|
|
542a2bb083 | ||
|
|
ced23fe6ab | ||
|
|
aa499bb5f3 | ||
|
|
c047bf9db2 | ||
|
|
7951ebb39e | ||
|
|
882f6b6c93 | ||
|
|
ed102cac10 | ||
|
|
144408331e | ||
|
|
7f829587b0 | ||
|
|
cc0a66884b | ||
|
|
7a0f627e2e | ||
|
|
5a1f2f5717 | ||
|
|
6b677a8f38 | ||
|
|
647baba801 | ||
|
|
977038a0b3 | ||
|
|
e5457e5062 | ||
|
|
00520f74d0 | ||
|
|
6fecf2adf7 | ||
|
|
166368b8b0 | ||
|
|
94ccf2ded8 | ||
|
|
eebea81587 | ||
|
|
4b7fce5642 | ||
|
|
1cbf0ba295 | ||
|
|
5a9490e567 | ||
|
|
fc4772603d | ||
|
|
0aa7efd292 | ||
|
|
31626a41c4 | ||
|
|
f4daaa09ba | ||
|
|
e88619e985 | ||
|
|
602c06373d | ||
|
|
c9ac53a722 | ||
|
|
4197bd5356 | ||
|
|
00d87bde7e | ||
|
|
9910cbc746 | ||
|
|
431a79ba3d | ||
|
|
3c6f82dfaf | ||
|
|
af6db3f107 | ||
|
|
6fd6b66466 | ||
|
|
654ad24e3b | ||
|
|
b35672be34 | ||
|
|
04298efa2d | ||
|
|
a5ad0bc3d3 | ||
|
|
f42187050f | ||
|
|
a4dcd7634a | ||
|
|
c32028201f |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,6 +17,7 @@ run_tests.log
|
||||
.autogenerated
|
||||
.coverage
|
||||
.testrepository/
|
||||
.idea/
|
||||
.tox/
|
||||
.venv/
|
||||
|
||||
|
||||
@@ -1 +1,10 @@
|
||||
========================
|
||||
Team and repository tags
|
||||
========================
|
||||
|
||||
.. image:: http://governance.openstack.org/badges/python-tackerclient.svg
|
||||
:target: http://governance.openstack.org/reference/tags/index.html
|
||||
|
||||
.. Change things from this point on
|
||||
|
||||
This is the client API library for Tacker.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
deprecations:
|
||||
- infra_driver and mgmt_driver attributes in VNFD client
|
||||
attribute is deprecated and will be removed in Ocata.
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Add support for multi delete feature for resources.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- Adds new CLI command 'vnf-resource-list' to view VNF
|
||||
resources, such as VDU, CP, etc.
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
fixes:
|
||||
- Remove passing mgmt and infra driver from client.
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Made VNFD/VNF/VIM names mandatory in tacker CLI.
|
||||
3
releasenotes/notes/vnffg-client-abd7d7f06860b91d.yaml
Normal file
3
releasenotes/notes/vnffg-client-abd7d7f06860b91d.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Add client support for VNFFG.
|
||||
@@ -259,3 +259,6 @@ texinfo_documents = [
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
# texinfo_show_urls = 'footnote'
|
||||
|
||||
# -- Options for Internationalization output ------------------------------
|
||||
locale_dirs = ['locale/']
|
||||
|
||||
@@ -7,3 +7,4 @@ Contents:
|
||||
:maxdepth: 2
|
||||
|
||||
unreleased
|
||||
newton
|
||||
|
||||
6
releasenotes/source/newton.rst
Normal file
6
releasenotes/source/newton.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
===================================
|
||||
Newton Series Release Notes
|
||||
===================================
|
||||
|
||||
.. release-notes::
|
||||
:branch: origin/stable/newton
|
||||
@@ -1,16 +1,19 @@
|
||||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
pbr>=1.6 # Apache-2.0
|
||||
cliff!=1.16.0,!=1.17.0,>=1.15.0 # Apache-2.0
|
||||
pbr>=1.8 # Apache-2.0
|
||||
cliff>=2.3.0 # Apache-2.0
|
||||
iso8601>=0.1.11 # MIT
|
||||
netaddr!=0.7.16,>=0.7.12 # BSD
|
||||
requests>=2.10.0 # Apache-2.0
|
||||
python-keystoneclient!=1.8.0,!=2.1.0,>=1.7.0 # Apache-2.0
|
||||
netaddr!=0.7.16,>=0.7.13 # BSD
|
||||
requests!=2.12.2,>=2.10.0 # Apache-2.0
|
||||
python-keystoneclient>=3.8.0 # Apache-2.0
|
||||
simplejson>=2.2.0 # MIT
|
||||
six>=1.9.0 # MIT
|
||||
stevedore>=1.17.1 # Apache-2.0
|
||||
Babel>=2.3.4 # BSD
|
||||
|
||||
oslo.i18n>=2.1.0 # Apache-2.0
|
||||
oslo.utils>=3.11.0 # Apache-2.0
|
||||
oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
|
||||
oslo.log>=3.11.0 # Apache-2.0
|
||||
oslo.utils>=3.18.0 # Apache-2.0
|
||||
oslosphinx>=4.7.0 # Apache-2.0
|
||||
oslo.serialization>=1.10.0 # Apache-2.0
|
||||
|
||||
@@ -5,7 +5,7 @@ description-file =
|
||||
README.rst
|
||||
author = OpenStack
|
||||
author-email = openstack-dev@lists.openstack.org
|
||||
home-page = http://www.openstack.org/
|
||||
home-page = http://docs.openstack.org/developer/tacker/
|
||||
classifier =
|
||||
Environment :: OpenStack
|
||||
Intended Audience :: Developers
|
||||
|
||||
@@ -17,15 +17,10 @@
|
||||
"""Manage access to the clients, including authenticating when needed.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from tackerclient import client
|
||||
from tackerclient.tacker import client as tacker_client
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ClientCache(object):
|
||||
"""Descriptor class for caching created client handles."""
|
||||
|
||||
|
||||
@@ -21,10 +21,10 @@ import argparse
|
||||
import logging
|
||||
import os
|
||||
|
||||
from oslo_log import versionutils
|
||||
from oslo_utils import encodeutils
|
||||
from oslo_utils import importutils
|
||||
import six
|
||||
import six.moves.urllib.parse as urlparse
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
from tackerclient.i18n import _
|
||||
@@ -174,8 +174,13 @@ def add_boolean_argument(parser, name, **kwargs):
|
||||
**kwargs)
|
||||
|
||||
|
||||
def validate_url(url):
|
||||
url_parts = urlparse.urlparse(url)
|
||||
if not url_parts.scheme or not url_parts.netloc or not url_parts.port:
|
||||
raise exceptions.TackerClientException(message='Invalid URL')
|
||||
return url_parts
|
||||
def get_file_path(filename):
|
||||
file_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'../%s' % filename))
|
||||
return file_path
|
||||
|
||||
|
||||
def deprecate_warning(what, as_of, in_favor_of=None, remove_in=1):
|
||||
versionutils.deprecation_warning(as_of=as_of, what=what,
|
||||
in_favor_of=in_favor_of,
|
||||
remove_in=remove_in)
|
||||
|
||||
@@ -45,10 +45,15 @@ from tackerclient.common import exceptions as exc
|
||||
from tackerclient.common import extension as client_extension
|
||||
from tackerclient.common import utils
|
||||
from tackerclient.i18n import _
|
||||
from tackerclient.tacker.v1_0.events import events
|
||||
from tackerclient.tacker.v1_0 import extension
|
||||
from tackerclient.tacker.v1_0.nfvo import ns
|
||||
from tackerclient.tacker.v1_0.nfvo import nsd
|
||||
from tackerclient.tacker.v1_0.nfvo import vim
|
||||
from tackerclient.tacker.v1_0.vm import vnf
|
||||
from tackerclient.tacker.v1_0.vm import vnfd
|
||||
from tackerclient.tacker.v1_0.nfvo import vnffg
|
||||
from tackerclient.tacker.v1_0.nfvo import vnffgd
|
||||
from tackerclient.tacker.v1_0.vnfm import vnf
|
||||
from tackerclient.tacker.v1_0.vnfm import vnfd
|
||||
from tackerclient.version import __version__
|
||||
|
||||
|
||||
@@ -115,6 +120,8 @@ COMMAND_V1 = {
|
||||
'vnf-delete': vnf.DeleteVNF,
|
||||
'vnf-list': vnf.ListVNF,
|
||||
'vnf-show': vnf.ShowVNF,
|
||||
'vnf-scale': vnf.ScaleVNF,
|
||||
'vnf-resource-list': vnf.ListVNFResources,
|
||||
# 'vnf-config-create'
|
||||
# 'vnf-config-push'
|
||||
|
||||
@@ -123,6 +130,44 @@ COMMAND_V1 = {
|
||||
'vim-delete': vim.DeleteVIM,
|
||||
'vim-list': vim.ListVIM,
|
||||
'vim-show': vim.ShowVIM,
|
||||
|
||||
'events-list': events.ListResourceEvents,
|
||||
'event-show': events.ShowEvent,
|
||||
'vnf-events-list': events.ListVNFEvents,
|
||||
'vim-events-list': events.ListVIMEvents,
|
||||
'vnfd-events-list': events.ListVNFDEvents,
|
||||
|
||||
'vnffgd-create': vnffgd.CreateVNFFGD,
|
||||
'vnffgd-delete': vnffgd.DeleteVNFFGD,
|
||||
'vnffgd-list': vnffgd.ListVNFFGD,
|
||||
'vnffgd-show': vnffgd.ShowVNFFGD,
|
||||
'vnffgd-template-show': vnffgd.ShowTemplateVNFFGD,
|
||||
|
||||
'vnffg-create': vnffg.CreateVNFFG,
|
||||
'vnffg-delete': vnffg.DeleteVNFFG,
|
||||
'vnffg-list': vnffg.ListVNFFG,
|
||||
'vnffg-show': vnffg.ShowVNFFG,
|
||||
'vnffg-update': vnffg.UpdateVNFFG,
|
||||
|
||||
'nfp-list': vnffg.ListNFP,
|
||||
'nfp-show': vnffg.ShowNFP,
|
||||
|
||||
'chain-list': vnffg.ListSFC,
|
||||
'chain-show': vnffg.ShowSFC,
|
||||
|
||||
'classifier-list': vnffg.ListFC,
|
||||
'classifier-show': vnffg.ShowFC,
|
||||
|
||||
'nsd-create': nsd.CreateNSD,
|
||||
'nsd-list': nsd.ListNSD,
|
||||
'nsd-delete': nsd.DeleteNSD,
|
||||
'nsd-show': nsd.ShowNSD,
|
||||
'nsd-template-show': nsd.ShowTemplateNSD,
|
||||
|
||||
'ns-create': ns.CreateNS,
|
||||
'ns-list': ns.ListNS,
|
||||
'ns-delete': ns.DeleteNS,
|
||||
'ns-show': ns.ShowNS,
|
||||
}
|
||||
|
||||
COMMANDS = {'1.0': COMMAND_V1}
|
||||
@@ -296,10 +341,10 @@ class TackerShell(app.App):
|
||||
'--os-project-name',
|
||||
metavar='<auth-project-name>',
|
||||
default=utils.env('OS_PROJECT_NAME'),
|
||||
help='Another way to specify tenant name. '
|
||||
'This option is mutually exclusive with '
|
||||
' --os-tenant-name. '
|
||||
'Defaults to env[OS_PROJECT_NAME].')
|
||||
help=_('Another way to specify tenant name. '
|
||||
'This option is mutually exclusive with '
|
||||
' --os-tenant-name. '
|
||||
'Defaults to env[OS_PROJECT_NAME].'))
|
||||
|
||||
parser.add_argument(
|
||||
'--os_tenant_name',
|
||||
@@ -315,10 +360,10 @@ class TackerShell(app.App):
|
||||
'--os-project-id',
|
||||
metavar='<auth-project-id>',
|
||||
default=utils.env('OS_PROJECT_ID'),
|
||||
help='Another way to specify tenant ID. '
|
||||
'This option is mutually exclusive with '
|
||||
' --os-tenant-id. '
|
||||
'Defaults to env[OS_PROJECT_ID].')
|
||||
help=_('Another way to specify tenant ID. '
|
||||
'This option is mutually exclusive with '
|
||||
' --os-tenant-id. '
|
||||
'Defaults to env[OS_PROJECT_ID].'))
|
||||
|
||||
parser.add_argument(
|
||||
'--os-username', metavar='<auth-username>',
|
||||
@@ -341,8 +386,8 @@ class TackerShell(app.App):
|
||||
'--os-user-domain-id',
|
||||
metavar='<auth-user-domain-id>',
|
||||
default=utils.env('OS_USER_DOMAIN_ID'),
|
||||
help='OpenStack user domain ID. '
|
||||
'Defaults to env[OS_USER_DOMAIN_ID].')
|
||||
help=_('OpenStack user domain ID. '
|
||||
'Defaults to env[OS_USER_DOMAIN_ID].'))
|
||||
|
||||
parser.add_argument(
|
||||
'--os_user_domain_id',
|
||||
@@ -352,8 +397,8 @@ class TackerShell(app.App):
|
||||
'--os-user-domain-name',
|
||||
metavar='<auth-user-domain-name>',
|
||||
default=utils.env('OS_USER_DOMAIN_NAME'),
|
||||
help='OpenStack user domain name. '
|
||||
'Defaults to env[OS_USER_DOMAIN_NAME].')
|
||||
help=_('OpenStack user domain name. '
|
||||
'Defaults to env[OS_USER_DOMAIN_NAME].'))
|
||||
|
||||
parser.add_argument(
|
||||
'--os_user_domain_name',
|
||||
@@ -371,13 +416,13 @@ class TackerShell(app.App):
|
||||
'--os-project-domain-id',
|
||||
metavar='<auth-project-domain-id>',
|
||||
default=utils.env('OS_PROJECT_DOMAIN_ID'),
|
||||
help='Defaults to env[OS_PROJECT_DOMAIN_ID].')
|
||||
help=_('Defaults to env[OS_PROJECT_DOMAIN_ID].'))
|
||||
|
||||
parser.add_argument(
|
||||
'--os-project-domain-name',
|
||||
metavar='<auth-project-domain-name>',
|
||||
default=utils.env('OS_PROJECT_DOMAIN_NAME'),
|
||||
help='Defaults to env[OS_PROJECT_DOMAIN_NAME].')
|
||||
help=_('Defaults to env[OS_PROJECT_DOMAIN_NAME].'))
|
||||
|
||||
parser.add_argument(
|
||||
'--os-cert',
|
||||
|
||||
@@ -25,7 +25,6 @@ from cliff.formatters import table
|
||||
from cliff import lister
|
||||
from cliff import show
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import strutils
|
||||
import six
|
||||
|
||||
from tackerclient.common._i18n import _
|
||||
@@ -50,8 +49,10 @@ def _get_resource_plural(resource, client):
|
||||
def find_resourceid_by_id(client, resource, resource_id):
|
||||
resource_plural = _get_resource_plural(resource, client)
|
||||
obj_lister = getattr(client, "list_%s" % resource_plural)
|
||||
# perform search by id only if we are passing a valid UUID
|
||||
match = re.match(UUID_PATTERN, resource_id)
|
||||
if resource == 'event':
|
||||
match = resource_id.isdigit() and resource_id != 0
|
||||
else:
|
||||
match = re.match(UUID_PATTERN, resource_id)
|
||||
collection = resource_plural
|
||||
if match:
|
||||
data = obj_lister(id=resource_id, fields='id')
|
||||
@@ -283,7 +284,7 @@ def parse_args_to_dict(values_specs):
|
||||
_args = _parser.parse_args(_values_specs)
|
||||
|
||||
result_dict = {}
|
||||
for opt in _options.iterkeys():
|
||||
for opt in _options.keys():
|
||||
_opt = opt.split('--', 2)[1]
|
||||
_opt = _opt.replace('-', '_')
|
||||
_value = getattr(_args, _opt)
|
||||
@@ -386,8 +387,6 @@ class TackerCommand(command.OpenStackCommand):
|
||||
def format_output_data(self, data):
|
||||
# Modify data to make it more readable
|
||||
if self.resource in data:
|
||||
data[self.resource] = strutils.mask_dict_password(
|
||||
data[self.resource])
|
||||
for k, v in six.iteritems(data[self.resource]):
|
||||
if isinstance(v, list):
|
||||
value = '\n'.join(jsonutils.dumps(
|
||||
@@ -429,7 +428,7 @@ class CreateCommand(TackerCommand, show.ShowOne):
|
||||
return parser
|
||||
|
||||
def get_data(self, parsed_args):
|
||||
self.log.debug('get_data(%s)' % parsed_args)
|
||||
self.log.debug('get_data(%s)', parsed_args)
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
_extra_values = parse_args_to_dict(self.values_specs)
|
||||
@@ -501,7 +500,7 @@ class UpdateCommand(TackerCommand):
|
||||
|
||||
|
||||
class DeleteCommand(TackerCommand):
|
||||
"""Delete a given resource
|
||||
"""Delete given resource(s)
|
||||
|
||||
"""
|
||||
|
||||
@@ -509,34 +508,61 @@ class DeleteCommand(TackerCommand):
|
||||
resource = None
|
||||
log = None
|
||||
allow_names = True
|
||||
deleted_msg = {}
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteCommand, self).get_parser(prog_name)
|
||||
if self.allow_names:
|
||||
help_str = _('ID or name of %s to delete')
|
||||
help_str = _('IDs or names of %s to delete')
|
||||
else:
|
||||
help_str = _('ID of %s to delete')
|
||||
help_str = _('IDs of %s to delete')
|
||||
parser.add_argument(
|
||||
'id', metavar=self.resource.upper(),
|
||||
'ids', nargs='+',
|
||||
metavar=self.resource.upper(),
|
||||
help=help_str % self.resource)
|
||||
return parser
|
||||
|
||||
def run(self, parsed_args):
|
||||
self.log.debug('run(%s)', parsed_args)
|
||||
failure = False
|
||||
deleted_ids = []
|
||||
failed_items = {}
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
obj_deleter = getattr(tacker_client,
|
||||
"delete_%s" % self.resource)
|
||||
if self.allow_names:
|
||||
_id = find_resourceid_by_name_or_id(tacker_client, self.resource,
|
||||
parsed_args.id)
|
||||
for resource_id in parsed_args.ids:
|
||||
try:
|
||||
if self.allow_names:
|
||||
_id = find_resourceid_by_name_or_id(
|
||||
tacker_client, self.resource, resource_id)
|
||||
else:
|
||||
_id = resource_id
|
||||
obj_deleter(_id)
|
||||
deleted_ids.append(resource_id)
|
||||
except Exception as e:
|
||||
failure = True
|
||||
failed_items[resource_id] = e
|
||||
if failure:
|
||||
msg = ''
|
||||
if deleted_ids:
|
||||
status_msg = self.deleted_msg.get(self.resource, 'deleted')
|
||||
msg = (_('Successfully %(status_msg)s %(resource)s(s):'
|
||||
' %(deleted_list)s') % {'status_msg': status_msg,
|
||||
'deleted_list':
|
||||
', '.join(deleted_ids),
|
||||
'resource': self.resource})
|
||||
err_msg = _("\n\nUnable to delete the below"
|
||||
" %s(s):") % self.resource
|
||||
for failed_id, error in failed_items.iteritems():
|
||||
err_msg += (_('\n Cannot delete %(failed_id)s: %(error)s')
|
||||
% {'failed_id': failed_id,
|
||||
'error': error})
|
||||
msg += err_msg
|
||||
raise exceptions.CommandError(msg)
|
||||
else:
|
||||
_id = parsed_args.id
|
||||
obj_deleter(_id)
|
||||
print((_('Deleted %(resource)s: %(id)s')
|
||||
% {'id': parsed_args.id,
|
||||
'resource': self.resource}),
|
||||
file=self.app.stdout)
|
||||
print((_('All %(resource)s(s) %(msg)s successfully')
|
||||
% {'msg': self.deleted_msg.get(self.resource, 'deleted'),
|
||||
'resource': self.resource}))
|
||||
return
|
||||
|
||||
|
||||
@@ -649,6 +675,10 @@ class ShowCommand(TackerCommand, show.ShowOne):
|
||||
log = None
|
||||
allow_names = True
|
||||
|
||||
def get_id(self):
|
||||
if self.resource:
|
||||
return self.resource.upper()
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowCommand, self).get_parser(prog_name)
|
||||
add_show_list_common_argument(parser)
|
||||
@@ -657,7 +687,7 @@ class ShowCommand(TackerCommand, show.ShowOne):
|
||||
else:
|
||||
help_str = _('ID of %s to look up')
|
||||
parser.add_argument(
|
||||
'id', metavar=self.resource.upper(),
|
||||
'id', metavar=self.get_id(),
|
||||
help=help_str % self.resource)
|
||||
return parser
|
||||
|
||||
|
||||
65
tackerclient/tacker/v1_0/events/events.py
Normal file
65
tackerclient/tacker/v1_0/events/events.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# Copyright 2016 Brocade Communications Systems 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.
|
||||
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
|
||||
_EVENT = "event"
|
||||
|
||||
|
||||
class ListResourceEvents(tackerV10.ListCommand):
|
||||
"""List events that belong to a given resource.
|
||||
|
||||
The supported args are --id, --resource_id, --resource_state,
|
||||
--resource_type, --event_type
|
||||
"""
|
||||
|
||||
resource = _EVENT
|
||||
list_columns = ['id', 'resource_type', 'resource_id',
|
||||
'resource_state', 'event_type',
|
||||
'timestamp', 'event_details']
|
||||
|
||||
|
||||
class ListVNFEvents(ListResourceEvents):
|
||||
"""List events that belong to a given VNF.
|
||||
|
||||
The supported args are --id, --resource_id, --resource_state, --event_type
|
||||
"""
|
||||
|
||||
resource = "vnf_event"
|
||||
|
||||
|
||||
class ListVNFDEvents(ListResourceEvents):
|
||||
"""List events that belong to a given VNFD.
|
||||
|
||||
The supported args are --id, --resource_id, --resource_state, --event_type
|
||||
"""
|
||||
|
||||
resource = "vnfd_event"
|
||||
|
||||
|
||||
class ListVIMEvents(ListResourceEvents):
|
||||
"""List events that belong to a given VIM.
|
||||
|
||||
The supported args are --id, --resource_id, --resource_state, --event_type
|
||||
"""
|
||||
|
||||
resource = "vim_event"
|
||||
|
||||
|
||||
class ShowEvent(tackerV10.ShowCommand):
|
||||
"""Show event given the event id."""
|
||||
|
||||
resource = _EVENT
|
||||
@@ -14,7 +14,6 @@
|
||||
# under the License.
|
||||
#
|
||||
|
||||
from tackerclient.common._i18n import _
|
||||
from tackerclient.tacker import v1_0 as cmd_base
|
||||
|
||||
|
||||
@@ -31,10 +30,5 @@ class ShowExt(cmd_base.ShowCommand):
|
||||
resource = "extension"
|
||||
allow_names = False
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowExt, self).get_parser(prog_name)
|
||||
cmd_base.add_show_list_common_argument(parser)
|
||||
parser.add_argument(
|
||||
'id', metavar='EXT-ALIAS',
|
||||
help=_('The extension alias'))
|
||||
return parser
|
||||
def get_id(self):
|
||||
return 'EXT-ALIAS'
|
||||
|
||||
106
tackerclient/tacker/v1_0/nfvo/ns.py
Normal file
106
tackerclient/tacker/v1_0/nfvo/ns.py
Normal file
@@ -0,0 +1,106 @@
|
||||
# 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 yaml
|
||||
|
||||
from tackerclient.i18n import _
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
|
||||
|
||||
_NS = 'ns'
|
||||
_RESOURCE = 'resource'
|
||||
|
||||
|
||||
class ListNS(tackerV10.ListCommand):
|
||||
"""List NS that belong to a given tenant."""
|
||||
|
||||
resource = _NS
|
||||
list_columns = ['id', 'name', 'nsd_id', 'mgmt_urls', 'status']
|
||||
|
||||
|
||||
class ShowNS(tackerV10.ShowCommand):
|
||||
"""Show information of a given NS."""
|
||||
|
||||
resource = _NS
|
||||
|
||||
|
||||
class CreateNS(tackerV10.CreateCommand):
|
||||
"""Create a NS."""
|
||||
|
||||
resource = _NS
|
||||
remove_output_fields = ["attributes"]
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME', required=True,
|
||||
help=_('Set a name for the NS'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help=_('Set description for the NS'))
|
||||
nsd_group = parser.add_mutually_exclusive_group(required=True)
|
||||
nsd_group.add_argument(
|
||||
'--nsd-id',
|
||||
help=_('NSD ID to use as template to create NS'))
|
||||
nsd_group.add_argument(
|
||||
'--nsd-name',
|
||||
help=_('NSD name to use as template to create NS'))
|
||||
vim_group = parser.add_mutually_exclusive_group()
|
||||
vim_group.add_argument(
|
||||
'--vim-id',
|
||||
help=_('VIM ID to use to create NS on the specified VIM'))
|
||||
vim_group.add_argument(
|
||||
'--vim-name',
|
||||
help=_('VIM name to use to create NS on the specified VIM'))
|
||||
parser.add_argument(
|
||||
'--vim-region-name',
|
||||
help=_('VIM Region to use to create NS on the specified VIM'))
|
||||
parser.add_argument(
|
||||
'--param-file',
|
||||
help=_('Specify parameter yaml file'))
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
args = {'attributes': {}}
|
||||
body = {self.resource: args}
|
||||
if parsed_args.vim_region_name:
|
||||
args.setdefault('placement_attr', {})['region_name'] = \
|
||||
parsed_args.vim_region_name
|
||||
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
if parsed_args.vim_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
'vim',
|
||||
parsed_args.
|
||||
vim_name)
|
||||
parsed_args.vim_id = _id
|
||||
if parsed_args.nsd_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
'nsd',
|
||||
parsed_args.
|
||||
nsd_name)
|
||||
parsed_args.nsd_id = _id
|
||||
if parsed_args.param_file:
|
||||
with open(parsed_args.param_file) as f:
|
||||
param_yaml = f.read()
|
||||
args['attributes']['param_values'] = yaml.load(
|
||||
param_yaml, Loader=yaml.SafeLoader)
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'description',
|
||||
'nsd_id', 'vim_id'])
|
||||
return body
|
||||
|
||||
|
||||
class DeleteNS(tackerV10.DeleteCommand):
|
||||
"""Delete given NS(s)."""
|
||||
|
||||
resource = _NS
|
||||
deleted_msg = {'ns': 'delete initiated'}
|
||||
85
tackerclient/tacker/v1_0/nfvo/nsd.py
Normal file
85
tackerclient/tacker/v1_0/nfvo/nsd.py
Normal file
@@ -0,0 +1,85 @@
|
||||
# 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.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import yaml
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from tackerclient.i18n import _
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
|
||||
_NSD = "nsd"
|
||||
|
||||
|
||||
class ListNSD(tackerV10.ListCommand):
|
||||
"""List NSDs that belong to a given tenant."""
|
||||
|
||||
resource = _NSD
|
||||
list_columns = ['id', 'name', 'description']
|
||||
|
||||
|
||||
class ShowNSD(tackerV10.ShowCommand):
|
||||
"""Show information of a given NSD."""
|
||||
|
||||
resource = _NSD
|
||||
|
||||
|
||||
class CreateNSD(tackerV10.CreateCommand):
|
||||
"""Create a NSD."""
|
||||
resource = _NSD
|
||||
remove_output_fields = ["attributes"]
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
parser.add_argument('--nsd-file', help='Specify NSD file',
|
||||
required=True)
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help='Set a name for the NSD', required=True)
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help='Set a description for the NSD')
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {self.resource: {}}
|
||||
nsd = None
|
||||
with open(parsed_args.nsd_file) as f:
|
||||
nsd = yaml.safe_load(f.read())
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'description'])
|
||||
if nsd:
|
||||
body[self.resource]['attributes'] = {'nsd': nsd}
|
||||
|
||||
return body
|
||||
|
||||
|
||||
class DeleteNSD(tackerV10.DeleteCommand):
|
||||
"""Delete a given NSD."""
|
||||
resource = _NSD
|
||||
|
||||
|
||||
class ShowTemplateNSD(tackerV10.ShowCommand):
|
||||
"""Show template of a given NSD."""
|
||||
resource = _NSD
|
||||
|
||||
def run(self, parsed_args):
|
||||
self.log.debug('run(%s)', parsed_args)
|
||||
template = None
|
||||
data = self.get_data(parsed_args)
|
||||
try:
|
||||
attributes_index = data[0].index('attributes')
|
||||
attributes_json = data[1][attributes_index]
|
||||
template = jsonutils.loads(attributes_json).get('nsd', None)
|
||||
except (IndexError, TypeError, ValueError) as e:
|
||||
self.log.debug('Data handling error: %s', str(e))
|
||||
print(template or _('Unable to display NSD template!'))
|
||||
@@ -14,11 +14,12 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_utils import strutils
|
||||
import yaml
|
||||
|
||||
from oslo_utils import strutils
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
from tackerclient.common import utils
|
||||
from tackerclient.i18n import _
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
from tackerclient.tacker.v1_0.nfvo import vim_utils
|
||||
|
||||
@@ -30,11 +31,7 @@ class ListVIM(tackerV10.ListCommand):
|
||||
|
||||
resource = _VIM
|
||||
list_columns = ['id', 'tenant_id', 'name', 'type', 'description',
|
||||
'auth_url', 'placement_attr', 'auth_cred']
|
||||
|
||||
def extend_list(self, data, parsed_args):
|
||||
for index, value in enumerate(data):
|
||||
data[index] = strutils.mask_dict_password(value)
|
||||
'auth_url', 'placement_attr', 'auth_cred', 'status']
|
||||
|
||||
|
||||
class ShowVIM(tackerV10.ShowCommand):
|
||||
@@ -49,27 +46,28 @@ class CreateVIM(tackerV10.CreateCommand):
|
||||
resource = _VIM
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('--config-file', help='Specify VIM specific '
|
||||
'config parameters in a file')
|
||||
group.add_argument('--config', help='Specify VIM config parameters '
|
||||
'as a direct input')
|
||||
parser.add_argument(
|
||||
'--name',
|
||||
help='Set a name for the VIM')
|
||||
'--config-file',
|
||||
required=True,
|
||||
help=_('YAML file with VIM configuration parameters'))
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help=_('Set a name for the VIM'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help='Set a description for the VIM')
|
||||
help=_('Set a description for the VIM'))
|
||||
parser.add_argument(
|
||||
'--is-default',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=_('Set as default VIM'))
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {self.resource: {}}
|
||||
if parsed_args.config_file:
|
||||
with open(parsed_args.config_file) as f:
|
||||
vim_config = f.read()
|
||||
config_param = yaml.load(vim_config)
|
||||
if parsed_args.config:
|
||||
parsed_args.config = parsed_args.config.decode('unicode_escape')
|
||||
config_param = yaml.load(parsed_args.config)
|
||||
config_param = yaml.load(vim_config, Loader=yaml.SafeLoader)
|
||||
vim_obj = body[self.resource]
|
||||
try:
|
||||
auth_url = config_param.pop('auth_url')
|
||||
@@ -77,11 +75,12 @@ class CreateVIM(tackerV10.CreateCommand):
|
||||
raise exceptions.TackerClientException(message='Auth URL must be '
|
||||
'specified',
|
||||
status_code=404)
|
||||
vim_obj['auth_url'] = utils.validate_url(auth_url).geturl()
|
||||
vim_obj['auth_url'] = vim_utils.validate_auth_url(auth_url).geturl()
|
||||
vim_obj['type'] = config_param.pop('type', 'openstack')
|
||||
vim_utils.args2body_vim(config_param, vim_obj)
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'description'])
|
||||
['tenant_id', 'name', 'description',
|
||||
'is_default'])
|
||||
return body
|
||||
|
||||
|
||||
@@ -91,13 +90,21 @@ class UpdateVIM(tackerV10.UpdateCommand):
|
||||
resource = _VIM
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument(
|
||||
parser.add_argument(
|
||||
'--config-file',
|
||||
help='Specify VIM specific config parameters in a file')
|
||||
group.add_argument(
|
||||
'--config',
|
||||
help='Specify VIM config parameters as a direct input')
|
||||
required=True,
|
||||
help=_('YAML file with VIM configuration parameters'))
|
||||
parser.add_argument(
|
||||
'--name',
|
||||
help=_('New name for the VIM'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help=_('New description for the VIM'))
|
||||
parser.add_argument(
|
||||
'--is-default',
|
||||
type=strutils.bool_from_string,
|
||||
metavar='{True,False}',
|
||||
help=_('Indicate whether the VIM is used as default'))
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {self.resource: {}}
|
||||
@@ -106,19 +113,18 @@ class UpdateVIM(tackerV10.UpdateCommand):
|
||||
with open(parsed_args.config_file) as f:
|
||||
config_yaml = f.read()
|
||||
config_param = yaml.load(config_yaml)
|
||||
if parsed_args.config:
|
||||
parsed_args.config = parsed_args.config.decode('unicode_escape')
|
||||
config_param = yaml.load(parsed_args.config)
|
||||
if 'auth_url' in config_param:
|
||||
raise exceptions.TackerClientException(message='Auth URL cannot '
|
||||
'be updated',
|
||||
status_code=404)
|
||||
vim_obj = body[self.resource]
|
||||
vim_utils.args2body_vim(config_param, vim_obj)
|
||||
tackerV10.update_dict(parsed_args, body[self.resource], ['tenant_id'])
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'description',
|
||||
'is_default'])
|
||||
return body
|
||||
|
||||
|
||||
class DeleteVIM(tackerV10.DeleteCommand):
|
||||
"""Delete a given VIM."""
|
||||
"""Delete given VIM(s)."""
|
||||
resource = _VIM
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# 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 six.moves.urllib.parse as urlparse
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
|
||||
@@ -25,11 +25,22 @@ def args2body_vim(config_param, vim):
|
||||
:return: vim body with args populated
|
||||
"""
|
||||
vim['vim_project'] = {'id': config_param.pop('project_id', ''),
|
||||
'name': config_param.pop('project_name', '')}
|
||||
'name': config_param.pop('project_name', ''),
|
||||
'project_domain_name':
|
||||
config_param.pop('project_domain_name', '')}
|
||||
if not vim['vim_project']['id'] and not vim['vim_project']['name']:
|
||||
raise exceptions.TackerClientException(message='Project Id or name '
|
||||
'must be specified',
|
||||
status_code=404)
|
||||
vim['auth_cred'] = {'username': config_param.pop('username', ''),
|
||||
'password': config_param.pop('password', ''),
|
||||
'user_id': config_param.pop('user_id', '')}
|
||||
'user_id': config_param.pop('user_id', ''),
|
||||
'user_domain_name':
|
||||
config_param.pop('user_domain_name', '')}
|
||||
|
||||
|
||||
def validate_auth_url(url):
|
||||
url_parts = urlparse.urlparse(url)
|
||||
if not url_parts.scheme or not url_parts.netloc:
|
||||
raise exceptions.TackerClientException(message='Invalid auth URL')
|
||||
return url_parts
|
||||
|
||||
182
tackerclient/tacker/v1_0/nfvo/vnffg.py
Normal file
182
tackerclient/tacker/v1_0/nfvo/vnffg.py
Normal file
@@ -0,0 +1,182 @@
|
||||
# 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.
|
||||
|
||||
from tackerclient.i18n import _
|
||||
import yaml
|
||||
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
|
||||
|
||||
_VNFFG = 'vnffg'
|
||||
_NFP = 'nfp'
|
||||
_SFC = 'sfc'
|
||||
_FC = 'classifier'
|
||||
|
||||
|
||||
class ListFC(tackerV10.ListCommand):
|
||||
"""List FCs that belong to a given tenant."""
|
||||
|
||||
resource = _FC
|
||||
list_columns = ['id', 'status', 'nfp_id', 'chain_id']
|
||||
|
||||
|
||||
class ShowFC(tackerV10.ShowCommand):
|
||||
"""Show information of a given FC."""
|
||||
|
||||
resource = _FC
|
||||
|
||||
|
||||
class ListSFC(tackerV10.ListCommand):
|
||||
"""List SFCs that belong to a given tenant."""
|
||||
|
||||
resource = _SFC
|
||||
list_columns = ['id', 'status', 'nfp_id']
|
||||
|
||||
|
||||
class ShowSFC(tackerV10.ShowCommand):
|
||||
"""Show information of a given SFC."""
|
||||
|
||||
resource = _SFC
|
||||
|
||||
|
||||
class ListNFP(tackerV10.ListCommand):
|
||||
"""List NFPs that belong to a given tenant."""
|
||||
|
||||
resource = _NFP
|
||||
list_columns = ['id', 'name', 'status', 'vnffg_id', 'path_id']
|
||||
|
||||
|
||||
class ShowNFP(tackerV10.ShowCommand):
|
||||
"""Show information of a given NFP."""
|
||||
|
||||
resource = _NFP
|
||||
|
||||
|
||||
class ListVNFFG(tackerV10.ListCommand):
|
||||
"""List VNFFGs that belong to a given tenant."""
|
||||
|
||||
resource = _VNFFG
|
||||
list_columns = ['id', 'name', 'description', 'status', 'vnffgd_id']
|
||||
|
||||
|
||||
class ShowVNFFG(tackerV10.ShowCommand):
|
||||
"""Show information of a given VNFFG."""
|
||||
|
||||
resource = _VNFFG
|
||||
|
||||
|
||||
class CreateVNFFG(tackerV10.CreateCommand):
|
||||
"""Create a VNFFG."""
|
||||
|
||||
resource = _VNFFG
|
||||
remove_output_fields = ["attributes"]
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help=_('Set a name for the VNFFG'))
|
||||
vnffgd_group = parser.add_mutually_exclusive_group(required=True)
|
||||
vnffgd_group.add_argument(
|
||||
'--vnffgd-id',
|
||||
help=_('VNFFGD ID to use as template to create VNFFG'))
|
||||
vnffgd_group.add_argument(
|
||||
'--vnffgd-name',
|
||||
help=_('VNFFGD Name to use as template to create VNFFG'))
|
||||
parser.add_argument(
|
||||
'--vnf-mapping',
|
||||
help=_('List of logical VNFD name to VNF instance name mapping. '
|
||||
'Example: VNF1:my_vnf1,VNF2:my_vnf2'))
|
||||
parser.add_argument(
|
||||
'--symmetrical', metavar='{True,False}',
|
||||
help=_('Should a reverse path be created for the NFP'))
|
||||
parser.add_argument(
|
||||
'--param-file',
|
||||
help='Specify parameter yaml file'
|
||||
)
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
args = {'attributes': {}}
|
||||
body = {self.resource: args}
|
||||
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
|
||||
if parsed_args.vnf_mapping:
|
||||
_vnf_mapping = dict()
|
||||
_vnf_mappings = parsed_args.vnf_mapping.split(",")
|
||||
for mapping in _vnf_mappings:
|
||||
vnfd_name, vnf = mapping.split(":", 1)
|
||||
_vnf_mapping[vnfd_name] = \
|
||||
tackerV10.find_resourceid_by_name_or_id(
|
||||
tacker_client, 'vnf', vnf)
|
||||
|
||||
parsed_args.vnf_mapping = _vnf_mapping
|
||||
|
||||
if parsed_args.vnffgd_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
'vnffgd',
|
||||
parsed_args.
|
||||
vnffgd_name)
|
||||
parsed_args.vnffgd_id = _id
|
||||
|
||||
if parsed_args.param_file:
|
||||
with open(parsed_args.param_file) as f:
|
||||
param_yaml = f.read()
|
||||
args['attributes']['param_values'] = yaml.load(
|
||||
param_yaml, Loader=yaml.SafeLoader)
|
||||
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'vnffgd_id',
|
||||
'symmetrical', 'vnf_mapping'])
|
||||
return body
|
||||
|
||||
|
||||
class UpdateVNFFG(tackerV10.UpdateCommand):
|
||||
"""Update a given VNFFG."""
|
||||
|
||||
resource = _VNFFG
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'--vnf-mapping',
|
||||
help=_('List of logical VNFD name to VNF instance name mapping. '
|
||||
'Example: VNF1:my_vnf1,VNF2:my_vnf2'))
|
||||
parser.add_argument(
|
||||
'--symmetrical', metavar='{True,False}',
|
||||
help=_('Should a reverse path be created for the NFP'))
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {self.resource: {}}
|
||||
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
|
||||
if parsed_args.vnf_mapping:
|
||||
_vnf_mapping = dict()
|
||||
_vnf_mappings = parsed_args.vnf_mapping.split(",")
|
||||
for mapping in _vnf_mappings:
|
||||
vnfd_name, vnf = mapping.split(":", 1)
|
||||
_vnf_mapping[vnfd_name] = \
|
||||
tackerV10.find_resourceid_by_name_or_id(
|
||||
tacker_client, 'vnf', vnf)
|
||||
|
||||
parsed_args.vnf_mapping = _vnf_mapping
|
||||
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'vnf_mapping', 'symmetrical'])
|
||||
return body
|
||||
|
||||
|
||||
class DeleteVNFFG(tackerV10.DeleteCommand):
|
||||
"""Delete a given VNFFG."""
|
||||
|
||||
resource = _VNFFG
|
||||
87
tackerclient/tacker/v1_0/nfvo/vnffgd.py
Normal file
87
tackerclient/tacker/v1_0/nfvo/vnffgd.py
Normal file
@@ -0,0 +1,87 @@
|
||||
# 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.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import yaml
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from tackerclient.i18n import _
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
|
||||
_VNFFGD = "vnffgd"
|
||||
|
||||
|
||||
class ListVNFFGD(tackerV10.ListCommand):
|
||||
"""List VNFFGDs that belong to a given tenant."""
|
||||
|
||||
resource = _VNFFGD
|
||||
list_columns = ['id', 'name', 'description']
|
||||
|
||||
|
||||
class ShowVNFFGD(tackerV10.ShowCommand):
|
||||
"""Show information of a given VNFFGD."""
|
||||
|
||||
resource = _VNFFGD
|
||||
|
||||
|
||||
class CreateVNFFGD(tackerV10.CreateCommand):
|
||||
"""Create a VNFFGD."""
|
||||
resource = _VNFFGD
|
||||
remove_output_fields = ["attributes"]
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('--vnffgd-file', help=_('Specify VNFFGD file'))
|
||||
group.add_argument('--vnffgd', help=_('Specify VNFFGD'))
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help=_('Set a name for the VNFFGD'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help=_('Set a description for the VNFFGD'))
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {self.resource: {}}
|
||||
if parsed_args.vnffgd_file:
|
||||
with open(parsed_args.vnffgd_file) as f:
|
||||
vnffgd = yaml.safe_load(f.read())
|
||||
body[self.resource]['template'] = {'vnffgd': vnffgd}
|
||||
if parsed_args.vnffgd:
|
||||
body[self.resource]['template'] = {
|
||||
'vnffgd': yaml.safe_load(parsed_args.vnffgd)}
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'description'])
|
||||
return body
|
||||
|
||||
|
||||
class DeleteVNFFGD(tackerV10.DeleteCommand):
|
||||
"""Delete a given VNFFGD."""
|
||||
resource = _VNFFGD
|
||||
|
||||
|
||||
class ShowTemplateVNFFGD(tackerV10.ShowCommand):
|
||||
"""Show template of a given VNFFGD."""
|
||||
resource = _VNFFGD
|
||||
|
||||
def run(self, parsed_args):
|
||||
self.log.debug('run(%s)', parsed_args)
|
||||
template = None
|
||||
data = self.get_data(parsed_args)
|
||||
try:
|
||||
attributes_index = data[0].index('attributes')
|
||||
attributes_json = data[1][attributes_index]
|
||||
template = jsonutils.loads(attributes_json).get('vnffgd', None)
|
||||
except (IndexError, TypeError, ValueError) as e:
|
||||
self.log.debug('Data handling error: %s', str(e))
|
||||
print(template or _('Unable to display VNFFGD template!'))
|
||||
@@ -1,145 +0,0 @@
|
||||
#
|
||||
# Copyright 2013 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
|
||||
#
|
||||
# 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.
|
||||
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
|
||||
|
||||
_VNF = 'vnf'
|
||||
|
||||
|
||||
class ListVNF(tackerV10.ListCommand):
|
||||
"""List VNF that belong to a given tenant."""
|
||||
|
||||
resource = _VNF
|
||||
list_columns = ['id', 'name', 'description', 'mgmt_url', 'status',
|
||||
'vim_id', 'placement_attr', 'error_reason']
|
||||
|
||||
|
||||
class ShowVNF(tackerV10.ShowCommand):
|
||||
"""Show information of a given VNF."""
|
||||
|
||||
resource = _VNF
|
||||
|
||||
|
||||
class CreateVNF(tackerV10.CreateCommand):
|
||||
"""Create a VNF."""
|
||||
|
||||
resource = _VNF
|
||||
remove_output_fields = ["attributes"]
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'--name',
|
||||
help='Set a name for the VNF')
|
||||
vnfd_group = parser.add_mutually_exclusive_group(required=True)
|
||||
vnfd_group.add_argument(
|
||||
'--vnfd-id',
|
||||
help='VNFD ID to use as template to create VNF')
|
||||
vnfd_group.add_argument(
|
||||
'--vnfd-name',
|
||||
help='VNFD Name to use as template to create VNF')
|
||||
vim_group = parser.add_mutually_exclusive_group()
|
||||
vim_group.add_argument(
|
||||
'--vim-id',
|
||||
help='VIM ID to use to create VNF on the specified VIM')
|
||||
vim_group.add_argument(
|
||||
'--vim-name',
|
||||
help='VIM name to use to create VNF on the specified VIM')
|
||||
parser.add_argument(
|
||||
'--vim-region-name',
|
||||
help='VIM Region to use to create VNF on the specified VIM')
|
||||
parser.add_argument(
|
||||
'--config-file',
|
||||
help='Specify config yaml file')
|
||||
parser.add_argument(
|
||||
'--config',
|
||||
help='Specify config yaml data')
|
||||
parser.add_argument(
|
||||
'--param-file',
|
||||
help='Specify parameter yaml file'
|
||||
)
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
args = {'attributes': {}}
|
||||
body = {self.resource: args}
|
||||
# config arg passed as data overrides config yaml when both args passed
|
||||
if parsed_args.config_file:
|
||||
with open(parsed_args.config_file) as f:
|
||||
config_yaml = f.read()
|
||||
args['attributes']['config'] = config_yaml
|
||||
if parsed_args.config:
|
||||
parsed_args.config = parsed_args.config.decode('unicode_escape')
|
||||
args['attributes']['config'] = parsed_args.config
|
||||
|
||||
if parsed_args.vim_region_name:
|
||||
args.setdefault('placement_attr', {})['region_name'] = \
|
||||
parsed_args.vim_region_name
|
||||
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
if parsed_args.vim_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
'vim',
|
||||
parsed_args.
|
||||
vim_name)
|
||||
parsed_args.vim_id = _id
|
||||
if parsed_args.vnfd_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
'vnfd',
|
||||
parsed_args.
|
||||
vnfd_name)
|
||||
parsed_args.vnfd_id = _id
|
||||
if parsed_args.param_file:
|
||||
with open(parsed_args.param_file) as f:
|
||||
param_yaml = f.read()
|
||||
args['attributes']['param_values'] = param_yaml
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'vnfd_id', 'vim_id'])
|
||||
return body
|
||||
|
||||
|
||||
class UpdateVNF(tackerV10.UpdateCommand):
|
||||
"""Update a given VNF."""
|
||||
|
||||
resource = _VNF
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'--config-file',
|
||||
help='Specify config yaml file')
|
||||
parser.add_argument(
|
||||
'--config',
|
||||
help='Specify config yaml data')
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {self.resource: {}}
|
||||
# config arg passed as data overrides config yaml when both args passed
|
||||
if parsed_args.config_file:
|
||||
with open(parsed_args.config_file) as f:
|
||||
config_yaml = f.read()
|
||||
body[self.resource]['attributes'] = {'config': config_yaml}
|
||||
if parsed_args.config:
|
||||
parsed_args.config = parsed_args.config.decode('unicode_escape')
|
||||
body[self.resource]['attributes'] = {'config': parsed_args.config}
|
||||
tackerV10.update_dict(parsed_args, body[self.resource], ['tenant_id'])
|
||||
return body
|
||||
|
||||
|
||||
class DeleteVNF(tackerV10.DeleteCommand):
|
||||
"""Delete a given VNF."""
|
||||
|
||||
resource = _VNF
|
||||
0
tackerclient/tacker/v1_0/vnfm/__init__.py
Normal file
0
tackerclient/tacker/v1_0/vnfm/__init__.py
Normal file
292
tackerclient/tacker/v1_0/vnfm/vnf.py
Normal file
292
tackerclient/tacker/v1_0/vnfm/vnf.py
Normal file
@@ -0,0 +1,292 @@
|
||||
#
|
||||
# Copyright 2013 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
|
||||
#
|
||||
# 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 yaml
|
||||
|
||||
from tackerclient.common import utils
|
||||
from tackerclient.i18n import _
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
|
||||
|
||||
_VNF = 'vnf'
|
||||
_RESOURCE = 'resource'
|
||||
|
||||
|
||||
class ListVNF(tackerV10.ListCommand):
|
||||
"""List VNF that belong to a given tenant."""
|
||||
|
||||
resource = _VNF
|
||||
list_columns = ['id', 'name', 'description', 'mgmt_url', 'status',
|
||||
'vim_id', 'placement_attr', 'error_reason']
|
||||
|
||||
|
||||
class ShowVNF(tackerV10.ShowCommand):
|
||||
"""Show information of a given VNF."""
|
||||
|
||||
resource = _VNF
|
||||
|
||||
|
||||
class CreateVNF(tackerV10.CreateCommand):
|
||||
"""Create a VNF."""
|
||||
|
||||
resource = _VNF
|
||||
remove_output_fields = ["attributes"]
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help=_('Set a name for the VNF'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help=_('Set description for the VNF'))
|
||||
vnfd_group = parser.add_mutually_exclusive_group(required=True)
|
||||
vnfd_group.add_argument(
|
||||
'--vnfd-id',
|
||||
help=_('VNFD ID to use as template to create VNF'))
|
||||
vnfd_group.add_argument(
|
||||
'--vnfd-name',
|
||||
help=_('VNFD Name to use as template to create VNF'))
|
||||
vim_group = parser.add_mutually_exclusive_group()
|
||||
vim_group.add_argument(
|
||||
'--vim-id',
|
||||
help=_('VIM ID to use to create VNF on the specified VIM'))
|
||||
vim_group.add_argument(
|
||||
'--vim-name',
|
||||
help=_('VIM name to use to create VNF on the specified VIM'))
|
||||
parser.add_argument(
|
||||
'--vim-region-name',
|
||||
help=_('VIM Region to use to create VNF on the specified VIM'))
|
||||
parser.add_argument(
|
||||
'--config-file',
|
||||
help=_('YAML file with VNF configuration'))
|
||||
parser.add_argument(
|
||||
'--config',
|
||||
help=_('Specify config yaml data'))
|
||||
parser.add_argument(
|
||||
'--param-file',
|
||||
help=_('Specify parameter yaml file'))
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
args = {'attributes': {}}
|
||||
body = {self.resource: args}
|
||||
# config arg passed as data overrides config yaml when both args passed
|
||||
config = None
|
||||
if parsed_args.config_file:
|
||||
with open(parsed_args.config_file) as f:
|
||||
config_yaml = f.read()
|
||||
config = yaml.load(
|
||||
config_yaml, Loader=yaml.SafeLoader)
|
||||
if parsed_args.config:
|
||||
config = parsed_args.config
|
||||
if isinstance(config, str):
|
||||
config_str = parsed_args.config.decode('unicode_escape')
|
||||
config = yaml.load(config_str, Loader=yaml.SafeLoader)
|
||||
utils.deprecate_warning(what='yaml as string', as_of='N',
|
||||
in_favor_of='yaml as dictionary')
|
||||
|
||||
if config:
|
||||
args['attributes']['config'] = config
|
||||
if parsed_args.vim_region_name:
|
||||
args.setdefault('placement_attr', {})['region_name'] = \
|
||||
parsed_args.vim_region_name
|
||||
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
if parsed_args.vim_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
'vim',
|
||||
parsed_args.
|
||||
vim_name)
|
||||
parsed_args.vim_id = _id
|
||||
if parsed_args.vnfd_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
'vnfd',
|
||||
parsed_args.
|
||||
vnfd_name)
|
||||
parsed_args.vnfd_id = _id
|
||||
if parsed_args.param_file:
|
||||
with open(parsed_args.param_file) as f:
|
||||
param_yaml = f.read()
|
||||
args['attributes']['param_values'] = yaml.load(
|
||||
param_yaml, Loader=yaml.SafeLoader)
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'description',
|
||||
'vnfd_id', 'vim_id'])
|
||||
return body
|
||||
|
||||
|
||||
class UpdateVNF(tackerV10.UpdateCommand):
|
||||
"""Update a given VNF."""
|
||||
|
||||
resource = _VNF
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'--config-file',
|
||||
help=_('YAML file with VNF configuration'))
|
||||
parser.add_argument(
|
||||
'--config',
|
||||
help=_('Specify config yaml data'))
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {self.resource: {}}
|
||||
# config arg passed as data overrides config yaml when both args passed
|
||||
config = None
|
||||
if parsed_args.config_file:
|
||||
with open(parsed_args.config_file) as f:
|
||||
config_yaml = f.read()
|
||||
config = yaml.load(config_yaml, Loader=yaml.SafeLoader)
|
||||
if parsed_args.config:
|
||||
config = parsed_args.config
|
||||
if isinstance(parsed_args.config, str):
|
||||
config_str = parsed_args.config.decode('unicode_escape')
|
||||
config = yaml.load(config_str, Loader=yaml.SafeLoader)
|
||||
utils.deprecate_warning(what='yaml as string', as_of='N',
|
||||
in_favor_of='yaml as dictionary')
|
||||
if config:
|
||||
body[self.resource]['attributes'] = {'config': config}
|
||||
tackerV10.update_dict(parsed_args, body[self.resource], ['tenant_id'])
|
||||
return body
|
||||
|
||||
|
||||
class DeleteVNF(tackerV10.DeleteCommand):
|
||||
"""Delete given VNF(s)."""
|
||||
|
||||
resource = _VNF
|
||||
deleted_msg = {'vnf': 'delete initiated'}
|
||||
|
||||
|
||||
class ListVNFResources(tackerV10.ListCommand):
|
||||
"""List resources of a VNF like VDU, CP, etc."""
|
||||
|
||||
list_columns = ['name', 'id', 'type']
|
||||
allow_names = True
|
||||
resource = _VNF
|
||||
|
||||
def get_id(self):
|
||||
if self.resource:
|
||||
return self.resource.upper()
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListVNFResources, self).get_parser(prog_name)
|
||||
if self.allow_names:
|
||||
help_str = _('ID or name of %s to look up')
|
||||
else:
|
||||
help_str = _('ID of %s to look up')
|
||||
parser.add_argument(
|
||||
'id', metavar=self.get_id(),
|
||||
help=help_str % self.resource)
|
||||
return parser
|
||||
|
||||
def get_data(self, parsed_args):
|
||||
self.log.debug('get_data(%s)', parsed_args)
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
if self.allow_names:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
self.resource,
|
||||
parsed_args.id)
|
||||
else:
|
||||
_id = parsed_args.id
|
||||
|
||||
data = self.retrieve_list_by_id(_id, parsed_args)
|
||||
self.extend_list(data, parsed_args)
|
||||
return self.setup_columns(data, parsed_args)
|
||||
|
||||
def retrieve_list_by_id(self, id, parsed_args):
|
||||
"""Retrieve a list of sub resources from Tacker server"""
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
_extra_values = tackerV10.parse_args_to_dict(self.values_specs)
|
||||
tackerV10._merge_args(self, parsed_args, _extra_values,
|
||||
self.values_specs)
|
||||
search_opts = self.args2search_opts(parsed_args)
|
||||
search_opts.update(_extra_values)
|
||||
if self.pagination_support:
|
||||
page_size = parsed_args.page_size
|
||||
if page_size:
|
||||
search_opts.update({'limit': page_size})
|
||||
if self.sorting_support:
|
||||
keys = parsed_args.sort_key
|
||||
if keys:
|
||||
search_opts.update({'sort_key': keys})
|
||||
dirs = parsed_args.sort_dir
|
||||
len_diff = len(keys) - len(dirs)
|
||||
if len_diff > 0:
|
||||
dirs += ['asc'] * len_diff
|
||||
elif len_diff < 0:
|
||||
dirs = dirs[:len(keys)]
|
||||
if dirs:
|
||||
search_opts.update({'sort_dir': dirs})
|
||||
obj_lister = getattr(tacker_client, "list_vnf_resources")
|
||||
data = obj_lister(id, **search_opts)
|
||||
return data.get('resources', [])
|
||||
|
||||
|
||||
class ScaleVNF(tackerV10.TackerCommand):
|
||||
"""Scale a VNF."""
|
||||
|
||||
api = 'nfv-orchestration'
|
||||
resource = None
|
||||
log = None
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ScaleVNF, self).get_parser(prog_name)
|
||||
self.add_known_arguments(parser)
|
||||
return parser
|
||||
|
||||
def run(self, parsed_args):
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
body = self.args2body(parsed_args)
|
||||
obj_creator = getattr(tacker_client,
|
||||
"scale_vnf")
|
||||
obj_creator(body["scale"].pop('vnf_id'), body)
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
vnf_group = parser.add_mutually_exclusive_group(required=True)
|
||||
vnf_group.add_argument(
|
||||
'--vnf-id',
|
||||
help=_('VNF ID'))
|
||||
vnf_group.add_argument(
|
||||
'--vnf-name',
|
||||
help=_('VNF name'))
|
||||
parser.add_argument(
|
||||
'--scaling-policy-name',
|
||||
help=_('VNF policy name used to scale'))
|
||||
parser.add_argument(
|
||||
'--scaling-type',
|
||||
help=_('VNF scaling type, it could be either "out" or "in"'))
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
args = {}
|
||||
body = {"scale": args}
|
||||
|
||||
if parsed_args.vnf_name:
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
'vnf',
|
||||
parsed_args.
|
||||
vnf_name)
|
||||
parsed_args.vnf_id = _id
|
||||
|
||||
args['vnf_id'] = parsed_args.vnf_id
|
||||
args['type'] = parsed_args.scaling_type
|
||||
args['policy'] = parsed_args.scaling_policy_name
|
||||
|
||||
return body
|
||||
@@ -18,7 +18,9 @@
|
||||
from __future__ import print_function
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
import yaml
|
||||
|
||||
from tackerclient.common import utils
|
||||
from tackerclient.i18n import _
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
|
||||
@@ -30,7 +32,7 @@ class ListVNFD(tackerV10.ListCommand):
|
||||
"""List VNFD that belong to a given tenant."""
|
||||
|
||||
resource = _VNFD
|
||||
list_columns = ['id', 'name', 'description', 'infra_driver', 'mgmt_driver']
|
||||
list_columns = ['id', 'name', 'description']
|
||||
|
||||
|
||||
class ShowVNFD(tackerV10.ShowCommand):
|
||||
@@ -47,23 +49,32 @@ class CreateVNFD(tackerV10.CreateCommand):
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('--vnfd-file', help='Specify VNFD file')
|
||||
group.add_argument('--vnfd', help='Specify VNFD')
|
||||
group.add_argument('--vnfd-file', help=_('Specify VNFD file'))
|
||||
group.add_argument('--vnfd', help=_('Specify VNFD'))
|
||||
parser.add_argument(
|
||||
'--name',
|
||||
help='Set a name for the VNFD')
|
||||
'name', metavar='NAME',
|
||||
help=_('Set a name for the VNFD'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help='Set a description for the VNFD')
|
||||
help=_('Set a description for the VNFD'))
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {self.resource: {}}
|
||||
vnfd = None
|
||||
if parsed_args.vnfd_file:
|
||||
with open(parsed_args.vnfd_file) as f:
|
||||
vnfd = f.read()
|
||||
body[self.resource]['attributes'] = {'vnfd': vnfd}
|
||||
if "tosca_definitions_version" in vnfd:
|
||||
vnfd = yaml.load(vnfd, Loader=yaml.SafeLoader)
|
||||
if parsed_args.vnfd:
|
||||
body[self.resource]['attributes'] = {'vnfd': parsed_args.vnfd}
|
||||
vnfd = parsed_args.vnfd
|
||||
if isinstance(vnfd, str):
|
||||
vnfd = yaml.load(vnfd, Loader=yaml.SafeLoader)
|
||||
utils.deprecate_warning(what='yaml as string',
|
||||
as_of='N',
|
||||
in_favor_of='yaml as dictionary')
|
||||
if vnfd:
|
||||
body[self.resource]['attributes'] = {'vnfd': vnfd}
|
||||
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'description'])
|
||||
@@ -71,7 +82,7 @@ class CreateVNFD(tackerV10.CreateCommand):
|
||||
|
||||
|
||||
class DeleteVNFD(tackerV10.DeleteCommand):
|
||||
"""Delete a given VNFD."""
|
||||
"""Delete given VNFD(s)."""
|
||||
resource = _VNFD
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
import urllib
|
||||
|
||||
import contextlib
|
||||
import cStringIO
|
||||
import fixtures
|
||||
import mox
|
||||
import mock
|
||||
import six
|
||||
import six.moves.urllib.parse as urlparse
|
||||
import sys
|
||||
import testtools
|
||||
|
||||
@@ -28,6 +28,7 @@ from tackerclient.common import constants
|
||||
from tackerclient.common import exceptions
|
||||
from tackerclient import shell
|
||||
from tackerclient.tacker import v1_0 as tackerV1_0
|
||||
from tackerclient.tacker.v1_0 import TackerCommand
|
||||
from tackerclient.v1_0 import client
|
||||
|
||||
API_VERSION = "1.0"
|
||||
@@ -38,7 +39,7 @@ ENDURL = 'localurl'
|
||||
|
||||
@contextlib.contextmanager
|
||||
def capture_std_streams():
|
||||
fake_stdout, fake_stderr = cStringIO.StringIO(), cStringIO.StringIO()
|
||||
fake_stdout, fake_stderr = six.StringIO(), six.StringIO()
|
||||
stdout, stderr = sys.stdout, sys.stderr
|
||||
try:
|
||||
sys.stdout, sys.stderr = fake_stdout, fake_stderr
|
||||
@@ -79,13 +80,23 @@ def end_url(path, query=None, format=FORMAT):
|
||||
return query and _url_str + "?" + query or _url_str
|
||||
|
||||
|
||||
class MyUrlComparator(mox.Comparator):
|
||||
class MyUrlComparator(object):
|
||||
def __init__(self, lhs, client):
|
||||
self.lhs = lhs
|
||||
self.client = client
|
||||
|
||||
def equals(self, rhs):
|
||||
return str(self) == rhs
|
||||
lhsp = urlparse.urlparse(self.lhs)
|
||||
rhsp = urlparse.urlparse(rhs)
|
||||
|
||||
lhs_qs = urlparse.parse_qsl(lhsp.query)
|
||||
rhs_qs = urlparse.parse_qsl(rhsp.query)
|
||||
|
||||
return (lhsp.scheme == rhsp.scheme and
|
||||
lhsp.netloc == rhsp.netloc and
|
||||
lhsp.path == rhsp.path and
|
||||
len(lhs_qs) == len(rhs_qs) and
|
||||
set(lhs_qs) == set(rhs_qs))
|
||||
|
||||
def __str__(self):
|
||||
if self.client and self.client.format != FORMAT:
|
||||
@@ -104,7 +115,7 @@ class MyUrlComparator(mox.Comparator):
|
||||
return str(self)
|
||||
|
||||
|
||||
class MyComparator(mox.Comparator):
|
||||
class MyComparator(object):
|
||||
def __init__(self, lhs, client):
|
||||
self.lhs = lhs
|
||||
self.client = client
|
||||
@@ -155,6 +166,12 @@ class MyComparator(mox.Comparator):
|
||||
return self.client.serialize(self.lhs)
|
||||
return str(self.lhs)
|
||||
|
||||
def __eq__(self, rhs):
|
||||
return self.equals(rhs)
|
||||
|
||||
def __ne__(self, rhs):
|
||||
return not self.__eq__(rhs)
|
||||
|
||||
|
||||
class CLITestV10Base(testtools.TestCase):
|
||||
|
||||
@@ -165,14 +182,6 @@ class CLITestV10Base(testtools.TestCase):
|
||||
def _find_resourceid(self, client, resource, name_or_id):
|
||||
return name_or_id
|
||||
|
||||
def _get_attr_metadata(self):
|
||||
return self.metadata
|
||||
client.Client.EXTED_PLURALS.update(constants.PLURALS)
|
||||
client.Client.EXTED_PLURALS.update({'tags': 'tag'})
|
||||
return {'plurals': client.Client.EXTED_PLURALS,
|
||||
'xmlns': constants.XML_NS_V10,
|
||||
constants.EXT_NS: {'prefix': 'http://xxxx.yy.com'}}
|
||||
|
||||
def setUp(self, plurals={}):
|
||||
"""Prepare the test environment."""
|
||||
super(CLITestV10Base, self).setUp()
|
||||
@@ -182,7 +191,6 @@ class CLITestV10Base(testtools.TestCase):
|
||||
'xmlns': constants.XML_NS_V10,
|
||||
constants.EXT_NS: {'prefix':
|
||||
'http://xxxx.yy.com'}}
|
||||
self.mox = mox.Mox()
|
||||
self.endurl = ENDURL
|
||||
self.fake_stdout = FakeStdout()
|
||||
self.useFixture(fixtures.MonkeyPatch('sys.stdout', self.fake_stdout))
|
||||
@@ -192,20 +200,17 @@ class CLITestV10Base(testtools.TestCase):
|
||||
self.useFixture(fixtures.MonkeyPatch(
|
||||
'tackerclient.tacker.v1_0.find_resourceid_by_id',
|
||||
self._find_resourceid))
|
||||
self.useFixture(fixtures.MonkeyPatch(
|
||||
'tackerclient.v1_0.client.Client.get_attr_metadata',
|
||||
self._get_attr_metadata))
|
||||
self.client = client.Client(token=TOKEN, endpoint_url=self.endurl)
|
||||
|
||||
@mock.patch.object(TackerCommand, 'get_client')
|
||||
def _test_create_resource(self, resource, cmd,
|
||||
name, myid, args,
|
||||
position_names, position_values, tenant_id=None,
|
||||
position_names, position_values, mock_get,
|
||||
tenant_id=None, get_client_called_count=1,
|
||||
tags=None, admin_state_up=True, extra_body=None,
|
||||
**kwargs):
|
||||
self.mox.StubOutWithMock(cmd, "get_client")
|
||||
self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
cmd.get_client().MultipleTimes().AndReturn(self.client)
|
||||
non_admin_status_resources = ['vnfd', 'vnf', 'vim']
|
||||
mock_get.return_value = self.client
|
||||
non_admin_status_resources = ['vnfd', 'vnf', 'vim', 'vnffgd', 'vnffg']
|
||||
if (resource in non_admin_status_resources):
|
||||
body = {resource: {}, }
|
||||
else:
|
||||
@@ -233,53 +238,56 @@ class CLITestV10Base(testtools.TestCase):
|
||||
# Work around for LP #1217791. XML deserializer called from
|
||||
# MyComparator does not decodes XML string correctly.
|
||||
if self.format == 'json':
|
||||
mox_body = MyComparator(body, self.client)
|
||||
_body = MyComparator(body, self.client)
|
||||
else:
|
||||
mox_body = self.client.serialize(body)
|
||||
self.client.httpclient.request(
|
||||
end_url(path, format=self.format), 'POST',
|
||||
body=mox_body,
|
||||
headers=mox.ContainsKeyValue(
|
||||
'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr))
|
||||
args.extend(['--request-format', self.format])
|
||||
self.mox.ReplayAll()
|
||||
cmd_parser = cmd.get_parser('create_' + resource)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
self.mox.VerifyAll()
|
||||
self.mox.UnsetStubs()
|
||||
_body = self.client.serialize(body)
|
||||
with mock.patch.object(self.client.httpclient, 'request') as mock_req:
|
||||
mock_req.return_value = (MyResp(200), resstr)
|
||||
self.client.httpclient.request(
|
||||
end_url(path, format=self.format), 'POST',
|
||||
body=_body,
|
||||
headers={'X-Auth-Token', TOKEN})
|
||||
mock_req.assert_called_once_with(
|
||||
end_url(path, format=self.format), 'POST',
|
||||
body=_body,
|
||||
headers={'X-Auth-Token', TOKEN})
|
||||
args.extend(['--request-format', self.format])
|
||||
cmd_parser = cmd.get_parser('create_' + resource)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
self.assertEqual(get_client_called_count, mock_get.call_count)
|
||||
_str = self.fake_stdout.make_string()
|
||||
self.assertIn(myid, _str)
|
||||
if name:
|
||||
self.assertIn(name, _str)
|
||||
|
||||
@mock.patch.object(TackerCommand, 'get_client')
|
||||
def _test_list_columns(self, cmd, resources_collection,
|
||||
resources_out, args=['-f', 'json']):
|
||||
self.mox.StubOutWithMock(cmd, "get_client")
|
||||
self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
cmd.get_client().MultipleTimes().AndReturn(self.client)
|
||||
resources_out, mock_get,
|
||||
args=['-f', 'json']):
|
||||
mock_get.return_value = self.client
|
||||
self.client.format = self.format
|
||||
resstr = self.client.serialize(resources_out)
|
||||
|
||||
path = getattr(self.client, resources_collection + "_path")
|
||||
self.client.httpclient.request(
|
||||
end_url(path, format=self.format), 'GET',
|
||||
body=None,
|
||||
headers=mox.ContainsKeyValue(
|
||||
'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr))
|
||||
args.extend(['--request-format', self.format])
|
||||
self.mox.ReplayAll()
|
||||
cmd_parser = cmd.get_parser("list_" + resources_collection)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
self.mox.VerifyAll()
|
||||
self.mox.UnsetStubs()
|
||||
with mock.patch.object(self.client.httpclient, 'request') as mock_req:
|
||||
mock_req.return_value = (MyResp(200), resstr)
|
||||
self.client.httpclient.request(
|
||||
end_url(path, format=self.format), 'GET',
|
||||
body=None,
|
||||
headers={'X-Auth-Token': TOKEN})
|
||||
mock_req.assert_called_once_with(
|
||||
end_url(path, format=self.format), 'GET',
|
||||
body=None,
|
||||
headers={'X-Auth-Token': TOKEN})
|
||||
args.extend(['--request-format', self.format])
|
||||
cmd_parser = cmd.get_parser("list_" + resources_collection)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
mock_get.assert_called_once_with()
|
||||
|
||||
def _test_list_resources(self, resources, cmd, detail=False, tags=[],
|
||||
fields_1=[], fields_2=[], page_size=None,
|
||||
sort_key=[], sort_dir=[], response_contents=None,
|
||||
base_args=None, path=None):
|
||||
self.mox.StubOutWithMock(cmd, "get_client")
|
||||
self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
cmd.get_client().MultipleTimes().AndReturn(self.client)
|
||||
if response_contents is None:
|
||||
contents = [{self.id_field: 'myid1', },
|
||||
{self.id_field: 'myid2', }, ]
|
||||
@@ -352,147 +360,289 @@ class CLITestV10Base(testtools.TestCase):
|
||||
query += 'sort_dir=%s' % dir
|
||||
if path is None:
|
||||
path = getattr(self.client, resources + "_path")
|
||||
self.client.httpclient.request(
|
||||
MyUrlComparator(end_url(path, query, format=self.format),
|
||||
self.client),
|
||||
'GET',
|
||||
body=None,
|
||||
headers=mox.ContainsKeyValue(
|
||||
'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr))
|
||||
self.mox.ReplayAll()
|
||||
cmd_parser = cmd.get_parser("list_" + resources)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
self.mox.VerifyAll()
|
||||
self.mox.UnsetStubs()
|
||||
with mock.patch.object(self.client.httpclient, 'request') as mock_req:
|
||||
mock_req.return_value = (MyResp(200), resstr)
|
||||
self.client.httpclient.request(
|
||||
MyUrlComparator(end_url(path, query, format=self.format),
|
||||
self.client),
|
||||
'GET',
|
||||
body=None,
|
||||
headers={'X-Auth-Token': TOKEN})
|
||||
with mock.patch.object(TackerCommand, 'get_client') as mock_get:
|
||||
mock_get.return_value = self.client
|
||||
cmd_parser = cmd.get_parser("list_" + resources)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
_str = self.fake_stdout.make_string()
|
||||
if response_contents is None:
|
||||
self.assertIn('myid1', _str)
|
||||
return _str
|
||||
|
||||
def _test_list_resources_with_pagination(self, resources, cmd):
|
||||
self.mox.StubOutWithMock(cmd, "get_client")
|
||||
self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
cmd.get_client().MultipleTimes().AndReturn(self.client)
|
||||
path = getattr(self.client, resources + "_path")
|
||||
fake_query = "marker=myid2&limit=2"
|
||||
reses1 = {resources: [{'id': 'myid1', },
|
||||
{'id': 'myid2', }],
|
||||
'%s_links' % resources: [{'href': end_url(path, fake_query),
|
||||
'rel': 'next'}]}
|
||||
reses2 = {resources: [{'id': 'myid3', },
|
||||
{'id': 'myid4', }]}
|
||||
@mock.patch.object(TackerCommand, 'get_client')
|
||||
def _test_list_sub_resources(self, resources, api_resource, cmd, myid,
|
||||
mock_get, detail=False,
|
||||
tags=[], fields_1=[], fields_2=[],
|
||||
page_size=None, sort_key=[], sort_dir=[],
|
||||
response_contents=None, base_args=None,
|
||||
path=None):
|
||||
mock_get.return_value = self.client
|
||||
if response_contents is None:
|
||||
contents = [{self.id_field: 'myid1', },
|
||||
{self.id_field: 'myid2', }, ]
|
||||
else:
|
||||
contents = response_contents
|
||||
reses = {api_resource: contents}
|
||||
self.client.format = self.format
|
||||
resstr1 = self.client.serialize(reses1)
|
||||
resstr2 = self.client.serialize(reses2)
|
||||
self.client.httpclient.request(
|
||||
end_url(path, "", format=self.format), 'GET',
|
||||
body=None,
|
||||
headers=mox.ContainsKeyValue(
|
||||
'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr1))
|
||||
self.client.httpclient.request(
|
||||
end_url(path, fake_query, format=self.format), 'GET',
|
||||
body=None,
|
||||
headers=mox.ContainsKeyValue(
|
||||
'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr2))
|
||||
self.mox.ReplayAll()
|
||||
cmd_parser = cmd.get_parser("list_" + resources)
|
||||
args = ['--request-format', self.format]
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
self.mox.VerifyAll()
|
||||
self.mox.UnsetStubs()
|
||||
resstr = self.client.serialize(reses)
|
||||
# url method body
|
||||
query = ""
|
||||
args = base_args if base_args is not None else []
|
||||
if detail:
|
||||
args.append('-D')
|
||||
args.extend(['--request-format', self.format])
|
||||
if fields_1:
|
||||
for field in fields_1:
|
||||
args.append('--fields')
|
||||
args.append(field)
|
||||
|
||||
def _test_update_resource(self, resource, cmd, myid, args, extrafields):
|
||||
self.mox.StubOutWithMock(cmd, "get_client")
|
||||
self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
cmd.get_client().MultipleTimes().AndReturn(self.client)
|
||||
if tags:
|
||||
args.append('--')
|
||||
args.append("--tag")
|
||||
for tag in tags:
|
||||
args.append(tag)
|
||||
if isinstance(tag, six.string_types):
|
||||
tag = urllib.quote(tag.encode('utf-8'))
|
||||
if query:
|
||||
query += "&tag=" + tag
|
||||
else:
|
||||
query = "tag=" + tag
|
||||
if (not tags) and fields_2:
|
||||
args.append('--')
|
||||
if fields_2:
|
||||
args.append("--fields")
|
||||
for field in fields_2:
|
||||
args.append(field)
|
||||
if detail:
|
||||
query = query and query + '&verbose=True' or 'verbose=True'
|
||||
fields_1.extend(fields_2)
|
||||
for field in fields_1:
|
||||
if query:
|
||||
query += "&fields=" + field
|
||||
else:
|
||||
query = "fields=" + field
|
||||
if page_size:
|
||||
args.append("--page-size")
|
||||
args.append(str(page_size))
|
||||
if query:
|
||||
query += "&limit=%s" % page_size
|
||||
else:
|
||||
query = "limit=%s" % page_size
|
||||
if sort_key:
|
||||
for key in sort_key:
|
||||
args.append('--sort-key')
|
||||
args.append(key)
|
||||
if query:
|
||||
query += '&'
|
||||
query += 'sort_key=%s' % key
|
||||
if sort_dir:
|
||||
len_diff = len(sort_key) - len(sort_dir)
|
||||
if len_diff > 0:
|
||||
sort_dir += ['asc'] * len_diff
|
||||
elif len_diff < 0:
|
||||
sort_dir = sort_dir[:len(sort_key)]
|
||||
for dir in sort_dir:
|
||||
args.append('--sort-dir')
|
||||
args.append(dir)
|
||||
if query:
|
||||
query += '&'
|
||||
query += 'sort_dir=%s' % dir
|
||||
if path is None:
|
||||
path = getattr(self.client, resources + "_path")
|
||||
with mock.patch.object(self.client.httpclient, 'request') as mock_req:
|
||||
mock_req.return_value = (MyResp(200), resstr)
|
||||
self.client.httpclient.request(
|
||||
end_url(path, format=self.format), 'GET',
|
||||
body=None,
|
||||
headers={'X-Auth-Token': TOKEN})
|
||||
mock_req.assert_called_once_with(
|
||||
end_url(path, format=self.format), 'GET',
|
||||
body=None,
|
||||
headers={'X-Auth-Token': TOKEN})
|
||||
args.extend(['--request-format', self.format])
|
||||
cmd_parser = cmd.get_parser("list_" + resources)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
|
||||
_str = self.fake_stdout.make_string()
|
||||
if response_contents is None:
|
||||
self.assertIn('myid1', _str)
|
||||
return _str
|
||||
|
||||
# TODO(gongysh) add pagination unit test BUG 1633255
|
||||
# def _test_list_sub_resources_with_pagination(
|
||||
# self, resources, api_resource, cmd, myid):
|
||||
# self.mox.StubOutWithMock(cmd, "get_client")
|
||||
# self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
# cmd.get_client().MultipleTimes().AndReturn(self.client)
|
||||
# path = getattr(self.client, resources + "_path")
|
||||
# fake_query = "marker=myid2&limit=2"
|
||||
# reses1 = {api_resource: [{'id': 'myid1', },
|
||||
# {'id': 'myid2', }],
|
||||
# '%s_links' % api_resource: [
|
||||
# {'href': end_url(path % myid, fake_query),
|
||||
# 'rel': 'next'}]
|
||||
# }
|
||||
# reses2 = {api_resource: [{'id': 'myid3', },
|
||||
# {'id': 'myid4', }]}
|
||||
# self.client.format = self.format
|
||||
# resstr1 = self.client.serialize(reses1)
|
||||
# resstr2 = self.client.serialize(reses2)
|
||||
# self.client.httpclient.request(
|
||||
# end_url(path % myid, "", format=self.format), 'GET',
|
||||
# body=None,
|
||||
# headers=mox.ContainsKeyValue(
|
||||
# 'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr1))
|
||||
# self.client.httpclient.request(
|
||||
# MyUrlComparator(end_url(path % myid, fake_query,
|
||||
# format=self.format), self.client), 'GET',
|
||||
# body=None, headers=mox.ContainsKeyValue(
|
||||
# 'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr2))
|
||||
# self.mox.ReplayAll()
|
||||
# cmd_parser = cmd.get_parser("list_" + resources)
|
||||
# args = [myid, '--request-format', self.format]
|
||||
# shell.run_command(cmd, cmd_parser, args)
|
||||
# self.mox.VerifyAll()
|
||||
# self.mox.UnsetStubs()
|
||||
|
||||
# def _test_list_resources_with_pagination(self, resources, cmd):
|
||||
# self.mox.StubOutWithMock(cmd, "get_client")
|
||||
# self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
# cmd.get_client().MultipleTimes().AndReturn(self.client)
|
||||
# path = getattr(self.client, resources + "_path")
|
||||
# fake_query = "marker=myid2&limit=2"
|
||||
# reses1 = {resources: [{'id': 'myid1', },
|
||||
# {'id': 'myid2', }],
|
||||
# '%s_links' % resources: [
|
||||
# {'href': end_url(path, fake_query),
|
||||
# 'rel': 'next'}]}
|
||||
# reses2 = {resources: [{'id': 'myid3', },
|
||||
# {'id': 'myid4', }]}
|
||||
# self.client.format = self.format
|
||||
# resstr1 = self.client.serialize(reses1)
|
||||
# resstr2 = self.client.serialize(reses2)
|
||||
# self.client.httpclient.request(
|
||||
# end_url(path, "", format=self.format), 'GET',
|
||||
# body=None,
|
||||
# headers=mox.ContainsKeyValue(
|
||||
# 'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr1))
|
||||
# self.client.httpclient.request(
|
||||
# MyUrlComparator(end_url(path, fake_query, format=self.format),
|
||||
# self.client), 'GET', body=None,
|
||||
# headers=mox.ContainsKeyValue(
|
||||
# 'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr2))
|
||||
# self.mox.ReplayAll()
|
||||
# cmd_parser = cmd.get_parser("list_" + resources)
|
||||
# args = ['--request-format', self.format]
|
||||
# shell.run_command(cmd, cmd_parser, args)
|
||||
# self.mox.VerifyAll()
|
||||
# self.mox.UnsetStubs()
|
||||
|
||||
@mock.patch.object(TackerCommand, 'get_client')
|
||||
def _test_update_resource(self, resource, cmd, myid, args, extrafields,
|
||||
mock_get, get_client_called_count=1):
|
||||
mock_get.return_value = self.client
|
||||
body = {resource: extrafields}
|
||||
path = getattr(self.client, resource + "_path")
|
||||
self.client.format = self.format
|
||||
# Work around for LP #1217791. XML deserializer called from
|
||||
# MyComparator does not decodes XML string correctly.
|
||||
if self.format == 'json':
|
||||
mox_body = MyComparator(body, self.client)
|
||||
_body = MyComparator(body, self.client)
|
||||
else:
|
||||
mox_body = self.client.serialize(body)
|
||||
self.client.httpclient.request(
|
||||
MyUrlComparator(end_url(path % myid, format=self.format),
|
||||
self.client),
|
||||
'PUT',
|
||||
body=mox_body,
|
||||
headers=mox.ContainsKeyValue(
|
||||
'X-Auth-Token', TOKEN)).AndReturn((MyResp(204), None))
|
||||
args.extend(['--request-format', self.format])
|
||||
self.mox.ReplayAll()
|
||||
cmd_parser = cmd.get_parser("update_" + resource)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
self.mox.VerifyAll()
|
||||
self.mox.UnsetStubs()
|
||||
_body = self.client.serialize(body)
|
||||
with mock.patch.object(self.client.httpclient, 'request') as mock_req:
|
||||
comparator = MyUrlComparator(
|
||||
end_url(path % myid, format=self.format), self.client)
|
||||
mock_req.return_value = (MyResp(204), None)
|
||||
self.client.httpclient.request(
|
||||
comparator, 'PUT', body=_body,
|
||||
headers={'X-Auth-Token', TOKEN})
|
||||
mock_req.assert_called_once_with(
|
||||
comparator,
|
||||
'PUT',
|
||||
body=_body,
|
||||
headers={'X-Auth-Token', TOKEN})
|
||||
args.extend(['--request-format', self.format])
|
||||
cmd_parser = cmd.get_parser("update_" + resource)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
self.assertEqual(get_client_called_count, mock_get.call_count)
|
||||
_str = self.fake_stdout.make_string()
|
||||
self.assertIn(myid, _str)
|
||||
|
||||
def _test_show_resource(self, resource, cmd, myid, args, fields=[]):
|
||||
self.mox.StubOutWithMock(cmd, "get_client")
|
||||
self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
cmd.get_client().MultipleTimes().AndReturn(self.client)
|
||||
query = "&".join(["fields=%s" % field for field in fields])
|
||||
expected_res = {resource:
|
||||
{self.id_field: myid,
|
||||
'name': 'myname', }, }
|
||||
self.client.format = self.format
|
||||
resstr = self.client.serialize(expected_res)
|
||||
path = getattr(self.client, resource + "_path")
|
||||
self.client.httpclient.request(
|
||||
end_url(path % myid, query, format=self.format), 'GET',
|
||||
body=None,
|
||||
headers=mox.ContainsKeyValue(
|
||||
'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr))
|
||||
args.extend(['--request-format', self.format])
|
||||
self.mox.ReplayAll()
|
||||
cmd_parser = cmd.get_parser("show_" + resource)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
self.mox.VerifyAll()
|
||||
self.mox.UnsetStubs()
|
||||
_str = self.fake_stdout.make_string()
|
||||
self.assertIn(myid, _str)
|
||||
self.assertIn('myname', _str)
|
||||
with mock.patch.object(cmd, 'get_client') as mock_get:
|
||||
mock_get.return_value = self.client
|
||||
query = "&".join(["fields=%s" % field for field in fields])
|
||||
expected_res = {resource:
|
||||
{self.id_field: myid,
|
||||
'name': 'myname', }, }
|
||||
self.client.format = self.format
|
||||
resstr = self.client.serialize(expected_res)
|
||||
path = getattr(self.client, resource + "_path")
|
||||
with mock.patch.object(self.client.httpclient, 'request') as\
|
||||
mock_req:
|
||||
mock_req.return_value = (MyResp(200), resstr)
|
||||
self.client.httpclient.request(
|
||||
end_url(path % myid, query, format=self.format), 'GET',
|
||||
body=None, headers={'X-Auth-Token': TOKEN})
|
||||
mock_req.assert_called_once_with(
|
||||
end_url(path % myid, query, format=self.format), 'GET',
|
||||
body=None, headers={'X-Auth-Token': TOKEN})
|
||||
args.extend(['--request-format', self.format])
|
||||
cmd_parser = cmd.get_parser("show_" + resource)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
_str = self.fake_stdout.make_string()
|
||||
mock_get.assert_called_once_with()
|
||||
self.assertIn(myid, _str)
|
||||
self.assertIn('myname', _str)
|
||||
|
||||
def _test_delete_resource(self, resource, cmd, myid, args):
|
||||
self.mox.StubOutWithMock(cmd, "get_client")
|
||||
self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
cmd.get_client().MultipleTimes().AndReturn(self.client)
|
||||
@mock.patch.object(TackerCommand, 'get_client')
|
||||
def _test_delete_resource(self, resource, cmd, myid, args, mock_get):
|
||||
deleted_msg = {'vnf': 'delete initiated'}
|
||||
mock_get.return_value = self.client
|
||||
path = getattr(self.client, resource + "_path")
|
||||
self.client.httpclient.request(
|
||||
end_url(path % myid, format=self.format), 'DELETE',
|
||||
body=None,
|
||||
headers=mox.ContainsKeyValue(
|
||||
'X-Auth-Token', TOKEN)).AndReturn((MyResp(204), None))
|
||||
args.extend(['--request-format', self.format])
|
||||
self.mox.ReplayAll()
|
||||
cmd_parser = cmd.get_parser("delete_" + resource)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
self.mox.VerifyAll()
|
||||
self.mox.UnsetStubs()
|
||||
with mock.patch.object(self.client.httpclient, 'request') as mock_req:
|
||||
mock_req.return_value = (MyResp(204), None)
|
||||
self.client.httpclient.request(
|
||||
end_url(path % myid, format=self.format), 'DELETE',
|
||||
body=None,
|
||||
headers={'X-Auth-Token', TOKEN})
|
||||
args.extend(['--request-format', self.format])
|
||||
mock_req.assert_called_once_with(
|
||||
end_url(path % myid, format=self.format), 'DELETE',
|
||||
body=None, headers={'X-Auth-Token', TOKEN})
|
||||
cmd_parser = cmd.get_parser("delete_" + resource)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
mock_get.assert_called_once_with()
|
||||
_str = self.fake_stdout.make_string()
|
||||
self.assertIn(myid, _str)
|
||||
msg = 'All %(resource)s(s) %(msg)s successfully\n' % {
|
||||
'msg': deleted_msg.get(resource, 'deleted'),
|
||||
'resource': resource}
|
||||
self.assertEqual(msg, _str)
|
||||
|
||||
@mock.patch.object(TackerCommand, 'get_client')
|
||||
def _test_update_resource_action(self, resource, cmd, myid, action, args,
|
||||
body, retval=None):
|
||||
self.mox.StubOutWithMock(cmd, "get_client")
|
||||
self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
cmd.get_client().MultipleTimes().AndReturn(self.client)
|
||||
body, mock_get, retval=None):
|
||||
mock_get.return_value = self.client
|
||||
path = getattr(self.client, resource + "_path")
|
||||
path_action = '%s/%s' % (myid, action)
|
||||
self.client.httpclient.request(
|
||||
end_url(path % path_action, format=self.format), 'PUT',
|
||||
body=MyComparator(body, self.client),
|
||||
headers=mox.ContainsKeyValue(
|
||||
'X-Auth-Token', TOKEN)).AndReturn((MyResp(204), retval))
|
||||
args.extend(['--request-format', self.format])
|
||||
self.mox.ReplayAll()
|
||||
cmd_parser = cmd.get_parser("delete_" + resource)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
self.mox.VerifyAll()
|
||||
self.mox.UnsetStubs()
|
||||
with mock.patch.object(self.client.httpclient, 'request') as mock_req:
|
||||
mock_req.return_value = (MyResp(204), retval)
|
||||
self.client.httpclient.request(
|
||||
end_url(path % path_action, format=self.format), 'PUT',
|
||||
body=MyComparator(body, self.client),
|
||||
headers={'X-Auth-Token': TOKEN})
|
||||
args.extend(['--request-format', self.format])
|
||||
cmd_parser = cmd.get_parser("delete_" + resource)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
_str = self.fake_stdout.make_string()
|
||||
self.assertIn(myid, _str)
|
||||
|
||||
@@ -500,7 +650,6 @@ class CLITestV10Base(testtools.TestCase):
|
||||
class ClientV1TestJson(CLITestV10Base):
|
||||
def test_do_request_unicode(self):
|
||||
self.client.format = self.format
|
||||
self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
unicode_text = u'\u7f51\u7edc'
|
||||
# url with unicode
|
||||
action = u'/test'
|
||||
@@ -515,47 +664,33 @@ class ClientV1TestJson(CLITestV10Base):
|
||||
# headers with unicode
|
||||
self.client.httpclient.auth_token = unicode_text
|
||||
expected_auth_token = unicode_text.encode('utf-8')
|
||||
|
||||
self.client.httpclient.request(
|
||||
end_url(expected_action, query=expect_query, format=self.format),
|
||||
'PUT', body=expect_body,
|
||||
headers=mox.ContainsKeyValue(
|
||||
'X-Auth-Token',
|
||||
expected_auth_token)).AndReturn((MyResp(200), expect_body))
|
||||
|
||||
self.mox.ReplayAll()
|
||||
res_body = self.client.do_request('PUT', action, body=body,
|
||||
params=params)
|
||||
self.mox.VerifyAll()
|
||||
self.mox.UnsetStubs()
|
||||
|
||||
with mock.patch.object(self.client.httpclient, 'request') as mock_req:
|
||||
mock_req.return_value = (MyResp(200), expect_body)
|
||||
self.client.httpclient.request(
|
||||
end_url(expected_action, query=expect_query,
|
||||
format=self.format), 'PUT', body=expect_body,
|
||||
headers={'X-Auth-Token': expected_auth_token})
|
||||
res_body = self.client.do_request('PUT', action, body=body,
|
||||
params=params)
|
||||
# test response with unicode
|
||||
self.assertEqual(res_body, body)
|
||||
|
||||
def test_do_request_error_without_response_body(self):
|
||||
self.client.format = self.format
|
||||
self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
params = {'test': 'value'}
|
||||
expect_query = urllib.urlencode(params)
|
||||
self.client.httpclient.auth_token = 'token'
|
||||
|
||||
self.client.httpclient.request(
|
||||
end_url('/test', query=expect_query, format=self.format),
|
||||
'PUT', body='',
|
||||
headers=mox.ContainsKeyValue('X-Auth-Token', 'token')
|
||||
).AndReturn((MyResp(400, reason='An error'), ''))
|
||||
|
||||
self.mox.ReplayAll()
|
||||
error = self.assertRaises(exceptions.TackerClientException,
|
||||
self.client.do_request, 'PUT', '/test',
|
||||
body='', params=params)
|
||||
self.assertEqual("An error", str(error))
|
||||
self.mox.VerifyAll()
|
||||
self.mox.UnsetStubs()
|
||||
|
||||
|
||||
class ClientV1UnicodeTestXML(ClientV1TestJson):
|
||||
format = 'xml'
|
||||
with mock.patch.object(self.client.httpclient, 'request') as mock_req:
|
||||
mock_req.return_value = (MyResp(400, reason='An error'), '')
|
||||
self.client.httpclient.request(
|
||||
end_url('/test', query=expect_query, format=self.format),
|
||||
'PUT', body='',
|
||||
headers={'X-Auth-Token': 'token'}
|
||||
)
|
||||
error = self.assertRaises(exceptions.TackerClientException,
|
||||
self.client.do_request, 'PUT', '/test',
|
||||
body='', params=params)
|
||||
self.assertEqual("An error", str(error))
|
||||
|
||||
|
||||
class CLITestV10ExceptionHandler(CLITestV10Base):
|
||||
@@ -579,7 +714,7 @@ class CLITestV10ExceptionHandler(CLITestV10Base):
|
||||
expected_msg = '\n'.join([error_msg, error_detail])
|
||||
else:
|
||||
expected_msg = error_msg
|
||||
self.assertEqual(expected_msg, e.message)
|
||||
self.assertEqual(expected_msg, str(e))
|
||||
|
||||
def test_exception_handler_v10_ip_address_in_use(self):
|
||||
err_msg = ('Unable to complete operation for network '
|
||||
|
||||
@@ -70,7 +70,7 @@ class TestHTTPClient(testtools.TestCase):
|
||||
|
||||
e = self.assertRaises(exceptions.Unauthorized,
|
||||
self.http._cs_request, URL, METHOD)
|
||||
self.assertEqual('unauthorized message', e.message)
|
||||
self.assertEqual('unauthorized message', str(e))
|
||||
self.mox.VerifyAll()
|
||||
|
||||
def test_request_forbidden_is_returned_to_caller(self):
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
# under the License.
|
||||
|
||||
import argparse
|
||||
import cStringIO
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import six
|
||||
import sys
|
||||
|
||||
import fixtures
|
||||
@@ -61,8 +61,8 @@ class ShellTest(testtools.TestCase):
|
||||
clean_env = {}
|
||||
_old_env, os.environ = os.environ, clean_env.copy()
|
||||
try:
|
||||
sys.stdout = cStringIO.StringIO()
|
||||
sys.stderr = cStringIO.StringIO()
|
||||
sys.stdout = six.StringIO()
|
||||
sys.stderr = six.StringIO()
|
||||
_shell = openstack_shell.TackerShell('1.0')
|
||||
_shell.run(argstr.split())
|
||||
except SystemExit:
|
||||
@@ -118,7 +118,6 @@ class ShellTest(testtools.TestCase):
|
||||
'either --os-url or env[OS_URL]', stderr.strip())
|
||||
|
||||
def test_auth(self):
|
||||
# import pdb; pdb.set_trace()
|
||||
tacker_shell = openstack_shell.TackerShell('1.0')
|
||||
self.addCleanup(self.mox.UnsetStubs)
|
||||
self.mox.StubOutWithMock(clientmanager.ClientManager, '__init__')
|
||||
@@ -146,7 +145,7 @@ class ShellTest(testtools.TestCase):
|
||||
def test_build_option_parser(self):
|
||||
tacker_shell = openstack_shell.TackerShell('1.0')
|
||||
result = tacker_shell.build_option_parser('descr', '1.0')
|
||||
self.assertEqual(True, isinstance(result, argparse.ArgumentParser))
|
||||
self.assertIsInstance(result, argparse.ArgumentParser)
|
||||
|
||||
def test_main_with_unicode(self):
|
||||
self.mox.StubOutClassWithMocks(openstack_shell, 'TackerShell')
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import datetime
|
||||
import sys
|
||||
|
||||
import testtools
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
@@ -106,90 +103,7 @@ class TestUtils(testtools.TestCase):
|
||||
self.assertEqual(('test_name', 'test_id', 'test', 'pass'), act)
|
||||
|
||||
|
||||
class JSONUtilsTestCase(testtools.TestCase):
|
||||
def test_dumps(self):
|
||||
self.assertEqual(utils.dumps({'a': 'b'}), '{"a": "b"}')
|
||||
|
||||
def test_dumps_dict_with_date_value(self):
|
||||
x = datetime.datetime(1920, 2, 3, 4, 5, 6, 7)
|
||||
res = utils.dumps({1: 'a', 2: x})
|
||||
expected = '{"1": "a", "2": "1920-02-03 04:05:06.000007"}'
|
||||
self.assertEqual(expected, res)
|
||||
|
||||
def test_dumps_dict_with_spaces(self):
|
||||
x = datetime.datetime(1920, 2, 3, 4, 5, 6, 7)
|
||||
res = utils.dumps({1: 'a ', 2: x})
|
||||
expected = '{"1": "a ", "2": "1920-02-03 04:05:06.000007"}'
|
||||
self.assertEqual(expected, res)
|
||||
|
||||
def test_loads(self):
|
||||
self.assertEqual(utils.loads('{"a": "b"}'), {'a': 'b'})
|
||||
|
||||
|
||||
class ToPrimitiveTestCase(testtools.TestCase):
|
||||
def test_list(self):
|
||||
self.assertEqual(utils.to_primitive([1, 2, 3]), [1, 2, 3])
|
||||
|
||||
def test_empty_list(self):
|
||||
self.assertEqual(utils.to_primitive([]), [])
|
||||
|
||||
def test_tuple(self):
|
||||
self.assertEqual(utils.to_primitive((1, 2, 3)), [1, 2, 3])
|
||||
|
||||
def test_empty_tuple(self):
|
||||
self.assertEqual(utils.to_primitive(()), [])
|
||||
|
||||
def test_dict(self):
|
||||
self.assertEqual(
|
||||
utils.to_primitive(dict(a=1, b=2, c=3)),
|
||||
dict(a=1, b=2, c=3))
|
||||
|
||||
def test_empty_dict(self):
|
||||
self.assertEqual(utils.to_primitive({}), {})
|
||||
|
||||
def test_datetime(self):
|
||||
x = datetime.datetime(1920, 2, 3, 4, 5, 6, 7)
|
||||
self.assertEqual(
|
||||
utils.to_primitive(x),
|
||||
'1920-02-03 04:05:06.000007')
|
||||
|
||||
def test_iter(self):
|
||||
x = range(1, 6)
|
||||
self.assertEqual(utils.to_primitive(x), [1, 2, 3, 4, 5])
|
||||
|
||||
def test_iteritems(self):
|
||||
d = {'a': 1, 'b': 2, 'c': 3}
|
||||
|
||||
class IterItemsClass(object):
|
||||
def iteritems(self):
|
||||
return d.iteritems()
|
||||
|
||||
x = IterItemsClass()
|
||||
p = utils.to_primitive(x)
|
||||
self.assertEqual(p, {'a': 1, 'b': 2, 'c': 3})
|
||||
|
||||
def test_nasties(self):
|
||||
def foo():
|
||||
pass
|
||||
x = [datetime, foo, dir]
|
||||
ret = utils.to_primitive(x)
|
||||
self.assertEqual(len(ret), 3)
|
||||
|
||||
def test_to_primitive_dict_with_date_value(self):
|
||||
x = datetime.datetime(1920, 2, 3, 4, 5, 6, 7)
|
||||
res = utils.to_primitive({'a': x})
|
||||
self.assertEqual({'a': '1920-02-03 04:05:06.000007'}, res)
|
||||
|
||||
|
||||
class ImportClassTestCase(testtools.TestCase):
|
||||
def test_import_class(self):
|
||||
dt = utils.import_class('datetime.datetime')
|
||||
self.assertTrue(sys.modules['datetime'].datetime is dt)
|
||||
|
||||
def test_import_bad_class(self):
|
||||
self.assertRaises(
|
||||
ImportError, utils.import_class,
|
||||
'lol.u_mad.brah')
|
||||
|
||||
def test_get_client_class_invalid_version(self):
|
||||
self.assertRaises(
|
||||
|
||||
6
tackerclient/tests/unit/vm/samples/vim_config.yaml
Normal file
6
tackerclient/tests/unit/vm/samples/vim_config.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
auth_url: 'http://1.2.3.4:5000'
|
||||
username: 'xyz'
|
||||
password: '12345'
|
||||
project_name: 'abc'
|
||||
project_domain_name: 'prj_domain_name'
|
||||
user_domain_name: 'user_domain_name'
|
||||
@@ -0,0 +1,5 @@
|
||||
username: 'xyz'
|
||||
password: '12345'
|
||||
project_name: 'abc'
|
||||
project_domain_name: 'prj_domain_name'
|
||||
user_domain_name: 'user_domain_name'
|
||||
69
tackerclient/tests/unit/vm/test_cli10_v10_event.py
Normal file
69
tackerclient/tests/unit/vm/test_cli10_v10_event.py
Normal file
@@ -0,0 +1,69 @@
|
||||
# Copyright 2014 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
|
||||
#
|
||||
# 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 sys
|
||||
|
||||
from tackerclient.tacker.v1_0.events import events
|
||||
from tackerclient.tests.unit import test_cli10
|
||||
|
||||
API_VERSION = "1.0"
|
||||
FORMAT = 'json'
|
||||
TOKEN = 'testtoken'
|
||||
ENDURL = 'localurl'
|
||||
|
||||
|
||||
class CLITestV10EventJSON(test_cli10.CLITestV10Base):
|
||||
_EVT_RESOURCE = 'event'
|
||||
_EVT_RESOURCES = _EVT_RESOURCE + 's'
|
||||
_VNF_EVT_RESOURCE = "vnf_event"
|
||||
_VNF_EVT_RESOURCES = _VNF_EVT_RESOURCE + 's'
|
||||
_VNFD_EVT_RESOURCE = "vnfd_event"
|
||||
_VNFD_EVT_RESOURCES = _VNFD_EVT_RESOURCE + 's'
|
||||
_VIM_EVT_RESOURCE = "vim_event"
|
||||
_VIM_EVT_RESOURCES = _VIM_EVT_RESOURCE + 's'
|
||||
|
||||
def setUp(self):
|
||||
plurals = {'events': 'event', 'vnf_events': 'vnf_event',
|
||||
'vnfd_events': 'vnfd_event', 'vim_events': 'vim_event'}
|
||||
super(CLITestV10EventJSON, self).setUp(plurals=plurals)
|
||||
|
||||
def test_list_events(self):
|
||||
cmd = events.ListResourceEvents(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._EVT_RESOURCES, cmd, True)
|
||||
|
||||
def test_show_event_id(self):
|
||||
cmd = events.ShowEvent(test_cli10.MyApp(sys.stdout), None)
|
||||
args = ['--fields', 'id', self.test_id]
|
||||
self._test_show_resource(self._EVT_RESOURCE, cmd, self.test_id, args,
|
||||
['id'])
|
||||
|
||||
def notest_list_vnf_events(self):
|
||||
# TODO(vishwanathj): Need to enhance _test_list_resources()
|
||||
# for supporting filters to get this test working
|
||||
cmd = events.ListVNFEvents(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._VNF_EVT_RESOURCES, cmd, True)
|
||||
|
||||
def notest_list_vnfd_events(self):
|
||||
# TODO(vishwanathj): Need to enhance _test_list_resources()
|
||||
# for supporting filters to get this test working
|
||||
cmd = events.ListVNFDEvents(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._VNFD_EVT_RESOURCES, cmd, True)
|
||||
|
||||
def notest_list_vim_events(self):
|
||||
# TODO(vishwanathj): Need to enhance _test_list_resources()
|
||||
# for supporting filters to get this test working
|
||||
cmd = events.ListVIMEvents(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._VIM_EVT_RESOURCES, cmd, True)
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
import sys
|
||||
|
||||
import mox
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
from tackerclient.common import utils
|
||||
from tackerclient.tacker.v1_0.nfvo import vim
|
||||
from tackerclient.tests.unit import test_cli10
|
||||
|
||||
@@ -34,43 +34,77 @@ class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
|
||||
def setUp(self):
|
||||
plurals = {'vims': 'vim'}
|
||||
super(CLITestV10VIMJSON, self).setUp(plurals=plurals)
|
||||
self.vim_project = {'name': 'abc', 'id': ''}
|
||||
self.vim_project = {
|
||||
'name': 'abc', 'id': '',
|
||||
'project_domain_name': 'prj_domain_name'}
|
||||
self.auth_cred = {'username': 'xyz', 'password': '12345', 'user_id':
|
||||
''}
|
||||
'', 'user_domain_name': 'user_domain_name'}
|
||||
self.auth_url = 'http://1.2.3.4:5000'
|
||||
|
||||
def test_register_vim_all_params(self):
|
||||
cmd = vim.CreateVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
name = 'my-name'
|
||||
my_id = 'my-id'
|
||||
name = 'test_vim'
|
||||
description = 'Vim Description'
|
||||
vim_config = {'auth_url': 'http://1.2.3.4:5000', 'username': 'xyz',
|
||||
'password': '12345', 'project_name': 'abc'}
|
||||
vim_config = utils.get_file_path(
|
||||
'tests/unit/vm/samples/vim_config.yaml')
|
||||
args = [
|
||||
'--config', str(vim_config),
|
||||
'--name', name,
|
||||
name,
|
||||
'--config-file', vim_config,
|
||||
'--description', description]
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url']
|
||||
position_values = [self.auth_cred, self.vim_project, self.auth_url]
|
||||
extra_body = {'type': 'openstack', 'name': name, 'description':
|
||||
description}
|
||||
position_values = [self.auth_cred, self.vim_project,
|
||||
self.auth_url]
|
||||
extra_body = {'type': 'openstack', 'name': name,
|
||||
'description': description, 'is_default': False}
|
||||
self._test_create_resource(self._RESOURCE, cmd, None, my_id,
|
||||
args, position_names, position_values,
|
||||
extra_body=extra_body)
|
||||
|
||||
def test_register_vim_with_mandatory_params(self):
|
||||
def test_register_vim_with_no_auth_url(self):
|
||||
cmd = vim.CreateVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
|
||||
vim_config = {'auth_url': 'http://1.2.3.4:5000', 'username': 'xyz',
|
||||
'password': '12345', 'project_name': 'abc'}
|
||||
name = 'test_vim'
|
||||
description = 'Vim Description'
|
||||
vim_config = utils.get_file_path(
|
||||
'tests/unit/vm/samples/vim_config_without_auth_url.yaml')
|
||||
args = [
|
||||
'--config', str(vim_config),
|
||||
name,
|
||||
'--config-file', vim_config,
|
||||
'--description', description]
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url']
|
||||
position_values = [self.auth_cred, self.vim_project,
|
||||
self.auth_url]
|
||||
extra_body = {'type': 'openstack', 'name': name,
|
||||
'description': description, 'is_default': False}
|
||||
message = 'Auth URL must be specified'
|
||||
ex = self.assertRaises(exceptions.TackerClientException,
|
||||
self._test_create_resource,
|
||||
self._RESOURCE, cmd, None, my_id, args,
|
||||
position_names, position_values,
|
||||
extra_body=extra_body)
|
||||
self.assertEqual(message, ex.message)
|
||||
self.assertEqual(404, ex.status_code)
|
||||
|
||||
def test_register_vim_with_mandatory_params(self):
|
||||
cmd = vim.CreateVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
name = 'my-name'
|
||||
my_id = 'my-id'
|
||||
|
||||
vim_config = utils.get_file_path(
|
||||
'tests/unit/vm/samples/vim_config.yaml')
|
||||
args = [
|
||||
name,
|
||||
'--config-file', vim_config,
|
||||
]
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url']
|
||||
position_values = [self.auth_cred, self.vim_project, self.auth_url]
|
||||
extra_body = {'type': 'openstack'}
|
||||
self._test_create_resource(self._RESOURCE, cmd, None, my_id, args,
|
||||
position_values = [
|
||||
self.auth_cred,
|
||||
self.vim_project,
|
||||
self.auth_url
|
||||
]
|
||||
extra_body = {'type': 'openstack', 'name': name, 'is_default': False}
|
||||
self._test_create_resource(self._RESOURCE, cmd, name, my_id, args,
|
||||
position_names, position_values,
|
||||
extra_body=extra_body)
|
||||
|
||||
@@ -78,39 +112,6 @@ class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
|
||||
cmd = vim.ListVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True)
|
||||
|
||||
def _test_list_vims_extend(self, data, expected_data, args=['-f', 'json']):
|
||||
resp_str = self.client.serialize({self._RESOURCES: data})
|
||||
resp = (test_cli10.MyResp(200), resp_str)
|
||||
cmd = vim.ListVIM(
|
||||
test_cli10.MyApp(sys.stdout), None)
|
||||
self.mox.StubOutWithMock(cmd, "get_client")
|
||||
self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
|
||||
cmd.get_client().MultipleTimes().AndReturn(self.client)
|
||||
path = getattr(self.client, self._RESOURCES + '_path')
|
||||
self.client.httpclient.request(test_cli10.MyUrlComparator(
|
||||
test_cli10.end_url(path, format=self.format), self.client),
|
||||
'GET', body=None, headers=mox.ContainsKeyValue(
|
||||
'X-Auth-Token', test_cli10.TOKEN)).AndReturn(resp)
|
||||
self.mox.ReplayAll()
|
||||
cmd_parser = cmd.get_parser("list_" + self._RESOURCES)
|
||||
parsed_args = cmd_parser.parse_args(args)
|
||||
result = cmd.take_action(parsed_args)
|
||||
res_data = [res for res in result[1]]
|
||||
self.mox.VerifyAll()
|
||||
self.mox.UnsetStubs()
|
||||
for res, exp in zip(res_data, expected_data):
|
||||
self.assertEqual(len(exp), len(res))
|
||||
self.assertEqual(exp, res)
|
||||
|
||||
def test_list_vims_extend(self):
|
||||
vim_data = [{'id': 'my_id1', 'auth_cred': {'password':
|
||||
'encrypted_pw'}}, {'id': 'my_id2', 'auth_cred': {
|
||||
'password': 'another_encrypted_pw'}}]
|
||||
expected_data = [('my_id1', {'password': '***'}),
|
||||
('my_id2', {'password': '***'})]
|
||||
self._test_list_vims_extend(vim_data, expected_data)
|
||||
|
||||
def test_show_vim_id(self):
|
||||
cmd = vim.ShowVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
args = ['--fields', 'id', self.test_id]
|
||||
@@ -123,18 +124,37 @@ class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
|
||||
self._test_show_resource(self._RESOURCE, cmd, self.test_id,
|
||||
args, ['id', 'name'])
|
||||
|
||||
def test_update_vim(self):
|
||||
def test_update_vim_all_params(self):
|
||||
cmd = vim.UpdateVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
update_config = {'username': 'xyz', 'password': '12345',
|
||||
'project_name': 'abc'}
|
||||
update_config = utils.get_file_path(
|
||||
'tests/unit/vm/samples/vim_config_without_auth_url.yaml')
|
||||
my_id = 'my-id'
|
||||
key = 'config'
|
||||
value = str(update_config)
|
||||
name = 'new_name'
|
||||
description = 'new_description'
|
||||
is_default = 'True'
|
||||
args = [
|
||||
my_id,
|
||||
'--config-file', str(update_config),
|
||||
'--name', name,
|
||||
'--description', description,
|
||||
'--is_default', is_default]
|
||||
extra_fields = {'vim_project': self.vim_project, 'auth_cred':
|
||||
self.auth_cred}
|
||||
self._test_update_resource(self._RESOURCE, cmd, my_id, [my_id,
|
||||
'--%s' %
|
||||
key, value],
|
||||
self.auth_cred, 'is_default': 'True',
|
||||
'name': name, 'description': description}
|
||||
self._test_update_resource(self._RESOURCE, cmd, my_id, args,
|
||||
extra_fields)
|
||||
|
||||
def test_update_vim_with_mandatory_params(self):
|
||||
cmd = vim.UpdateVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
update_config = utils.get_file_path(
|
||||
'tests/unit/vm/samples/vim_config_without_auth_url.yaml')
|
||||
my_id = 'my-id'
|
||||
args = [
|
||||
my_id,
|
||||
'--config-file', str(update_config)]
|
||||
extra_fields = {'vim_project': self.vim_project,
|
||||
'auth_cred': self.auth_cred}
|
||||
self._test_update_resource(self._RESOURCE, cmd, my_id, args,
|
||||
extra_fields)
|
||||
|
||||
def test_delete_vim(self):
|
||||
@@ -142,3 +162,9 @@ class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
|
||||
my_id = 'my-id'
|
||||
args = [my_id]
|
||||
self._test_delete_resource(self._RESOURCE, cmd, my_id, args)
|
||||
|
||||
def test_multi_delete_vim(self):
|
||||
cmd = vim.DeleteVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
vim_ids = 'my-id1 my-id2 my-id3'
|
||||
args = [vim_ids]
|
||||
self._test_delete_resource(self._RESOURCE, cmd, vim_ids, args)
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
# 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 mox
|
||||
|
||||
import sys
|
||||
|
||||
import mock
|
||||
|
||||
from tackerclient import shell
|
||||
from tackerclient.tacker import v1_0 as tackerV1_0
|
||||
from tackerclient.tacker.v1_0.vm import vnf
|
||||
from tackerclient.tacker.v1_0 import TackerCommand
|
||||
from tackerclient.tacker.v1_0.vnfm import vnf
|
||||
from tackerclient.tests.unit import test_cli10
|
||||
|
||||
API_VERSION = "1.0"
|
||||
@@ -32,19 +32,19 @@ ENDURL = 'localurl'
|
||||
class CLITestV10VmVNFJSON(test_cli10.CLITestV10Base):
|
||||
_RESOURCE = 'vnf'
|
||||
_RESOURCES = 'vnfs'
|
||||
_VNF_RESOURCES = 'vnf_resources'
|
||||
|
||||
def setUp(self):
|
||||
plurals = {'vnfs': 'vnf'}
|
||||
plurals = {'vnfs': 'vnf',
|
||||
'resources': 'resource'}
|
||||
super(CLITestV10VmVNFJSON, self).setUp(plurals=plurals)
|
||||
|
||||
def _test_create_resource(self, resource, cmd,
|
||||
name, myid, args,
|
||||
position_names, position_values, tenant_id=None,
|
||||
tags=None, admin_state_up=True, extra_body=None,
|
||||
**kwargs):
|
||||
self.mox.StubOutWithMock(cmd, "get_client")
|
||||
self.mox.StubOutWithMock(self.client.httpclient, "request")
|
||||
cmd.get_client().MultipleTimes().AndReturn(self.client)
|
||||
@mock.patch.object(TackerCommand, 'get_client')
|
||||
def _test_create_resource(self, resource, cmd, name, myid, args,
|
||||
position_names, position_values, mock_get,
|
||||
tenant_id=None, tags=None, admin_state_up=True,
|
||||
extra_body=None, **kwargs):
|
||||
mock_get.return_value = self.client
|
||||
non_admin_status_resources = ['vnfd', 'vnf']
|
||||
if (resource in non_admin_status_resources):
|
||||
body = {resource: {}, }
|
||||
@@ -73,53 +73,91 @@ class CLITestV10VmVNFJSON(test_cli10.CLITestV10Base):
|
||||
# Work around for LP #1217791. XML deserializer called from
|
||||
# MyComparator does not decodes XML string correctly.
|
||||
if self.format == 'json':
|
||||
mox_body = test_cli10.MyComparator(body, self.client)
|
||||
_body = test_cli10.MyComparator(body, self.client)
|
||||
else:
|
||||
mox_body = self.client.serialize(body)
|
||||
self.client.httpclient.request(
|
||||
test_cli10.end_url(path, format=self.format), 'POST',
|
||||
body=mox_body,
|
||||
headers=mox.ContainsKeyValue(
|
||||
'X-Auth-Token', TOKEN)).AndReturn((
|
||||
test_cli10.MyResp(200), resstr))
|
||||
args.extend(['--request-format', self.format])
|
||||
args.extend(['--vnfd-id', 'vnfd'])
|
||||
self.mox.ReplayAll()
|
||||
cmd_parser = cmd.get_parser('create_' + resource)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
self.mox.VerifyAll()
|
||||
_body = self.client.serialize(body)
|
||||
with mock.patch.object(self.client.httpclient, 'request') as mock_req:
|
||||
mock_req.return_value = (test_cli10.MyResp(200), resstr)
|
||||
self.client.httpclient.request(
|
||||
test_cli10.end_url(path, format=self.format), 'POST',
|
||||
body=_body,
|
||||
headers={'X-Auth-Token', TOKEN})
|
||||
mock_req.assert_called_once_with(
|
||||
test_cli10.end_url(path, format=self.format), 'POST',
|
||||
body=_body,
|
||||
headers={'X-Auth-Token', TOKEN})
|
||||
args.extend(['--request-format', self.format])
|
||||
args.extend(['--vnfd-id', 'vnfd'])
|
||||
cmd_parser = cmd.get_parser('create_' + resource)
|
||||
shell.run_command(cmd, cmd_parser, args)
|
||||
mock_get.assert_any_call()
|
||||
|
||||
def test_create_vnf_all_params(self):
|
||||
cmd = vnf.CreateVNF(test_cli10.MyApp(sys.stdout), None)
|
||||
name = 'my_name'
|
||||
my_id = 'my-id'
|
||||
vnfd_id = 'vnfd'
|
||||
vim_id = 'vim_id'
|
||||
description = 'my-description'
|
||||
region_name = 'region'
|
||||
key = 'key'
|
||||
value = 'value'
|
||||
|
||||
args = [
|
||||
name,
|
||||
'--vnfd-id', vnfd_id,
|
||||
'--vim-id', vim_id,
|
||||
'--description', description,
|
||||
'--vim-region-name', region_name,
|
||||
'--%s' % key, value]
|
||||
position_names = ['vnfd_id', 'vim_id', 'attributes']
|
||||
position_values = [vnfd_id, vim_id, {}]
|
||||
position_names = [
|
||||
'name',
|
||||
'vnfd_id',
|
||||
'vim_id',
|
||||
'description',
|
||||
'attributes'
|
||||
]
|
||||
position_values = [
|
||||
name,
|
||||
vnfd_id,
|
||||
vim_id,
|
||||
description,
|
||||
{}
|
||||
]
|
||||
extra_body = {key: value, 'placement_attr': {'region_name':
|
||||
region_name}}
|
||||
self._test_create_resource(self._RESOURCE, cmd, None, my_id,
|
||||
self._test_create_resource(self._RESOURCE, cmd, name, my_id,
|
||||
args, position_names, position_values,
|
||||
extra_body=extra_body)
|
||||
|
||||
def test_create_vnf_with_mandatory_params(self):
|
||||
cmd = vnf.CreateVNF(test_cli10.MyApp(sys.stdout), None)
|
||||
name = 'my_name'
|
||||
my_id = 'my-id'
|
||||
vnfd_id = 'vnfd'
|
||||
args = [
|
||||
name,
|
||||
'--vnfd-id', vnfd_id,
|
||||
]
|
||||
position_names = ['vnfd_id', 'attributes']
|
||||
position_values = [vnfd_id, {}]
|
||||
position_names = ['name', 'vnfd_id', 'attributes']
|
||||
position_values = [name, vnfd_id, {}]
|
||||
self._test_create_resource(self._RESOURCE, cmd, name, my_id,
|
||||
args, position_names, position_values)
|
||||
|
||||
def test_create_vnf_with_description_param(self):
|
||||
cmd = vnf.CreateVNF(test_cli10.MyApp(sys.stdout), None)
|
||||
name = 'my_name'
|
||||
my_id = 'my-id'
|
||||
vnfd_id = 'vnfd'
|
||||
description = 'my-description'
|
||||
args = [
|
||||
name,
|
||||
'--vnfd-id', vnfd_id,
|
||||
'--description', description,
|
||||
]
|
||||
position_names = ['name', 'vnfd_id', 'description',
|
||||
'attributes']
|
||||
position_values = [name, vnfd_id, description, {}]
|
||||
self._test_create_resource(self._RESOURCE, cmd, None, my_id,
|
||||
args, position_names, position_values)
|
||||
|
||||
@@ -157,3 +195,22 @@ class CLITestV10VmVNFJSON(test_cli10.CLITestV10Base):
|
||||
my_id = 'my-id'
|
||||
args = [my_id]
|
||||
self._test_delete_resource(self._RESOURCE, cmd, my_id, args)
|
||||
|
||||
def test_list_vnf_resources(self):
|
||||
cmd = vnf.ListVNFResources(test_cli10.MyApp(sys.stdout), None)
|
||||
base_args = [self.test_id]
|
||||
response = [{'name': 'CP11', 'id': 'id1', 'type': 'NeutronPort'},
|
||||
{'name': 'CP12', 'id': 'id2', 'type': 'NeutronPort'}]
|
||||
val = self._test_list_sub_resources(self._VNF_RESOURCES, 'resources',
|
||||
cmd, self.test_id,
|
||||
response_contents=response,
|
||||
detail=True, base_args=base_args)
|
||||
self.assertIn('id1', val)
|
||||
self.assertIn('NeutronPort', val)
|
||||
self.assertIn('CP11', val)
|
||||
|
||||
def test_multi_delete_vnf(self):
|
||||
cmd = vnf.DeleteVNF(test_cli10.MyApp(sys.stdout), None)
|
||||
vnf_ids = 'vnf1 vnf2 vnf3'
|
||||
args = [vnf_ids]
|
||||
self._test_delete_resource(self._RESOURCE, cmd, vnf_ids, args)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import sys
|
||||
|
||||
from tackerclient.tacker.v1_0.vm import vnfd
|
||||
from tackerclient.tacker.v1_0.vnfm import vnfd
|
||||
from tackerclient.tests.unit import test_cli10
|
||||
|
||||
|
||||
@@ -33,16 +33,14 @@ class CLITestV10VmVNFDJSON(test_cli10.CLITestV10Base):
|
||||
test_cli10.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
name = 'my-name'
|
||||
mgmt_driver = 'noop'
|
||||
infra_driver = 'heat'
|
||||
attr_key = 'vnfd'
|
||||
attr_val = 'vnfd'
|
||||
args = [
|
||||
'--name', name,
|
||||
name,
|
||||
'--vnfd', 'vnfd'
|
||||
]
|
||||
position_names = ['name', 'mgmt_driver', 'infra_driver']
|
||||
position_values = [name, mgmt_driver, infra_driver]
|
||||
position_names = ['name']
|
||||
position_values = [name]
|
||||
extra_body = {
|
||||
'service_types': [{'service_type': 'vnfd'}],
|
||||
'attributes': {attr_key: attr_val},
|
||||
@@ -54,17 +52,16 @@ class CLITestV10VmVNFDJSON(test_cli10.CLITestV10Base):
|
||||
def test_create_vnfd_with_mandatory_params(self):
|
||||
cmd = vnfd.CreateVNFD(
|
||||
test_cli10.MyApp(sys.stdout), None)
|
||||
name = 'my_name'
|
||||
my_id = 'my-id'
|
||||
mgmt_driver = 'noop'
|
||||
infra_driver = 'heat'
|
||||
args = ['--vnfd', 'vnfd', ]
|
||||
position_names = ['mgmt_driver', 'infra_driver']
|
||||
position_values = [mgmt_driver, infra_driver]
|
||||
args = [name, '--vnfd', 'vnfd', ]
|
||||
position_names = ['name']
|
||||
position_values = [name]
|
||||
extra_body = {
|
||||
'service_types': [{'service_type': 'vnfd'}],
|
||||
'attributes': {'vnfd': 'vnfd'}
|
||||
}
|
||||
self._test_create_resource(self._RESOURCE, cmd, None, my_id,
|
||||
self._test_create_resource(self._RESOURCE, cmd, name, my_id,
|
||||
args, position_names, position_values,
|
||||
extra_body=extra_body)
|
||||
|
||||
@@ -94,3 +91,10 @@ class CLITestV10VmVNFDJSON(test_cli10.CLITestV10Base):
|
||||
my_id = 'my-id'
|
||||
args = [my_id]
|
||||
self._test_delete_resource(self._RESOURCE, cmd, my_id, args)
|
||||
|
||||
def test_multi_delete_vnfd(self):
|
||||
cmd = vnfd.DeleteVNFD(
|
||||
test_cli10.MyApp(sys.stdout), None)
|
||||
vnfd_ids = 'my-id1 my-id2 my-id3'
|
||||
args = [vnfd_ids]
|
||||
self._test_delete_resource(self._RESOURCE, cmd, vnfd_ids, args)
|
||||
|
||||
106
tackerclient/tests/unit/vm/test_cli10_vnffg.py
Normal file
106
tackerclient/tests/unit/vm/test_cli10_vnffg.py
Normal file
@@ -0,0 +1,106 @@
|
||||
# Copyright 2014 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
|
||||
#
|
||||
# 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 sys
|
||||
|
||||
from tackerclient.tacker.v1_0.nfvo import vnffg
|
||||
from tackerclient.tests.unit import test_cli10
|
||||
|
||||
API_VERSION = "1.0"
|
||||
FORMAT = 'json'
|
||||
TOKEN = 'testtoken'
|
||||
ENDURL = 'localurl'
|
||||
|
||||
|
||||
class CLITestV10VmVNFFGJSON(test_cli10.CLITestV10Base):
|
||||
_RESOURCE = 'vnffg'
|
||||
_RESOURCES = 'vnffgs'
|
||||
|
||||
def setUp(self):
|
||||
plurals = {'vnffgs': 'vnffg'}
|
||||
super(CLITestV10VmVNFFGJSON, self).setUp(plurals=plurals)
|
||||
|
||||
def test_create_vnffg_all_params(self):
|
||||
cmd = vnffg.CreateVNFFG(test_cli10.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
vnffgd_id = 'vnffgd'
|
||||
vnffg_name = 'fake-vnffg'
|
||||
vnf_mapping = 'VNFD1:VNF1'
|
||||
|
||||
args = [
|
||||
vnffg_name,
|
||||
'--vnffgd-id', vnffgd_id,
|
||||
'--vnf-mapping', vnf_mapping,
|
||||
'--symmetrical', 'True']
|
||||
position_names = ['vnffgd_id', 'vnf_mapping', 'symmetrical']
|
||||
position_values = [vnffgd_id, {"VNFD1": "VNF1"}, 'True']
|
||||
extra_body = {'name': vnffg_name}
|
||||
self._test_create_resource(self._RESOURCE, cmd, None, my_id,
|
||||
args, position_names, position_values,
|
||||
extra_body=extra_body,
|
||||
get_client_called_count=2)
|
||||
|
||||
def test_create_vnffg_with_mandatory_params(self):
|
||||
cmd = vnffg.CreateVNFFG(test_cli10.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
vnffg_name = 'fake-vnffg'
|
||||
vnffgd_id = 'vnffgd'
|
||||
args = [
|
||||
vnffg_name,
|
||||
'--vnffgd-id', vnffgd_id,
|
||||
]
|
||||
position_names = ['vnffgd_id']
|
||||
position_values = [vnffgd_id]
|
||||
extra_body = {'name': vnffg_name}
|
||||
self._test_create_resource(self._RESOURCE, cmd, vnffg_name, my_id,
|
||||
args, position_names, position_values,
|
||||
extra_body=extra_body,
|
||||
get_client_called_count=2)
|
||||
|
||||
def test_list_vnffgs(self):
|
||||
cmd = vnffg.ListVNFFG(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True)
|
||||
|
||||
def test_list_vnffgs_pagenation(self):
|
||||
cmd = vnffg.ListVNFFG(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True)
|
||||
|
||||
def test_show_vnffg_id(self):
|
||||
cmd = vnffg.ShowVNFFG(test_cli10.MyApp(sys.stdout), None)
|
||||
args = ['--fields', 'id', self.test_id]
|
||||
self._test_show_resource(self._RESOURCE, cmd, self.test_id, args,
|
||||
['id'])
|
||||
|
||||
def test_show_vnffg_id_name(self):
|
||||
cmd = vnffg.ShowVNFFG(test_cli10.MyApp(sys.stdout), None)
|
||||
args = ['--fields', 'id', '--fields', 'name', self.test_id]
|
||||
self._test_show_resource(self._RESOURCE, cmd, self.test_id,
|
||||
args, ['id', 'name'])
|
||||
|
||||
def test_update_vnffg(self):
|
||||
cmd = vnffg.UpdateVNFFG(test_cli10.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
key = 'new_key'
|
||||
value = 'new-value'
|
||||
self._test_update_resource(self._RESOURCE, cmd, my_id,
|
||||
[my_id, '--%s' % key, value],
|
||||
{key: value}, get_client_called_count=2)
|
||||
|
||||
def test_delete_vnffg(self):
|
||||
cmd = vnffg.DeleteVNFFG(test_cli10.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
args = [my_id]
|
||||
self._test_delete_resource(self._RESOURCE, cmd, my_id, args)
|
||||
93
tackerclient/tests/unit/vm/test_cli10_vnffgd.py
Normal file
93
tackerclient/tests/unit/vm/test_cli10_vnffgd.py
Normal file
@@ -0,0 +1,93 @@
|
||||
# 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 sys
|
||||
|
||||
from tackerclient.tacker.v1_0.nfvo import vnffgd
|
||||
from tackerclient.tests.unit import test_cli10
|
||||
|
||||
|
||||
class CLITestV10VmVNFFGDJSON(test_cli10.CLITestV10Base):
|
||||
_RESOURCE = 'vnffgd'
|
||||
_RESOURCES = 'vnffgds'
|
||||
|
||||
def setUp(self):
|
||||
plurals = {'vnffgds': 'vnffgd'}
|
||||
super(CLITestV10VmVNFFGDJSON, self).setUp(plurals=plurals)
|
||||
|
||||
def test_create_vnffgd_all_params(self):
|
||||
cmd = vnffgd.CreateVNFFGD(test_cli10.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
name = 'my-name'
|
||||
attr_key = 'vnffgd'
|
||||
attr_val = 'vnffgd'
|
||||
description = 'vnffgd description'
|
||||
args = [
|
||||
name,
|
||||
'--vnffgd', 'vnffgd',
|
||||
'--description', description,
|
||||
]
|
||||
position_names = ['name', 'description']
|
||||
position_values = [name, description]
|
||||
extra_body = {
|
||||
'template': {attr_key: attr_val},
|
||||
}
|
||||
|
||||
self._test_create_resource(self._RESOURCE, cmd, name, my_id,
|
||||
args, position_names, position_values,
|
||||
extra_body=extra_body)
|
||||
|
||||
def test_create_vnffgd_with_mandatory_params(self):
|
||||
cmd = vnffgd.CreateVNFFGD(test_cli10.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
name = 'my-name'
|
||||
attr_key = 'vnffgd'
|
||||
attr_val = 'vnffgd'
|
||||
args = [
|
||||
name,
|
||||
'--vnffgd', 'vnffgd',
|
||||
]
|
||||
position_names = ['name']
|
||||
position_values = [name]
|
||||
extra_body = {
|
||||
'template': {attr_key: attr_val},
|
||||
}
|
||||
|
||||
self._test_create_resource(self._RESOURCE, cmd, name, my_id,
|
||||
args, position_names, position_values,
|
||||
extra_body=extra_body)
|
||||
|
||||
def test_list_vnffgds(self):
|
||||
cmd = vnffgd.ListVNFFGD(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True)
|
||||
|
||||
def test_list_vnffgds_pagenation(self):
|
||||
cmd = vnffgd.ListVNFFGD(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True)
|
||||
|
||||
def test_show_vnffgd_id(self):
|
||||
cmd = vnffgd.ShowVNFFGD(test_cli10.MyApp(sys.stdout), None)
|
||||
args = ['--fields', 'id', self.test_id]
|
||||
self._test_show_resource(self._RESOURCE, cmd, self.test_id, args,
|
||||
['id'])
|
||||
|
||||
def test_show_vnffgd_id_name(self):
|
||||
cmd = vnffgd.ShowVNFFGD(test_cli10.MyApp(sys.stdout), None)
|
||||
args = ['--fields', 'id', '--fields', 'name', self.test_id]
|
||||
self._test_show_resource(self._RESOURCE, cmd, self.test_id,
|
||||
args, ['id', 'name'])
|
||||
|
||||
def test_delete_vnffgd(self):
|
||||
cmd = vnffgd.DeleteVNFFGD(test_cli10.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
args = [my_id]
|
||||
self._test_delete_resource(self._RESOURCE, cmd, my_id, args)
|
||||
71
tackerclient/tests/unit/vm/test_vim_utils.py
Normal file
71
tackerclient/tests/unit/vm/test_vim_utils.py
Normal file
@@ -0,0 +1,71 @@
|
||||
# Copyright 2016 OpenStack Foundation.
|
||||
# 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.
|
||||
|
||||
|
||||
from mock import sentinel
|
||||
import testtools
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
from tackerclient.tacker.v1_0.nfvo import vim_utils
|
||||
|
||||
|
||||
class TestVIMUtils(testtools.TestCase):
|
||||
|
||||
def test_args2body_vim(self):
|
||||
config_param = {'project_id': sentinel.prj_id1,
|
||||
'username': sentinel.usrname1,
|
||||
'password': sentinel.password1,
|
||||
'project_domain_name': sentinel.prj_domain_name1,
|
||||
'user_domain_name': sentinel.user_domain.name, }
|
||||
vim = {}
|
||||
auth_cred = config_param.copy()
|
||||
auth_cred.pop('project_id')
|
||||
auth_cred.pop('project_domain_name')
|
||||
auth_cred.update({'user_id': ''})
|
||||
expected_vim = {'auth_cred': auth_cred,
|
||||
'vim_project':
|
||||
{'id': sentinel.prj_id1,
|
||||
'name': '',
|
||||
'project_domain_name': sentinel.prj_domain_name1}}
|
||||
vim_utils.args2body_vim(config_param.copy(), vim)
|
||||
self.assertEqual(expected_vim, vim)
|
||||
|
||||
def test_args2body_vim_no_project(self):
|
||||
config_param = {'username': sentinel.usrname1,
|
||||
'password': sentinel.password1,
|
||||
'user_domain_name': sentinel.user_domain.name, }
|
||||
vim = {}
|
||||
self.assertRaises(exceptions.TackerClientException,
|
||||
vim_utils.args2body_vim,
|
||||
config_param, vim)
|
||||
|
||||
def test_validate_auth_url_with_port(self):
|
||||
auth_url = "http://localhost:8000/test"
|
||||
url_parts = vim_utils.validate_auth_url(auth_url)
|
||||
self.assertEqual('http', url_parts.scheme)
|
||||
self.assertEqual('localhost:8000', url_parts.netloc)
|
||||
self.assertEqual(8000, url_parts.port)
|
||||
|
||||
def test_validate_auth_url_without_port(self):
|
||||
auth_url = "http://localhost/test"
|
||||
url_parts = vim_utils.validate_auth_url(auth_url)
|
||||
self.assertEqual('http', url_parts.scheme)
|
||||
self.assertEqual('localhost', url_parts.netloc)
|
||||
|
||||
def test_validate_auth_url_exception(self):
|
||||
auth_url = "localhost/test"
|
||||
self.assertRaises(exceptions.TackerClientException,
|
||||
vim_utils.validate_auth_url,
|
||||
auth_url)
|
||||
@@ -338,10 +338,36 @@ class Client(ClientBase):
|
||||
vnfd_path = '/vnfds/%s'
|
||||
vnfs_path = '/vnfs'
|
||||
vnf_path = '/vnfs/%s'
|
||||
vnf_scale_path = '/vnfs/%s/actions'
|
||||
vnf_resources_path = '/vnfs/%s/resources'
|
||||
|
||||
vims_path = '/vims'
|
||||
vim_path = '/vims/%s'
|
||||
|
||||
events_path = '/events'
|
||||
event_path = '/events/%s'
|
||||
|
||||
vnffgds_path = '/vnffgds'
|
||||
vnffgd_path = '/vnffgds/%s'
|
||||
|
||||
vnffgs_path = '/vnffgs'
|
||||
vnffg_path = '/vnffgs/%s'
|
||||
|
||||
nfps_path = '/nfps'
|
||||
nfp_path = '/nfps/%s'
|
||||
|
||||
sfcs_path = '/sfcs'
|
||||
sfc_path = '/sfcs/%s'
|
||||
|
||||
fcs_path = '/classifiers'
|
||||
fc_path = '/classifiers/%s'
|
||||
|
||||
nsds_path = '/nsds'
|
||||
nsd_path = '/nsds/%s'
|
||||
|
||||
nss_path = '/nss'
|
||||
ns_path = '/nss/%s'
|
||||
|
||||
# API has no way to report plurals, so we have to hard code them
|
||||
# EXTED_PLURALS = {}
|
||||
|
||||
@@ -356,6 +382,7 @@ class Client(ClientBase):
|
||||
return self.get(self.extension_path % ext_alias, params=_params)
|
||||
|
||||
_VNFD = "vnfd"
|
||||
_NSD = "nsd"
|
||||
|
||||
@APIParamsCall
|
||||
def list_vnfds(self, retrieve_all=True, **_params):
|
||||
@@ -376,13 +403,12 @@ class Client(ClientBase):
|
||||
params=_params)
|
||||
|
||||
@APIParamsCall
|
||||
def create_vnfd(self, body=None):
|
||||
if body is not None:
|
||||
body[self._VNFD]['service_types'] = [{'service_type': 'vnfd'}]
|
||||
body[self._VNFD]['infra_driver'] = 'heat'
|
||||
body[self._VNFD]['mgmt_driver'] = 'noop'
|
||||
else:
|
||||
body = None
|
||||
def create_vnfd(self, body):
|
||||
if ("tosca_definitions_version" not in
|
||||
body[self._VNFD]['attributes']['vnfd']):
|
||||
_logger.warning("VNFD legacy templates are deprecated. Please "
|
||||
"use NFV TOSCA templates.")
|
||||
body[self._VNFD]['service_types'] = [{'service_type': 'vnfd'}]
|
||||
return self.post(self.vnfds_path, body)
|
||||
|
||||
@APIParamsCall
|
||||
@@ -406,7 +432,7 @@ class Client(ClientBase):
|
||||
return self.get(self.vnf_path % vnf, params=_params)
|
||||
|
||||
@APIParamsCall
|
||||
def create_vnf(self, body=None):
|
||||
def create_vnf(self, body):
|
||||
return self.post(self.vnfs_path, body=body)
|
||||
|
||||
@APIParamsCall
|
||||
@@ -414,9 +440,18 @@ class Client(ClientBase):
|
||||
return self.delete(self.vnf_path % vnf)
|
||||
|
||||
@APIParamsCall
|
||||
def update_vnf(self, vnf, body=None):
|
||||
def update_vnf(self, vnf, body):
|
||||
return self.put(self.vnf_path % vnf, body=body)
|
||||
|
||||
@APIParamsCall
|
||||
def list_vnf_resources(self, vnf, retrieve_all=True, **_params):
|
||||
return self.list('resources', self.vnf_resources_path % vnf,
|
||||
retrieve_all, **_params)
|
||||
|
||||
@APIParamsCall
|
||||
def scale_vnf(self, vnf, body=None):
|
||||
return self.post(self.vnf_scale_path % vnf, body=body)
|
||||
|
||||
@APIParamsCall
|
||||
def show_vim(self, vim, **_params):
|
||||
return self.get(self.vim_path % vim, params=_params)
|
||||
@@ -424,7 +459,7 @@ class Client(ClientBase):
|
||||
_VIM = "vim"
|
||||
|
||||
@APIParamsCall
|
||||
def create_vim(self, body=None):
|
||||
def create_vim(self, body):
|
||||
return self.post(self.vims_path, body=body)
|
||||
|
||||
@APIParamsCall
|
||||
@@ -432,9 +467,201 @@ class Client(ClientBase):
|
||||
return self.delete(self.vim_path % vim)
|
||||
|
||||
@APIParamsCall
|
||||
def update_vim(self, vim, body=None):
|
||||
def update_vim(self, vim, body):
|
||||
return self.put(self.vim_path % vim, body=body)
|
||||
|
||||
@APIParamsCall
|
||||
def list_vims(self, retrieve_all=True, **_params):
|
||||
return self.list('vims', self.vims_path, retrieve_all, **_params)
|
||||
|
||||
@APIParamsCall
|
||||
def list_events(self, retrieve_all=True, **_params):
|
||||
events = self.list('events', self.events_path, retrieve_all,
|
||||
**_params)
|
||||
return events
|
||||
|
||||
@APIParamsCall
|
||||
def list_vnf_events(self, retrieve_all=True, **_params):
|
||||
_params['resource_type'] = 'vnf'
|
||||
events = self.list('events', self.events_path, retrieve_all,
|
||||
**_params)
|
||||
vnf_events = {}
|
||||
vnf_events['vnf_events'] = events['events']
|
||||
return vnf_events
|
||||
|
||||
@APIParamsCall
|
||||
def list_vnfd_events(self, retrieve_all=True, **_params):
|
||||
_params['resource_type'] = 'vnfd'
|
||||
events = self.list('events', self.events_path, retrieve_all,
|
||||
**_params)
|
||||
vnfd_events = {}
|
||||
vnfd_events['vnfd_events'] = events['events']
|
||||
return vnfd_events
|
||||
|
||||
@APIParamsCall
|
||||
def list_vim_events(self, retrieve_all=True, **_params):
|
||||
_params['resource_type'] = 'vim'
|
||||
events = self.list('events', self.events_path, retrieve_all,
|
||||
**_params)
|
||||
vim_events = {}
|
||||
vim_events['vim_events'] = events['events']
|
||||
return vim_events
|
||||
|
||||
@APIParamsCall
|
||||
def show_event(self, event_id, **_params):
|
||||
return self.get(self.event_path % event_id, params=_params)
|
||||
|
||||
_VNFFGD = "vnffgd"
|
||||
|
||||
@APIParamsCall
|
||||
def create_vnffgd(self, body):
|
||||
return self.post(self.vnffgds_path, body)
|
||||
|
||||
@APIParamsCall
|
||||
def list_vnffgds(self, retrieve_all=True, **_params):
|
||||
vnffgds_dict = self.list(self._VNFFGD + 's',
|
||||
self.vnffgds_path,
|
||||
retrieve_all,
|
||||
**_params)
|
||||
for vnffgd in vnffgds_dict['vnffgds']:
|
||||
if 'description' in vnffgd.keys() and \
|
||||
len(vnffgd['description']) > DEFAULT_DESC_LENGTH:
|
||||
vnffgd['description'] = vnffgd['description'][
|
||||
:DEFAULT_DESC_LENGTH]
|
||||
vnffgd['description'] += '...'
|
||||
return vnffgds_dict
|
||||
|
||||
@APIParamsCall
|
||||
def show_vnffgd(self, vnffgd, **_params):
|
||||
return self.get(self.vnffgd_path % vnffgd, params=_params)
|
||||
|
||||
@APIParamsCall
|
||||
def delete_vnffgd(self, vnffgd):
|
||||
return self.delete(self.vnffgd_path % vnffgd)
|
||||
|
||||
@APIParamsCall
|
||||
def list_vnffgs(self, retrieve_all=True, **_params):
|
||||
vnffgs = self.list('vnffgs', self.vnffgs_path, retrieve_all, **_params)
|
||||
for vnffg in vnffgs['vnffgs']:
|
||||
error_reason = vnffg.get('error_reason', None)
|
||||
if error_reason and \
|
||||
len(error_reason) > DEFAULT_ERROR_REASON_LENGTH:
|
||||
vnffg['error_reason'] = error_reason[
|
||||
:DEFAULT_ERROR_REASON_LENGTH]
|
||||
vnffg['error_reason'] += '...'
|
||||
return vnffgs
|
||||
|
||||
@APIParamsCall
|
||||
def show_vnffg(self, vnffg, **_params):
|
||||
return self.get(self.vnffg_path % vnffg, params=_params)
|
||||
|
||||
@APIParamsCall
|
||||
def create_vnffg(self, body):
|
||||
return self.post(self.vnffgs_path, body=body)
|
||||
|
||||
@APIParamsCall
|
||||
def delete_vnffg(self, vnffg):
|
||||
return self.delete(self.vnffg_path % vnffg)
|
||||
|
||||
@APIParamsCall
|
||||
def update_vnffg(self, vnffg, body):
|
||||
return self.put(self.vnffg_path % vnffg, body=body)
|
||||
|
||||
@APIParamsCall
|
||||
def list_sfcs(self, retrieve_all=True, **_params):
|
||||
sfcs = self.list('sfcs', self.sfcs_path, retrieve_all, **_params)
|
||||
for chain in sfcs['sfcs']:
|
||||
error_reason = chain.get('error_reason', None)
|
||||
if error_reason and \
|
||||
len(error_reason) > DEFAULT_ERROR_REASON_LENGTH:
|
||||
chain['error_reason'] = error_reason[
|
||||
:DEFAULT_ERROR_REASON_LENGTH]
|
||||
chain['error_reason'] += '...'
|
||||
return sfcs
|
||||
|
||||
@APIParamsCall
|
||||
def show_sfc(self, chain, **_params):
|
||||
return self.get(self.sfc_path % chain, params=_params)
|
||||
|
||||
@APIParamsCall
|
||||
def list_nfps(self, retrieve_all=True, **_params):
|
||||
nfps = self.list('nfps', self.nfps_path, retrieve_all, **_params)
|
||||
for nfp in nfps['nfps']:
|
||||
error_reason = nfp.get('error_reason', None)
|
||||
if error_reason and \
|
||||
len(error_reason) > DEFAULT_ERROR_REASON_LENGTH:
|
||||
nfp['error_reason'] = error_reason[
|
||||
:DEFAULT_ERROR_REASON_LENGTH]
|
||||
nfp['error_reason'] += '...'
|
||||
return nfps
|
||||
|
||||
@APIParamsCall
|
||||
def show_nfp(self, nfp, **_params):
|
||||
return self.get(self.nfp_path % nfp, params=_params)
|
||||
|
||||
@APIParamsCall
|
||||
def list_classifiers(self, retrieve_all=True, **_params):
|
||||
classifiers = self.list('classifiers', self.fcs_path, retrieve_all,
|
||||
**_params)
|
||||
for classifier in classifiers['classifiers']:
|
||||
error_reason = classifier.get('error_reason', None)
|
||||
if error_reason and \
|
||||
len(error_reason) > DEFAULT_ERROR_REASON_LENGTH:
|
||||
classifier['error_reason'] = error_reason[
|
||||
:DEFAULT_ERROR_REASON_LENGTH]
|
||||
classifier['error_reason'] += '...'
|
||||
return classifiers
|
||||
|
||||
@APIParamsCall
|
||||
def show_classifier(self, classifier, **_params):
|
||||
return self.get(self.fc_path % classifier, params=_params)
|
||||
|
||||
@APIParamsCall
|
||||
def list_nsds(self, retrieve_all=True, **_params):
|
||||
nsds_dict = self.list(self._NSD + 's',
|
||||
self.nsds_path,
|
||||
retrieve_all,
|
||||
**_params)
|
||||
for nsd in nsds_dict['nsds']:
|
||||
if 'description' in nsd.keys() and \
|
||||
len(nsd['description']) > DEFAULT_DESC_LENGTH:
|
||||
nsd['description'] = nsd['description'][:DEFAULT_DESC_LENGTH]
|
||||
nsd['description'] += '...'
|
||||
return nsds_dict
|
||||
|
||||
@APIParamsCall
|
||||
def show_nsd(self, nsd, **_params):
|
||||
return self.get(self.nsd_path % nsd,
|
||||
params=_params)
|
||||
|
||||
@APIParamsCall
|
||||
def create_nsd(self, body):
|
||||
return self.post(self.nsds_path, body)
|
||||
|
||||
@APIParamsCall
|
||||
def delete_nsd(self, nsd):
|
||||
return self.delete(self.nsd_path % nsd)
|
||||
|
||||
@APIParamsCall
|
||||
def list_nss(self, retrieve_all=True, **_params):
|
||||
nss = self.list('nss', self.nss_path, retrieve_all, **_params)
|
||||
for ns in nss['nss']:
|
||||
error_reason = ns.get('error_reason', None)
|
||||
if error_reason and \
|
||||
len(error_reason) > DEFAULT_ERROR_REASON_LENGTH:
|
||||
ns['error_reason'] = error_reason[
|
||||
:DEFAULT_ERROR_REASON_LENGTH]
|
||||
ns['error_reason'] += '...'
|
||||
return nss
|
||||
|
||||
@APIParamsCall
|
||||
def show_ns(self, ns, **_params):
|
||||
return self.get(self.ns_path % ns, params=_params)
|
||||
|
||||
@APIParamsCall
|
||||
def create_ns(self, body):
|
||||
return self.post(self.nss_path, body=body)
|
||||
|
||||
@APIParamsCall
|
||||
def delete_ns(self, ns):
|
||||
return self.delete(self.ns_path % ns)
|
||||
|
||||
@@ -2,18 +2,16 @@
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
hacking<0.11,>=0.10.2
|
||||
cliff-tablib>=1.0 # Apache-2.0
|
||||
coverage>=3.6 # Apache-2.0
|
||||
discover # BSD
|
||||
coverage>=4.0 # Apache-2.0
|
||||
fixtures>=3.0.0 # Apache-2.0/BSD
|
||||
mox>=0.5.3 # Apache-2.0
|
||||
flake8<2.6.0,>=2.5.4 # MIT
|
||||
pep8==1.5.7 # MIT
|
||||
pyflakes==0.8.1 # MIT
|
||||
python-subunit>=0.0.18 # Apache-2.0/BSD
|
||||
sphinx!=1.3b1,<1.3,>=1.2.1 # BSD
|
||||
sphinx!=1.3b1,<1.4,>=1.2.1 # BSD
|
||||
testrepository>=0.0.18 # Apache-2.0/BSD
|
||||
testtools>=1.4.0 # MIT
|
||||
|
||||
# releasenotes
|
||||
reno>=1.6.2 # Apache2
|
||||
reno>=1.8.0 # Apache-2.0
|
||||
mock>=2.0 # BSD
|
||||
|
||||
30
tools/tox_install.sh
Executable file
30
tools/tox_install.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Client constraint file contains this client version pin that is in conflict
|
||||
# with installing the client from source. We should remove the version pin in
|
||||
# the constraints file before applying it for from-source installation.
|
||||
|
||||
CONSTRAINTS_FILE="$1"
|
||||
shift 1
|
||||
|
||||
set -e
|
||||
|
||||
# NOTE(tonyb): Place this in the tox enviroment's log dir so it will get
|
||||
# published to logs.openstack.org for easy debugging.
|
||||
localfile="$VIRTUAL_ENV/log/upper-constraints.txt"
|
||||
|
||||
if [[ "$CONSTRAINTS_FILE" != http* ]]; then
|
||||
CONSTRAINTS_FILE="file://$CONSTRAINTS_FILE"
|
||||
fi
|
||||
# NOTE(tonyb): need to add curl to bindep.txt if the project supports bindep
|
||||
curl "$CONSTRAINTS_FILE" --insecure --progress-bar --output "$localfile"
|
||||
|
||||
pip install -c"$localfile" openstack-requirements
|
||||
|
||||
# This is the main purpose of the script: Allow local installation of
|
||||
# the current repo. It is listed in constraints file and thus any
|
||||
# install will be constrained and we need to unconstrain it.
|
||||
edit-constraints "$localfile" -- "$CLIENT_NAME"
|
||||
|
||||
pip install -c"$localfile" -U "$@"
|
||||
exit $?
|
||||
6
tox.ini
6
tox.ini
@@ -1,15 +1,17 @@
|
||||
[tox]
|
||||
envlist = py34,py27,pypy,pep8
|
||||
minversion = 1.6
|
||||
minversion = 2.0
|
||||
skipsdist = True
|
||||
|
||||
[testenv]
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
BRANCH_NAME=master
|
||||
CLIENT_NAME=python-tackerclient
|
||||
LANG=en_US.UTF-8
|
||||
LANGUAGE=en_US:en
|
||||
LC_ALL=C
|
||||
usedevelop = True
|
||||
install_command = pip install -U {opts} {packages}
|
||||
install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = python setup.py testr --testr-args='{posargs}'
|
||||
|
||||
Reference in New Issue
Block a user