Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8509a590aa | ||
|
|
99fc9b7bda | ||
|
|
b9c53e664a | ||
|
|
ed0cdb5460 | ||
|
|
573de86f7f | ||
|
|
8d0e9825ae | ||
|
|
b472a2d50e | ||
|
|
1c3cdf58ec | ||
|
|
8ce414c612 | ||
|
|
b6ef835d89 | ||
|
|
4a772e74d8 | ||
|
|
e026ae17e5 | ||
|
|
0fcd6c31c3 | ||
|
|
b7075c91d7 | ||
|
|
09bf59d764 | ||
|
|
d4bf57ee3e | ||
|
|
d86e111ddf | ||
|
|
67d2cd836b | ||
|
|
5881bec6a6 | ||
|
|
cb9651ef9d | ||
|
|
04b5b7c528 | ||
|
|
1dc4cbef6b | ||
|
|
73592154f1 | ||
|
|
90c251b84e | ||
|
|
c74447bf72 | ||
|
|
42107c3d14 | ||
|
|
6f1792b490 | ||
|
|
3e31720ed6 | ||
|
|
8ea5e29b44 | ||
|
|
584b44c8e7 | ||
|
|
bab4900db2 | ||
|
|
4458d3dce1 | ||
|
|
9630f711a8 | ||
|
|
537c525095 | ||
|
|
245af4c7fa | ||
|
|
06d210fa65 | ||
|
|
1a749c310c | ||
|
|
d8b0dbcbb7 | ||
|
|
543a89e763 | ||
| 8a93fea142 | |||
|
|
761f0b37b2 | ||
|
|
6ddc62bbad | ||
|
|
95ddcbe966 | ||
|
|
bfed79e1b0 | ||
|
|
3b88fbcda1 | ||
|
|
a11344c318 | ||
|
|
ad3f2b5ab7 | ||
|
|
b7a494e7d4 | ||
|
|
a7266637e6 |
@@ -2,4 +2,3 @@
|
||||
host=review.openstack.org
|
||||
port=29418
|
||||
project=openstack/python-tackerclient.git
|
||||
defaultbranch=stable/pike
|
||||
|
||||
@@ -2,7 +2,7 @@ Tacker Style Commandments
|
||||
================================
|
||||
|
||||
- Step 1: Read the OpenStack Style Commandments
|
||||
http://docs.openstack.org/developer/hacking/
|
||||
https://docs.openstack.org/hacking/latest
|
||||
- Step 2: Read on
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Running Tests
|
||||
-------------
|
||||
The testing system is based on a combination of tox and testr. The canonical
|
||||
approach to running tests is to simply run the command `tox`. This will
|
||||
create virtual environments, populate them with depenedencies and run all of
|
||||
create virtual environments, populate them with dependencies and run all of
|
||||
the tests that OpenStack CI systems run. Behind the scenes, tox is running
|
||||
`testr run --parallel`, but is set up such that you can supply any additional
|
||||
testr arguments that are needed to tox. For example, you can run:
|
||||
@@ -23,4 +23,4 @@ installed locally already. In this case, you can interact with the testr
|
||||
command directly. Running `testr run` will run the entire test suite. `testr
|
||||
run --parallel` will run it in parallel (this is the default incantation tox
|
||||
uses.) More information about testr can be found at:
|
||||
http://wiki.openstack.org/testr
|
||||
https://wiki.openstack.org/wiki/Testr
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
Team and repository tags
|
||||
========================
|
||||
|
||||
.. image:: http://governance.openstack.org/badges/python-tackerclient.svg
|
||||
:target: http://governance.openstack.org/reference/tags/index.html
|
||||
.. image:: https://governance.openstack.org/tc/badges/python-tackerclient.svg
|
||||
:target: https://governance.openstack.org/tc/reference/tags/index.html
|
||||
|
||||
.. Change things from this point on
|
||||
|
||||
|
||||
40
doc/source/cli/index.rst
Normal file
40
doc/source/cli/index.rst
Normal file
@@ -0,0 +1,40 @@
|
||||
..
|
||||
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.
|
||||
|
||||
|
||||
Convention for heading levels in Neutron devref:
|
||||
======= Heading 0 (reserved for the title in a document)
|
||||
------- Heading 1
|
||||
~~~~~~~ Heading 2
|
||||
+++++++ Heading 3
|
||||
''''''' Heading 4
|
||||
(Avoid deeper levels because they do not render well.)
|
||||
|
||||
=========
|
||||
Using CLI
|
||||
=========
|
||||
|
||||
There are two CLIs which support the Networking API:
|
||||
`OpenStackClient (OSC)
|
||||
<https://docs.openstack.org/python-openstackclient/latest/>`__
|
||||
and :doc:`neutron CLI <neutron>` (deprecated).
|
||||
|
||||
OpenStackClient
|
||||
---------------
|
||||
|
||||
#TODO
|
||||
|
||||
neutron CLI
|
||||
-----------
|
||||
|
||||
#TODO
|
||||
@@ -1,10 +1,22 @@
|
||||
project = 'python-tackerclient'
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
# -- General configuration ---------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx']
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'reno.sphinxext',
|
||||
'openstackdocstheme',
|
||||
'cliff.sphinxext',
|
||||
]
|
||||
|
||||
# openstackdocstheme options
|
||||
repository_name = 'openstack/python-tackerclient'
|
||||
bug_project = 'python-tackerclient'
|
||||
bug_tag = 'doc'
|
||||
html_last_updated_fmt = '%Y-%m-%d %H:%M'
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
@@ -32,21 +44,11 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. Major themes that come with
|
||||
# Sphinx are currently 'default' and 'sphinxdoc'.
|
||||
html_theme = 'nature'
|
||||
html_theme = 'openstackdocs'
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = '%sdoc' % project
|
||||
htmlhelp_basename = 'tackerclientdoc'
|
||||
|
||||
# -- Options for cliff.sphinxext plugin ---------------------------------------
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index',
|
||||
'%s.tex' % project,
|
||||
u'%s Documentation' % project,
|
||||
u'OpenStack Foundation', 'manual'),
|
||||
]
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {'http://docs.python.org/': None}
|
||||
autoprogram_cliff_application = 'openstack'
|
||||
|
||||
31
doc/source/contributor/index.rst
Normal file
31
doc/source/contributor/index.rst
Normal file
@@ -0,0 +1,31 @@
|
||||
..
|
||||
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.
|
||||
|
||||
|
||||
Convention for heading levels in Neutron devref:
|
||||
======= Heading 0 (reserved for the title in a document)
|
||||
------- Heading 1
|
||||
~~~~~~~ Heading 2
|
||||
+++++++ Heading 3
|
||||
''''''' Heading 4
|
||||
(Avoid deeper levels because they do not render well.)
|
||||
|
||||
=================
|
||||
Contributor Guide
|
||||
=================
|
||||
|
||||
In the Contributor Guide, you will find information on tackerclient's
|
||||
lower level programming details or APIs as well as the transition to
|
||||
OpenStack client.
|
||||
|
||||
#TODO
|
||||
@@ -1,25 +1,57 @@
|
||||
Python bindings to the OpenStack Tacker API
|
||||
============================================
|
||||
..
|
||||
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
|
||||
|
||||
In order to use the python tacker client directly, you must first obtain an auth token and identify which endpoint you wish to speak to. Once you have done so, you can use the API.
|
||||
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.
|
||||
|
||||
Convention for heading levels in Neutron devref:
|
||||
======= Heading 0 (reserved for the title in a document)
|
||||
------- Heading 1
|
||||
~~~~~~~ Heading 2
|
||||
+++++++ Heading 3
|
||||
''''''' Heading 4
|
||||
(Avoid deeper levels because they do not render well.)
|
||||
|
||||
==================================
|
||||
python-tackerclient documentation
|
||||
==================================
|
||||
|
||||
This is a client for OpenStack NFV MANO API. It provides
|
||||
:doc:`Python API bindings <reference/index>` (the tackerclient module) and
|
||||
:doc:`command-line interface (CLI) <cli/index>`.
|
||||
|
||||
|
||||
Command-line Tool
|
||||
=================
|
||||
In order to use the CLI, you must provide your OpenStack username, password, tenant, and auth endpoint. Use the corresponding configuration options (``--os-username``, ``--os-password``, ``--os-tenant-name``, and ``--os-auth-url``) or set them in environment variables::
|
||||
User Documentation
|
||||
------------------
|
||||
|
||||
export OS_USERNAME=user
|
||||
export OS_PASSWORD=pass
|
||||
export OS_TENANT_NAME=tenant
|
||||
export OS_AUTH_URL=http://auth.example.com:5000/v2.0
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
The command line tool will attempt to reauthenticate using your provided credentials for every request. You can override this behavior by manually supplying an auth token using ``--os-url`` and ``--os-auth-token``. You can alternatively set these environment variables::
|
||||
cli/index
|
||||
reference/index
|
||||
|
||||
export OS_URL=http://tacker.example.org:9890/
|
||||
export OS_TOKEN=3bcc3d3a03f44e3d8377f9247b0ad155
|
||||
Contributor Guide
|
||||
-----------------
|
||||
|
||||
If tacker server does not require authentication, besides these two arguments or environment variables (We can use any value as token.), we need manually supply ``--os-auth-strategy`` or set the environment variable::
|
||||
In the :doc:`Contributor Guide <contributor/index>`, you will find
|
||||
information on tackerclient's lower level programming details or APIs
|
||||
as well as the transition to OpenStack client.
|
||||
|
||||
export OS_AUTH_STRATEGY=noauth
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
Once you've configured your authentication parameters, you can run ``tacker -h`` to see a complete listing of available commands.
|
||||
contributor/index
|
||||
|
||||
|
||||
History
|
||||
-------
|
||||
|
||||
Release notes is available at
|
||||
http://docs.openstack.org/releasenotes/python-tackerclient/.
|
||||
|
||||
38
doc/source/install/index.rst
Normal file
38
doc/source/install/index.rst
Normal file
@@ -0,0 +1,38 @@
|
||||
..
|
||||
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.
|
||||
|
||||
|
||||
Convention for heading levels in Neutron devref:
|
||||
======= Heading 0 (reserved for the title in a document)
|
||||
------- Heading 1
|
||||
~~~~~~~ Heading 2
|
||||
+++++++ Heading 3
|
||||
''''''' Heading 4
|
||||
(Avoid deeper levels because they do not render well.)
|
||||
|
||||
=================
|
||||
Install Guide
|
||||
=================
|
||||
|
||||
To install ``python-tackerclient``, it is required to have ``pip``
|
||||
(in most cases). Make sure that ``pip`` is installed. Then type::
|
||||
|
||||
$ pip install python-tackerclient
|
||||
|
||||
Or, if it is needed to install ``python-tackerclient`` from master branch,
|
||||
type::
|
||||
|
||||
$ pip install git+https://github.com/openstack/python-tackerclient.git
|
||||
|
||||
After ``python-tackerclient`` is installed you will see command ``tacker``
|
||||
in your environment.
|
||||
29
doc/source/reference/index.rst
Normal file
29
doc/source/reference/index.rst
Normal file
@@ -0,0 +1,29 @@
|
||||
..
|
||||
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.
|
||||
|
||||
|
||||
Convention for heading levels in Neutron devref:
|
||||
======= Heading 0 (reserved for the title in a document)
|
||||
------- Heading 1
|
||||
~~~~~~~ Heading 2
|
||||
+++++++ Heading 3
|
||||
''''''' Heading 4
|
||||
(Avoid deeper levels because they do not render well.)
|
||||
|
||||
tackerclient Python API
|
||||
========================
|
||||
|
||||
Basic Usage
|
||||
-----------
|
||||
|
||||
#TODO
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Support to create directly VNFFG and NS from its descriptor template
|
||||
without creating VNFFGD and NSD.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
-
|
||||
As user gives input of project and user name in vim_config.yaml,
|
||||
delete the user and project id from the vim specific commands
|
||||
output.
|
||||
@@ -37,7 +37,8 @@
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = [
|
||||
'oslosphinx',
|
||||
'reno.sphinxext'
|
||||
'reno.sphinxext',
|
||||
'openstackdocstheme'
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
@@ -56,14 +57,9 @@ master_doc = 'index'
|
||||
project = u'Tacker Client Release Notes'
|
||||
copyright = u'2016, Tacker Developers'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
import pbr.version
|
||||
tacker_client_version = pbr.version.VersionInfo('python-tackerclient')
|
||||
release = tacker_client_version.version_string_with_vcs()
|
||||
version = tacker_client_version.canonical_version_string()
|
||||
# Release notes are version independent.
|
||||
release = ''
|
||||
version = ''
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -105,7 +101,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
html_theme = 'openstackdocs'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@@ -262,3 +258,8 @@ texinfo_documents = [
|
||||
|
||||
# -- Options for Internationalization output ------------------------------
|
||||
locale_dirs = ['locale/']
|
||||
|
||||
# -- Options for openstackdocstheme -------------------------------------------
|
||||
repository_name = 'openstack/python-tackerclient'
|
||||
bug_project = 'python-tackerclient'
|
||||
bug_tag = ''
|
||||
|
||||
@@ -7,5 +7,6 @@ Contents:
|
||||
:maxdepth: 2
|
||||
|
||||
unreleased
|
||||
pike
|
||||
ocata
|
||||
newton
|
||||
|
||||
6
releasenotes/source/pike.rst
Normal file
6
releasenotes/source/pike.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
===================================
|
||||
Pike Series Release Notes
|
||||
===================================
|
||||
|
||||
.. release-notes::
|
||||
:branch: stable/pike
|
||||
@@ -2,18 +2,18 @@
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
pbr!=2.1.0,>=2.0.0 # Apache-2.0
|
||||
cliff>=2.8.0 # Apache-2.0
|
||||
cliff!=2.9.0,>=2.8.0 # Apache-2.0
|
||||
iso8601>=0.1.11 # MIT
|
||||
netaddr!=0.7.16,>=0.7.13 # BSD
|
||||
netaddr>=0.7.18 # BSD
|
||||
requests>=2.14.2 # Apache-2.0
|
||||
python-keystoneclient>=3.8.0 # Apache-2.0
|
||||
simplejson>=2.2.0 # MIT
|
||||
six>=1.9.0 # MIT
|
||||
simplejson>=3.5.1 # MIT
|
||||
six>=1.10.0 # MIT
|
||||
stevedore>=1.20.0 # Apache-2.0
|
||||
Babel!=2.4.0,>=2.3.4 # BSD
|
||||
|
||||
oslo.i18n!=3.15.2,>=2.1.0 # Apache-2.0
|
||||
oslo.log>=3.22.0 # Apache-2.0
|
||||
oslo.utils>=3.20.0 # Apache-2.0
|
||||
oslosphinx>=4.7.0 # Apache-2.0
|
||||
oslo.serialization!=2.19.1,>=1.10.0 # Apache-2.0
|
||||
oslo.i18n>=3.15.3 # Apache-2.0
|
||||
osc-lib>=1.8.0 # Apache-2.0
|
||||
oslo.log>=3.36.0 # Apache-2.0
|
||||
oslo.utils>=3.33.0 # Apache-2.0
|
||||
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
|
||||
|
||||
13
setup.cfg
13
setup.cfg
@@ -5,7 +5,7 @@ description-file =
|
||||
README.rst
|
||||
author = OpenStack
|
||||
author-email = openstack-dev@lists.openstack.org
|
||||
home-page = http://docs.openstack.org/developer/tacker/
|
||||
home-page = https://docs.openstack.org/tacker/latest
|
||||
classifier =
|
||||
Environment :: OpenStack
|
||||
Intended Audience :: Developers
|
||||
@@ -31,6 +31,17 @@ setup-hooks =
|
||||
console_scripts =
|
||||
tacker = tackerclient.shell:main
|
||||
|
||||
openstack.cli.extension =
|
||||
tackerclient = tackerclient.osc.plugin
|
||||
|
||||
openstack.tackerclient.v1 =
|
||||
vim_register = tackerclient.osc.v1.nfvo.vim:CreateVIM
|
||||
vim_list = tackerclient.osc.v1.nfvo.vim:ListVIM
|
||||
vim_set = tackerclient.osc.v1.nfvo.vim:UpdateVIM
|
||||
vim_delete = tackerclient.osc.v1.nfvo.vim:DeleteVIM
|
||||
vim_show = tackerclient.osc.v1.nfvo.vim:ShowVIM
|
||||
|
||||
|
||||
[build_sphinx]
|
||||
all_files = 1
|
||||
build-dir = doc/build
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
"""oslo.i18n integration module.
|
||||
|
||||
See http://docs.openstack.org/developer/oslo.i18n/usage.html .
|
||||
See https://docs.openstack.org/oslo.i18n/latest/user/index.html.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
@@ -203,6 +203,10 @@ class InvalidContentType(TackerClientException):
|
||||
message = _("Invalid content type %(content_type)s.")
|
||||
|
||||
|
||||
class InvalidInput(TackerClientException):
|
||||
message = _("Invalid input: %(reason)s")
|
||||
|
||||
|
||||
# Command line exceptions
|
||||
|
||||
class TackerCLIError(TackerException):
|
||||
|
||||
0
tackerclient/osc/__init__.py
Normal file
0
tackerclient/osc/__init__.py
Normal file
61
tackerclient/osc/plugin.py
Normal file
61
tackerclient/osc/plugin.py
Normal file
@@ -0,0 +1,61 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""OpenStackClient plugin for nfv-orchestration service."""
|
||||
|
||||
import logging
|
||||
|
||||
from osc_lib import utils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# Required by the OSC plugin interface
|
||||
DEFAULT_TACKER_API_VERSION = '1'
|
||||
API_NAME = 'tackerclient'
|
||||
API_VERSION_OPTION = 'os_tacker_api_version'
|
||||
API_VERSIONS = {
|
||||
'1': 'tackerclient.v1_0.client.Client',
|
||||
}
|
||||
|
||||
|
||||
def make_client(instance):
|
||||
"""Returns a client to the ClientManager."""
|
||||
|
||||
tacker_client = utils.get_client_class(
|
||||
API_NAME,
|
||||
instance._api_version[API_NAME],
|
||||
API_VERSIONS)
|
||||
LOG.debug('Instantiating tacker client: %s', tacker_client)
|
||||
|
||||
kwargs = {'service_type': 'nfv-orchestration',
|
||||
'region_name': instance._region_name,
|
||||
'endpoint_type': instance._interface,
|
||||
'interface': instance._interface,
|
||||
'session': instance.session
|
||||
}
|
||||
|
||||
client = tacker_client(**kwargs)
|
||||
|
||||
return client
|
||||
|
||||
|
||||
def build_option_parser(parser):
|
||||
"""Hook to add global options."""
|
||||
parser.add_argument(
|
||||
'--os-tacker-api-version',
|
||||
metavar='<tacker-api-version>',
|
||||
default=utils.env(
|
||||
'OS_TACKER_API_VERSION',
|
||||
default=DEFAULT_TACKER_API_VERSION))
|
||||
return parser
|
||||
102
tackerclient/osc/sdk_utils.py
Normal file
102
tackerclient/osc/sdk_utils.py
Normal file
@@ -0,0 +1,102 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
def get_osc_show_columns_for_sdk_resource(
|
||||
sdk_resource,
|
||||
osc_column_map,
|
||||
invisible_columns=None
|
||||
):
|
||||
"""Get and filter the display and attribute columns for an SDK resource.
|
||||
|
||||
Common utility function for preparing the output of an OSC show command.
|
||||
Some of the columns may need to get renamed, others made invisible.
|
||||
|
||||
:param sdk_resource: An SDK resource
|
||||
:param osc_column_map: A hash of mappings for display column names
|
||||
:param invisible_columns: A list of invisible column names
|
||||
|
||||
:returns: Two tuples containing the names of the display and attribute
|
||||
columns
|
||||
"""
|
||||
|
||||
if getattr(sdk_resource, 'allow_get', None) is not None:
|
||||
resource_dict = sdk_resource.to_dict(
|
||||
body=True, headers=False, ignore_none=False)
|
||||
else:
|
||||
resource_dict = sdk_resource
|
||||
|
||||
# Build the OSC column names to display for the SDK resource.
|
||||
attr_map = {}
|
||||
display_columns = list(resource_dict.keys())
|
||||
invisible_columns = [] if invisible_columns is None else invisible_columns
|
||||
for col_name in invisible_columns:
|
||||
if col_name in display_columns:
|
||||
display_columns.remove(col_name)
|
||||
for sdk_attr, osc_attr in osc_column_map.items():
|
||||
if sdk_attr in display_columns:
|
||||
attr_map[osc_attr] = sdk_attr
|
||||
display_columns.remove(sdk_attr)
|
||||
if osc_attr not in display_columns:
|
||||
display_columns.append(osc_attr)
|
||||
sorted_display_columns = sorted(display_columns)
|
||||
|
||||
# Build the SDK attribute names for the OSC column names.
|
||||
attr_columns = []
|
||||
for column in sorted_display_columns:
|
||||
new_column = attr_map[column] if column in attr_map else column
|
||||
attr_columns.append(new_column)
|
||||
return tuple(sorted_display_columns), tuple(attr_columns)
|
||||
|
||||
|
||||
class DictModel(dict):
|
||||
"""Convert dict into an object that provides attribute access to values."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Convert dict values to DictModel values."""
|
||||
super(DictModel, self).__init__(*args, **kwargs)
|
||||
|
||||
def needs_upgrade(item):
|
||||
return isinstance(item, dict) and not isinstance(item, DictModel)
|
||||
|
||||
def upgrade(item):
|
||||
"""Upgrade item if it needs to be upgraded."""
|
||||
if needs_upgrade(item):
|
||||
return DictModel(item)
|
||||
else:
|
||||
return item
|
||||
|
||||
for key, value in self.items():
|
||||
if isinstance(value, (list, tuple)):
|
||||
# Keep the same type but convert dicts to DictModels
|
||||
self[key] = type(value)(
|
||||
(upgrade(item) for item in value)
|
||||
)
|
||||
elif needs_upgrade(value):
|
||||
# Change dict instance values to DictModel instance values
|
||||
self[key] = DictModel(value)
|
||||
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
return self[name]
|
||||
except KeyError as e:
|
||||
raise AttributeError(e)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
self[name] = value
|
||||
|
||||
def __delattr__(self, name):
|
||||
del self[name]
|
||||
|
||||
def __str__(self):
|
||||
pairs = ['%s=%s' % (k, v) for k, v in self.items()]
|
||||
return ', '.join(sorted(pairs))
|
||||
207
tackerclient/osc/utils.py
Normal file
207
tackerclient/osc/utils.py
Normal file
@@ -0,0 +1,207 @@
|
||||
# Copyright 2016 NEC Corporation
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""This module should contain OSC plugin generic methods.
|
||||
|
||||
Methods in this module are candidates adopted to osc-lib.
|
||||
|
||||
Stuffs specific to tackerclient OSC plugin should not be added
|
||||
to this module. They should go to tackerclient.osc.v1.utils.
|
||||
"""
|
||||
|
||||
import operator
|
||||
|
||||
from keystoneclient import exceptions as identity_exc
|
||||
from keystoneclient.v3 import domains
|
||||
from keystoneclient.v3 import projects
|
||||
from osc_lib import utils
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from tackerclient.i18n import _
|
||||
|
||||
|
||||
LIST_BOTH = 'both'
|
||||
LIST_SHORT_ONLY = 'short_only'
|
||||
LIST_LONG_ONLY = 'long_only'
|
||||
|
||||
|
||||
def format_dict_with_indention(data):
|
||||
"""Return a formatted string of key value pairs
|
||||
|
||||
:param data: a dict
|
||||
:rtype: a string formatted to key='value'
|
||||
"""
|
||||
|
||||
if data is None:
|
||||
return None
|
||||
return jsonutils.dumps(data, indent=4)
|
||||
|
||||
|
||||
def get_column_definitions(attr_map, long_listing):
|
||||
"""Return table headers and column names for a listing table.
|
||||
|
||||
:param attr_map: a list of table entry definitions.
|
||||
Each entry should be a tuple consisting of
|
||||
(API attribute name, header name, listing mode). For example:
|
||||
(('id', 'ID', LIST_BOTH),
|
||||
('name', 'Name', LIST_BOTH),
|
||||
('tenant_id', 'Project', LIST_LONG_ONLY))
|
||||
The third field of each tuple must be one of LIST_BOTH,
|
||||
LIST_LONG_ONLY (a corresponding column is shown only in a long mode), or
|
||||
LIST_SHORT_ONLY (a corresponding column is shown only in a short mode).
|
||||
:param long_listing: A boolean value which indicates a long listing
|
||||
or not. In most cases, parsed_args.long is passed to this argument.
|
||||
:return: A tuple of a list of table headers and a list of column names.
|
||||
"""
|
||||
|
||||
if long_listing:
|
||||
headers = [hdr for col, hdr, listing_mode in attr_map
|
||||
if listing_mode in (LIST_BOTH, LIST_LONG_ONLY)]
|
||||
columns = [col for col, hdr, listing_mode in attr_map
|
||||
if listing_mode in (LIST_BOTH, LIST_LONG_ONLY)]
|
||||
else:
|
||||
headers = [hdr for col, hdr, listing_mode in attr_map
|
||||
if listing_mode in (LIST_BOTH, LIST_SHORT_ONLY)]
|
||||
columns = [col for col, hdr, listing_mode in attr_map
|
||||
if listing_mode in (LIST_BOTH, LIST_SHORT_ONLY)]
|
||||
|
||||
return headers, columns
|
||||
|
||||
|
||||
def get_columns(item, attr_map=None):
|
||||
"""Return pair of resource attributes and corresponding display names.
|
||||
|
||||
Assume the following item and attr_map are passed.
|
||||
item: {'id': 'myid', 'name': 'myname',
|
||||
'foo': 'bar', 'tenant_id': 'mytenan'}
|
||||
attr_map:
|
||||
(('id', 'ID', LIST_BOTH),
|
||||
('name', 'Name', LIST_BOTH),
|
||||
('tenant_id', 'Project', LIST_LONG_ONLY))
|
||||
|
||||
This method returns:
|
||||
|
||||
(('id', 'name', 'tenant_id', 'foo'), # attributes
|
||||
('ID', 'Name', 'Project', 'foo') # display names
|
||||
|
||||
Both tuples of attributes and display names are sorted by display names
|
||||
in the alphabetical order.
|
||||
Attributes not found in a given attr_map are kept as-is.
|
||||
|
||||
:param item: a dictionary which represents a resource.
|
||||
Keys of the dictionary are expected to be attributes of the resource.
|
||||
Values are not referred to by this method.
|
||||
:param attr_map: a list of mapping from attribute to display name.
|
||||
The same format is used as for get_column_definitions attr_map.
|
||||
:return: A pair of tuple of attributes and tuple of display names.
|
||||
"""
|
||||
attr_map = attr_map or tuple([])
|
||||
_attr_map_dict = dict((col, hdr) for col, hdr, listing_mode in attr_map)
|
||||
|
||||
columns = [(column, _attr_map_dict.get(column, column))
|
||||
for column in item.keys()]
|
||||
columns = sorted(columns, key=operator.itemgetter(1))
|
||||
return (tuple(col[0] for col in columns),
|
||||
tuple(col[1] for col in columns))
|
||||
|
||||
|
||||
# TODO(amotoki): Use osc-lib version once osc-lib provides this.
|
||||
def add_project_owner_option_to_parser(parser):
|
||||
"""Register project and project domain options.
|
||||
|
||||
:param parser: argparse.Argument parser object.
|
||||
|
||||
"""
|
||||
parser.add_argument(
|
||||
'--project',
|
||||
metavar='<project>',
|
||||
help=_("Owner's project (name or ID)")
|
||||
)
|
||||
# Borrowed from openstackclient.identity.common
|
||||
# as it is not exposed officially.
|
||||
parser.add_argument(
|
||||
'--project-domain',
|
||||
metavar='<project-domain>',
|
||||
help=_('Domain the project belongs to (name or ID). '
|
||||
'This can be used in case collisions between project names '
|
||||
'exist.'),
|
||||
)
|
||||
|
||||
|
||||
# The following methods are borrowed from openstackclient.identity.common
|
||||
# as it is not exposed officially.
|
||||
# TODO(amotoki): Use osc-lib version once osc-lib provides this.
|
||||
|
||||
|
||||
def find_domain(identity_client, name_or_id):
|
||||
return _find_identity_resource(identity_client.domains, name_or_id,
|
||||
domains.Domain)
|
||||
|
||||
|
||||
def find_project(identity_client, name_or_id, domain_name_or_id=None):
|
||||
domain_id = _get_domain_id_if_requested(identity_client, domain_name_or_id)
|
||||
if not domain_id:
|
||||
return _find_identity_resource(identity_client.projects, name_or_id,
|
||||
projects.Project)
|
||||
else:
|
||||
return _find_identity_resource(identity_client.projects, name_or_id,
|
||||
projects.Project, domain_id=domain_id)
|
||||
|
||||
|
||||
def _get_domain_id_if_requested(identity_client, domain_name_or_id):
|
||||
if not domain_name_or_id:
|
||||
return None
|
||||
domain = find_domain(identity_client, domain_name_or_id)
|
||||
return domain.id
|
||||
|
||||
|
||||
def _find_identity_resource(identity_client_manager, name_or_id,
|
||||
resource_type, **kwargs):
|
||||
"""Find a specific identity resource.
|
||||
|
||||
Using keystoneclient's manager, attempt to find a specific resource by its
|
||||
name or ID. If Forbidden to find the resource (a common case if the user
|
||||
does not have permission), then return the resource by creating a local
|
||||
instance of keystoneclient's Resource.
|
||||
|
||||
The parameter identity_client_manager is a keystoneclient manager,
|
||||
for example: keystoneclient.v3.users or keystoneclient.v3.projects.
|
||||
|
||||
The parameter resource_type is a keystoneclient resource, for example:
|
||||
keystoneclient.v3.users.User or keystoneclient.v3.projects.Project.
|
||||
|
||||
:param identity_client_manager: the manager that contains the resource
|
||||
:type identity_client_manager: `keystoneclient.base.CrudManager`
|
||||
:param name_or_id: the resources's name or ID
|
||||
:type name_or_id: string
|
||||
:param resource_type: class that represents the resource type
|
||||
:type resource_type: `keystoneclient.base.Resource`
|
||||
|
||||
:returns: the resource in question
|
||||
:rtype: `keystoneclient.base.Resource`
|
||||
|
||||
"""
|
||||
|
||||
try:
|
||||
identity_resource = utils.find_resource(identity_client_manager,
|
||||
name_or_id, **kwargs)
|
||||
if identity_resource is not None:
|
||||
return identity_resource
|
||||
except identity_exc.Forbidden:
|
||||
pass
|
||||
|
||||
return resource_type(None, {'id': name_or_id, 'name': name_or_id})
|
||||
|
||||
|
||||
# The above are borrowed from openstackclient.identity.common.
|
||||
0
tackerclient/osc/v1/__init__.py
Normal file
0
tackerclient/osc/v1/__init__.py
Normal file
0
tackerclient/osc/v1/nfvo/__init__.py
Normal file
0
tackerclient/osc/v1/nfvo/__init__.py
Normal file
267
tackerclient/osc/v1/nfvo/vim.py
Normal file
267
tackerclient/osc/v1/nfvo/vim.py
Normal file
@@ -0,0 +1,267 @@
|
||||
# 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.
|
||||
|
||||
import yaml
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import utils
|
||||
from oslo_utils import strutils
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
from tackerclient.i18n import _
|
||||
from tackerclient.osc import sdk_utils
|
||||
from tackerclient.osc import utils as tacker_osc_utils
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
from tackerclient.tacker.v1_0.nfvo import vim_utils
|
||||
|
||||
_attr_map = (
|
||||
('id', 'ID', tacker_osc_utils.LIST_BOTH),
|
||||
('name', 'Name', tacker_osc_utils.LIST_BOTH),
|
||||
('tenant_id', 'Tenant_id', tacker_osc_utils.LIST_BOTH),
|
||||
('type', 'Type', tacker_osc_utils.LIST_BOTH),
|
||||
('is_default', 'Is Default',
|
||||
tacker_osc_utils.LIST_BOTH),
|
||||
('placement_attr', 'Placement attribution',
|
||||
tacker_osc_utils.LIST_LONG_ONLY),
|
||||
('status', 'Status', tacker_osc_utils.LIST_BOTH),
|
||||
)
|
||||
|
||||
_VIM = 'vim'
|
||||
|
||||
|
||||
class ListVIM(command.Lister):
|
||||
_description = _("List VIMs that belong to a given tenant.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListVIM, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--long',
|
||||
action='store_true',
|
||||
help=_("List additional fields in output")
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
data = client.list_vims()
|
||||
headers, columns = tacker_osc_utils.get_column_definitions(
|
||||
_attr_map, long_listing=parsed_args.long)
|
||||
return (headers,
|
||||
(utils.get_dict_properties(
|
||||
s, columns,
|
||||
) for s in data[_VIM + 's']))
|
||||
|
||||
|
||||
class ShowVIM(command.ShowOne):
|
||||
_description = _("Display VIM details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowVIM, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VIM,
|
||||
metavar="<VIM>",
|
||||
help=_("VIM to display (name or ID)")
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
obj_id = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, _VIM, parsed_args.vim)
|
||||
obj = client.show_vim(obj_id)
|
||||
display_columns, columns = _get_columns(obj[_VIM])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_VIM]),
|
||||
columns,
|
||||
formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class CreateVIM(command.ShowOne):
|
||||
_description = _("Register a new VIM")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CreateVIM, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help=_('Set a name for the VIM'))
|
||||
parser.add_argument(
|
||||
'--config-file',
|
||||
required=True,
|
||||
help=_('YAML file with VIM configuration parameters'))
|
||||
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'))
|
||||
return parser
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {_VIM: {}}
|
||||
if parsed_args.config_file:
|
||||
with open(parsed_args.config_file) as f:
|
||||
vim_config = f.read()
|
||||
try:
|
||||
config_param = yaml.load(vim_config,
|
||||
Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
vim_obj = body[_VIM]
|
||||
try:
|
||||
auth_url = config_param.pop('auth_url')
|
||||
except KeyError:
|
||||
raise exceptions.TackerClientException(message='Auth URL must be '
|
||||
'specified',
|
||||
status_code=404)
|
||||
vim_obj['auth_url'] = vim_utils.validate_auth_url(auth_url).geturl()
|
||||
vim_utils.args2body_vim(config_param, vim_obj)
|
||||
tackerV10.update_dict(parsed_args, body[_VIM],
|
||||
['tenant_id', 'name', 'description',
|
||||
'is_default'])
|
||||
return body
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
vim = client.create_vim(self.args2body(parsed_args))
|
||||
display_columns, columns = _get_columns(vim[_VIM])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(vim[_VIM]),
|
||||
columns, formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class DeleteVIM(command.Command):
|
||||
_description = _("Delete VIM(s).")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteVIM, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VIM,
|
||||
metavar="<VIM>",
|
||||
nargs="+",
|
||||
help=_("VIM(s) to delete (name or ID)")
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
failure = False
|
||||
deleted_ids = []
|
||||
failed_items = {}
|
||||
for resource_id in parsed_args.vim:
|
||||
try:
|
||||
obj = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, _VIM, resource_id)
|
||||
client.delete_vim(obj)
|
||||
deleted_ids.append(resource_id)
|
||||
except Exception as e:
|
||||
failure = True
|
||||
failed_items[resource_id] = e
|
||||
if failure:
|
||||
msg = ''
|
||||
if deleted_ids:
|
||||
msg = (_('Successfully deleted %(resource)s(s):'
|
||||
' %(deleted_list)s') % {'deleted_list':
|
||||
', '.join(deleted_ids),
|
||||
'resource': _VIM})
|
||||
err_msg = _("\n\nUnable to delete the below"
|
||||
" %s(s):") % _VIM
|
||||
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:
|
||||
print((_('All specified %(resource)s(s) deleted successfully')
|
||||
% {'resource': _VIM}))
|
||||
return
|
||||
|
||||
|
||||
class UpdateVIM(command.ShowOne):
|
||||
_description = _("Update VIM.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(UpdateVIM, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'id', metavar="VIM",
|
||||
help=_('ID or name of %s to update') % _VIM)
|
||||
parser.add_argument(
|
||||
'--config-file',
|
||||
required=False,
|
||||
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'))
|
||||
return parser
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {_VIM: {}}
|
||||
config_param = None
|
||||
# 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()
|
||||
try:
|
||||
config_param = yaml.load(config_yaml)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
vim_obj = body[_VIM]
|
||||
if config_param is not None:
|
||||
vim_utils.args2body_vim(config_param, vim_obj)
|
||||
tackerV10.update_dict(parsed_args, body[_VIM],
|
||||
['tenant_id', 'name', 'description',
|
||||
'is_default'])
|
||||
# type attribute is read-only, it can't be updated, so remove it
|
||||
# in update method
|
||||
body[_VIM].pop('type', None)
|
||||
return body
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
obj_id = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, _VIM, parsed_args.id)
|
||||
vim = client.update_vim(obj_id, self.args2body(parsed_args))
|
||||
display_columns, columns = _get_columns(vim[_VIM])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(vim[_VIM]), columns,
|
||||
formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
_formatters = {
|
||||
'auth_cred': tacker_osc_utils.format_dict_with_indention,
|
||||
'placement_attr': tacker_osc_utils.format_dict_with_indention,
|
||||
'vim_project': tacker_osc_utils.format_dict_with_indention,
|
||||
}
|
||||
|
||||
|
||||
def _get_columns(item):
|
||||
column_map = {
|
||||
'tenant_id': 'project_id',
|
||||
}
|
||||
return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
|
||||
@@ -279,7 +279,7 @@ def parse_args_to_dict(values_specs):
|
||||
|
||||
# populate the parser with arguments
|
||||
_parser = argparse.ArgumentParser(add_help=False)
|
||||
for opt, optspec in six.iteritems(_options):
|
||||
for opt, optspec in _options.items():
|
||||
_parser.add_argument(opt, **optspec)
|
||||
_args = _parser.parse_args(_values_specs)
|
||||
|
||||
@@ -303,7 +303,7 @@ def _merge_args(qCmd, parsed_args, _extra_values, value_specs):
|
||||
@param values_specs: the unparsed unknown parts
|
||||
"""
|
||||
temp_values = _extra_values.copy()
|
||||
for key, value in six.iteritems(temp_values):
|
||||
for key, value in temp_values.items():
|
||||
if hasattr(parsed_args, key):
|
||||
arg_value = getattr(parsed_args, key)
|
||||
if arg_value is not None and value is not None:
|
||||
@@ -387,7 +387,7 @@ class TackerCommand(command.OpenStackCommand):
|
||||
def format_output_data(self, data):
|
||||
# Modify data to make it more readable
|
||||
if self.resource in data:
|
||||
for k, v in six.iteritems(data[self.resource]):
|
||||
for k, v in data[self.resource].items():
|
||||
if isinstance(v, list):
|
||||
value = '\n'.join(jsonutils.dumps(
|
||||
i, indent=self.json_indent) if isinstance(i, dict)
|
||||
@@ -450,7 +450,7 @@ class CreateCommand(TackerCommand, show.ShowOne):
|
||||
info.pop(f)
|
||||
else:
|
||||
info = {'': ''}
|
||||
return zip(*sorted(six.iteritems(info)))
|
||||
return zip(*sorted(info.items()))
|
||||
|
||||
|
||||
class UpdateCommand(TackerCommand):
|
||||
@@ -712,6 +712,6 @@ class ShowCommand(TackerCommand, show.ShowOne):
|
||||
self.format_output_data(data)
|
||||
resource = data[self.resource]
|
||||
if self.resource in data:
|
||||
return zip(*sorted(six.iteritems(resource)))
|
||||
return zip(*sorted(resource.items()))
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
import yaml
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
from tackerclient.i18n import _
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
|
||||
@@ -50,6 +51,9 @@ class CreateNS(tackerV10.CreateCommand):
|
||||
nsd_group.add_argument(
|
||||
'--nsd-id',
|
||||
help=_('NSD ID to use as template to create NS'))
|
||||
nsd_group.add_argument(
|
||||
'--nsd-template',
|
||||
help=_('NSD file to create NS'))
|
||||
nsd_group.add_argument(
|
||||
'--nsd-name',
|
||||
help=_('NSD name to use as template to create NS'))
|
||||
@@ -88,11 +92,25 @@ class CreateNS(tackerV10.CreateCommand):
|
||||
parsed_args.
|
||||
nsd_name)
|
||||
parsed_args.nsd_id = _id
|
||||
elif parsed_args.nsd_template:
|
||||
with open(parsed_args.nsd_template) as f:
|
||||
template = f.read()
|
||||
try:
|
||||
args['nsd_template'] = yaml.load(
|
||||
template, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not args['nsd_template']:
|
||||
raise exceptions.InvalidInput('The nsd file is empty')
|
||||
|
||||
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)
|
||||
try:
|
||||
args['attributes']['param_values'] = yaml.load(
|
||||
param_yaml, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'description',
|
||||
'nsd_id', 'vim_id'])
|
||||
|
||||
@@ -26,7 +26,24 @@ class ListNSD(tackerV10.ListCommand):
|
||||
"""List NSDs that belong to a given tenant."""
|
||||
|
||||
resource = _NSD
|
||||
list_columns = ['id', 'name', 'description']
|
||||
list_columns = ['id', 'name', 'template_source', 'description']
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListNSD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--template-source',
|
||||
help=_("List NSD with specified template source. Available \
|
||||
options are 'onboared' (default), 'inline' or 'all'"),
|
||||
action='store',
|
||||
default='onboarded')
|
||||
return parser
|
||||
|
||||
def args2search_opts(self, parsed_args):
|
||||
search_opts = super(ListNSD, self).args2search_opts(parsed_args)
|
||||
template_source = parsed_args.template_source
|
||||
if parsed_args.template_source:
|
||||
search_opts.update({'template_source': template_source})
|
||||
return search_opts
|
||||
|
||||
|
||||
class ShowNSD(tackerV10.ShowCommand):
|
||||
|
||||
@@ -67,7 +67,11 @@ class CreateVIM(tackerV10.CreateCommand):
|
||||
if parsed_args.config_file:
|
||||
with open(parsed_args.config_file) as f:
|
||||
vim_config = f.read()
|
||||
config_param = yaml.load(vim_config, Loader=yaml.SafeLoader)
|
||||
try:
|
||||
config_param = yaml.load(vim_config,
|
||||
Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
vim_obj = body[self.resource]
|
||||
try:
|
||||
auth_url = config_param.pop('auth_url')
|
||||
@@ -76,7 +80,6 @@ class CreateVIM(tackerV10.CreateCommand):
|
||||
'specified',
|
||||
status_code=404)
|
||||
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',
|
||||
@@ -113,13 +116,19 @@ class UpdateVIM(tackerV10.UpdateCommand):
|
||||
if parsed_args.config_file:
|
||||
with open(parsed_args.config_file) as f:
|
||||
config_yaml = f.read()
|
||||
config_param = yaml.load(config_yaml)
|
||||
try:
|
||||
config_param = yaml.load(config_yaml)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
vim_obj = body[self.resource]
|
||||
if config_param is not None:
|
||||
vim_utils.args2body_vim(config_param, vim_obj)
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'description',
|
||||
'is_default'])
|
||||
# type attribute is read-only, it can't be updated, so remove it
|
||||
# in update method
|
||||
body['vim'].pop('type', None)
|
||||
return body
|
||||
|
||||
|
||||
|
||||
@@ -24,24 +24,66 @@ def args2body_vim(config_param, vim):
|
||||
:param vim: vim request object
|
||||
:return: vim body with args populated
|
||||
"""
|
||||
vim_type = ['openstack', 'kubernetes']
|
||||
cert_verify_type = ['True', 'False']
|
||||
vim['vim_project'] = {'name': config_param.pop('project_name', ''),
|
||||
'project_domain_name':
|
||||
config_param.pop('project_domain_name', '')}
|
||||
if not vim['vim_project']['name']:
|
||||
raise exceptions.TackerClientException(message='Project name '
|
||||
'must be specified',
|
||||
status_code=404)
|
||||
cert_verify = config_param.pop('cert_verify', 'True')
|
||||
if cert_verify not in cert_verify_type:
|
||||
raise exceptions.TackerClientException(
|
||||
message='Supported cert_verify types: True, False',
|
||||
status_code=400)
|
||||
vim['auth_cred'] = {'username': config_param.pop('username', ''),
|
||||
'password': config_param.pop('password', ''),
|
||||
'user_domain_name':
|
||||
config_param.pop('user_domain_name', ''),
|
||||
'cert_verify': cert_verify}
|
||||
|
||||
if 'type' in config_param:
|
||||
vim['type'] = config_param.pop('type', '')
|
||||
if not vim['type'] in vim_type:
|
||||
raise exceptions.TackerClientException(
|
||||
message='Supported VIM types: openstack, kubernetes',
|
||||
status_code=400)
|
||||
else:
|
||||
vim['type'] = 'openstack'
|
||||
if vim['type'] == 'openstack':
|
||||
vim['vim_project'] = {
|
||||
'name': config_param.pop('project_name', ''),
|
||||
'project_domain_name':
|
||||
config_param.pop('project_domain_name', '')}
|
||||
if not vim['vim_project']['name']:
|
||||
raise exceptions.TackerClientException(
|
||||
message='Project name must be specified',
|
||||
status_code=404)
|
||||
cert_verify = config_param.pop('cert_verify', 'True')
|
||||
if cert_verify not in cert_verify_type:
|
||||
raise exceptions.TackerClientException(
|
||||
message='Supported cert_verify types: True, False',
|
||||
status_code=400)
|
||||
vim['auth_cred'] = {'username': config_param.pop('username', ''),
|
||||
'password': config_param.pop('password', ''),
|
||||
'user_domain_name':
|
||||
config_param.pop('user_domain_name', ''),
|
||||
'cert_verify': cert_verify}
|
||||
elif vim['type'] == 'kubernetes':
|
||||
vim['vim_project'] = {
|
||||
'name': config_param.pop('project_name', '')}
|
||||
if not vim['vim_project']['name']:
|
||||
raise exceptions.TackerClientException(
|
||||
message='Project name must be specified in Kubernetes VIM,'
|
||||
'it is namespace in Kubernetes environment',
|
||||
status_code=404)
|
||||
if ('username' in config_param) and ('password' in config_param):
|
||||
vim['auth_cred'] = {
|
||||
'username': config_param.pop('username', ''),
|
||||
'password': config_param.pop('password', '')}
|
||||
elif 'bearer_token' in config_param:
|
||||
vim['auth_cred'] = {
|
||||
'bearer_token': config_param.pop('bearer_token', '')}
|
||||
else:
|
||||
raise exceptions.TackerClientException(
|
||||
message='username and password or bearer_token must be'
|
||||
'provided',
|
||||
status_code=404)
|
||||
if 'ssl_ca_cert' in config_param:
|
||||
ssl_ca_cert = config_param.pop('ssl_ca_cert', '')
|
||||
if ssl_ca_cert == 'None':
|
||||
vim['auth_cred']['ssl_ca_cert'] = None
|
||||
else:
|
||||
vim['auth_cred']['ssl_ca_cert'] = ssl_ca_cert
|
||||
else:
|
||||
raise exceptions.TackerClientException(
|
||||
message='ssl_ca_cert must be provided or leave it with None',
|
||||
status_code=404)
|
||||
|
||||
|
||||
def validate_auth_url(url):
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tackerclient.i18n import _
|
||||
import yaml
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
from tackerclient.i18n import _
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
|
||||
|
||||
@@ -28,6 +29,18 @@ class ListFC(tackerV10.ListCommand):
|
||||
resource = _FC
|
||||
list_columns = ['id', 'status', 'nfp_id', 'chain_id']
|
||||
|
||||
def extend_list(self, data, parsed_args):
|
||||
"""Update the list_columns list.
|
||||
|
||||
This method update the list_columns list by adding the
|
||||
'name' column in case the retrieved FC list from the tacker
|
||||
server side contains the names of the FCs.
|
||||
"""
|
||||
for item in data:
|
||||
if 'name' in item:
|
||||
self.list_columns.insert(1, 'name')
|
||||
break
|
||||
|
||||
|
||||
class ShowFC(tackerV10.ShowCommand):
|
||||
"""Show information of a given FC."""
|
||||
@@ -91,6 +104,9 @@ class CreateVNFFG(tackerV10.CreateCommand):
|
||||
vnffgd_group.add_argument(
|
||||
'--vnffgd-name',
|
||||
help=_('VNFFGD Name to use as template to create VNFFG'))
|
||||
vnffgd_group.add_argument(
|
||||
'--vnffgd-template',
|
||||
help=_('VNFFGD file to create VNFFG'))
|
||||
parser.add_argument(
|
||||
'--vnf-mapping',
|
||||
help=_('List of logical VNFD name to VNF instance name mapping. '
|
||||
@@ -129,12 +145,25 @@ class CreateVNFFG(tackerV10.CreateCommand):
|
||||
parsed_args.
|
||||
vnffgd_name)
|
||||
parsed_args.vnffgd_id = _id
|
||||
elif parsed_args.vnffgd_template:
|
||||
with open(parsed_args.vnffgd_template) as f:
|
||||
template = f.read()
|
||||
try:
|
||||
args['vnffgd_template'] = yaml.load(
|
||||
template, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not args['vnffgd_template']:
|
||||
raise exceptions.InvalidInput('The vnffgd file is empty')
|
||||
|
||||
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)
|
||||
try:
|
||||
args['attributes']['param_values'] = yaml.load(
|
||||
param_yaml, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'vnffgd_id',
|
||||
@@ -148,16 +177,23 @@ class UpdateVNFFG(tackerV10.UpdateCommand):
|
||||
resource = _VNFFG
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'--vnffgd-template',
|
||||
help=_('VNFFGD file to update 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}',
|
||||
'--symmetrical',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=_('Should a reverse path be created for the NFP'))
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {self.resource: {}}
|
||||
args = {}
|
||||
body = {self.resource: args}
|
||||
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
@@ -173,6 +209,17 @@ class UpdateVNFFG(tackerV10.UpdateCommand):
|
||||
|
||||
parsed_args.vnf_mapping = _vnf_mapping
|
||||
|
||||
if parsed_args.vnffgd_template:
|
||||
with open(parsed_args.vnffgd_template) as f:
|
||||
template = f.read()
|
||||
try:
|
||||
args['vnffgd_template'] = yaml.load(
|
||||
template, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not args['vnffgd_template']:
|
||||
raise exceptions.InvalidInput('The vnffgd template is empty')
|
||||
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'vnf_mapping', 'symmetrical'])
|
||||
return body
|
||||
|
||||
@@ -26,7 +26,24 @@ class ListVNFFGD(tackerV10.ListCommand):
|
||||
"""List VNFFGDs that belong to a given tenant."""
|
||||
|
||||
resource = _VNFFGD
|
||||
list_columns = ['id', 'name', 'description']
|
||||
list_columns = ['id', 'name', 'template_source', 'description']
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListVNFFGD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--template-source',
|
||||
help=_("List VNFFGD with specified template source. Available \
|
||||
options are 'onboarded' (default), 'inline' or 'all'"),
|
||||
action='store',
|
||||
default='onboarded')
|
||||
return parser
|
||||
|
||||
def args2search_opts(self, parsed_args):
|
||||
search_opts = super(ListVNFFGD, self).args2search_opts(parsed_args)
|
||||
template_source = parsed_args.template_source
|
||||
if parsed_args.template_source:
|
||||
search_opts.update({'template_source': template_source})
|
||||
return search_opts
|
||||
|
||||
|
||||
class ShowVNFFGD(tackerV10.ShowCommand):
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
import yaml
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
from tackerclient.i18n import _
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
|
||||
@@ -87,8 +88,11 @@ class CreateVNF(tackerV10.CreateCommand):
|
||||
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)
|
||||
try:
|
||||
config = yaml.load(
|
||||
config_yaml, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
|
||||
if config:
|
||||
args['attributes']['config'] = config
|
||||
@@ -113,14 +117,20 @@ class CreateVNF(tackerV10.CreateCommand):
|
||||
elif parsed_args.vnfd_template:
|
||||
with open(parsed_args.vnfd_template) as f:
|
||||
template = f.read()
|
||||
args['vnfd_template'] = yaml.load(
|
||||
template, Loader=yaml.SafeLoader)
|
||||
try:
|
||||
args['vnfd_template'] = yaml.load(
|
||||
template, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
|
||||
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)
|
||||
try:
|
||||
args['attributes']['param_values'] = yaml.load(
|
||||
param_yaml, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'description',
|
||||
'vnfd_id', 'vim_id'])
|
||||
@@ -147,12 +157,18 @@ class UpdateVNF(tackerV10.UpdateCommand):
|
||||
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)
|
||||
try:
|
||||
config = yaml.load(config_yaml, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if parsed_args.config:
|
||||
config = parsed_args.config
|
||||
if isinstance(config, str) or isinstance(config, unicode):
|
||||
config_str = parsed_args.config.decode('unicode_escape')
|
||||
config = yaml.load(config_str, Loader=yaml.SafeLoader)
|
||||
try:
|
||||
config = yaml.load(config_str, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if config:
|
||||
body[self.resource]['attributes'] = {'config': config}
|
||||
tackerV10.update_dict(parsed_args, body[self.resource], ['tenant_id'])
|
||||
|
||||
@@ -20,6 +20,7 @@ from __future__ import print_function
|
||||
from oslo_serialization import jsonutils
|
||||
import yaml
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
from tackerclient.i18n import _
|
||||
from tackerclient.tacker import v1_0 as tackerV10
|
||||
|
||||
@@ -75,13 +76,17 @@ 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()
|
||||
if not parsed_args.vnfd_file:
|
||||
raise exceptions.InvalidInput("Invalid input for vnfd file")
|
||||
with open(parsed_args.vnfd_file) as f:
|
||||
vnfd = f.read()
|
||||
try:
|
||||
vnfd = yaml.load(vnfd, Loader=yaml.SafeLoader)
|
||||
if vnfd:
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not vnfd:
|
||||
raise exceptions.InvalidInput("vnfd file is empty")
|
||||
body[self.resource]['attributes'] = {'vnfd': vnfd}
|
||||
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'description'])
|
||||
return body
|
||||
|
||||
@@ -4,3 +4,4 @@ password: '12345'
|
||||
project_name: 'abc'
|
||||
project_domain_name: 'prj_domain_name'
|
||||
user_domain_name: 'user_domain_name'
|
||||
type: 'openstack'
|
||||
@@ -5,3 +5,4 @@ project_name: 'abc'
|
||||
project_domain_name: 'prj_domain_name'
|
||||
user_domain_name: 'user_domain_name'
|
||||
cert_verify: 'False'
|
||||
type: 'openstack'
|
||||
@@ -3,3 +3,4 @@ password: '12345'
|
||||
project_name: 'abc'
|
||||
project_domain_name: 'prj_domain_name'
|
||||
user_domain_name: 'user_domain_name'
|
||||
type: 'openstack'
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
auth_url: 'https://1.2.3.4:6443'
|
||||
bearer_token: 'xyz'
|
||||
ssl_ca_cert: None
|
||||
project_name: 'default'
|
||||
type: 'kubernetes'
|
||||
@@ -0,0 +1,4 @@
|
||||
bearer_token: 'xyz'
|
||||
ssl_ca_cert: None
|
||||
project_name: 'default'
|
||||
type: 'kubernetes'
|
||||
6
tackerclient/tests/unit/vm/samples/vim_k8s_config.yaml
Normal file
6
tackerclient/tests/unit/vm/samples/vim_k8s_config.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
auth_url: 'https://1.2.3.4:6443'
|
||||
username: 'xyz'
|
||||
password: '12345'
|
||||
ssl_ca_cert: 'abcxyz'
|
||||
project_name: 'default'
|
||||
type: 'kubernetes'
|
||||
@@ -0,0 +1,5 @@
|
||||
username: 'xyz'
|
||||
password: '12345'
|
||||
ssl_ca_cert: 'abcxyz'
|
||||
project_name: 'default'
|
||||
type: 'kubernetes'
|
||||
@@ -0,0 +1 @@
|
||||
abcxyz
|
||||
@@ -41,6 +41,7 @@ class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
|
||||
'user_domain_name': 'user_domain_name',
|
||||
'cert_verify': 'True'}
|
||||
self.auth_url = 'http://1.2.3.4:5000'
|
||||
self.type = 'openstack'
|
||||
|
||||
def test_register_vim_all_params(self):
|
||||
cmd = vim.CreateVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
@@ -53,9 +54,9 @@ class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
|
||||
name,
|
||||
'--config-file', vim_config,
|
||||
'--description', description]
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url']
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url', 'type']
|
||||
position_values = [self.auth_cred, self.vim_project,
|
||||
self.auth_url]
|
||||
self.auth_url, self.type]
|
||||
extra_body = {'type': 'openstack', 'name': name,
|
||||
'description': description, 'is_default': False}
|
||||
self._test_create_resource(self._RESOURCE, cmd, None, my_id,
|
||||
@@ -77,9 +78,9 @@ class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
|
||||
name,
|
||||
'--config-file', vim_config,
|
||||
'--description', description]
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url']
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url', 'type']
|
||||
position_values = [self.auth_cred, self.vim_project,
|
||||
self.auth_url]
|
||||
self.auth_url, self.type]
|
||||
extra_body = {'type': 'openstack', 'name': name,
|
||||
'description': description, 'is_default': False}
|
||||
self._test_create_resource(self._RESOURCE, cmd, None, my_id,
|
||||
@@ -97,9 +98,9 @@ class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
|
||||
name,
|
||||
'--config-file', vim_config,
|
||||
'--description', description]
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url']
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url', 'type']
|
||||
position_values = [self.auth_cred, self.vim_project,
|
||||
self.auth_url]
|
||||
self.auth_url, self.type]
|
||||
extra_body = {'type': 'openstack', 'name': name,
|
||||
'description': description, 'is_default': False}
|
||||
message = 'Auth URL must be specified'
|
||||
@@ -122,11 +123,12 @@ class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
|
||||
name,
|
||||
'--config-file', vim_config,
|
||||
]
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url']
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url', 'type']
|
||||
position_values = [
|
||||
self.auth_cred,
|
||||
self.vim_project,
|
||||
self.auth_url
|
||||
self.auth_url,
|
||||
self.type
|
||||
]
|
||||
extra_body = {'type': 'openstack', 'name': name, 'is_default': False}
|
||||
self._test_create_resource(self._RESOURCE, cmd, name, my_id, args,
|
||||
@@ -163,8 +165,9 @@ class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
|
||||
'--name', name,
|
||||
'--description', description,
|
||||
'--is_default', is_default]
|
||||
extra_fields = {'vim_project': self.vim_project, 'auth_cred':
|
||||
self.auth_cred, 'is_default': 'True',
|
||||
extra_fields = {'vim_project': self.vim_project,
|
||||
'auth_cred': self.auth_cred,
|
||||
'is_default': 'True',
|
||||
'name': name, 'description': description}
|
||||
self._test_update_resource(self._RESOURCE, cmd, my_id, args,
|
||||
extra_fields)
|
||||
|
||||
172
tackerclient/tests/unit/vm/test_cli10_vim_k8s.py
Normal file
172
tackerclient/tests/unit/vm/test_cli10_vim_k8s.py
Normal file
@@ -0,0 +1,172 @@
|
||||
# Copyright 2015-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.
|
||||
|
||||
import sys
|
||||
|
||||
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
|
||||
|
||||
API_VERSION = "1.0"
|
||||
FORMAT = 'json'
|
||||
TOKEN = 'testtoken'
|
||||
ENDURL = 'localurl'
|
||||
|
||||
|
||||
class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
|
||||
_RESOURCE = 'vim'
|
||||
_RESOURCES = 'vims'
|
||||
|
||||
def setUp(self):
|
||||
plurals = {'vims': 'vim'}
|
||||
super(CLITestV10VIMJSON, self).setUp(plurals=plurals)
|
||||
self.vim_project = {'name': 'default'}
|
||||
self.auth_cred = {'username': 'xyz', 'password': '12345',
|
||||
'ssl_ca_cert': 'abcxyz'}
|
||||
self.auth_url = 'https://1.2.3.4:6443'
|
||||
self.type = 'kubernetes'
|
||||
|
||||
def test_register_vim_all_params(self):
|
||||
cmd = vim.CreateVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
name = 'my-name'
|
||||
my_id = 'my-id'
|
||||
description = 'Vim Description'
|
||||
vim_config = utils.get_file_path(
|
||||
'tests/unit/vm/samples/vim_k8s_config.yaml')
|
||||
args = [
|
||||
name,
|
||||
'--config-file', vim_config,
|
||||
'--description', description]
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url', 'type']
|
||||
position_values = [self.auth_cred, self.vim_project,
|
||||
self.auth_url, self.type]
|
||||
extra_body = {'type': 'kubernetes', '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_no_auth_url(self):
|
||||
cmd = vim.CreateVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
name = 'test_vim'
|
||||
description = 'Vim Description'
|
||||
vim_config = utils.get_file_path(
|
||||
'tests/unit/vm/samples/vim_k8s_config_without_auth_url.yaml')
|
||||
args = [
|
||||
name,
|
||||
'--config-file', vim_config,
|
||||
'--description', description]
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url', 'type']
|
||||
position_values = [self.auth_cred, self.vim_project,
|
||||
self.auth_url, self.type]
|
||||
extra_body = {'type': 'kubernetes', '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_k8s_config.yaml')
|
||||
args = [
|
||||
name,
|
||||
'--config-file', vim_config,
|
||||
]
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url', 'type']
|
||||
position_values = [
|
||||
self.auth_cred,
|
||||
self.vim_project,
|
||||
self.auth_url,
|
||||
self.type
|
||||
]
|
||||
extra_body = {'type': 'kubernetes', 'name': name, 'is_default': False}
|
||||
self._test_create_resource(self._RESOURCE, cmd, name, my_id, args,
|
||||
position_names, position_values,
|
||||
extra_body=extra_body)
|
||||
|
||||
def test_list_vims(self):
|
||||
cmd = vim.ListVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True)
|
||||
|
||||
def test_show_vim_id(self):
|
||||
cmd = vim.ShowVIM(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_vim_id_name(self):
|
||||
cmd = vim.ShowVIM(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_vim_all_params(self):
|
||||
cmd = vim.UpdateVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
update_config = utils.get_file_path(
|
||||
'tests/unit/vm/samples/vim_k8s_config_without_auth_url.yaml')
|
||||
my_id = 'my-id'
|
||||
name = 'new_name'
|
||||
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,
|
||||
'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_k8s_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):
|
||||
cmd = vim.DeleteVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
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)
|
||||
@@ -0,0 +1,170 @@
|
||||
# Copyright 2015-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.
|
||||
|
||||
import sys
|
||||
|
||||
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
|
||||
|
||||
API_VERSION = "1.0"
|
||||
FORMAT = 'json'
|
||||
TOKEN = 'testtoken'
|
||||
ENDURL = 'localurl'
|
||||
|
||||
|
||||
class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
|
||||
_RESOURCE = 'vim'
|
||||
_RESOURCES = 'vims'
|
||||
|
||||
def setUp(self):
|
||||
plurals = {'vims': 'vim'}
|
||||
super(CLITestV10VIMJSON, self).setUp(plurals=plurals)
|
||||
self.vim_project = {'name': 'default'}
|
||||
self.auth_cred = {'bearer_token': 'xyz', 'ssl_ca_cert': None}
|
||||
self.auth_url = 'https://1.2.3.4:6443'
|
||||
self.type = 'kubernetes'
|
||||
|
||||
def test_register_vim_all_params(self):
|
||||
cmd = vim.CreateVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
name = 'my-name'
|
||||
my_id = 'my-id'
|
||||
description = 'Vim Description'
|
||||
vim_config = utils.get_file_path(
|
||||
'tests/unit/vm/samples/vim_k8s_bearer_token.yaml')
|
||||
args = [
|
||||
name,
|
||||
'--config-file', vim_config,
|
||||
'--description', description]
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url', 'type']
|
||||
position_values = [self.auth_cred, self.vim_project,
|
||||
self.auth_url, self.type]
|
||||
extra_body = {'type': 'kubernetes', '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_no_auth_url(self):
|
||||
cmd = vim.CreateVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
name = 'test_vim'
|
||||
description = 'Vim Description'
|
||||
vim_config = utils.get_file_path(
|
||||
'tests/unit/vm/samples/vim_k8s_bearer_token_without_auth_url.yaml')
|
||||
args = [
|
||||
name,
|
||||
'--config-file', vim_config,
|
||||
'--description', description]
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url', 'type']
|
||||
position_values = [self.auth_cred, self.vim_project,
|
||||
self.auth_url, self.type]
|
||||
extra_body = {'type': 'kubernetes', '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_k8s_bearer_token.yaml')
|
||||
args = [
|
||||
name,
|
||||
'--config-file', vim_config,
|
||||
]
|
||||
position_names = ['auth_cred', 'vim_project', 'auth_url', 'type']
|
||||
position_values = [
|
||||
self.auth_cred,
|
||||
self.vim_project,
|
||||
self.auth_url,
|
||||
self.type
|
||||
]
|
||||
extra_body = {'type': 'kubernetes', 'name': name, 'is_default': False}
|
||||
self._test_create_resource(self._RESOURCE, cmd, name, my_id, args,
|
||||
position_names, position_values,
|
||||
extra_body=extra_body)
|
||||
|
||||
def test_list_vims(self):
|
||||
cmd = vim.ListVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True)
|
||||
|
||||
def test_show_vim_id(self):
|
||||
cmd = vim.ShowVIM(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_vim_id_name(self):
|
||||
cmd = vim.ShowVIM(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_vim_all_params(self):
|
||||
cmd = vim.UpdateVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
update_config = utils.get_file_path(
|
||||
'tests/unit/vm/samples/vim_k8s_bearer_token_without_auth_url.yaml')
|
||||
my_id = 'my-id'
|
||||
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,
|
||||
'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_k8s_bearer_token_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):
|
||||
cmd = vim.DeleteVIM(test_cli10.MyApp(sys.stdout), None)
|
||||
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)
|
||||
@@ -18,6 +18,7 @@ from mock import mock_open
|
||||
from mock import patch
|
||||
import sys
|
||||
|
||||
from tackerclient.common.exceptions import InvalidInput
|
||||
from tackerclient.tacker.v1_0.vnfm import vnfd
|
||||
from tackerclient.tests.unit import test_cli10
|
||||
|
||||
@@ -73,6 +74,30 @@ class CLITestV10VmVNFDJSON(test_cli10.CLITestV10Base):
|
||||
args, position_names, position_values,
|
||||
extra_body=extra_body)
|
||||
|
||||
@patch("tackerclient.tacker.v1_0.vnfm.vnfd.open",
|
||||
side_effect=mock_open(read_data=""),
|
||||
create=True)
|
||||
def test_create_vnfd_with_empty_file(self, mo):
|
||||
cmd = vnfd.CreateVNFD(
|
||||
test_cli10.MyApp(sys.stdout), None)
|
||||
name = 'my_name'
|
||||
my_id = 'my-id'
|
||||
args = [name, '--vnfd-file', 'vnfd-file', ]
|
||||
position_names = ['name']
|
||||
position_values = [name]
|
||||
extra_body = {
|
||||
'service_types': [{'service_type': 'vnfd'}],
|
||||
'attributes': {'vnfd': 'vnfd'}
|
||||
}
|
||||
err = None
|
||||
try:
|
||||
self._test_create_resource(self._RESOURCE, cmd, name, my_id,
|
||||
args, position_names, position_values,
|
||||
extra_body=extra_body)
|
||||
except InvalidInput:
|
||||
err = True
|
||||
self.assertEqual(True, err)
|
||||
|
||||
def test_list_vnfds(self):
|
||||
cmd = vnfd.ListVNFD(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import sys
|
||||
|
||||
from tackerclient.common import utils
|
||||
from tackerclient.tacker.v1_0.nfvo import vnffg
|
||||
from tackerclient.tests.unit import test_cli10
|
||||
|
||||
@@ -94,11 +95,23 @@ class CLITestV10VmVNFFGJSON(test_cli10.CLITestV10Base):
|
||||
def test_update_vnffg(self):
|
||||
cmd = vnffg.UpdateVNFFG(test_cli10.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
key = 'new_key'
|
||||
value = 'new-value'
|
||||
update_vnffg = utils.get_file_path(
|
||||
'tests/unit/vm/samples/vnffg_update_file.yaml')
|
||||
vnf_mapping = 'VNFD1:VNF1'
|
||||
args = [
|
||||
my_id,
|
||||
'--vnf-mapping', vnf_mapping,
|
||||
'--vnffgd-template', str(update_vnffg),
|
||||
'--symmetrical'
|
||||
]
|
||||
extra_fields = {
|
||||
"vnf_mapping": {"VNFD1": "VNF1"},
|
||||
"vnffgd_template": "abcxyz",
|
||||
"symmetrical": True
|
||||
}
|
||||
self._test_update_resource(self._RESOURCE, cmd, my_id,
|
||||
[my_id, '--%s' % key, value],
|
||||
{key: value}, get_client_called_count=2)
|
||||
args, extra_fields,
|
||||
get_client_called_count=2)
|
||||
|
||||
def test_delete_vnffg(self):
|
||||
cmd = vnffg.DeleteVNFFG(test_cli10.MyApp(sys.stdout), None)
|
||||
|
||||
@@ -76,11 +76,23 @@ class CLITestV10VmVNFFGDJSON(test_cli10.CLITestV10Base):
|
||||
|
||||
def test_list_vnffgds(self):
|
||||
cmd = vnffgd.ListVNFFGD(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True,
|
||||
template_source='onboarded')
|
||||
|
||||
def test_list_inline_vnffgds(self):
|
||||
cmd = vnffgd.ListVNFFGD(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True,
|
||||
template_source='inline')
|
||||
|
||||
def test_list_all_vnffgds(self):
|
||||
cmd = vnffgd.ListVNFFGD(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True,
|
||||
template_source='all')
|
||||
|
||||
def test_list_vnffgds_pagenation(self):
|
||||
cmd = vnffgd.ListVNFFGD(test_cli10.MyApp(sys.stdout), None)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True)
|
||||
self._test_list_resources(self._RESOURCES, cmd, True,
|
||||
template_source='onboarded')
|
||||
|
||||
def test_show_vnffgd_id(self):
|
||||
cmd = vnffgd.ShowVNFFGD(test_cli10.MyApp(sys.stdout), None)
|
||||
|
||||
@@ -28,24 +28,61 @@ class TestVIMUtils(testtools.TestCase):
|
||||
'username': sentinel.usrname1,
|
||||
'password': sentinel.password1,
|
||||
'project_domain_name': sentinel.prj_domain_name1,
|
||||
'user_domain_name': sentinel.user_domain.name,
|
||||
'cert_verify': 'True',
|
||||
'user_domain_name': sentinel.user_domain.name, }
|
||||
'type': 'openstack'}
|
||||
vim = {}
|
||||
auth_cred = config_param.copy()
|
||||
auth_cred.pop('project_name')
|
||||
auth_cred.pop('project_domain_name')
|
||||
auth_cred.pop('type')
|
||||
expected_vim = {'auth_cred': auth_cred,
|
||||
'vim_project':
|
||||
{'name': sentinel.prj_name,
|
||||
'project_domain_name': sentinel.prj_domain_name1}}
|
||||
'project_domain_name': sentinel.prj_domain_name1},
|
||||
'type': 'openstack'}
|
||||
vim_utils.args2body_vim(config_param.copy(), vim)
|
||||
self.assertEqual(expected_vim, vim)
|
||||
|
||||
def test_args2body_kubernetes_vim(self):
|
||||
config_param = {'username': sentinel.usrname1,
|
||||
'password': sentinel.password1,
|
||||
'ssl_ca_cert': 'abcxyz',
|
||||
'project_name': sentinel.prj_name,
|
||||
'type': 'kubernetes'}
|
||||
vim = {}
|
||||
auth_cred = config_param.copy()
|
||||
auth_cred.pop('project_name')
|
||||
auth_cred.pop('type')
|
||||
expected_vim = {'auth_cred': auth_cred,
|
||||
'vim_project':
|
||||
{'name': sentinel.prj_name},
|
||||
'type': 'kubernetes'}
|
||||
vim_utils.args2body_vim(config_param.copy(), vim)
|
||||
self.assertEqual(expected_vim, vim)
|
||||
|
||||
def test_args2body_kubernetes_vim_bearer(self):
|
||||
config_param = {'bearer_token': sentinel.bearer_token,
|
||||
'ssl_ca_cert': None,
|
||||
'project_name': sentinel.prj_name,
|
||||
'type': 'kubernetes'}
|
||||
vim = {}
|
||||
auth_cred = config_param.copy()
|
||||
auth_cred.pop('project_name')
|
||||
auth_cred.pop('type')
|
||||
expected_vim = {'auth_cred': auth_cred,
|
||||
'vim_project':
|
||||
{'name': sentinel.prj_name},
|
||||
'type': 'kubernetes'}
|
||||
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,
|
||||
'cert_verify': 'True',
|
||||
'user_domain_name': sentinel.user_domain.name, }
|
||||
'type': 'openstack'}
|
||||
vim = {}
|
||||
self.assertRaises(exceptions.TackerClientException,
|
||||
vim_utils.args2body_vim,
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
|
||||
coverage!=4.4,>=4.0 # Apache-2.0
|
||||
fixtures>=3.0.0 # Apache-2.0/BSD
|
||||
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.6.2 # BSD
|
||||
python-subunit>=1.0.0 # Apache-2.0/BSD
|
||||
sphinx!=1.6.6,>=1.6.2 # BSD
|
||||
testrepository>=0.0.18 # Apache-2.0/BSD
|
||||
testtools>=1.4.0 # MIT
|
||||
testtools>=2.2.0 # MIT
|
||||
oslosphinx>=4.7.0 # Apache-2.0
|
||||
openstackdocstheme>=1.18.1 # Apache-2.0
|
||||
|
||||
# releasenotes
|
||||
reno!=2.3.1,>=1.8.0 # Apache-2.0
|
||||
mock>=2.0 # BSD
|
||||
reno>=2.5.0 # Apache-2.0
|
||||
mock>=2.0.0 # BSD
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#!/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 $?
|
||||
11
tox.ini
11
tox.ini
@@ -5,14 +5,14 @@ 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 = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt?h=stable/pike} {opts} {packages}
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
install_command = pip install {opts} {packages}
|
||||
deps =
|
||||
-c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
|
||||
-r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = python setup.py testr --testr-args='{posargs}'
|
||||
|
||||
@@ -23,6 +23,9 @@ distribute = false
|
||||
[testenv:venv]
|
||||
commands = {posargs}
|
||||
|
||||
[testenv:docs]
|
||||
commands = sphinx-build -W -b html doc/source doc/build/html
|
||||
|
||||
[testenv:releasenotes]
|
||||
commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
|
||||
|
||||
|
||||
Reference in New Issue
Block a user