Compare commits

...

53 Commits

Author SHA1 Message Date
gong yong sheng
258aa70e3b Allow auth url without port for vim registration
This patch allows vim-register command to register keystone
URL without port.

Change-Id: Ie04a0253aa3f42ef532ccf8a7bddbbd1f88e3e34
Closes-bug: 1618756
(cherry picked from commit 3b60ab1aaa)
2017-01-20 22:56:21 +00:00
OpenStack Proposal Bot
a3c4723161 Updated from global requirements
Change-Id: Iee4f4946386d1eec4ead9a59c017e8e60d159537
2016-09-20 13:16:36 +00:00
Doug Hellmann
22c72c1c0a Update .gitreview for stable/newton
Change-Id: Ica1c231811ee7b8a57897a2d267ebf43b10e2fa9
2016-09-02 09:44:46 -04:00
Jenkins
48d458d290 Merge "Modify MyURLComparator to handle deep match on URL" 2016-08-27 14:29:16 +00:00
Jenkins
32ad7f33b6 Merge "Moving test files to vm directory" 2016-08-27 14:18:08 +00:00
vish
f1eef18974 Moving test files to vm directory
This commit moves the test files from events and nfvo directory
to the vm directory. Currently tests are executed if they are in
the vm directory.

Change-Id: I7ac08fb5686597926ec3b3c62d8221abf2b0f066
Implements: blueprint: audit-support
2016-08-27 03:40:54 +00:00
OpenStack Proposal Bot
23f34cdf1a Updated from global requirements
Change-Id: I9de7f7fdc86598cfbc23a760769e4dcc806d52d7
2016-08-27 00:41:11 +00:00
Jenkins
78b0876baf Merge "cli: modify vnfd, param & config attr. to dict obj" 2016-08-26 23:33:49 +00:00
Sripriya
f6848f0f31 Modify MyURLComparator to handle deep match on URL
MyURLComparator equals method is enhanced to perfom url comparison
based on url parts such as scheme, netloc, path and query instead
of raw string comparison.

pagination methods are modified to wrap the url requests with pagination
params within MyURLComparator objects.

Change-Id: I69b835dce64d662d1af6a14556fb8281e3b04d63
Closes-Bug: #1617480
2016-08-26 16:03:27 -07:00
Jenkins
542a2bb083 Merge "Deprecate infra_driver and mgmt_driver" 2016-08-26 22:34:28 +00:00
digambar
ced23fe6ab Deprecate infra_driver and mgmt_driver
infra_driver will be automatically figured out
in the VNF instantiation based on target VIM type
mgmt_driver is specified in the TOSCA template
per-VDU and the value the client API is ignored

Both these attributes will be removed in Ocata.

Change-Id: Ic59d7f8af6e4b1a27f4125f57d8165dc1011ce9e
Closes-bug: #1524243
2016-08-26 20:26:40 +00:00
Sripriya
aa499bb5f3 Remove list_vnf_resource_pagination unit test
This patch removes the list_vnf_resource_pagination unit test
which tested the pagination support of list_vnf_resources.
Pagination support is not enabled for vnf resources and hence
removed the test case.

Change-Id: I98843a63f6566595ceeb4758926a441fff2ee0ff
2016-08-26 12:54:41 -07:00
Jenkins
c047bf9db2 Merge "Add client support for VNFFG in NFVO" 2016-08-26 17:25:42 +00:00
xu-haiwei
882f6b6c93 Add client support for VNFFG in NFVO
Co-Authored-By: Tim Rozet <trozet@redhat.com>

implements blueprint: tacker-vnffg
Change-Id: Ic5273319a01b8003e9497fbf7f984972602c7698
2016-08-26 09:23:35 -04:00
Sripriya
ed102cac10 cli: modify vnfd, param & config attr. to dict obj
vnfd templates, parameter and config files are sent as yaml
strings in requests body to tacker server.

Change the attributes to dictionary objects. New behavior
is applicable to tosca templates only. Also, this change may mangle
the order of nodes in tosca templates. In order to address this
concern and preserve the network interfaces order in these nodes,
there will be follow on patch (on server) to addres this.

Change-Id: I05a1d60dc643dca864aff559f37491914b1fcfc3
Partial-Bug: #1591361
2016-08-26 00:57:13 -07:00
Tim Rozet
144408331e Adds client commands for listing a VNF resources
Support now for being able list sub resources of a vnf. REST path is
/vnf/<vnf_id>/resources/.  Resources will contain 'name', 'id', and
'type'.

APIImpact
Partial-Bug: 1602112

Change-Id: Ib9f0163c0c86df2a4d17630a5e6f7ca2d2fb22de
Signed-off-by: Tim Rozet <trozet@redhat.com>
2016-08-25 22:34:03 +00:00
Jenkins
7f829587b0 Merge "Revert "Creates details API to fetch VNF detials"" 2016-08-25 21:55:25 +00:00
Janki Chhatbar
cc0a66884b Revert "Creates details API to fetch VNF detials"
This reverts commit 5a1f2f5717.

Reverting in account of a new patch [1].

[1]. https://review.openstack.org/#/c/360197/

Change-Id: Iaf5f65bd20bb098120378f9b63c86b97a86df35d
2016-08-25 14:22:29 +00:00
Jenkins
7a0f627e2e Merge "Add "Description" parameter while creating VNF with CLI." 2016-08-24 21:03:57 +00:00
Janki
5a1f2f5717 Creates details API to fetch VNF detials
Created details API to fetch VNF details. This is optional
based on the --show-details flag enabled.

APIImpact
Partial-Bug: #1602112

Change-Id: I63bcf3f9ad23fbbcfdec6f72e45540ce55e6bd7c
2016-08-20 05:35:42 +05:30
Jenkins
6b677a8f38 Merge "Remove '--config' option when create/update a vim" 2016-08-18 02:59:51 +00:00
vish
647baba801 Adds audit support in client
This commit enables support in the client for the resource event
logging

Implements: blueprint: audit-support

Co-Authored-By: Kanagaraj Manickam <mkr1481@gmail.com>

Change-Id: Ia54aed6720043840b00dd2eb00ca03a2ed92da5e
Depends-On: Change-Id: Ib82be521c5aa8b627e3f34a3696b10508371d3a0
2016-08-16 22:35:03 +00:00
Jenkins
977038a0b3 Merge "VNF scaling: CLI and python client" 2016-08-16 21:28:03 +00:00
xu-haiwei
e5457e5062 Remove '--config' option when create/update a vim
When create/update a vim, only enable '--config-file' option, will
remove '--config' option.

Change-Id: I8a728134ce0229db98de10bff5f4f46e7f2a9f2c
Closes-bug: #1587216
2016-08-15 13:14:39 +00:00
OpenStack Proposal Bot
00520f74d0 Updated from global requirements
Change-Id: I99264b7f6e6211ef486b77e9dcd198d7eaa218ff
2016-08-11 18:18:28 +00:00
Manikantha Srinivas Tadi
6fecf2adf7 Add "Description" parameter while creating VNF with CLI.
Partial-Bug: #1586300

Change-Id: Ifaea2344b7f00414de743be1c035bd750e0af87b
2016-08-11 04:17:44 -04:00
Jenkins
166368b8b0 Merge "Make VNFD/VNF/VIM Name Mandatory in Tacker CLI" 2016-08-11 02:23:41 +00:00
Kanagaraj Manickam
94ccf2ded8 VNF scaling: CLI and python client
vnf-scale --vnf-name <vnf-name> --vnf-id <vnf-id>
          --scaling-policy-name <policy-name>
          --scaling-type <type>

implements:  blueprint #vnf-scaling
depends-on: Ib8cdd1295460e617806eec173e4d4ed8f35e6642

Change-Id: If88273efad41eaff466895ad7dbba6a8de31d119
2016-08-05 06:22:21 +05:30
Jenkins
eebea81587 Merge "VNFD legacy template deprecation warning" 2016-08-04 22:28:43 +00:00
Jenkins
4b7fce5642 Merge "Unified formats of log_xxx function" 2016-08-04 18:40:45 +00:00
Jenkins
1cbf0ba295 Merge "Remove discover from test-requirements" 2016-08-03 20:04:13 +00:00
Janki Chhatbar
5a9490e567 VNFD legacy template deprecation warning
Throws VNFD legacy template deprecation warning in favor of using
TOSCA templates. This is client-side patch.

Partial-Bug: #1582928
Change-Id: Ia8bed682c1724a7d0e4e6330fc99c6ff49f71388
2016-08-03 11:54:13 +05:30
OpenStack Proposal Bot
fc4772603d Updated from global requirements
Change-Id: Iaa1f5337866a6ab3390c6c0de2896e67cc901849
2016-07-29 02:35:14 +00:00
gong yong sheng
0aa7efd292 Add domain information into auth cred.
If we use v3 keystone, these information should be passed
into tacker server.

Change-Id: Ieb5612c966b2110930faac0401f5dabde064ffc1
Partial-Bug: #1603851
2016-07-28 14:06:48 +08:00
Lu lei
31626a41c4 Unified formats of log_xxx function
This patch is used to unified formats of
log_xxx function.I have founded all log_xxx
funtions of project files.Only this one is still
not the same as others. I think change this formats
may make codes more readable and uniform.

OpenStack supports translating some log levels
using separate message catalogs, when we add
Variables to Log Messages, We do not do this:
    LOG.info(_LI('some message: variable=%s') % variable)
actually, we use this style insteaded:
    LOG.info(_LI('some message: variable=%s'), variable)

Change-Id: I3fd924516969853b2b9dced7659d33cdadd8d4ad
2016-07-28 13:35:32 +08:00
Manikantha Srinivas Tadi
f4daaa09ba Make VNFD/VNF/VIM Name Mandatory in Tacker CLI
Change-Id: I7e94cc43a61fbeb2b406d1e973ca422359e761a0
Partial-Bug: #1474966
2016-07-26 00:09:58 -04:00
Jenkins
e88619e985 Merge "Transition default VIM to API and DB operation" 2016-07-25 18:05:44 +00:00
Jenkins
602c06373d Merge "Remove the mask password logic in vim list and vim show" 2016-07-23 02:31:44 +00:00
Kawaguchi Kentaro
c9ac53a722 Remove the mask password logic in vim list and vim show
In vim list and vim show command,
since hashed password masking on server-side,
the "mask_dict_password" modules are removed on client-side.

Change-Id: I463cb04696dc09157fbbc4b0bd64e66850feac84
Depends-On: Ice5c51b6a66cd27f21c144d3a672cf790e4cec41
Closes-bug: #1594495
2016-07-22 14:03:33 +09:00
Swapnil Kulkarni (coolsvap)
4197bd5356 Remove discover from test-requirements
It's only needed for python < 2.7 which is not supported

Change-Id: I5c4982787b561a988eb837fdb8caad50cf0697a3
2016-07-22 04:14:59 +00:00
Saju Madhavan
00d87bde7e Transition default VIM to API and DB operation
Set the default-vim in the tacker-db and provide
API to manage it.

Change-Id: Ie447f13c1d30e3cf5c1756c424fe60882082c211
Partial-Bug: 1592957
2016-07-20 18:27:39 +05:30
xu-haiwei
9910cbc746 Remove unused import library
TrivialFix

Change-Id: I3f75282a0b9b0493f8d0ead8092cee76824290a8
2016-07-20 01:11:11 +00:00
Jenkins
431a79ba3d Merge "remove unused LOG" 2016-07-15 13:14:13 +00:00
Jenkins
3c6f82dfaf Merge "Display Health status of VIM" 2016-07-11 19:30:22 +00:00
Jenkins
af6db3f107 Merge "Updated from global requirements" 2016-07-11 04:15:41 +00:00
Jenkins
6fd6b66466 Merge "Add .idea/ to python-tackerclient .gitignore" 2016-07-11 04:06:18 +00:00
ji-xuepeng
654ad24e3b remove unused LOG
This is to remove unused LOG to keep code clean

Change-Id: Iba4e29892f3011356ce927f73ce9f418365df609
2016-07-10 14:59:47 +08:00
OpenStack Proposal Bot
b35672be34 Updated from global requirements
Change-Id: Icfa8e264b51ffdf10e6891f40b025c5d61933002
2016-07-09 19:27:25 +00:00
Neeldhwaj Pathak
04298efa2d Add .idea/ to python-tackerclient .gitignore
Change-Id: I03c4403d6256825f6d82e81256b60d03b42c52de
2016-07-08 21:23:13 +05:30
xu-haiwei
a5ad0bc3d3 Fix ext-show command error
Currently ext-show command can not be ran correctly, because
there are duplicated arguments added to command options.

Change-Id: I36fdb3608f9976c633902bba04d61c3cd63b1b39
Closes-bug: #1595036
2016-07-08 01:14:20 +00:00
OpenStack Proposal Bot
f42187050f Updated from global requirements
Change-Id: I155f111afd011f42146b24a7591ad0452cd8ed76
2016-06-30 18:50:03 +00:00
OpenStack Proposal Bot
a4dcd7634a Updated from global requirements
Change-Id: Id797401c8b23fba00ac9c20737b5f51a51c2309f
2016-06-24 08:45:56 +00:00
Bharath Thiruveedula
c32028201f Display Health status of VIM
Change-Id: I59993e2b2187588cc216cba3d05e3da1b4f1cc2c
Closes-Bug: #1554280
Depends-On: I25beaa5e1fd2fca87503c45d720f89d6f8156622
2016-05-12 16:39:52 +05:30
32 changed files with 1401 additions and 148 deletions

1
.gitignore vendored
View File

@@ -17,6 +17,7 @@ run_tests.log
.autogenerated
.coverage
.testrepository/
.idea/
.tox/
.venv/

View File

@@ -2,3 +2,4 @@
host=review.openstack.org
port=29418
project=openstack/python-tackerclient.git
defaultbranch=stable/newton

View File

@@ -0,0 +1,4 @@
---
deprecations:
- infra_driver and mgmt_driver attributes in VNFD client
attribute is deprecated and will be removed in Ocata.

View File

@@ -0,0 +1,4 @@
---
features:
- Adds new CLI command 'vnf-resource-list' to view VNF
resources, such as VDU, CP, etc.

View File

@@ -0,0 +1,3 @@
---
features:
- Made VNFD/VNF/VIM names mandatory in tacker CLI.

View File

@@ -0,0 +1,3 @@
---
features:
- Add client support for VNFFG.

View File

@@ -4,13 +4,15 @@
pbr>=1.6 # Apache-2.0
cliff!=1.16.0,!=1.17.0,>=1.15.0 # Apache-2.0
iso8601>=0.1.11 # MIT
netaddr!=0.7.16,>=0.7.12 # BSD
netaddr!=0.7.16,>=0.7.13 # BSD
requests>=2.10.0 # Apache-2.0
python-keystoneclient!=1.8.0,!=2.1.0,>=1.7.0 # Apache-2.0
python-keystoneclient!=2.1.0,>=2.0.0 # Apache-2.0
simplejson>=2.2.0 # MIT
six>=1.9.0 # MIT
Babel>=2.3.4 # BSD
oslo.i18n>=2.1.0 # Apache-2.0
oslo.utils>=3.11.0 # Apache-2.0
oslo.log>=1.14.0 # Apache-2.0
oslo.utils>=3.16.0 # Apache-2.0
oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0

View File

@@ -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."""

View File

@@ -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)

View File

@@ -45,8 +45,11 @@ 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 vim
from tackerclient.tacker.v1_0.nfvo import vnffg
from tackerclient.tacker.v1_0.nfvo import vnffgd
from tackerclient.tacker.v1_0.vm import vnf
from tackerclient.tacker.v1_0.vm import vnfd
from tackerclient.version import __version__
@@ -115,6 +118,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 +128,33 @@ 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,
}
COMMANDS = {'1.0': COMMAND_V1}

View File

@@ -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')
@@ -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)
@@ -649,6 +648,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 +660,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

View 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

View File

@@ -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'

View File

@@ -14,11 +14,9 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_utils import strutils
import yaml
from tackerclient.common import exceptions
from tackerclient.common import utils
from tackerclient.tacker import v1_0 as tackerV10
from tackerclient.tacker.v1_0.nfvo import vim_utils
@@ -30,11 +28,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 +43,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',
'--config-file',
required=True,
help='Specify VIM specific config parameters in a file')
parser.add_argument(
'name', metavar='NAME',
help='Set a name for the VIM')
parser.add_argument(
'--description',
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 +72,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 +87,14 @@ 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')
parser.add_argument(
'--is-default',
action='store_true',
default=False,
help='Set as default VIM')
def args2body(self, parsed_args):
body = {self.resource: {}}
@@ -106,16 +103,14 @@ 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', 'is_default'])
return body

View File

@@ -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

View File

@@ -0,0 +1,168 @@
# 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
_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')
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
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
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

View 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!'))

View File

@@ -15,10 +15,15 @@
# 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):
@@ -43,8 +48,11 @@ class CreateVNF(tackerV10.CreateCommand):
def add_known_arguments(self, parser):
parser.add_argument(
'--name',
'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',
@@ -77,14 +85,22 @@ class CreateVNF(tackerV10.CreateCommand):
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()
args['attributes']['config'] = config_yaml
config = yaml.load(
config_yaml, Loader=yaml.SafeLoader)
if parsed_args.config:
parsed_args.config = parsed_args.config.decode('unicode_escape')
args['attributes']['config'] = 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
@@ -106,9 +122,11 @@ class CreateVNF(tackerV10.CreateCommand):
if parsed_args.param_file:
with open(parsed_args.param_file) as f:
param_yaml = f.read()
args['attributes']['param_values'] = param_yaml
args['attributes']['param_values'] = yaml.load(
param_yaml, Loader=yaml.SafeLoader)
tackerV10.update_dict(parsed_args, body[self.resource],
['tenant_id', 'name', 'vnfd_id', 'vim_id'])
['tenant_id', 'name', 'description',
'vnfd_id', 'vim_id'])
return body
@@ -128,13 +146,20 @@ class UpdateVNF(tackerV10.UpdateCommand):
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()
body[self.resource]['attributes'] = {'config': config_yaml}
config = yaml.load(config_yaml, Loader=yaml.SafeLoader)
if parsed_args.config:
parsed_args.config = parsed_args.config.decode('unicode_escape')
body[self.resource]['attributes'] = {'config': 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
@@ -143,3 +168,125 @@ class DeleteVNF(tackerV10.DeleteCommand):
"""Delete a given VNF."""
resource = _VNF
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

View File

@@ -15,10 +15,10 @@
# License for the specific language governing permissions and limitations
# under the License.
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
@@ -50,7 +50,7 @@ class CreateVNFD(tackerV10.CreateCommand):
group.add_argument('--vnfd-file', help='Specify VNFD file')
group.add_argument('--vnfd', help='Specify VNFD')
parser.add_argument(
'--name',
'name', metavar='NAME',
help='Set a name for the VNFD')
parser.add_argument(
'--description',
@@ -58,12 +58,21 @@ class CreateVNFD(tackerV10.CreateCommand):
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'])

View File

@@ -21,6 +21,7 @@ import cStringIO
import fixtures
import mox
import six
import six.moves.urllib.parse as urlparse
import sys
import testtools
@@ -85,7 +86,17 @@ class MyUrlComparator(mox.Comparator):
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:
@@ -205,7 +216,7 @@ class CLITestV10Base(testtools.TestCase):
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']
non_admin_status_resources = ['vnfd', 'vnf', 'vim', 'vnffgd', 'vnffg']
if (resource in non_admin_status_resources):
body = {resource: {}, }
else:
@@ -369,6 +380,139 @@ class CLITestV10Base(testtools.TestCase):
self.assertIn('myid1', _str)
return _str
def _test_list_sub_resources(self, resources, api_resource, cmd, myid,
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', }, ]
else:
contents = response_contents
reses = {api_resource: contents}
self.client.format = self.format
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)
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")
self.client.httpclient.request(
MyUrlComparator(end_url(path % myid, 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()
_str = self.fake_stdout.make_string()
if response_contents is None:
self.assertIn('myid1', _str)
return _str
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")
@@ -390,8 +534,8 @@ class CLITestV10Base(testtools.TestCase):
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,
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()

View 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'

View File

@@ -0,0 +1,5 @@
username: 'xyz'
password: '12345'
project_name: 'abc'
project_domain_name: 'prj_domain_name'
user_domain_name: 'user_domain_name'

View 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)

View File

@@ -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]
@@ -125,13 +126,13 @@ class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
def test_update_vim(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'
key = 'config-file'
value = str(update_config)
extra_fields = {'vim_project': self.vim_project, 'auth_cred':
self.auth_cred}
self.auth_cred, 'is_default': False}
self._test_update_resource(self._RESOURCE, cmd, my_id, [my_id,
'--%s' %
key, value],

View File

@@ -32,9 +32,11 @@ 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,
@@ -91,35 +93,70 @@ class CLITestV10VmVNFJSON(test_cli10.CLITestV10Base):
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 +194,16 @@ 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)

View File

@@ -38,7 +38,7 @@ class CLITestV10VmVNFDJSON(test_cli10.CLITestV10Base):
attr_key = 'vnfd'
attr_val = 'vnfd'
args = [
'--name', name,
name,
'--vnfd', 'vnfd'
]
position_names = ['name', 'mgmt_driver', 'infra_driver']
@@ -54,17 +54,18 @@ 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', 'mgmt_driver', 'infra_driver']
position_values = [name, mgmt_driver, infra_driver]
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)

View File

@@ -0,0 +1,104 @@
# 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)
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)
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})
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)

View 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)

View 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)

View File

@@ -338,10 +338,30 @@ 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'
# API has no way to report plurals, so we have to hard code them
# EXTED_PLURALS = {}
@@ -378,7 +398,16 @@ class Client(ClientBase):
@APIParamsCall
def create_vnfd(self, body=None):
if body is not None:
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'}]
_logger.warning(
"Passing infra_driver and mgmt_driver in the VNFD"
" API is deprecated. infra_driver will be automatically"
" derived from target vim type. mgmt_driver will be"
" derived from TOSCA template values.")
body[self._VNFD]['infra_driver'] = 'heat'
body[self._VNFD]['mgmt_driver'] = 'noop'
else:
@@ -417,6 +446,15 @@ class Client(ClientBase):
def update_vnf(self, vnf, body=None):
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)
@@ -438,3 +476,145 @@ class Client(ClientBase):
@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=None):
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=None):
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=None):
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)

View File

@@ -4,7 +4,6 @@
hacking<0.11,>=0.10.2
cliff-tablib>=1.0 # Apache-2.0
coverage>=3.6 # Apache-2.0
discover # BSD
fixtures>=3.0.0 # Apache-2.0/BSD
mox>=0.5.3 # Apache-2.0
flake8<2.6.0,>=2.5.4 # MIT
@@ -16,4 +15,5 @@ testrepository>=0.0.18 # Apache-2.0/BSD
testtools>=1.4.0 # MIT
# releasenotes
reno>=1.6.2 # Apache2
reno>=1.8.0 # Apache2
mock>=2.0 # BSD