Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9879a46f58 | ||
|
|
9cd0fc13f1 | ||
|
|
1a31f11a53 | ||
|
|
6cdc4cf084 | ||
|
|
4308bf66ad | ||
|
|
a325233647 | ||
|
|
e40b9c8a47 | ||
|
|
d5a8170a35 | ||
|
|
d7a59b951d | ||
|
|
e3b3d7e50c | ||
|
|
ae77851d98 | ||
|
|
30bd8ffd1a | ||
|
|
04584a666d | ||
|
|
9b2027930b | ||
|
|
09c13e1c5d | ||
|
|
7a13c3ce96 | ||
|
|
75b316ae51 | ||
|
|
17d108e146 | ||
|
|
9a36c0e4ea | ||
|
|
68c0c9d0f1 | ||
|
|
331588ab12 | ||
|
|
a6b721690c | ||
|
|
d967a881aa | ||
|
|
a7b17cc238 | ||
|
|
0f64739dda | ||
|
|
c5eb5c319f | ||
|
|
1cb2431782 | ||
|
|
c5ed02513c | ||
|
|
de7efad575 | ||
|
|
ac8394730f | ||
|
|
c097d89ff9 | ||
|
|
c3fc53a4f3 | ||
|
|
f037a0b8ed | ||
|
|
1c4e32d0f6 | ||
|
|
a23aa68676 | ||
|
|
f76a15d4ec | ||
|
|
1062eb78bb | ||
|
|
75d08f07d9 | ||
|
|
8fe5966b3e | ||
|
|
5d338b8a75 | ||
|
|
4d0cd3b7f2 | ||
|
|
e557ecde72 | ||
|
|
5ab6421941 | ||
|
|
df80486f32 | ||
| d1c3710c0d |
16
CONTRIBUTING.rst
Normal file
16
CONTRIBUTING.rst
Normal file
@@ -0,0 +1,16 @@
|
||||
If you would like to contribute to the development of OpenStack,
|
||||
you must follow the steps in this page:
|
||||
|
||||
http://docs.openstack.org/infra/manual/developers.html
|
||||
|
||||
Once those steps have been completed, changes to OpenStack
|
||||
should be submitted for review via the Gerrit tool, following
|
||||
the workflow documented at:
|
||||
|
||||
http://docs.openstack.org/infra/manual/developers.html#development-workflow
|
||||
|
||||
Pull requests submitted through GitHub will be ignored.
|
||||
|
||||
Bugs should be filed on Launchpad, not GitHub:
|
||||
|
||||
https://bugs.launchpad.net/python-tackerclient
|
||||
60
README.rst
60
README.rst
@@ -7,4 +7,62 @@ Team and repository tags
|
||||
|
||||
.. Change things from this point on
|
||||
|
||||
This is the client API library for Tacker.
|
||||
NFV Orchestration (Tacker) Client
|
||||
=================================
|
||||
|
||||
CLI and Client Library for OpenStack Tacker
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
**Note:** The paths we are using for configuration files in these steps
|
||||
are with reference to Ubuntu Operating System. The paths may vary for
|
||||
other Operating Systems.
|
||||
|
||||
The branch_name which is used in commands, specify the branch_name
|
||||
as stable/<branch> for any stable branch installation. For eg:
|
||||
stable/queens, stable/pike. If unspecified the default will be
|
||||
master branch.
|
||||
|
||||
Using python install
|
||||
--------------------
|
||||
1. Clone python-tackerclient repository.
|
||||
|
||||
::
|
||||
|
||||
$ cd ~/
|
||||
$ git clone https://github.com/openstack/python-tackerclient -b <branch_name>
|
||||
|
||||
|
||||
2. Install python-tackerclient.
|
||||
|
||||
::
|
||||
|
||||
$ cd python-tackerclient
|
||||
$ sudo python setup.py install
|
||||
|
||||
|
||||
Using pip
|
||||
---------
|
||||
|
||||
You can also install the latest version by using ``pip`` command:
|
||||
|
||||
::
|
||||
|
||||
$ 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
|
||||
|
||||
|
||||
More Information
|
||||
================
|
||||
|
||||
* Python-tackerclient documentation: https://docs.openstack.org/python-tackerclient/
|
||||
* Tacker Documentation: https://docs.openstack.org/tacker/
|
||||
* Tacker Wiki: https://wiki.openstack.org/wiki/Tacker
|
||||
|
||||
7
doc/requirements.txt
Normal file
7
doc/requirements.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
# These are needed for docs generation
|
||||
sphinx!=1.6.6,>=1.6.2 # BSD
|
||||
openstackdocstheme>=1.18.1 # Apache-2.0
|
||||
reno>=2.5.0 # Apache-2.0
|
||||
@@ -11,7 +11,6 @@
|
||||
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
|
||||
@@ -21,20 +20,233 @@
|
||||
(Avoid deeper levels because they do not render well.)
|
||||
|
||||
=========
|
||||
Using CLI
|
||||
CLI Usage
|
||||
=========
|
||||
|
||||
There are two CLIs which support the Networking API:
|
||||
There are two CLIs which support the Tacker API:
|
||||
`OpenStackClient (OSC)
|
||||
<https://docs.openstack.org/python-openstackclient/latest/>`__
|
||||
and :doc:`neutron CLI <neutron>` (deprecated).
|
||||
and `tacker CLI <tacker>`.
|
||||
|
||||
OpenStackClient
|
||||
---------------
|
||||
Tacker CLI
|
||||
----------
|
||||
|
||||
#TODO
|
||||
.. code-block:: console
|
||||
|
||||
usage: tacker [--version] [-v] [-q] [-h] [-r NUM]
|
||||
[--os-service-type <os-service-type>]
|
||||
[--os-endpoint-type <os-endpoint-type>]
|
||||
[--service-type <service-type>]
|
||||
[--endpoint-type <endpoint-type>]
|
||||
[--os-auth-strategy <auth-strategy>] [--os-auth-url <auth-url>]
|
||||
[--os-tenant-name <auth-tenant-name> | --os-project-name <auth-project-name>]
|
||||
[--os-tenant-id <auth-tenant-id> | --os-project-id <auth-project-id>]
|
||||
[--os-username <auth-username>] [--os-user-id <auth-user-id>]
|
||||
[--os-user-domain-id <auth-user-domain-id>]
|
||||
[--os-user-domain-name <auth-user-domain-name>]
|
||||
[--os-project-domain-id <auth-project-domain-id>]
|
||||
[--os-project-domain-name <auth-project-domain-name>]
|
||||
[--os-cert <certificate>] [--os-cacert <ca-certificate>]
|
||||
[--os-key <key>] [--os-password <auth-password>]
|
||||
[--os-region-name <auth-region-name>] [--os-token <token>]
|
||||
[--http-timeout <seconds>] [--os-url <url>] [--insecure]
|
||||
|
||||
Command-line interface to the Tacker APIs
|
||||
|
||||
optional arguments:
|
||||
--version show program's version number and exit
|
||||
-v, --verbose, --debug
|
||||
Increase verbosity of output and show tracebacks on
|
||||
errors. You can repeat this option.
|
||||
-q, --quiet Suppress output except warnings and errors.
|
||||
-h, --help Show this help message and exit.
|
||||
-r NUM, --retries NUM
|
||||
How many times the request to the Tacker server should
|
||||
be retried if it fails.
|
||||
--os-service-type <os-service-type>
|
||||
Defaults to env[OS_TACKER_SERVICE_TYPE] or nfv-
|
||||
orchestration.
|
||||
--os-endpoint-type <os-endpoint-type>
|
||||
Defaults to env[OS_ENDPOINT_TYPE] or publicURL.
|
||||
--service-type <service-type>
|
||||
DEPRECATED! Use --os-service-type.
|
||||
--endpoint-type <endpoint-type>
|
||||
DEPRECATED! Use --os-endpoint-type.
|
||||
--os-auth-strategy <auth-strategy>
|
||||
DEPRECATED! Only keystone is supported.
|
||||
--os-auth-url <auth-url>
|
||||
Authentication URL, defaults to env[OS_AUTH_URL].
|
||||
--os-tenant-name <auth-tenant-name>
|
||||
Authentication tenant name, defaults to
|
||||
env[OS_TENANT_NAME].
|
||||
--os-project-name <auth-project-name>
|
||||
Another way to specify tenant name. This option is
|
||||
mutually exclusive with --os-tenant-name. Defaults to
|
||||
env[OS_PROJECT_NAME].
|
||||
--os-tenant-id <auth-tenant-id>
|
||||
Authentication tenant ID, defaults to
|
||||
env[OS_TENANT_ID].
|
||||
--os-project-id <auth-project-id>
|
||||
Another way to specify tenant ID. This option is
|
||||
mutually exclusive with --os-tenant-id. Defaults to
|
||||
env[OS_PROJECT_ID].
|
||||
--os-username <auth-username>
|
||||
Authentication username, defaults to env[OS_USERNAME].
|
||||
--os-user-id <auth-user-id>
|
||||
Authentication user ID (Env: OS_USER_ID)
|
||||
--os-user-domain-id <auth-user-domain-id>
|
||||
OpenStack user domain ID. Defaults to
|
||||
env[OS_USER_DOMAIN_ID].
|
||||
--os-user-domain-name <auth-user-domain-name>
|
||||
OpenStack user domain name. Defaults to
|
||||
env[OS_USER_DOMAIN_NAME].
|
||||
--os-project-domain-id <auth-project-domain-id>
|
||||
Defaults to env[OS_PROJECT_DOMAIN_ID].
|
||||
--os-project-domain-name <auth-project-domain-name>
|
||||
Defaults to env[OS_PROJECT_DOMAIN_NAME].
|
||||
--os-cert <certificate>
|
||||
Path of certificate file to use in SSL connection.
|
||||
This file can optionally be prepended with the private
|
||||
key. Defaults to env[OS_CERT].
|
||||
--os-cacert <ca-certificate>
|
||||
Specify a CA bundle file to use in verifying a TLS
|
||||
(https) server certificate. Defaults to
|
||||
env[OS_CACERT].
|
||||
--os-key <key> Path of client key to use in SSL connection. This
|
||||
option is not necessary if your key is prepended to
|
||||
your certificate file. Defaults to env[OS_KEY].
|
||||
--os-password <auth-password>
|
||||
Authentication password, defaults to env[OS_PASSWORD].
|
||||
--os-region-name <auth-region-name>
|
||||
Authentication region name, defaults to
|
||||
env[OS_REGION_NAME].
|
||||
--os-token <token> Authentication token, defaults to env[OS_TOKEN].
|
||||
--http-timeout <seconds>
|
||||
Timeout in seconds to wait for an HTTP response.
|
||||
Defaults to env[OS_NETWORK_TIMEOUT] or None if not
|
||||
specified.
|
||||
--os-url <url> Defaults to env[OS_URL].
|
||||
--insecure Explicitly allow tackerclient to perform "insecure"
|
||||
SSL (https) requests. The server's certificate will
|
||||
not be verified against any certificate authorities.
|
||||
This option should be used with caution.
|
||||
|
||||
Commands for API v1.0:
|
||||
bash-completion Prints all of the commands and options for bash-completion.
|
||||
chain-list List SFCs that belong to a given tenant.
|
||||
chain-show Show information of a given SFC.
|
||||
classifier-list List FCs that belong to a given tenant.
|
||||
classifier-show Show information of a given FC.
|
||||
cluster-create Create a Cluster.
|
||||
cluster-delete Delete a given Cluster.
|
||||
cluster-list List Clusters that belong to a given tenant.
|
||||
cluster-member-add Add a new Cluster Member to given Cluster.
|
||||
cluster-member-delete Delete a given Cluster Member.
|
||||
cluster-member-list List Cluster Members that belong to a given tenant.
|
||||
cluster-member-show Show information of a given Cluster Member.
|
||||
cluster-show Show information of a given Cluster.
|
||||
event-show Show event given the event id.
|
||||
events-list List events of resources.
|
||||
ext-list List all extensions.
|
||||
ext-show Show information of a given resource.
|
||||
help print detailed help for another command
|
||||
nfp-list List NFPs that belong to a given tenant.
|
||||
nfp-show Show information of a given NFP.
|
||||
ns-create Create a NS.
|
||||
ns-delete Delete given NS(s).
|
||||
ns-list List NS that belong to a given tenant.
|
||||
ns-show Show information of a given NS.
|
||||
nsd-create Create a NSD.
|
||||
nsd-delete Delete a given NSD.
|
||||
nsd-list List NSDs that belong to a given tenant.
|
||||
nsd-show Show information of a given NSD.
|
||||
nsd-template-show Show template of a given NSD.
|
||||
vim-delete Delete given VIM(s).
|
||||
vim-events-list List events of VIMs.
|
||||
vim-list List VIMs that belong to a given tenant.
|
||||
vim-register Create a VIM.
|
||||
vim-show Show information of a given VIM.
|
||||
vim-update Update a given VIM.
|
||||
vnf-create Create a VNF.
|
||||
vnf-delete Delete given VNF(s).
|
||||
vnf-events-list List events of VNFs.
|
||||
vnf-list List VNF that belong to a given tenant.
|
||||
vnf-resource-list List resources of a VNF like VDU, CP, etc.
|
||||
vnf-scale Scale a VNF.
|
||||
vnf-show Show information of a given VNF.
|
||||
vnf-update Update a given VNF.
|
||||
vnfd-create Create a VNFD.
|
||||
vnfd-delete Delete given VNFD(s).
|
||||
vnfd-events-list List events of VNFDs.
|
||||
vnfd-list List VNFD that belong to a given tenant.
|
||||
vnfd-show Show information of a given VNFD.
|
||||
vnfd-template-show Show template of a given VNFD.
|
||||
vnffg-create Create a VNFFG.
|
||||
vnffg-delete Delete a given VNFFG.
|
||||
vnffg-list List VNFFGs that belong to a given tenant.
|
||||
vnffg-show Show information of a given VNFFG.
|
||||
vnffg-update Update a given VNFFG.
|
||||
vnffgd-create Create a VNFFGD.
|
||||
vnffgd-delete Delete a given VNFFGD.
|
||||
vnffgd-list List VNFFGDs that belong to a given tenant.
|
||||
vnffgd-show Show information of a given VNFFGD.
|
||||
vnffgd-template-show Show template of a given VNFFGD.
|
||||
|
||||
|
||||
OpenStackClient CLI
|
||||
-------------------
|
||||
|
||||
The following list covers the extended commands for Tacker services
|
||||
available in **openstack** command.
|
||||
|
||||
These commands can be referenced by doing **openstack help** and the detail
|
||||
of individual command can be referred by **openstack help <command-name>**.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
openstack vnf create Create a VNF.
|
||||
openstack vnf delete Delete given VNF(s).
|
||||
openstack vnf list List VNF(s) that belong to a given tenant.
|
||||
openstack vnf resource list List resources of a VNF like VDU, CP, etc.
|
||||
openstack vnf scale Scale a VNF.
|
||||
openstack vnf show Show information of a given VNF.
|
||||
openstack vnf set Update a given VNF.
|
||||
openstack vnf descriptor create Create a VNFD.
|
||||
openstack vnf descriptor delete Delete given VNFD(s).
|
||||
openstack vnf descriptor list List VNFD(s) that belong to a given tenant.
|
||||
openstack vnf descriptor show Show information of a given VNFD.
|
||||
openstack vnf descriptor template show Show template of a given VNFD.
|
||||
openstack vim list List VIM(s) that belong to a given tenant.
|
||||
openstack vim register Create a VIM.
|
||||
openstack vim show Show information of a given VIM.
|
||||
openstack vim set Update a given VIM.
|
||||
openstack vim delete Delete given VIM(s).
|
||||
openstack ns create Create a NS.
|
||||
openstack ns delete Delete given NS(s).
|
||||
openstack ns list List NS that belong to a given tenant.
|
||||
openstack ns show Show information of a given NS.
|
||||
openstack ns descriptor create Create a NSD.
|
||||
openstack ns descriptor delete Delete a given NSD.
|
||||
openstack ns descriptor list List NSD(s) that belong to a given tenant.
|
||||
openstack ns descriptor show Show information of a given NSD.
|
||||
openstack ns descriptor template show Show template of a given NSD.
|
||||
openstack vnf graph create Create a VNFFG.
|
||||
openstack vnf graph delete Delete a given VNFFG.
|
||||
openstack vnf graph list List VNFFG(s) that belong to a given tenant.
|
||||
openstack vnf graph show Show information of a given VNFFG.
|
||||
openstack vnf graph set Update a given VNFFG.
|
||||
openstack vnf graph descriptor create Create a VNFFGD.
|
||||
openstack vnf graph descriptor delete Delete a given VNFFGD.
|
||||
openstack vnf graph descriptor list List VNFFGD(s) that belong to a given tenant.
|
||||
openstack vnf graph descriptor show Show information of a given VNFFGD.
|
||||
openstack vnf graph descriptor template show Show template of a given VNFFGD.
|
||||
openstack vnf chain list List SFC(s) that belong to a given tenant.
|
||||
openstack vnf chain show Show information of a given SFC.
|
||||
openstack vnf classifier list List FC(s) that belong to a given tenant.
|
||||
openstack vnf classifier show Show information of a given FC.
|
||||
openstack vnf network forwarding path list List NFP(s) that belong to a given tenant.
|
||||
openstack vnf network forwarding path show Show information of a given NFP.
|
||||
openstack nfv event show Show event given the event id.
|
||||
openstack nfv event list List events of resources.
|
||||
|
||||
neutron CLI
|
||||
-----------
|
||||
|
||||
#TODO
|
||||
|
||||
@@ -1,7 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# 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.
|
||||
|
||||
# -- General configuration ---------------------------------------------
|
||||
# python-tackerclient documentation build configuration file
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
# sys.path.append(os.path.abspath('.'))
|
||||
|
||||
sys.path.insert(0, os.path.abspath('../..'))
|
||||
|
||||
# -- 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.
|
||||
@@ -12,12 +34,6 @@ extensions = [
|
||||
'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']
|
||||
|
||||
@@ -28,7 +44,8 @@ source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
copyright = u'OpenStack Foundation'
|
||||
project = 'python-tackerclient'
|
||||
copyright = 'OpenStack Contributors'
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
add_function_parentheses = True
|
||||
@@ -40,7 +57,7 @@ add_module_names = True
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------
|
||||
# -- Options for HTML output --------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. Major themes that come with
|
||||
# Sphinx are currently 'default' and 'sphinxdoc'.
|
||||
@@ -49,6 +66,19 @@ html_theme = 'openstackdocs'
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'tackerclientdoc'
|
||||
|
||||
# -- Options for cliff.sphinxext plugin ---------------------------------------
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
html_last_updated_fmt = '%Y-%m-%d %H:%M'
|
||||
|
||||
autoprogram_cliff_application = 'openstack'
|
||||
# -- Options for manual page output -------------------------------------------
|
||||
|
||||
man_pages = [
|
||||
('cli/index', 'tacker', u'Client for Tacker API',
|
||||
[u'OpenStack Contributors'], 1),
|
||||
]
|
||||
|
||||
# -- Options for openstackdocstheme -------------------------------------------
|
||||
|
||||
repository_name = 'openstack/python-tackerclient'
|
||||
bug_project = 'python-tackerclient'
|
||||
bug_tag = 'doc'
|
||||
|
||||
26
doc/source/contributor/contributing.rst
Normal file
26
doc/source/contributor/contributing.rst
Normal file
@@ -0,0 +1,26 @@
|
||||
..
|
||||
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.)
|
||||
|
||||
============
|
||||
Contributing
|
||||
============
|
||||
|
||||
.. include:: ../../../CONTRIBUTING.rst
|
||||
195
doc/source/contributor/developing.rst
Normal file
195
doc/source/contributor/developing.rst
Normal file
@@ -0,0 +1,195 @@
|
||||
..
|
||||
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.)
|
||||
|
||||
===================================
|
||||
Developing with Python-TackerClient
|
||||
===================================
|
||||
|
||||
Project Info
|
||||
============
|
||||
|
||||
* **Free software:** under the `Apache license <http://www.apache.org/licenses/LICENSE-2.0>`_
|
||||
* **Tacker Service:** http://git.openstack.org/cgit/openstack/tacker
|
||||
* **Tacker Client Library:** http://git.openstack.org/cgit/openstack/python-tackerclient
|
||||
* **Tacker Service Bugs:** http://bugs.launchpad.net/tacker
|
||||
* **Client Bugs:** https://bugs.launchpad.net/python-tackerclient
|
||||
* **Blueprints:** https://blueprints.launchpad.net/tacker
|
||||
|
||||
Meetings
|
||||
========
|
||||
For details please refer to the `OpenStack IRC meetings`_ page.
|
||||
|
||||
.. _`OpenStack IRC meetings`: http://eavesdrop.openstack.org/#Tacker_(NFV_Orchestrator_and_VNF_Manager)_Team_Meeting
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
Install the prerequisites for Tox:
|
||||
|
||||
* On Ubuntu or Debian:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ apt-get install gcc gettext python-dev libxml2-dev libxslt1-dev \
|
||||
zlib1g-dev
|
||||
|
||||
You may need to use pip install for some packages.
|
||||
|
||||
|
||||
* On RHEL or CentOS including Fedora:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ yum install gcc python-devel libxml2-devel libxslt-devel
|
||||
|
||||
* On openSUSE or SUSE linux Enterprise:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ zypper install gcc python-devel libxml2-devel libxslt-devel
|
||||
|
||||
Install python-tox:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install tox
|
||||
|
||||
To run the full suite of tests maintained within TackerClient.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ tox
|
||||
|
||||
.. NOTE::
|
||||
|
||||
The first time you run ``tox``, it will take additional time to build
|
||||
virtualenvs. You can later use the ``-r`` option with ``tox`` to rebuild
|
||||
your virtualenv in a similar manner.
|
||||
|
||||
|
||||
To run tests for one or more specific test environments(for example, the
|
||||
most common configuration of Python 2.7, Python 3.5 and PEP-8), list the
|
||||
environments with the ``-e`` option, separated by spaces:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ tox -e py27,py35,pep8
|
||||
|
||||
See ``tox.ini`` for the full list of available test environments.
|
||||
|
||||
Building the Documentation
|
||||
==========================
|
||||
|
||||
The documentation is generated with Sphinx using the ``tox`` command. To
|
||||
create HTML docs, run the commands:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ tox -e docs
|
||||
|
||||
The resultant HTML will be in the ``doc/build/html`` directory.
|
||||
|
||||
Release Notes
|
||||
=============
|
||||
|
||||
The release notes for a patch should be included in the patch. See the
|
||||
`Project Team Guide`_ for more information on using reno in OpenStack.
|
||||
|
||||
.. _`Project Team Guide`: http://docs.openstack.org/project-team-guide/release-management.html#managing-release-notes
|
||||
|
||||
If any of the following applies to the patch, a release note is required:
|
||||
|
||||
* The deployer needs to take an action when upgrading
|
||||
* The plugin interface changes
|
||||
* A new feature is implemented
|
||||
* A command or option is removed
|
||||
* Current behavior is changed
|
||||
* A security bug is fixed
|
||||
|
||||
Reno is used to generate release notes. Use the commands:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ tox -e venv -- reno new <bug-,bp-,whatever>
|
||||
|
||||
Then edit the sample file that was created and push it with your change.
|
||||
|
||||
To run the commands and see results:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ git commit # Commit the change because reno scans git log.
|
||||
|
||||
$ tox -e releasenotes
|
||||
|
||||
At last, look at the generated release notes
|
||||
files in ``releasenotes/build/html`` in your browser.
|
||||
|
||||
Testing new code
|
||||
================
|
||||
|
||||
If a developer wants to test new code (feature, command or option) that
|
||||
they have written, Python-TackerClient may be installed from source by running
|
||||
the following commands in the base directory of the project:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ python setup.py install
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install -e .
|
||||
|
||||
Standardize Import Format
|
||||
=========================
|
||||
|
||||
.. _`Import Order Guide`: https://docs.openstack.org/hacking/latest/user/hacking.html#imports
|
||||
|
||||
The import order shows below:
|
||||
|
||||
* {{stdlib imports in human alphabetical order}}
|
||||
* \n
|
||||
* {{third-party lib imports in human alphabetical order}}
|
||||
* \n
|
||||
* {{project imports in human alphabetical order}}
|
||||
* \n
|
||||
* \n
|
||||
* {{begin your code}}
|
||||
|
||||
Example
|
||||
~~~~~~~
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import copy
|
||||
import fixtures
|
||||
import mock
|
||||
import os
|
||||
|
||||
from osc_lib.api import auth
|
||||
from osc_lib import utils
|
||||
import six
|
||||
|
||||
from openstackclient import shell
|
||||
from openstackclient.tests import utils
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
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
|
||||
@@ -28,4 +27,10 @@ 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
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
contributing.rst
|
||||
developing.rst
|
||||
|
||||
|
||||
|
||||
@@ -19,39 +19,38 @@
|
||||
''''''' Heading 4
|
||||
(Avoid deeper levels because they do not render well.)
|
||||
|
||||
==================================
|
||||
python-tackerclient documentation
|
||||
==================================
|
||||
=================================
|
||||
Python-TackerClient Documentation
|
||||
=================================
|
||||
|
||||
This is a client for OpenStack NFV MANO API. It provides
|
||||
This is a client for OpenStack NFV MANO (Tacker) API. It provides
|
||||
:doc:`Python API bindings <reference/index>` (the tackerclient module) and
|
||||
:doc:`command-line interface (CLI) <cli/index>`.
|
||||
|
||||
|
||||
User Documentation
|
||||
------------------
|
||||
Contents
|
||||
--------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
install/index
|
||||
cli/index
|
||||
contributor/index
|
||||
reference/index
|
||||
|
||||
Contributor Guide
|
||||
-----------------
|
||||
|
||||
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.
|
||||
Release Notes
|
||||
-------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
contributor/index
|
||||
Release Notes <http://docs.openstack.org/releasenotes/python-tackerclient>
|
||||
|
||||
|
||||
History
|
||||
-------
|
||||
Indices and Tables
|
||||
------------------
|
||||
|
||||
Release notes is available at
|
||||
http://docs.openstack.org/releasenotes/python-tackerclient/.
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
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
|
||||
@@ -20,19 +19,51 @@
|
||||
''''''' Heading 4
|
||||
(Avoid deeper levels because they do not render well.)
|
||||
|
||||
=================
|
||||
Install Guide
|
||||
=================
|
||||
============
|
||||
Installation
|
||||
============
|
||||
|
||||
To install ``python-tackerclient``, it is required to have ``pip``
|
||||
(in most cases). Make sure that ``pip`` is installed. Then type::
|
||||
**Note:** The paths we are using for configuration files in these steps
|
||||
are with reference to Ubuntu Operating System. The paths may vary for
|
||||
other Operating Systems.
|
||||
|
||||
The branch_name which is used in commands, specify the branch_name
|
||||
as stable/<branch> for any stable branch installation. For eg:
|
||||
stable/queens, stable/pike. If unspecified the default will be
|
||||
master branch.
|
||||
|
||||
Using python install
|
||||
====================
|
||||
1. Clone python-tackerclient repository.
|
||||
|
||||
::
|
||||
|
||||
$ cd ~/
|
||||
$ git clone https://github.com/openstack/python-tackerclient -b <branch_name>
|
||||
|
||||
|
||||
2. Install python-tackerclient.
|
||||
|
||||
::
|
||||
|
||||
$ cd python-tackerclient
|
||||
$ sudo python setup.py install
|
||||
|
||||
|
||||
Using pip
|
||||
=========
|
||||
|
||||
You can also install the latest version by using ``pip`` command:
|
||||
|
||||
::
|
||||
|
||||
$ pip install python-tackerclient
|
||||
|
||||
|
||||
Or, if it is needed to install ``python-tackerclient`` from master branch,
|
||||
type::
|
||||
type
|
||||
|
||||
::
|
||||
|
||||
$ pip install git+https://github.com/openstack/python-tackerclient.git
|
||||
|
||||
After ``python-tackerclient`` is installed you will see command ``tacker``
|
||||
in your environment.
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
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
|
||||
@@ -20,10 +19,8 @@
|
||||
''''''' Heading 4
|
||||
(Avoid deeper levels because they do not render well.)
|
||||
|
||||
tackerclient Python API
|
||||
========================
|
||||
=========
|
||||
Reference
|
||||
=========
|
||||
|
||||
Basic Usage
|
||||
-----------
|
||||
|
||||
#TODO
|
||||
(To be updated)
|
||||
|
||||
4
releasenotes/notes/bug-1754556-53268d3081fa18d1.yaml
Normal file
4
releasenotes/notes/bug-1754556-53268d3081fa18d1.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Add documentation for python-tackerclient
|
||||
4
releasenotes/notes/bug-1754926-06ac4d7ffd17b5ce.yaml
Normal file
4
releasenotes/notes/bug-1754926-06ac4d7ffd17b5ce.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Fix local test fail with InterpreterNotFound: pypy
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Enalble CLI to support clustering service in Tacker Server
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Add python-vnfd, vnf, nsd, ns, vnffgd, vnffg, event commands support.
|
||||
@@ -36,9 +36,8 @@
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = [
|
||||
'oslosphinx',
|
||||
'reno.sphinxext',
|
||||
'openstackdocstheme'
|
||||
'openstackdocstheme',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
|
||||
@@ -7,6 +7,7 @@ Contents:
|
||||
:maxdepth: 2
|
||||
|
||||
unreleased
|
||||
queens
|
||||
pike
|
||||
ocata
|
||||
newton
|
||||
|
||||
6
releasenotes/source/queens.rst
Normal file
6
releasenotes/source/queens.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
===================================
|
||||
Queens Series Release Notes
|
||||
===================================
|
||||
|
||||
.. release-notes::
|
||||
:branch: stable/queens
|
||||
@@ -11,7 +11,6 @@ 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.3 # Apache-2.0
|
||||
osc-lib>=1.8.0 # Apache-2.0
|
||||
oslo.log>=3.36.0 # Apache-2.0
|
||||
|
||||
48
setup.cfg
48
setup.cfg
@@ -40,12 +40,56 @@ openstack.tackerclient.v1 =
|
||||
vim_set = tackerclient.osc.v1.nfvo.vim:UpdateVIM
|
||||
vim_delete = tackerclient.osc.v1.nfvo.vim:DeleteVIM
|
||||
vim_show = tackerclient.osc.v1.nfvo.vim:ShowVIM
|
||||
vnf_descriptor_create = tackerclient.osc.v1.vnfm.vnfd:CreateVNFD
|
||||
vnf_descriptor_delete = tackerclient.osc.v1.vnfm.vnfd:DeleteVNFD
|
||||
vnf_descriptor_list = tackerclient.osc.v1.vnfm.vnfd:ListVNFD
|
||||
vnf_descriptor_show = tackerclient.osc.v1.vnfm.vnfd:ShowVNFD
|
||||
vnf_descriptor_template_show = tackerclient.osc.v1.vnfm.vnfd:ShowTemplateVNFD
|
||||
vnf_create = tackerclient.osc.v1.vnfm.vnf:CreateVNF
|
||||
vnf_delete = tackerclient.osc.v1.vnfm.vnf:DeleteVNF
|
||||
vnf_list = tackerclient.osc.v1.vnfm.vnf:ListVNF
|
||||
vnf_show = tackerclient.osc.v1.vnfm.vnf:ShowVNF
|
||||
vnf_resource_list = tackerclient.osc.v1.vnfm.vnf:ListVNFResources
|
||||
vnf_set = tackerclient.osc.v1.vnfm.vnf:UpdateVNF
|
||||
vnf_scale = tackerclient.osc.v1.vnfm.vnf:ScaleVNF
|
||||
vnf_graph_descriptor_create = tackerclient.osc.v1.nfvo.vnffgd:CreateVNFFGD
|
||||
vnf_graph_descriptor_delete = tackerclient.osc.v1.nfvo.vnffgd:DeleteVNFFGD
|
||||
vnf_graph_descriptor_list = tackerclient.osc.v1.nfvo.vnffgd:ListVNFFGD
|
||||
vnf_graph_descriptor_show = tackerclient.osc.v1.nfvo.vnffgd:ShowVNFFGD
|
||||
vnf_graph_descriptor_template_show = tackerclient.osc.v1.nfvo.vnffgd:ShowTemplateVNFFGD
|
||||
ns_descriptor_create = tackerclient.osc.v1.nfvo.nsd:CreateNSD
|
||||
ns_descriptor_delete = tackerclient.osc.v1.nfvo.nsd:DeleteNSD
|
||||
ns_descriptor_list = tackerclient.osc.v1.nfvo.nsd:ListNSD
|
||||
ns_descriptor_show = tackerclient.osc.v1.nfvo.nsd:ShowNSD
|
||||
ns_descriptor_template_show = tackerclient.osc.v1.nfvo.nsd:ShowTemplateNSD
|
||||
nfv_event_show = tackerclient.osc.v1.events.events:ShowEvent
|
||||
nfv_event_list = tackerclient.osc.v1.events.events:ListEvent
|
||||
ns_create = tackerclient.osc.v1.nfvo.ns:CreateNS
|
||||
ns_delete = tackerclient.osc.v1.nfvo.ns:DeleteNS
|
||||
ns_list = tackerclient.osc.v1.nfvo.ns:ListNS
|
||||
ns_show = tackerclient.osc.v1.nfvo.ns:ShowNS
|
||||
vnf_graph_create = tackerclient.osc.v1.nfvo.vnffg:CreateVNFFG
|
||||
vnf_graph_delete = tackerclient.osc.v1.nfvo.vnffg:DeleteVNFFG
|
||||
vnf_graph_set = tackerclient.osc.v1.nfvo.vnffg:UpdateVNFFG
|
||||
vnf_graph_list = tackerclient.osc.v1.nfvo.vnffg:ListVNFFG
|
||||
vnf_graph_show = tackerclient.osc.v1.nfvo.vnffg:ShowVNFFG
|
||||
vnf_network_forwarding_path_list = tackerclient.osc.v1.nfvo.vnffg:ListNFP
|
||||
vnf_network_forwarding_path_show = tackerclient.osc.v1.nfvo.vnffg:ShowNFP
|
||||
vnf_classifier_list = tackerclient.osc.v1.nfvo.vnffg:ListFC
|
||||
vnf_classifier_show = tackerclient.osc.v1.nfvo.vnffg:ShowFC
|
||||
vnf_chain_list = tackerclient.osc.v1.nfvo.vnffg:ListSFC
|
||||
vnf_chain_show = tackerclient.osc.v1.nfvo.vnffg:ShowSFC
|
||||
|
||||
|
||||
[build_sphinx]
|
||||
all_files = 1
|
||||
build-dir = doc/build
|
||||
builders = html,man
|
||||
source-dir = doc/source
|
||||
build-dir = doc/build
|
||||
all-files = 1
|
||||
warning-is-error = 1
|
||||
|
||||
[upload_sphinx]
|
||||
upload-dir = doc/build/html
|
||||
|
||||
[build_releasenotes]
|
||||
all_files = 1
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
# under the License.
|
||||
#
|
||||
|
||||
from sys import stderr
|
||||
|
||||
from cliff import command
|
||||
|
||||
|
||||
@@ -23,6 +25,8 @@ class OpenStackCommand(command.Command):
|
||||
api = None
|
||||
|
||||
def run(self, parsed_args):
|
||||
stderr.write("Deprecated: tacker command line is deprecated, "
|
||||
"will be deleted after Rocky is released.\n")
|
||||
if not self.api:
|
||||
return
|
||||
else:
|
||||
|
||||
0
tackerclient/osc/v1/events/__init__.py
Normal file
0
tackerclient/osc/v1/events/__init__.py
Normal file
116
tackerclient/osc/v1/events/events.py
Normal file
116
tackerclient/osc/v1/events/events.py
Normal file
@@ -0,0 +1,116 @@
|
||||
# Copyright 2018 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 osc_lib.command import command
|
||||
from osc_lib import utils
|
||||
|
||||
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
|
||||
|
||||
_attr_map = (
|
||||
('id', 'ID', tacker_osc_utils.LIST_BOTH),
|
||||
('resource_type', 'Resource Type', tacker_osc_utils.LIST_BOTH),
|
||||
('resource_id', 'Resource ID', tacker_osc_utils.LIST_BOTH),
|
||||
('resource_state', 'Resource State', tacker_osc_utils.LIST_BOTH),
|
||||
('event_type', 'Event Type', tacker_osc_utils.LIST_BOTH),
|
||||
('timestamp', 'Timestamp', tacker_osc_utils.LIST_BOTH),
|
||||
('event_details', 'Event Details', tacker_osc_utils.LIST_LONG_ONLY),
|
||||
)
|
||||
|
||||
_EVENT = "event"
|
||||
|
||||
events_path = '/events'
|
||||
|
||||
|
||||
def _get_columns(item):
|
||||
column_map = {}
|
||||
return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
|
||||
|
||||
|
||||
class ShowEvent(command.ShowOne):
|
||||
_description = _("Show event given the event id.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowEvent, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_EVENT,
|
||||
metavar="ID",
|
||||
help=_("ID of event to display")
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
obj_id = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, _EVENT, parsed_args.event)
|
||||
obj = client.show_event(obj_id)
|
||||
display_columns, columns = _get_columns(obj[_EVENT])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_EVENT]),
|
||||
columns,)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class ListEvent(command.Lister):
|
||||
_description = _("List events of resources.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListEvent, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--id',
|
||||
help=_("id of the event to look up."))
|
||||
parser.add_argument(
|
||||
'--resource-type',
|
||||
help=_("resource type of the events to look up."))
|
||||
parser.add_argument(
|
||||
'--resource-id',
|
||||
help=_("resource id of the events to look up."))
|
||||
parser.add_argument(
|
||||
'--resource-state',
|
||||
help=_("resource state of the events to look up."))
|
||||
parser.add_argument(
|
||||
'--event-type',
|
||||
help=_("event type of the events to look up."))
|
||||
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
|
||||
_params = {}
|
||||
if parsed_args.id:
|
||||
_params['id'] = parsed_args.id
|
||||
if parsed_args.resource_id:
|
||||
_params['resource_id'] = parsed_args.resource_id
|
||||
if parsed_args.resource_state:
|
||||
_params['resource_state'] = parsed_args.resource_id
|
||||
if parsed_args.event_type:
|
||||
_params['event_type'] = parsed_args.event_type
|
||||
if parsed_args.resource_type:
|
||||
_params['resource_type'] = parsed_args.resource_type
|
||||
events = client.list('events', events_path, True, **_params)
|
||||
data = {}
|
||||
data['events'] = events['events']
|
||||
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[_EVENT + 's']))
|
||||
239
tackerclient/osc/v1/nfvo/ns.py
Normal file
239
tackerclient/osc/v1/nfvo/ns.py
Normal file
@@ -0,0 +1,239 @@
|
||||
# Copyright 2018 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.
|
||||
#
|
||||
|
||||
import yaml
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import utils
|
||||
|
||||
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
|
||||
|
||||
_attr_map = (
|
||||
('id', 'ID', tacker_osc_utils.LIST_BOTH),
|
||||
('name', 'Name', tacker_osc_utils.LIST_BOTH),
|
||||
('nsd_id', 'NSD ID',
|
||||
tacker_osc_utils.LIST_BOTH),
|
||||
('mgmt_urls', 'Mgmt Urls', tacker_osc_utils.LIST_BOTH),
|
||||
('status', 'Status', tacker_osc_utils.LIST_BOTH),
|
||||
)
|
||||
|
||||
_NS = 'ns'
|
||||
_RESOURCE = 'resource'
|
||||
|
||||
|
||||
def _get_columns(item):
|
||||
column_map = {
|
||||
'tenant_id': 'project_id',
|
||||
}
|
||||
return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
|
||||
|
||||
|
||||
class CreateNS(command.ShowOne):
|
||||
_description = _("Create a new NS")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CreateNS, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help=_('Name for NS'))
|
||||
parser.add_argument(
|
||||
'--tenant-id', metavar='TENANT_ID',
|
||||
help=_('The owner tenant ID'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help=_('Set description for the NS'))
|
||||
nsd_group = parser.add_mutually_exclusive_group(required=True)
|
||||
nsd_group.add_argument(
|
||||
'--nsd-id',
|
||||
help=_('NSD ID to use as template to create NS'))
|
||||
nsd_group.add_argument(
|
||||
'--nsd-template',
|
||||
help=_('NSD file to create NS'))
|
||||
nsd_group.add_argument(
|
||||
'--nsd-name',
|
||||
help=_('NSD name to use as template to create NS'))
|
||||
vim_group = parser.add_mutually_exclusive_group()
|
||||
vim_group.add_argument(
|
||||
'--vim-id',
|
||||
help=_('VIM ID to use to create NS on the specified VIM'))
|
||||
vim_group.add_argument(
|
||||
'--vim-name',
|
||||
help=_('VIM name to use to create NS on the specified VIM'))
|
||||
parser.add_argument(
|
||||
'--vim-region-name',
|
||||
help=_('VIM Region to use to create NS on the specified VIM'))
|
||||
parser.add_argument(
|
||||
'--param-file',
|
||||
help=_('Specify parameter YAML file'))
|
||||
return parser
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {_NS: {}}
|
||||
body[_NS]['attributes'] = {}
|
||||
|
||||
if parsed_args.vim_region_name:
|
||||
body[_NS].setdefault('placement_attr', {})['region_name'] = \
|
||||
parsed_args.vim_region_name
|
||||
|
||||
client = self.app.client_manager.tackerclient
|
||||
if parsed_args.vim_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(client, 'vim',
|
||||
parsed_args.vim_name)
|
||||
parsed_args.vim_id = _id
|
||||
if parsed_args.nsd_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(client, 'nsd',
|
||||
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:
|
||||
template = yaml.load(
|
||||
template, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not template:
|
||||
raise exceptions.InvalidInput('The nsd file is empty')
|
||||
body[_NS]['nsd_template'] = template
|
||||
|
||||
if parsed_args.param_file:
|
||||
with open(parsed_args.param_file) as f:
|
||||
param_yaml = f.read()
|
||||
try:
|
||||
param_yaml = yaml.load(
|
||||
param_yaml, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not param_yaml:
|
||||
raise exceptions.InvalidInput('The parameter file is empty')
|
||||
body[_NS]['attributes'] = {'param_values': param_yaml}
|
||||
tackerV10.update_dict(parsed_args, body[_NS],
|
||||
['tenant_id', 'name', 'description',
|
||||
'nsd_id', 'vim_id'])
|
||||
return body
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
ns = client.create_ns(self.args2body(parsed_args))
|
||||
display_columns, columns = _get_columns(ns[_NS])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(ns[_NS]),
|
||||
columns)
|
||||
lstdata = list(data)
|
||||
for index, value in enumerate(lstdata):
|
||||
if value is None:
|
||||
lstdata[index] = ''
|
||||
data = tuple(lstdata)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class DeleteNS(command.Command):
|
||||
_description = _("Delete NS(s).")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteNS, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_NS,
|
||||
metavar="<NS>",
|
||||
nargs="+",
|
||||
help=_("NS(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.ns:
|
||||
try:
|
||||
obj = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, _NS, resource_id)
|
||||
client.delete_ns(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': _NS})
|
||||
err_msg = _("\n\nUnable to delete the below"
|
||||
" %s(s):") % _NS
|
||||
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': _NS}))
|
||||
return
|
||||
|
||||
|
||||
class ListNS(command.Lister):
|
||||
_description = ("List (NS)s that belong to a given tenant.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListNS, self).get_parser(prog_name)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
data = client.list_nss()
|
||||
headers, columns = tacker_osc_utils.get_column_definitions(
|
||||
_attr_map, long_listing=None)
|
||||
return (headers,
|
||||
(utils.get_dict_properties(
|
||||
s, columns,
|
||||
) for s in data[_NS + 's']))
|
||||
|
||||
|
||||
class ShowNS(command.ShowOne):
|
||||
_description = _("Display NS details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowNS, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_NS,
|
||||
metavar="<NS>",
|
||||
help=_("NS 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, _NS, parsed_args.ns)
|
||||
obj = client.show_ns(obj_id)
|
||||
display_columns, columns = _get_columns(obj[_NS])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_NS]),
|
||||
columns)
|
||||
lstdata = list(data)
|
||||
for index, value in enumerate(lstdata):
|
||||
if value is None:
|
||||
lstdata[index] = ''
|
||||
data = tuple(lstdata)
|
||||
return (display_columns, data)
|
||||
223
tackerclient/osc/v1/nfvo/nsd.py
Normal file
223
tackerclient/osc/v1/nfvo/nsd.py
Normal file
@@ -0,0 +1,223 @@
|
||||
# Copyright 2018 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.
|
||||
#
|
||||
|
||||
import yaml
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import utils
|
||||
|
||||
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
|
||||
|
||||
_attr_map = (
|
||||
('id', 'ID', tacker_osc_utils.LIST_BOTH),
|
||||
('name', 'Name', tacker_osc_utils.LIST_BOTH),
|
||||
('template_source', 'Template_Source',
|
||||
tacker_osc_utils.LIST_BOTH),
|
||||
('description', 'Description', tacker_osc_utils.LIST_BOTH),
|
||||
)
|
||||
|
||||
_NSD = 'nsd'
|
||||
|
||||
_formatters = {
|
||||
'attributes': 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)
|
||||
|
||||
|
||||
class CreateNSD(command.ShowOne):
|
||||
_description = _("Create a new NSD.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CreateNSD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help=_('Name for NSD'))
|
||||
parser.add_argument(
|
||||
'--tenant-id', metavar='TENANT_ID',
|
||||
help=_('The owner tenant ID or project ID'))
|
||||
parser.add_argument(
|
||||
'--nsd-file',
|
||||
required=True,
|
||||
help=_('YAML file with NSD parameters'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help=_('Set a description for the NSD'))
|
||||
return parser
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {_NSD: {}}
|
||||
nsd = None
|
||||
if not parsed_args.nsd_file:
|
||||
raise exceptions.InvalidInput("Invalid input for nsd file")
|
||||
with open(parsed_args.nsd_file) as f:
|
||||
nsd = f.read()
|
||||
try:
|
||||
nsd = yaml.load(nsd, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not nsd:
|
||||
raise exceptions.InvalidInput("nsd file is empty")
|
||||
body[_NSD]['attributes'] = {'nsd': nsd}
|
||||
tackerV10.update_dict(parsed_args, body[_NSD],
|
||||
['tenant_id', 'name', 'description'])
|
||||
return body
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
nsd = client.create_nsd(self.args2body(parsed_args))
|
||||
display_columns, columns = _get_columns(nsd[_NSD])
|
||||
nsd[_NSD]['attributes']['nsd'] = yaml.load(
|
||||
nsd[_NSD]['attributes']['nsd'])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(nsd[_NSD]),
|
||||
columns, formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class DeleteNSD(command.Command):
|
||||
_description = _("Delete NSD(s).")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteNSD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_NSD,
|
||||
metavar="<NSD>",
|
||||
nargs="+",
|
||||
help=_("NSD(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.nsd:
|
||||
try:
|
||||
obj = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, _NSD, resource_id)
|
||||
client.delete_nsd(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': _NSD})
|
||||
err_msg = _("\n\nUnable to delete the below"
|
||||
" %s(s):") % _NSD
|
||||
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': _NSD}))
|
||||
return
|
||||
|
||||
|
||||
class ListNSD(command.Lister):
|
||||
_description = ("List (NSD)s that belong to a given tenant.")
|
||||
|
||||
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 take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
data = client.list_nsds()
|
||||
headers, columns = tacker_osc_utils.get_column_definitions(
|
||||
_attr_map, long_listing=None)
|
||||
return (headers,
|
||||
(utils.get_dict_properties(
|
||||
s, columns,
|
||||
) for s in data[_NSD + 's']))
|
||||
|
||||
|
||||
class ShowNSD(command.ShowOne):
|
||||
_description = _("Display NSD details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowNSD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_NSD,
|
||||
metavar="<NSD>",
|
||||
help=_("NSD 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, _NSD, parsed_args.nsd)
|
||||
obj = client.show_nsd(obj_id)
|
||||
obj[_NSD]['attributes']['nsd'] = yaml.load(
|
||||
obj[_NSD]['attributes']['nsd'])
|
||||
display_columns, columns = _get_columns(obj[_NSD])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_NSD]),
|
||||
columns,
|
||||
formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class ShowTemplateNSD(command.ShowOne):
|
||||
_description = _("Display NSD Template details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowTemplateNSD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_NSD,
|
||||
metavar="<NSD>",
|
||||
help=_("NSD 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, _NSD, parsed_args.nsd)
|
||||
obj = client.show_nsd(obj_id)
|
||||
obj[_NSD]['attributes']['nsd'] = yaml.load(
|
||||
obj[_NSD]['attributes']['nsd'])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_NSD]),
|
||||
(u'attributes',),
|
||||
formatters=_formatters)
|
||||
data = (data or _('Unable to display NSD template!'))
|
||||
return ((u'attributes',), data)
|
||||
@@ -98,6 +98,9 @@ class CreateVIM(command.ShowOne):
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help=_('Set a name for the VIM'))
|
||||
parser.add_argument(
|
||||
'--tenant-id', metavar='TENANT_ID',
|
||||
help=_('The owner tenant ID or project ID'))
|
||||
parser.add_argument(
|
||||
'--config-file',
|
||||
required=True,
|
||||
|
||||
540
tackerclient/osc/v1/nfvo/vnffg.py
Normal file
540
tackerclient/osc/v1/nfvo/vnffg.py
Normal file
@@ -0,0 +1,540 @@
|
||||
# Copyright 2018 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.
|
||||
#
|
||||
|
||||
import yaml
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import utils
|
||||
|
||||
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
|
||||
|
||||
_VNFFG = 'vnffg' # VNF Forwarding Graph
|
||||
_NFP = 'nfp' # Network Forwarding Path
|
||||
_SFC = 'sfc' # Service Function Chain
|
||||
_FC = 'classifier' # Flow Classifier
|
||||
|
||||
nfps_path = '/nfps'
|
||||
fcs_path = '/classifiers'
|
||||
sfcs_path = '/sfcs'
|
||||
|
||||
DEFAULT_ERROR_REASON_LENGTH = 100
|
||||
|
||||
_attr_map_vnffg = (
|
||||
('id', 'ID', tacker_osc_utils.LIST_BOTH),
|
||||
('name', 'Name', tacker_osc_utils.LIST_BOTH),
|
||||
('vnffgd_id', 'VNFFGD ID', tacker_osc_utils.LIST_BOTH),
|
||||
('status', 'Status', tacker_osc_utils.LIST_BOTH),
|
||||
('description', 'Description', tacker_osc_utils.LIST_LONG_ONLY),
|
||||
)
|
||||
|
||||
_attr_map_nfp = (
|
||||
('id', 'ID', tacker_osc_utils.LIST_BOTH),
|
||||
('name', 'Name', tacker_osc_utils.LIST_BOTH),
|
||||
('status', 'Status', tacker_osc_utils.LIST_BOTH),
|
||||
('vnffg_id', 'VNFFG ID', tacker_osc_utils.LIST_BOTH),
|
||||
('path_id', 'Path ID', tacker_osc_utils.LIST_BOTH),
|
||||
)
|
||||
|
||||
_attr_map_sfc = (
|
||||
('id', 'ID', tacker_osc_utils.LIST_BOTH),
|
||||
('status', 'Status', tacker_osc_utils.LIST_BOTH),
|
||||
('nfp_id', 'NFP ID', tacker_osc_utils.LIST_BOTH),
|
||||
)
|
||||
|
||||
_attr_map_fc = (
|
||||
('id', 'ID', tacker_osc_utils.LIST_BOTH),
|
||||
('name', 'Name', tacker_osc_utils.LIST_BOTH),
|
||||
('status', 'Status', tacker_osc_utils.LIST_BOTH),
|
||||
('nfp_id', 'NFP ID', tacker_osc_utils.LIST_BOTH),
|
||||
('chain_id', 'Chain ID', tacker_osc_utils.LIST_BOTH),
|
||||
)
|
||||
|
||||
_formatters = {
|
||||
'attributes': tacker_osc_utils.format_dict_with_indention,
|
||||
'match': tacker_osc_utils.format_dict_with_indention,
|
||||
'chain': 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)
|
||||
|
||||
|
||||
class CreateVNFFG(command.ShowOne):
|
||||
_description = _("Create a new VNFFG.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CreateVNFFG, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help=_('Set a name for the VNFFG'))
|
||||
parser.add_argument(
|
||||
'--tenant-id', metavar='TENANT_ID',
|
||||
help=_('The owner tenant ID'))
|
||||
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'))
|
||||
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. '
|
||||
'Example: VNF1:my_vnf1,VNF2:my_vnf2'))
|
||||
parser.add_argument(
|
||||
'--symmetrical',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=_('Should a reverse path be created for the NFP '
|
||||
'(True or False)'))
|
||||
parser.add_argument(
|
||||
'--param-file',
|
||||
help=_('YAML file with specific VNFFG parameters'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help=_('Set a description for the VNFFG'))
|
||||
return parser
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {_VNFFG: {}}
|
||||
body[_VNFFG]['attributes'] = {}
|
||||
|
||||
client = self.app.client_manager.tackerclient
|
||||
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(
|
||||
client, 'vnf', vnf)
|
||||
parsed_args.vnf_mapping = _vnf_mapping
|
||||
|
||||
if parsed_args.vnffgd_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, 'vnffgd', 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:
|
||||
template = yaml.load(template, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not template:
|
||||
raise exceptions.InvalidInput('The vnffgd file is empty')
|
||||
body[_VNFFG]['vnffgd_template'] = template
|
||||
|
||||
if parsed_args.param_file:
|
||||
with open(parsed_args.param_file) as f:
|
||||
param_yaml = f.read()
|
||||
try:
|
||||
param_yaml = yaml.load(
|
||||
param_yaml, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not param_yaml:
|
||||
raise exceptions.InvalidInput('The parameter file is empty')
|
||||
body[_VNFFG]['attributes'] = {'param_values': param_yaml}
|
||||
tackerV10.update_dict(parsed_args, body[_VNFFG],
|
||||
['tenant_id', 'name', 'vnffgd_id',
|
||||
'symmetrical', 'vnf_mapping', 'description'])
|
||||
return body
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
vnffg = client.create_vnffg(self.args2body(parsed_args))
|
||||
display_columns, columns = _get_columns(vnffg[_VNFFG])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(vnffg[_VNFFG]),
|
||||
columns,
|
||||
formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class DeleteVNFFG(command.Command):
|
||||
_description = _("Delete VNFFG(s).")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteVNFFG, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNFFG,
|
||||
metavar="<VNFFG>",
|
||||
nargs="+",
|
||||
help=_("VNFFG(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.vnffg:
|
||||
try:
|
||||
obj = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, _VNFFG, resource_id)
|
||||
client.delete_vnffg(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': _VNFFG})
|
||||
err_msg = _("\n\nUnable to delete the below"
|
||||
" %s(s):") % _VNFFG
|
||||
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': _VNFFG}))
|
||||
return
|
||||
|
||||
|
||||
class UpdateVNFFG(command.ShowOne):
|
||||
_description = _("Update VNFFG.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(UpdateVNFFG, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNFFG,
|
||||
metavar="<VNFFG>",
|
||||
help=_('VNFFG to update (name or ID)'))
|
||||
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',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=_('Should a reverse path be created for the NFP'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help=_('Set a description for the VNFFG'))
|
||||
return parser
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {_VNFFG: {}}
|
||||
body[_VNFFG]['attributes'] = {}
|
||||
|
||||
client = self.app.client_manager.tackerclient
|
||||
|
||||
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(
|
||||
client, 'vnf', vnf)
|
||||
parsed_args.vnf_mapping = _vnf_mapping
|
||||
|
||||
if parsed_args.vnffgd_template:
|
||||
with open(parsed_args.vnffgd_template) as f:
|
||||
template = f.read()
|
||||
try:
|
||||
template = yaml.load(
|
||||
template, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not template:
|
||||
raise exceptions.InvalidInput('The vnffgd file is empty')
|
||||
body[_VNFFG]['vnffgd_template'] = template
|
||||
|
||||
if parsed_args.param_file:
|
||||
with open(parsed_args.param_file) as f:
|
||||
param_yaml = f.read()
|
||||
try:
|
||||
param_yaml = yaml.load(
|
||||
param_yaml, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not param_yaml:
|
||||
raise exceptions.InvalidInput('The parameter file is empty')
|
||||
body[_VNFFG]['attributes'] = {'param_values': param_yaml}
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['vnf_mapping', 'symmetrical', 'description'])
|
||||
return body
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
obj_id = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, _VNFFG, parsed_args.vnffg)
|
||||
vnffg = client.update_vnffg(obj_id, self.args2body(parsed_args))
|
||||
display_columns, columns = _get_columns(vnffg[_VNFFG])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(vnffg[_VNFFG]),
|
||||
columns,
|
||||
formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class ListVNFFG(command.Lister):
|
||||
_description = ("List VNFFG(s) that belong to a given tenant.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListVNFFG, 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_vnffgs()
|
||||
headers, columns = tacker_osc_utils.get_column_definitions(
|
||||
_attr_map_vnffg, long_listing=parsed_args.long)
|
||||
return (headers,
|
||||
(utils.get_dict_properties(
|
||||
s, columns,
|
||||
) for s in data[_VNFFG + 's']))
|
||||
|
||||
|
||||
class ShowVNFFG(command.ShowOne):
|
||||
_description = _("Display VNFFG details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowVNFFG, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNFFG,
|
||||
metavar="<VNFFG>",
|
||||
help=_('VNFFG 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, _VNFFG, parsed_args.vnffg)
|
||||
obj = client.show_vnffg(obj_id)
|
||||
display_columns, columns = _get_columns(obj[_VNFFG])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_VNFFG]),
|
||||
columns,
|
||||
formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class ListNFP(command.Lister):
|
||||
_description = ("List NFP(s) that belong to a given tenant.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListNFP, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--vnffg-id',
|
||||
help=_('List NFP(s) with specific VNFFG ID'))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
_params = {}
|
||||
if parsed_args.vnffg_id:
|
||||
_params['vnffg_id'] = parsed_args.vnffg_id
|
||||
nfps = client.list('nfps', nfps_path, True, **_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'] += '...'
|
||||
data = {}
|
||||
data['nfps'] = nfps['nfps']
|
||||
data = client.list_nfps()
|
||||
headers, columns = tacker_osc_utils.get_column_definitions(
|
||||
_attr_map_nfp, long_listing=None)
|
||||
return (headers,
|
||||
(utils.get_dict_properties(
|
||||
s, columns,
|
||||
) for s in data[_NFP + 's']))
|
||||
|
||||
|
||||
class ShowNFP(command.ShowOne):
|
||||
_description = _("Display NFP details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowNFP, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_NFP,
|
||||
metavar="<NFP>",
|
||||
help=_('NFP 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, _NFP, parsed_args.nfp)
|
||||
obj = client.show_nfp(obj_id)
|
||||
display_columns, columns = _get_columns(obj[_NFP])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_NFP]),
|
||||
columns)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class ListFC(command.Lister):
|
||||
_description = ("List flow classifier(s) that belong to a given tenant.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListFC, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--nfp-id',
|
||||
help=_('List flow classifier(s) with specific nfp id'))
|
||||
parser.add_argument(
|
||||
'--tenant-id', metavar='TENANT_ID',
|
||||
help=_('The owner tenant ID or project ID'))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
_params = {}
|
||||
if parsed_args.nfp_id:
|
||||
_params['nfp_id'] = parsed_args.nfp_id
|
||||
if parsed_args.tenant_id:
|
||||
_params['tenant_id'] = parsed_args.tenant_id
|
||||
classifiers = client.list('classifiers', fcs_path, True,
|
||||
**_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'] += '...'
|
||||
data = {}
|
||||
data['classifiers'] = classifiers['classifiers']
|
||||
data = client.list_classifiers()
|
||||
headers, columns = tacker_osc_utils.get_column_definitions(
|
||||
_attr_map_fc, long_listing=None)
|
||||
return (headers,
|
||||
(utils.get_dict_properties(
|
||||
s, columns,
|
||||
) for s in data[_FC + 's']))
|
||||
|
||||
|
||||
class ShowFC(command.ShowOne):
|
||||
_description = _("Display flow classifier details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowFC, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_FC,
|
||||
metavar="<Classifier ID>",
|
||||
help=_('Flow Classifier 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, _FC, parsed_args.classifier)
|
||||
obj = client.show_classifier(obj_id)
|
||||
display_columns, columns = _get_columns(obj[_FC])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_FC]),
|
||||
columns,
|
||||
formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class ListSFC(command.Lister):
|
||||
_description = ("List SFC(s) that belong to a given tenant.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListSFC, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--nfp-id',
|
||||
help=_('List SFC(s) with specific nfp id'))
|
||||
parser.add_argument(
|
||||
'--tenant-id', metavar='TENANT_ID',
|
||||
help=_('The owner tenant ID or project ID'))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
_params = {}
|
||||
if parsed_args.nfp_id:
|
||||
_params['nfp_id'] = parsed_args.nfp_id
|
||||
if parsed_args.tenant_id:
|
||||
_params['tenant_id'] = parsed_args.tenant_id
|
||||
sfcs = client.list('sfcs', sfcs_path, True, **_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'] += '...'
|
||||
data = {}
|
||||
data['sfcs'] = sfcs['sfcs']
|
||||
headers, columns = tacker_osc_utils.get_column_definitions(
|
||||
_attr_map_sfc, long_listing=None)
|
||||
return (headers,
|
||||
(utils.get_dict_properties(
|
||||
s, columns,
|
||||
) for s in data[_SFC + 's']))
|
||||
|
||||
|
||||
class ShowSFC(command.ShowOne):
|
||||
_description = _("Display SFC details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowSFC, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_SFC,
|
||||
metavar="<SFC>",
|
||||
help=_('SFC 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, _SFC, parsed_args.sfc)
|
||||
obj = client.show_sfc(obj_id)
|
||||
display_columns, columns = _get_columns(obj[_SFC])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_SFC]),
|
||||
columns,
|
||||
formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
216
tackerclient/osc/v1/nfvo/vnffgd.py
Normal file
216
tackerclient/osc/v1/nfvo/vnffgd.py
Normal file
@@ -0,0 +1,216 @@
|
||||
# Copyright 2018 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.
|
||||
#
|
||||
|
||||
import yaml
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import utils
|
||||
|
||||
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
|
||||
|
||||
_attr_map = (
|
||||
('id', 'ID', tacker_osc_utils.LIST_BOTH),
|
||||
('name', 'Name', tacker_osc_utils.LIST_BOTH),
|
||||
('template_source', 'Template_Source',
|
||||
tacker_osc_utils.LIST_BOTH),
|
||||
('description', 'Description', tacker_osc_utils.LIST_BOTH),
|
||||
)
|
||||
|
||||
_VNFFGD = "vnffgd"
|
||||
|
||||
_formatters = {
|
||||
'template': 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)
|
||||
|
||||
|
||||
class CreateVNFFGD(command.ShowOne):
|
||||
_description = _("Create a new VNFFGD")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CreateVNFFGD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help=_('Name for VNFFGD'))
|
||||
parser.add_argument(
|
||||
'--tenant-id', metavar='TENANT_ID',
|
||||
help=_('The owner tenant ID or project ID'))
|
||||
parser.add_argument(
|
||||
'--vnffgd-file',
|
||||
required=True,
|
||||
help=_('YAML file with VNFFGD parameters'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help=_('Set a description for the VNFFGD'))
|
||||
return parser
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {_VNFFGD: {}}
|
||||
vnffgd = None
|
||||
if not parsed_args.vnffgd_file:
|
||||
raise exceptions.InvalidInput("Invalid input for vnffgd file")
|
||||
with open(parsed_args.vnffgd_file) as f:
|
||||
vnffgd = f.read()
|
||||
try:
|
||||
vnffgd = yaml.load(vnffgd, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not vnffgd:
|
||||
raise exceptions.InvalidInput("vnffgd file is empty")
|
||||
body[_VNFFGD]['template'] = {'vnffgd': vnffgd}
|
||||
tackerV10.update_dict(parsed_args, body[_VNFFGD],
|
||||
['tenant_id', 'name', 'description'])
|
||||
return body
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
vnffgd = client.create_vnffgd(self.args2body(parsed_args))
|
||||
display_columns, columns = _get_columns(vnffgd[_VNFFGD])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(vnffgd[_VNFFGD]),
|
||||
columns, formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class DeleteVNFFGD(command.Command):
|
||||
_description = _("Delete VNFFGD(s).")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteVNFFGD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNFFGD,
|
||||
metavar="<VNFFGD>",
|
||||
nargs="+",
|
||||
help=_("VNFFGD(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.vnffgd:
|
||||
try:
|
||||
obj = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, _VNFFGD, resource_id)
|
||||
client.delete_vnffgd(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': _VNFFGD})
|
||||
err_msg = _("\n\nUnable to delete the below"
|
||||
" %s(s):") % _VNFFGD
|
||||
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': _VNFFGD}))
|
||||
return
|
||||
|
||||
|
||||
class ListVNFFGD(command.Lister):
|
||||
_description = ("List (VNFFGD)s that belong to a given tenant.")
|
||||
|
||||
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 take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
data = client.list_vnffgds()
|
||||
headers, columns = tacker_osc_utils.get_column_definitions(
|
||||
_attr_map, long_listing=None)
|
||||
return (headers,
|
||||
(utils.get_dict_properties(
|
||||
s, columns,
|
||||
) for s in data[_VNFFGD + 's']))
|
||||
|
||||
|
||||
class ShowVNFFGD(command.ShowOne):
|
||||
_description = _("Display VNFFGD details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowVNFFGD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNFFGD,
|
||||
metavar="<VNFFGD>",
|
||||
help=_("VNFFGD 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, _VNFFGD, parsed_args.vnffgd)
|
||||
obj = client.show_vnffgd(obj_id)
|
||||
display_columns, columns = _get_columns(obj[_VNFFGD])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_VNFFGD]),
|
||||
columns, formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class ShowTemplateVNFFGD(command.ShowOne):
|
||||
_description = _("Display VNFFGD Template details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowTemplateVNFFGD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNFFGD,
|
||||
metavar="<VNFFGD>",
|
||||
help=_("VNFFGD 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, _VNFFGD, parsed_args.vnffgd)
|
||||
obj = client.show_vnffgd(obj_id)
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_VNFFGD]),
|
||||
(u'template',),
|
||||
formatters=_formatters)
|
||||
data = (data or _('Unable to display VNFFGD template!'))
|
||||
return ((u'template',), data)
|
||||
0
tackerclient/osc/v1/vnfm/__init__.py
Normal file
0
tackerclient/osc/v1/vnfm/__init__.py
Normal file
442
tackerclient/osc/v1/vnfm/vnf.py
Normal file
442
tackerclient/osc/v1/vnfm/vnf.py
Normal file
@@ -0,0 +1,442 @@
|
||||
# Copyright 2018 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.
|
||||
#
|
||||
|
||||
import yaml
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import utils
|
||||
|
||||
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
|
||||
|
||||
_attr_map = (
|
||||
('id', 'ID', tacker_osc_utils.LIST_BOTH),
|
||||
('name', 'Name', tacker_osc_utils.LIST_BOTH),
|
||||
('mgmt_url', 'Mgmt Url',
|
||||
tacker_osc_utils.LIST_BOTH),
|
||||
('status', 'Status', tacker_osc_utils.LIST_BOTH),
|
||||
('vim_id', 'VIM ID', tacker_osc_utils.LIST_BOTH),
|
||||
('vnfd_id', 'VNFD ID', tacker_osc_utils.LIST_BOTH),
|
||||
('tenant_id', 'Project ID', tacker_osc_utils.LIST_LONG_ONLY),
|
||||
)
|
||||
|
||||
_attr_map_rsc = (
|
||||
('id', 'ID', tacker_osc_utils.LIST_BOTH),
|
||||
('name', 'Name', tacker_osc_utils.LIST_BOTH),
|
||||
('type', 'Type', tacker_osc_utils.LIST_BOTH),
|
||||
)
|
||||
|
||||
_VNF = "vnf"
|
||||
|
||||
|
||||
def _get_columns(item):
|
||||
column_map = {
|
||||
'tenant_id': 'project_id',
|
||||
}
|
||||
return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
|
||||
|
||||
|
||||
def _break_string(vnf_monitoring_policy):
|
||||
count_space = 0
|
||||
monitoring_policy = "\n"
|
||||
for i in range(0, len(vnf_monitoring_policy)):
|
||||
monitoring_policy += vnf_monitoring_policy[i]
|
||||
if vnf_monitoring_policy[i] == ' ':
|
||||
count_space += 1
|
||||
if count_space == 9:
|
||||
monitoring_policy += "\n"
|
||||
count_space = 0
|
||||
return monitoring_policy
|
||||
|
||||
|
||||
class CreateVNF(command.ShowOne):
|
||||
_description = _("Create a new VNF")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CreateVNF, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help=_('Set a name for the VNF'))
|
||||
parser.add_argument(
|
||||
'--tenant-id', metavar='TENANT_ID',
|
||||
help=_('The owner tenant ID or project ID'))
|
||||
vnfd_group = parser.add_mutually_exclusive_group(required=True)
|
||||
vnfd_group.add_argument(
|
||||
'--vnfd-id',
|
||||
help=_('VNFD ID to use as template to create VNF'))
|
||||
vnfd_group.add_argument(
|
||||
'--vnfd-name',
|
||||
help=_('VNFD Name to use as template to create VNF'))
|
||||
vnfd_group.add_argument(
|
||||
'--vnfd-template',
|
||||
help=_("VNFD file to create VNF"))
|
||||
vim_group = parser.add_mutually_exclusive_group()
|
||||
vim_group.add_argument(
|
||||
'--vim-id',
|
||||
help=_('VIM ID to deploy VNF on specified VIM'))
|
||||
vim_group.add_argument(
|
||||
'--vim-name',
|
||||
help=_('VIM name to deploy VNF on specified VIM'))
|
||||
parser.add_argument(
|
||||
'--vim-region-name',
|
||||
help=_('VIM Region to deploy VNF on specified VIM'))
|
||||
parser.add_argument(
|
||||
'--config-file',
|
||||
help=_('YAML file with VNF configuration'))
|
||||
parser.add_argument(
|
||||
'--param-file',
|
||||
help=_('Specify parameter yaml file'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help=_('Set description for the VNF'))
|
||||
return parser
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {_VNF: {}}
|
||||
body[_VNF]['attributes'] = {}
|
||||
|
||||
config = None
|
||||
if parsed_args.config_file:
|
||||
with open(parsed_args.config_file) as f:
|
||||
config_yaml = f.read()
|
||||
try:
|
||||
config = yaml.load(
|
||||
config_yaml, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if config:
|
||||
body[_VNF]['attributes'] = {'config': config}
|
||||
|
||||
if parsed_args.vim_region_name:
|
||||
body[_VNF].setdefault('placement_attr', {})['region_name'] = \
|
||||
parsed_args.vim_region_name
|
||||
|
||||
client = self.app.client_manager.tackerclient
|
||||
if parsed_args.vim_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(client, 'vim',
|
||||
parsed_args.vim_name)
|
||||
parsed_args.vim_id = _id
|
||||
if parsed_args.vnfd_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, 'vnfd',
|
||||
parsed_args.vnfd_name
|
||||
)
|
||||
parsed_args.vnfd_id = _id
|
||||
elif parsed_args.vnfd_template:
|
||||
with open(parsed_args.vnfd_template) as f:
|
||||
template = f.read()
|
||||
try:
|
||||
template = yaml.load(
|
||||
template, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not template:
|
||||
raise exceptions.InvalidInput('The vnfd file is empty')
|
||||
body[_VNF]['vnfd_template'] = template
|
||||
|
||||
if parsed_args.param_file:
|
||||
with open(parsed_args.param_file) as f:
|
||||
param_yaml = f.read()
|
||||
try:
|
||||
param_yaml = yaml.load(
|
||||
param_yaml, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not param_yaml:
|
||||
raise exceptions.InvalidInput('The parameter file is empty')
|
||||
body[_VNF]['attributes'] = {'param_values': param_yaml}
|
||||
tackerV10.update_dict(parsed_args, body[_VNF],
|
||||
['tenant_id', 'name', 'description',
|
||||
'vnfd_id', 'vim_id'])
|
||||
return body
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
vnf = client.create_vnf(self.args2body(parsed_args))
|
||||
display_columns, columns = _get_columns(vnf[_VNF])
|
||||
if vnf[_VNF]['attributes'].get('monitoring_policy'):
|
||||
vnf[_VNF]['attributes']['monitoring_policy'] =\
|
||||
_break_string(vnf[_VNF]['attributes']['monitoring_policy'])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(vnf[_VNF]),
|
||||
columns)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class DeleteVNF(command.Command):
|
||||
_description = _("Delete VNF(s).")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteVNF, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNF,
|
||||
metavar="<VNF>",
|
||||
nargs="+",
|
||||
help=_("VNF(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.vnf:
|
||||
try:
|
||||
obj = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, _VNF, resource_id)
|
||||
client.delete_vnf(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': _VNF})
|
||||
err_msg = _("\n\nUnable to delete the below"
|
||||
" %s(s):") % _VNF
|
||||
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': _VNF}))
|
||||
return
|
||||
|
||||
|
||||
class ListVNF(command.Lister):
|
||||
_description = _("List VNF(s) that belong to a given tenant.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListVNF, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--template-source',
|
||||
help=_("List VNF with specified template source. Available \
|
||||
options are 'onboarded' (default), 'inline' or 'all'"),
|
||||
action='store',
|
||||
default='onboarded')
|
||||
vim_group = parser.add_mutually_exclusive_group()
|
||||
vim_group.add_argument(
|
||||
'--vim-id',
|
||||
help=_('List VNF(s) that belong to a given VIM ID'))
|
||||
vim_group.add_argument(
|
||||
'--vim-name',
|
||||
help=_('List VNF(s) that belong to a given VIM Name'))
|
||||
vnfd_group = parser.add_mutually_exclusive_group()
|
||||
vnfd_group.add_argument(
|
||||
'--vnfd-id',
|
||||
help=_('List VNF(s) that belong to a given VNFD ID'))
|
||||
vnfd_group.add_argument(
|
||||
'--vnfd-name',
|
||||
help=_('List VNF(s) that belong to a given VNFD Name'))
|
||||
parser.add_argument(
|
||||
'--tenant-id', metavar='TENANT_ID',
|
||||
help=_('The owner tenant ID or project ID'))
|
||||
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
|
||||
_params = {}
|
||||
if parsed_args.vim_id:
|
||||
_params['vim_id'] = parsed_args.vim_id
|
||||
if parsed_args.vim_name:
|
||||
vim_id = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, 'vim', parsed_args.vim_name
|
||||
)
|
||||
_params['vim_id'] = vim_id
|
||||
if parsed_args.vnfd_id:
|
||||
_params['vnfd_id'] = parsed_args.vnfd_id
|
||||
if parsed_args.vnfd_name:
|
||||
vim_id = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, 'vnfd', parsed_args.vnfd_name
|
||||
)
|
||||
_params['vnfd_id'] = vim_id
|
||||
if parsed_args.tenant_id:
|
||||
_params['tenant_id'] = parsed_args.tenant_id
|
||||
data = client.list_vnfs(**_params)
|
||||
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[_VNF + 's']))
|
||||
|
||||
|
||||
class ShowVNF(command.ShowOne):
|
||||
_description = _("Display VNF details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowVNF, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNF,
|
||||
metavar="<VNF>",
|
||||
help=_("VNF 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, _VNF, parsed_args.vnf)
|
||||
obj = client.show_vnf(obj_id)
|
||||
if obj[_VNF]['attributes'].get('monitoring_policy'):
|
||||
obj[_VNF]['attributes']['monitoring_policy'] =\
|
||||
_break_string(obj[_VNF]['attributes']['monitoring_policy'])
|
||||
display_columns, columns = _get_columns(obj[_VNF])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_VNF]),
|
||||
columns)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class ListVNFResources(command.Lister):
|
||||
_description = _("List resources of a VNF like VDU, CP, etc.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListVNFResources, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNF,
|
||||
metavar="<VNF>",
|
||||
help=_("VNF 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, _VNF, parsed_args.vnf)
|
||||
data = client.list_vnf_resources(obj_id)
|
||||
headers, columns = tacker_osc_utils.get_column_definitions(
|
||||
_attr_map_rsc, long_listing=None)
|
||||
return (headers,
|
||||
(utils.get_dict_properties(
|
||||
s, columns,
|
||||
) for s in data['resources']))
|
||||
|
||||
|
||||
class UpdateVNF(command.ShowOne):
|
||||
_description = _("Update a given VNF.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(UpdateVNF, self).get_parser(prog_name)
|
||||
config_group = parser.add_mutually_exclusive_group(required=True)
|
||||
config_group.add_argument(
|
||||
'--config-file',
|
||||
help=_('YAML file with VNF configuration'))
|
||||
config_group.add_argument(
|
||||
'--config',
|
||||
help=_('Specify config YAML data'))
|
||||
parser.add_argument(
|
||||
_VNF,
|
||||
metavar="<VNF>",
|
||||
help=_("VNF to update (name or ID)"))
|
||||
return parser
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {_VNF: {}}
|
||||
body[_VNF]['attributes'] = {}
|
||||
|
||||
config = None
|
||||
if parsed_args.config_file:
|
||||
with open(parsed_args.config_file) as f:
|
||||
config_yaml = f.read()
|
||||
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')
|
||||
try:
|
||||
config = yaml.load(config_str, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if config:
|
||||
body[_VNF]['attributes'] = {'config': config}
|
||||
tackerV10.update_dict(parsed_args, body[_VNF])
|
||||
return body
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
obj_id = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, _VNF, parsed_args.vnf)
|
||||
vnf = client.update_vnf(obj_id, self.args2body(parsed_args))
|
||||
if vnf[_VNF]['attributes'].get('monitoring_policy'):
|
||||
vnf[_VNF]['attributes']['monitoring_policy'] =\
|
||||
_break_string(vnf[_VNF]['attributes']['monitoring_policy'])
|
||||
display_columns, columns = _get_columns(vnf[_VNF])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(vnf[_VNF]),
|
||||
columns)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class ScaleVNF(command.ShowOne):
|
||||
_description = _("Scale a VNF.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ScaleVNF, self).get_parser(prog_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"'))
|
||||
parser.add_argument(
|
||||
_VNF,
|
||||
metavar="<VNF>",
|
||||
help=_("VNF to scale (name or ID)"))
|
||||
return parser
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
args = {}
|
||||
body = {"scale": args}
|
||||
client = self.app.client_manager.tackerclient
|
||||
client.format = parsed_args.request_format
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, 'vnf',
|
||||
parsed_args.vnf)
|
||||
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
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
obj_id = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, _VNF, parsed_args.vnf)
|
||||
vnf = client.scale_vnf(obj_id, self.args2body(parsed_args))
|
||||
if vnf[_VNF]['attributes'].get('monitoring_policy'):
|
||||
vnf[_VNF]['attributes']['monitoring_policy'] =\
|
||||
_break_string(vnf[_VNF]['attributes']['monitoring_policy'])
|
||||
display_columns, columns = _get_columns(vnf[_VNF])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(vnf[_VNF]),
|
||||
columns)
|
||||
return (display_columns, data)
|
||||
223
tackerclient/osc/v1/vnfm/vnfd.py
Normal file
223
tackerclient/osc/v1/vnfm/vnfd.py
Normal file
@@ -0,0 +1,223 @@
|
||||
# Copyright 2016 NEC Corporation.
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
import yaml
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import utils
|
||||
|
||||
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
|
||||
|
||||
_attr_map = (
|
||||
('id', 'ID', tacker_osc_utils.LIST_BOTH),
|
||||
('name', 'Name', tacker_osc_utils.LIST_BOTH),
|
||||
('template_source', 'Template_Source',
|
||||
tacker_osc_utils.LIST_BOTH),
|
||||
('description', 'Description', tacker_osc_utils.LIST_BOTH),
|
||||
)
|
||||
|
||||
_VNFD = "vnfd"
|
||||
|
||||
_formatters = {
|
||||
'attributes': 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)
|
||||
|
||||
|
||||
class CreateVNFD(command.ShowOne):
|
||||
_description = _("Create a new VNFD")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CreateVNFD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help=_('Name for VNFD'))
|
||||
parser.add_argument(
|
||||
'--tenant-id', metavar='TENANT_ID',
|
||||
help=_('The owner tenant ID or project ID'))
|
||||
parser.add_argument(
|
||||
'--vnfd-file',
|
||||
required=True,
|
||||
help=_('YAML file with VNFD parameters'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help=_('Set a description for the VNFD'))
|
||||
return parser
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {_VNFD: {}}
|
||||
vnfd = None
|
||||
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)
|
||||
except yaml.YAMLError as e:
|
||||
raise exceptions.InvalidInput(e)
|
||||
if not vnfd:
|
||||
raise exceptions.InvalidInput("vnfd file is empty")
|
||||
body[_VNFD]['attributes'] = {'vnfd': vnfd}
|
||||
tackerV10.update_dict(parsed_args, body[_VNFD],
|
||||
['tenant_id', 'name', 'description'])
|
||||
return body
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
vnfd = client.create_vnfd(self.args2body(parsed_args))
|
||||
display_columns, columns = _get_columns(vnfd[_VNFD])
|
||||
vnfd[_VNFD]['attributes']['vnfd'] = yaml.load(
|
||||
vnfd[_VNFD]['attributes']['vnfd'])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(vnfd[_VNFD]),
|
||||
columns, formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class DeleteVNFD(command.Command):
|
||||
_description = _("Delete VNFD(s).")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteVNFD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNFD,
|
||||
metavar="<VNFD>",
|
||||
nargs="+",
|
||||
help=_("VNFD(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.vnfd:
|
||||
try:
|
||||
obj = tackerV10.find_resourceid_by_name_or_id(
|
||||
client, _VNFD, resource_id)
|
||||
client.delete_vnfd(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': _VNFD})
|
||||
err_msg = _("\n\nUnable to delete the below"
|
||||
" %s(s):") % _VNFD
|
||||
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': _VNFD}))
|
||||
return
|
||||
|
||||
|
||||
class ListVNFD(command.Lister):
|
||||
_description = ("List (VNFD)s that belong to a given tenant.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListVNFD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--template-source',
|
||||
help=_("List VNFD with specified template source. Available \
|
||||
options are 'onboarded' (default), 'inline' or 'all'"),
|
||||
action='store',
|
||||
default='onboarded')
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
data = client.list_vnfds()
|
||||
headers, columns = tacker_osc_utils.get_column_definitions(
|
||||
_attr_map, long_listing=None)
|
||||
return (headers,
|
||||
(utils.get_dict_properties(
|
||||
s, columns,
|
||||
) for s in data[_VNFD + 's']))
|
||||
|
||||
|
||||
class ShowVNFD(command.ShowOne):
|
||||
_description = _("Display VNFD details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowVNFD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNFD,
|
||||
metavar="<VNFD>",
|
||||
help=_("VNFD 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, _VNFD, parsed_args.vnfd)
|
||||
obj = client.show_vnfd(obj_id)
|
||||
obj[_VNFD]['attributes']['vnfd'] = yaml.load(
|
||||
obj[_VNFD]['attributes']['vnfd'])
|
||||
display_columns, columns = _get_columns(obj[_VNFD])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_VNFD]),
|
||||
columns,
|
||||
formatters=_formatters)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class ShowTemplateVNFD(command.ShowOne):
|
||||
_description = _("Display VNFD Template details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowTemplateVNFD, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNFD,
|
||||
metavar="<VNFD>",
|
||||
help=_("VNFD 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, _VNFD, parsed_args.vnfd)
|
||||
obj = client.show_vnfd(obj_id)
|
||||
obj[_VNFD]['attributes']['vnfd'] = yaml.load(
|
||||
obj[_VNFD]['attributes']['vnfd'])
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj[_VNFD]),
|
||||
(u'attributes',),
|
||||
formatters=_formatters)
|
||||
data = (data or _('Unable to display VNFD template!'))
|
||||
return ((u'attributes',), data)
|
||||
@@ -50,6 +50,7 @@ from tackerclient.tacker.v1_0 import extension
|
||||
from tackerclient.tacker.v1_0.nfvo import ns
|
||||
from tackerclient.tacker.v1_0.nfvo import nsd
|
||||
from tackerclient.tacker.v1_0.nfvo import vim
|
||||
from tackerclient.tacker.v1_0.nfvo import vnfcluster
|
||||
from tackerclient.tacker.v1_0.nfvo import vnffg
|
||||
from tackerclient.tacker.v1_0.nfvo import vnffgd
|
||||
from tackerclient.tacker.v1_0.vnfm import vnf
|
||||
@@ -168,6 +169,16 @@ COMMAND_V1 = {
|
||||
'ns-list': ns.ListNS,
|
||||
'ns-delete': ns.DeleteNS,
|
||||
'ns-show': ns.ShowNS,
|
||||
|
||||
'cluster-create': vnfcluster.CreateCluster,
|
||||
'cluster-delete': vnfcluster.DeleteCluster,
|
||||
'cluster-list': vnfcluster.ListCluster,
|
||||
'cluster-show': vnfcluster.ShowCluster,
|
||||
|
||||
'cluster-member-add': vnfcluster.AddClusterMember,
|
||||
'cluster-member-show': vnfcluster.ShowClusterMember,
|
||||
'cluster-member-list': vnfcluster.ListClusterMember,
|
||||
'cluster-member-delete': vnfcluster.DeleteClusterMember,
|
||||
}
|
||||
|
||||
COMMANDS = {'1.0': COMMAND_V1}
|
||||
|
||||
@@ -74,16 +74,9 @@ def args2body_vim(config_param, vim):
|
||||
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)
|
||||
ssl_ca_cert = config_param.pop('ssl_ca_cert', '')
|
||||
if ssl_ca_cert:
|
||||
vim['auth_cred']['ssl_ca_cert'] = ssl_ca_cert
|
||||
|
||||
|
||||
def validate_auth_url(url):
|
||||
|
||||
191
tackerclient/tacker/v1_0/nfvo/vnfcluster.py
Normal file
191
tackerclient/tacker/v1_0/nfvo/vnfcluster.py
Normal file
@@ -0,0 +1,191 @@
|
||||
# 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
|
||||
import yaml
|
||||
|
||||
_CLUSTER = 'cluster'
|
||||
_CLUSTER_MEMBER = 'clustermember'
|
||||
|
||||
|
||||
class ListCluster(tackerV10.ListCommand):
|
||||
"""List Clusters that belong to a given tenant."""
|
||||
|
||||
resource = _CLUSTER
|
||||
list_columns = ['id', 'name', 'vnfd_id', 'status', 'vip_endpoint']
|
||||
|
||||
|
||||
class ShowCluster(tackerV10.ShowCommand):
|
||||
"""Show information of a given Cluster."""
|
||||
|
||||
resource = _CLUSTER
|
||||
|
||||
|
||||
class DeleteCluster(tackerV10.DeleteCommand):
|
||||
"""Delete a given Cluster."""
|
||||
|
||||
resource = _CLUSTER
|
||||
|
||||
|
||||
class CreateCluster(tackerV10.CreateCommand):
|
||||
"""Create a Cluster."""
|
||||
|
||||
resource = _CLUSTER
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help='Set a name for the VNF cluster')
|
||||
vnfd_group = parser.add_mutually_exclusive_group(required=True)
|
||||
vnfd_group.add_argument(
|
||||
'--vnfd-id',
|
||||
help='VNFD ID to use as template to create member VNF')
|
||||
vnfd_group.add_argument(
|
||||
'--vnfd-name',
|
||||
help='VNFD name to use as template to create member VNF')
|
||||
parser.add_argument('--policy-file',
|
||||
help='Specify policy file for cluster',
|
||||
required=True)
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help='Set a description for the created VNF cluster')
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {self.resource: {}}
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
|
||||
if parsed_args.vnfd_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
'vnfd',
|
||||
parsed_args.
|
||||
vnfd_name)
|
||||
parsed_args.vnfd_id = _id
|
||||
policy_info = None
|
||||
with open(parsed_args.policy_file) as f:
|
||||
policy_info = yaml.safe_load(f.read())
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'vnfd_id', 'description'])
|
||||
if policy_info:
|
||||
body[self.resource]['policy_info'] = policy_info
|
||||
return body
|
||||
|
||||
|
||||
class AddClusterMember(tackerV10.CreateCommand):
|
||||
"""Add a new Cluster Member to given Cluster."""
|
||||
|
||||
resource = _CLUSTER_MEMBER
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'name', metavar='NAME',
|
||||
help='Set a name for the VNF cluster member')
|
||||
cluster_group = parser.add_mutually_exclusive_group()
|
||||
cluster_group.add_argument(
|
||||
'--cluster-id',
|
||||
help='VNFD ID to use as template to create member VNF')
|
||||
cluster_group.add_argument(
|
||||
'--cluster-name',
|
||||
help='VNFD name to use as template to create member VNF')
|
||||
vnfd_group = parser.add_mutually_exclusive_group()
|
||||
vnfd_group.add_argument(
|
||||
'--vnfd-id',
|
||||
help='Set a id for the VNFD')
|
||||
vnfd_group.add_argument(
|
||||
'--vnfd-name',
|
||||
help='Set a name for the VNFD')
|
||||
parser.add_argument(
|
||||
'--role',
|
||||
help='Set a [Active/Standby] role to cluster member',
|
||||
required=True)
|
||||
vim_group = parser.add_mutually_exclusive_group()
|
||||
vim_group.add_argument(
|
||||
'--vim-id',
|
||||
help='Set a VIM ID to deploy cluster member')
|
||||
vim_group.add_argument(
|
||||
'--vim-name',
|
||||
help='Set a VIM name to deploy cluster member')
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {self.resource: {}}
|
||||
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
if parsed_args.cluster_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
'cluster',
|
||||
parsed_args.
|
||||
cluster_name)
|
||||
parsed_args.cluster_id = _id
|
||||
if parsed_args.vnfd_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
'vnfd',
|
||||
parsed_args.
|
||||
vnfd_name)
|
||||
parsed_args.vnfd_id = _id
|
||||
parsed_args.role = parsed_args.role.upper()
|
||||
if parsed_args.vim_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
'vim',
|
||||
parsed_args.
|
||||
vim_name)
|
||||
parsed_args.vim_id = _id
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'name', 'cluster_id', 'vnfd_id',
|
||||
'role', 'vim_id'])
|
||||
return body
|
||||
|
||||
|
||||
class ListClusterMember(tackerV10.ListCommand):
|
||||
"""List Cluster Members that belong to a given tenant."""
|
||||
|
||||
resource = _CLUSTER_MEMBER
|
||||
|
||||
def add_known_arguments(self, parser):
|
||||
cluster_group = parser.add_mutually_exclusive_group(required=True)
|
||||
cluster_group.add_argument(
|
||||
'--cluster-id',
|
||||
help='Set a ID for the queried cluster')
|
||||
cluster_group.add_argument(
|
||||
'--cluster-name',
|
||||
help='Set a name for the queried cluster')
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
body = {self.resource: {}}
|
||||
tacker_client = self.get_client()
|
||||
tacker_client.format = parsed_args.request_format
|
||||
|
||||
if parsed_args.cluster_name:
|
||||
_id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
|
||||
'cluster',
|
||||
parsed_args.
|
||||
cluster_name)
|
||||
parsed_args.cluster_id = _id
|
||||
|
||||
tackerV10.update_dict(parsed_args, body[self.resource],
|
||||
['tenant_id', 'cluster_id'])
|
||||
return body
|
||||
|
||||
list_columns = ['id', 'name', 'cluster_id', 'role', 'vnf_id',
|
||||
'vim_id', 'mgmt_url', 'lb_member_id']
|
||||
|
||||
|
||||
class DeleteClusterMember(tackerV10.DeleteCommand):
|
||||
"""Delete a given Cluster Member."""
|
||||
|
||||
resource = _CLUSTER_MEMBER
|
||||
|
||||
|
||||
class ShowClusterMember(tackerV10.ShowCommand):
|
||||
"""Show information of a given Cluster Member."""
|
||||
|
||||
resource = _CLUSTER_MEMBER
|
||||
@@ -163,7 +163,7 @@ class CLITestAuthKeystone(testtools.TestCase):
|
||||
self.client.auth_token = TOKEN
|
||||
self.client.endpoint_url = ENDPOINT_URL
|
||||
|
||||
# If a token is expired, tacker server retruns 401
|
||||
# If a token is expired, tacker server returns 401
|
||||
mock_request.return_value = (resp_401, '')
|
||||
self.assertRaises(exceptions.Unauthorized,
|
||||
self.client.do_request,
|
||||
@@ -184,7 +184,7 @@ class CLITestAuthKeystone(testtools.TestCase):
|
||||
self.client.auth_token = TOKEN
|
||||
self.client.endpoint_url = ENDPOINT_URL
|
||||
|
||||
# If a token is expired, tacker server retruns 401
|
||||
# If a token is expired, tacker server returns 401
|
||||
mock_request.return_value = (resp_401, '')
|
||||
self.assertRaises(exceptions.NoAuthURLProvided,
|
||||
self.client.do_request,
|
||||
|
||||
@@ -35,7 +35,7 @@ class CLITestV10VIMJSON(test_cli10.CLITestV10Base):
|
||||
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_cred = {'bearer_token': 'xyz', 'ssl_ca_cert': "None"}
|
||||
self.auth_url = 'https://1.2.3.4:6443'
|
||||
self.type = 'kubernetes'
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ class TestVIMUtils(testtools.TestCase):
|
||||
|
||||
def test_args2body_kubernetes_vim_bearer(self):
|
||||
config_param = {'bearer_token': sentinel.bearer_token,
|
||||
'ssl_ca_cert': None,
|
||||
'ssl_ca_cert': "None",
|
||||
'project_name': sentinel.prj_name,
|
||||
'type': 'kubernetes'}
|
||||
vim = {}
|
||||
|
||||
@@ -368,6 +368,11 @@ class Client(ClientBase):
|
||||
nss_path = '/nss'
|
||||
ns_path = '/nss/%s'
|
||||
|
||||
clusters_path = '/clusters'
|
||||
cluster_path = '/clusters/%s'
|
||||
cluster_members_path = '/clustermembers'
|
||||
cluster_member_path = '/clustermembers/%s'
|
||||
|
||||
# API has no way to report plurals, so we have to hard code them
|
||||
# EXTED_PLURALS = {}
|
||||
|
||||
@@ -662,3 +667,44 @@ class Client(ClientBase):
|
||||
@APIParamsCall
|
||||
def delete_ns(self, ns):
|
||||
return self.delete(self.ns_path % ns)
|
||||
|
||||
@APIParamsCall
|
||||
def create_cluster(self, body=None):
|
||||
return self.post(self.clusters_path, body)
|
||||
|
||||
@APIParamsCall
|
||||
def list_clusters(self, retrieve_all=True, **_params):
|
||||
clusters = self.list('clusters', self.clusters_path,
|
||||
retrieve_all, **_params)
|
||||
return clusters
|
||||
|
||||
@APIParamsCall
|
||||
def show_cluster(self, cluster, **_params):
|
||||
member = self.get(self.cluster_path % cluster,
|
||||
params=_params)
|
||||
return member
|
||||
|
||||
@APIParamsCall
|
||||
def delete_cluster(self, cluster):
|
||||
return self.delete(self.cluster_path % cluster)
|
||||
|
||||
@APIParamsCall
|
||||
def create_clustermember(self, body=None):
|
||||
return self.post(self.cluster_members_path, body)
|
||||
|
||||
@APIParamsCall
|
||||
def list_clustermembers(self, retrieve_all=True, **_params):
|
||||
cluster_members = self.list('clustermembers',
|
||||
self.cluster_members_path,
|
||||
retrieve_all, **_params)
|
||||
return cluster_members
|
||||
|
||||
@APIParamsCall
|
||||
def show_clustermember(self, clustermember, **_params):
|
||||
member = self.get(self.cluster_member_path % clustermember,
|
||||
params=_params)
|
||||
return member
|
||||
|
||||
@APIParamsCall
|
||||
def delete_clustermember(self, clustermember):
|
||||
return self.delete(self.cluster_member_path % clustermember)
|
||||
|
||||
@@ -5,12 +5,6 @@ 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
|
||||
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>=2.2.0 # MIT
|
||||
oslosphinx>=4.7.0 # Apache-2.0
|
||||
openstackdocstheme>=1.18.1 # Apache-2.0
|
||||
|
||||
# releasenotes
|
||||
reno>=2.5.0 # Apache-2.0
|
||||
mock>=2.0.0 # BSD
|
||||
|
||||
7
tox.ini
7
tox.ini
@@ -1,5 +1,5 @@
|
||||
[tox]
|
||||
envlist = py35,py27,pypy,pep8
|
||||
envlist = py35,py27,pep8,docs
|
||||
minversion = 2.0
|
||||
skipsdist = True
|
||||
|
||||
@@ -24,9 +24,11 @@ distribute = false
|
||||
commands = {posargs}
|
||||
|
||||
[testenv:docs]
|
||||
deps = -r{toxinidir}/doc/requirements.txt
|
||||
commands = sphinx-build -W -b html doc/source doc/build/html
|
||||
|
||||
[testenv:releasenotes]
|
||||
deps = -r{toxinidir}/doc/requirements.txt
|
||||
commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
|
||||
|
||||
[testenv:cover]
|
||||
@@ -37,3 +39,6 @@ commands = python setup.py testr --coverage --testr-args='{posargs}'
|
||||
ignore = E125
|
||||
show-source = true
|
||||
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,tools
|
||||
# F821 undefined name 'unicode'
|
||||
# if isinstance(config, str) or isinstance(config, unicode):
|
||||
builtins = unicode
|
||||
|
||||
Reference in New Issue
Block a user