Compare commits

...

44 Commits
7.3.0 ... 9.0.0

Author SHA1 Message Date
Rodolfo Alonso Hernandez
16a2cd127d Remove CLI warning message
This warning was added in [1]. This patch is partially reverting it
but we keep the release note. This warning message could be a bit
intrusive for those users still using it. In any case, the
recommendation to move to OSC is something already known and
publicly requested.

[1]https://review.opendev.org/c/openstack/python-neutronclient/+/862371

Change-Id: I0c2fba3e45a9de1eba09efcf8919661a855c7e89
2023-02-14 08:30:20 +01:00
elajkat
68cbf56f9c Move network trunk commands from python-neutronclient
The depends-on patch adds trunk commands to OSC, as we can
long consider trunk operations as core Networking operations.

Change-Id: Ie557a5d541cf117d20f3f2b548620a74dbadb383
Depends-On: https://review.opendev.org/c/openstack/python-openstackclient/+/869447
Related-Bug: #1999774
2023-01-16 14:18:27 +01:00
elajkat
33f1c89a84 Tox4: add allowlist_externals where necessary
With tox4 allowlist_externals is more strictly checked, so
fix it where necessary and fix pylint version.

Depends-On: https://review.opendev.org/c/zuul/zuul-jobs/+/866943
Related-Bug: #1999558

Change-Id: Id115a436b95b3ede5a1f3102b4bb9e3ade75c970
2023-01-16 08:34:36 +00:00
Elvira García
776e360e35 Fix help sentence in network log create --enable
As the documentation states [1], the default in network log objects is
to be enabled, not disabled.

[1] https://docs.openstack.org/neutron/latest/admin/config-logging.html

Change-Id: I13e9d1132fc38104e6e85d9c8442bc7506adc2fd
2022-11-25 15:32:46 +01:00
elajkat
f67af3d9be Add warning and reno for SDK
On the 2023.1 (Antelope) PTG we discussed the status of the python
binding (SDK) code in python-neutronclient and decided to not allow new
features to this repo (see [1]), and make users to use openstacksdk.
Let's add a warning log message and a releasenote to make it visible.

[1]: https://etherpad.opendev.org/p/neutron-antelope-ptg#L163

Change-Id: I03317179bd0d30a69b91eef6e451b8e40eb28191
2022-10-21 16:40:38 +02:00
ec84aff516 Switch to 2023.1 Python3 unit tests and generic template name
This is an automatically generated patch to ensure unit testing
is in place for all the of the tested runtimes for antelope. Also,
updating the template name to generic one.

See also the PTI in governance [1].

[1]: https://governance.openstack.org/tc/reference/project-testing-interface.html

Change-Id: I026505ff0d277fd4f15329ed26a5cecf1d573f68
2022-09-14 09:26:48 +00:00
f060429cfc Update master for stable/zed
Add file to the reno documentation build to show release notes for
stable/zed.

Use pbr instruction to increment the minor version number
automatically so that master versions are higher than the versions on
stable/zed.

Sem-Ver: feature
Change-Id: Ie6a0efba406cd26606168ce5b6dbc8ee7ae759ed
2022-09-09 11:48:19 +00:00
Pedro Henrique
7467c710f6 Add support to floating ip port forwarding
To extend Horizon to allow users to create
port forwarding rules for their floating ips,
we need to extend this client to allow it,
as Horizon uses this client.

This patch is the one of a series of patches
to implement floating ip port forwarding with
port ranges.

The specification is defined in:
https://github.com/openstack/neutron-specs/blob/master/specs/wallaby/port-forwarding-port-ranges.rst

Implements: blueprint floatingips-portforwarding-ranges
Related-Bug: #1885921
Change-Id: I3f616dba5e2ebe301cf6ce4bed8c2e6e4da2da9b
2022-07-15 10:06:03 -03:00
Ghanshyam Mann
b720fdaee7 Update python testing as per zed cycle teting runtime
In Zed cycle, we have dropped the python 3.6/3.7[1] testing
and its support. Add release notes, move py36 jobs to py38|9,
and update the python classifier for the same.

[1] https://governance.openstack.org/tc/reference/runtimes/zed.html

Change-Id: Ibeee0b16ee1ea95f05127563a9cb08ffd0f04e2b
2022-05-11 22:25:31 -05:00
Ghanshyam Mann
143db0177a Drop lower-constraints.txt and its testing
As discussed in TC PTG[1] and TC resolution[2], we are
dropping the lower-constraints.txt file and its testing.
We will keep lower bounds in the requirements.txt file but
with a note that these are not tested lower bounds and we
try our best to keep them updated.

[1] https://etherpad.opendev.org/p/tc-zed-ptg#L326
[2] https://governance.openstack.org/tc/resolutions/20220414-drop-lower-constraints.html#proposal

Change-Id: I9a985c439675dc3aa6120a0d9734b8cdeaedccf8
2022-04-30 20:28:29 -05:00
Zuul
8c72cc87da Merge "Update master for stable/yoga" 2022-03-08 12:02:40 +00:00
4575bea5a6 Update master for stable/yoga
Add file to the reno documentation build to show release notes for
stable/yoga.

Use pbr instruction to increment the minor version number
automatically so that master versions are higher than the versions on
stable/yoga.

Sem-Ver: feature
Change-Id: I3f709510026817ae2f36d646ca3fe9487637b717
2022-03-03 10:52:26 +00:00
Rodolfo Alonso Hernandez
28628e8f96 Skip B105 pep8 error: hardcoded passwords
Skip B105 pep8 error:
* https://bandit.readthedocs.io/en/latest/plugins/b105_hardcoded_password_string.html
* https://cwe.mitre.org/data/definitions/259.html

Trivial-Fix

Change-Id: I8e58da2d88d727018c8d5af5949e34f8c0893c1f
2022-03-03 00:26:29 +00:00
Zuul
6ca3341352 Merge "Add support for 'smart-nic' vnic-type" 2022-01-19 23:35:59 +00:00
dengzhaosen
517bef2c54 Update python testing classifier
Yoga testing runtime[1] has been updated to add py39
testing as voting. Unit tests update are handled by the
job template change in openstack-zuul-job

- https://review.opendev.org/c/openstack/openstack-zuul-jobs/+/820286

this commit updates the classifier in setup.cfg file.

[1] https://governance.openstack.org/tc/reference/runtimes/yoga.html

Change-Id: Iedb1c345df99ae9be5cce22ab930c6de7a5e7832
2021-12-24 09:36:50 +08:00
Zuul
d75e1e05b7 Merge "Add CURD actions for packet rate limit rule" 2021-12-06 15:32:48 +00:00
LIU Yulong
a92d8db81c Add CURD actions for packet rate limit rule
Neutron added new QoS rule [1] for packet rate limit.
Neutron fullstack test cases [2] rely on the neutron client
to interact with the neutron-server (API), so for new QoS rule
`packet rate limit`, we add the needed methods for new
cases of the QoS driver testing.

[1] https://docs.openstack.org/api-ref/network/v2/index.html#qos-packet-rate-limit-rules
[2] https://github.com/openstack/neutron/blob/master/neutron/tests/fullstack/resources/process.py#L24

Change-Id: I0ad236c9e585a25fbd405813ac48898a2df897d2
2021-11-24 00:23:08 +00:00
Przemyslaw Szczerbik
3b80135a3d Add support for minimum packet rate rule to the client
With the introduction of QoS minimum packet rate rule in Neutron,
it's important to ensure that tools like Heat support it as well.
Unfortunately, Heat still depends on python-neutronclient instead
of python-openstackclient. So even though QoS minimum packet rate
rule support have been proposed for python-openstackclient [1] and
openstacksdk [2], it's still necessary to extend python-neutronclient
code. Since Heat uses only the client part, can skip CLI support.

[1] https://review.opendev.org/c/openstack/python-openstackclient/+/810559
[2] https://review.opendev.org/c/openstack/openstacksdk/+/810364

Partial-Bug: #1922237
See-Also: https://review.opendev.org/785236
Change-Id: I4f16b963a202a476cd3cd2b69c1dd4e4ee6f0fc7
2021-11-19 08:05:56 +01:00
elajkat
3a65712b45 Fix lower-constraints and neutronclient-functional job
Change decorator in l-c.txt from 3.4.0 to 4.1.0
add neutron as devstack plugin to neutronclient-functional job.

Change-Id: Ib4b98f4e9e70f058ba5c7c43f559ab888edf1a88
2021-11-18 16:25:43 +01:00
Frode Nordahl
1df1f38a91 Add support for 'smart-nic' vnic-type
The 'smart-nic' vnic_type was added in the Train time frame in
I91f63810626ce4e054e358f5de5e46434c4da131.  This vnic_type will
also be used to support off-path SmartNIC port binding with OVN,
and it is expected that the user will create ports with this
vnic_type as part of the workflow.

As such the client must allow users to interact with this
vnic_type and this patch addresses that.

Partial-Bug: #1932154
Change-Id: I7f80bb47db7f8608db4d6a646b0f4b0ef6d6fb48
2021-09-14 14:31:24 +02:00
792ad115b3 Add Python3 yoga unit tests
This is an automatically generated patch to ensure unit testing
is in place for all the of the tested runtimes for yoga.

See also the PTI in governance [1].

[1]: https://governance.openstack.org/tc/reference/project-testing-interface.html

Change-Id: Ib343cb56e2512862d5b23482a9861ba7b3ce6373
2021-09-10 14:33:53 +00:00
ee73a48881 Update master for stable/xena
Add file to the reno documentation build to show release notes for
stable/xena.

Use pbr instruction to increment the minor version number
automatically so that master versions are higher than the versions on
stable/xena.

Sem-Ver: feature
Change-Id: If1185e64ff9e9c2a622f7a41df3993b3fe414b96
2021-09-10 14:33:52 +00:00
Zuul
4b29df7234 Merge "Replace deprecated assertDictContainsSubset" 2021-09-06 12:27:22 +00:00
Takashi Kajinami
cff9c266c0 Replace deprecated assertDictContainsSubset
The method is deprecated since Python 3.2[1] and shows the following
DeprecationWarning.

/usr/lib/python3.9/unittest/case.py:1134: DeprecationWarning:
assertDictContainsSubset is deprecated
  warnings.warn('assertDictContainsSubset is deprecated',

[1] https://docs.python.org/3/whatsnew/3.2.html#unittest

Closes-Bug: #1938103
Change-Id: I1d0ee6c77476707a7e4fe4fbf2b979bf34550d05
2021-09-05 00:56:38 +09:00
Zuul
983f0abc58 Merge "Use yaml.safe_load instead of yaml.load" 2021-09-02 02:27:46 +00:00
Takashi Kajinami
f83108d858 Use yaml.safe_load instead of yaml.load
Since PyYAML 5.1, yaml.load without specifying the Loader option is
deprecated and shows the following warning.

YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated,
as the default Loader is unsafe.
Please read https://msg.pyyaml.org/load for full details.

This change replaces usage of yaml.load by yaml.safe_load, to get rid
of that warning message.

Change-Id: Ibe25c4aaf3aa7226f28ec60b8a929ecc143face1
2021-09-01 17:53:41 +09:00
Zuul
e647baf4ca Merge "Ussuri+ is python3 only and update python to python3" 2021-09-01 07:43:35 +00:00
Bernard Cafarelli
2f047b1595 Set ML2/OVS backend explicitly for functional job
After default backend change to OVN, some client tests related to DHCP
or L3 agents are not working fine. Switch the job to ML2/OVS, as it was
done in openstack-client in changeset
Idf6466a59c6cf96be2f1d53e696f0564584fa233

test_neutron_dhcp_agent_list_hosting_net was skipped temporarily
to pass the gate in the parent commit. It is re-enabled now.

Change-Id: I91d03d13adcd38d46ba1b042239a290ae2c99ea4
Closes-Bug: #1936965
2021-07-27 15:29:10 +09:00
elajkat
23fb666f92 tests: change safe_hasattr to hasattr
testtools 2.5.0 removed the helper (see [0]) safe_hasattr, and assumes
that the hasattr implementation in python reliable enough now.

test_neutron_dhcp_agent_list_hosting_net is skipped temporarily
as there is no DHCP agent with ML2/OVN. It will be re-enabled [1].

[0] https://github.com/testing-cabal/testtools/blob/2.5.0/NEWS#L31
[1] https://review.opendev.org/c/openstack/python-neutronclient/+/801997

Change-Id: I4fe6fabc4f745e2c9a366e30dbea7e7200151f12
2021-07-27 14:56:36 +09:00
dengzhaosen
a1ebfaa7f2 Ussuri+ is python3 only and update python to python3
To remove the useless shebang

Change-Id: I611c5bc47562f8def9a8623117b7b0655474b555
2021-06-24 01:43:09 +00:00
Zuul
adf21f0288 Merge "Changed minversion in tox to 3.18.0" 2021-06-21 18:51:17 +00:00
Akihiro Motoki
ae397565be Add a release note on deprecation for removal of neutron CLI
Change-Id: I866ade23cd76cf1e44e10eeb15dcc02cc8d0dc66
2021-06-09 14:39:43 +09:00
wu.shiming
d6c211c139 Changed minversion in tox to 3.18.0
The patch bumps min version of tox to 3.18.0 in order to
replace tox's whitelist_externals by allowlist_externals option:
https://github.com/tox-dev/tox/blob/master/docs/changelog.rst#v3180-2020-07-23

Change-Id: I83717c5b2661df0d4288699903c38814cefb43d9
2021-06-03 07:00:38 +00:00
Slawek Kaplonski
76dd26f9fd Set when deprecated neutron client CLI will be removed
[1] was the last missing bit in OSC to have feature parity between
OpenStack client and Neutronclient CLI tools.
So now as [1] is merged we can really deprecate and specify that in Z
cycle we will remove neutronclient CLI.
This patch changes deprecation message to reflect that.

[1] https://review.opendev.org/c/openstack/python-openstackclient/+/768210

Change-Id: Ia68af29ea15bda7330fda1b18416798a0f4cb7a4
2021-05-27 12:09:32 +00:00
Slawek Kaplonski
439e290e95 Skip metering functional tests when metering extension is not enabled
Change-Id: I9e3f41a2be56c1fd5fc3aff9af8e5ff5163087bd
2021-05-27 14:07:21 +02:00
likui
10227b681f setup.cfg: Replace dashes with underscores
Setuptools v54.1.0 introduces a warning that the use of
dash-separated options in 'setup.cfg' will not be supported
in a future version [1].
Get ahead of the issue by replacing the dashes with underscores.
Without this, we see 'UserWarning' messages
like the following on new enough
versions of setuptools:

  UserWarning: Usage of dash-separated 'description-file' will not be
  supported in future versions. Please use the underscore name
  'description_file' instead

[1] https://github.com/pypa/setuptools/commit/a2e9ae4cb

Change-Id: I56804844c7438d7a5bffaaa363b9e3d79850c5c2
2021-05-11 17:43:33 +08:00
likui
2c2a1f4de7 Replace getargspec with getfullargspec
inspect.getargspec() is deprecated since py3

[1] https://docs.python.org/3/library/inspect.html#inspect.getargspec

Change-Id: I2ae460a7a7f01d7346d5e51ec6ccb44c22d0c53e
2021-05-10 18:09:17 +08:00
Zuul
f6d147e031 Merge "Support passing mTLS certificate/key to HTTPClient" 2021-03-26 19:51:12 +00:00
Zuul
7a1dca4131 Merge "Add Python3 xena unit tests" 2021-03-24 14:30:45 +00:00
Zuul
26ab1b1d0c Merge "Update master for stable/wallaby" 2021-03-24 08:32:47 +00:00
Elod Illes
d87683b59b Fix lower constraints
This patch updates lower-constraints.txt to eliminate contradictions.

keystoneauth1 lower constraint has to be bumped in requirements.txt as
another dependency, openstacksdk 0.15.0 depends on keystoneauth1>=3.8.0

dogpile.cache version bumped to 0.6.5 as older version had 'async' as
variable name which gives SyntaxError from py37.

Change-Id: I31464518cb7f76c0fa5275a4ef52b2a6b634cfa3
2021-03-19 14:01:54 +01:00
f3756a3d4a Add Python3 xena unit tests
This is an automatically generated patch to ensure unit testing
is in place for all the of the tested runtimes for xena.

See also the PTI in governance [1].

[1]: https://governance.openstack.org/tc/reference/project-testing-interface.html

Change-Id: I8475c835838bbd0d84540cef879b4769581ef06d
2021-03-18 12:56:37 +00:00
12373768da Update master for stable/wallaby
Add file to the reno documentation build to show release notes for
stable/wallaby.

Use pbr instruction to increment the minor version number
automatically so that master versions are higher than the versions on
stable/wallaby.

Sem-Ver: feature
Change-Id: I91d4355bb94ac18a80ff215796cd403be870986a
2021-03-18 12:56:13 +00:00
sri harsha mekala
3140fe014a Support passing mTLS certificate/key to HTTPClient
Change-Id: I00065293daf6b2e5d540e056c05f85b82f8bc72c
2021-03-05 11:48:03 -08:00
39 changed files with 263 additions and 1432 deletions

View File

@@ -1,8 +1,7 @@
- project:
templates:
- openstack-cover-jobs
- openstack-lower-constraints-jobs
- openstack-python3-wallaby-jobs
- openstack-python3-jobs
- publish-openstack-docs-pti
- check-requirements
- lib-forward-testing-python3
@@ -38,10 +37,33 @@
# NOTE: neutronclient.tests.functional.base.ClientTestBase does not
# support HTTPS endpoints now, so tls-proxy needs to be disabled.
tls-proxy: false
# Disable OVN services
br-ex-tcpdump: false
br-int-flows: false
ovn-controller: false
ovn-northd: false
ovs-vswitchd: false
ovsdb-server: false
q-ovn-metadata-agent: false
# Neutron services
q-agt: true
q-dhcp: true
q-l3: true
q-meta: true
neutron-network-segment-range: true
neutron-segments: true
q-metering: true
q-qos: true
neutron-tag-ports-during-bulk-creation: true
neutron-conntrack-helper: true
devstack_localrc:
USE_PYTHON3: true
LIBS_FROM_GIT: python-neutronclient
Q_AGENT: openvswitch
Q_ML2_TENANT_NETWORK_TYPE: vxlan
Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
devstack_plugins:
neutron: https://opendev.org/openstack/neutron
neutron-vpnaas: https://opendev.org/openstack/neutron-vpnaas
- job:

View File

@@ -4,3 +4,4 @@
openstackdocstheme>=2.2.0 # Apache-2.0
reno>=3.1.0 # Apache-2.0
sphinx>=2.0.0,!=2.1.0 # BSD
cliff>=3.4.0 # Apache-2.0

View File

@@ -1,16 +0,0 @@
=============
network trunk
=============
A **network trunk** is a container to group logical ports from different
networks and provide a single trunked vNIC for servers. It consists of
one parent port which is a regular VIF and multiple subports which allow
the server to connect to more networks.
Network v2
.. autoprogram-cliff:: openstack.neutronclient.v2
:command: network subport list
.. autoprogram-cliff:: openstack.neutronclient.v2
:command: network trunk *

View File

@@ -91,17 +91,17 @@ Transition Steps
* **Done** `Security Group Rule CRUD <https://bugs.launchpad.net/python-openstackclient/+bug/1519512>`_
6. **In Progress:** OSC continues enhancing its networking support.
6. **Done** OSC continues enhancing its networking support.
At this point and when applicable, enhancements to the ``neutron``
CLI must also be made to the ``openstack`` CLI and possibly the
OpenStack Python SDK. Users of the neutron client's command extensions
should start their transition to the OSC plugin system. See the
developer guide section below for more information on this step.
7. **In Progress:** Deprecate the ``neutron`` CLI. Running the CLI after
7. **Done** Deprecate the ``neutron`` CLI. Running the CLI after
it has been `deprecated <https://review.opendev.org/#/c/393903/>`_
will issue a warning message:
``neutron CLI is deprecated and will be removed in the future. Use openstack CLI instead.``
``neutron CLI is deprecated and will be removed in the Z cycle. Use openstack CLI instead.``
In addition, no new features will be added to the CLI, though fixes to
the CLI will be assessed on a case by case basis.

View File

@@ -1,111 +0,0 @@
alabaster==0.7.10
amqp==2.1.1
appdirs==1.3.0
asn1crypto==0.23.0
Babel==2.3.4
cachetools==2.0.0
cffi==1.14.0
cliff==3.4.0
cmd2==0.8.0
contextlib2==0.4.0
coverage==4.0
cryptography==2.7
debtcollector==1.2.0
decorator==3.4.0
deprecation==1.0
docutils==0.11
dogpile.cache==0.6.2
dulwich==0.15.0
eventlet==0.18.2
extras==1.0.0
fasteners==0.7.0
fixtures==3.0.0
flake8-import-order==0.12
flake8==2.5.5
future==0.16.0
futurist==1.2.0
greenlet==0.4.10
hacking==1.1.0
idna==2.6
imagesize==0.7.1
iso8601==0.1.11
Jinja2==2.10
jmespath==0.9.0
jsonpatch==1.16
jsonpointer==1.13
jsonschema==2.6.0
keystoneauth1==3.4.0
kombu==4.0.0
linecache2==1.0.0
MarkupSafe==1.0
mccabe==0.2.1
monotonic==0.6
msgpack-python==0.4.0
munch==2.1.0
netaddr==0.7.18
netifaces==0.10.4
openstacksdk==0.11.2
os-client-config==1.28.0
os-service-types==1.2.0
osc-lib==1.12.0
oslo.concurrency==3.25.0
oslo.config==5.2.0
oslo.context==2.19.2
oslo.i18n==3.15.3
oslo.log==3.36.0
oslo.messaging==5.29.0
oslo.middleware==3.31.0
oslo.serialization==2.18.0
oslo.service==1.24.0
oslo.utils==3.33.0
oslotest==3.2.0
osprofiler==2.3.0
paramiko==2.0.0
Paste==2.0.2
PasteDeploy==1.5.0
pbr==2.0.0
pika-pool==0.1.3
pika==0.10.0
positional==1.2.1
prettytable==0.7.2
pyasn1==0.1.8
pycodestyle==2.3.1
pycparser==2.18
pyflakes==0.8.1
Pygments==2.2.0
pyinotify==0.9.6
pyOpenSSL==17.1.0
pyparsing==2.1.0
pyperclip==1.5.27
python-cinderclient==3.3.0
python-dateutil==2.5.3
python-glanceclient==2.8.0
python-keystoneclient==3.8.0
python-mimeparse==1.6.0
python-novaclient==9.1.0
python-openstackclient==3.12.0
python-subunit==1.0.0
pytz==2013.6
PyYAML==3.13
repoze.lru==0.7
requests-mock==1.2.0
requests==2.14.2
requestsexceptions==1.2.0
rfc3986==0.3.1
Routes==2.3.1
simplejson==3.5.1
snowballstemmer==1.2.1
statsd==3.2.1
stestr==2.0.0
stevedore==1.20.0
tempest==17.1.0
tenacity==3.2.1
testscenarios==0.4
testtools==2.2.0
traceback2==1.4.0
unittest2==1.1.0
urllib3==1.21.1
vine==1.1.4
warlock==1.2.0
WebOb==1.7.1
wrapt==1.7.0

View File

@@ -61,9 +61,9 @@ class HTTPClient(object):
token=None, region_name=None, timeout=None,
endpoint_url=None, insecure=False,
endpoint_type='publicURL',
auth_strategy='keystone', ca_cert=None, log_credentials=False,
service_type='network', global_request_id=None,
**kwargs):
auth_strategy='keystone', ca_cert=None, cert=None,
log_credentials=False, service_type='network',
global_request_id=None, **kwargs):
self.username = username
self.user_id = user_id
@@ -82,6 +82,7 @@ class HTTPClient(object):
self.auth_strategy = auth_strategy
self.log_credentials = log_credentials
self.global_request_id = global_request_id
self.cert = cert
if insecure:
self.verify_cert = False
else:
@@ -167,6 +168,7 @@ class HTTPClient(object):
data=body,
headers=headers,
verify=self.verify_cert,
cert=self.cert,
timeout=self.timeout,
**kwargs)
@@ -399,6 +401,7 @@ def construct_http_client(username=None,
log_credentials=None,
auth_strategy='keystone',
ca_cert=None,
cert=None,
service_type='network',
session=None,
global_request_id=None,
@@ -430,6 +433,7 @@ def construct_http_client(username=None,
endpoint_type=endpoint_type,
service_type=service_type,
ca_cert=ca_cert,
cert=cert,
log_credentials=log_credentials,
auth_strategy=auth_strategy,
global_request_id=global_request_id)

View File

@@ -245,15 +245,15 @@ class CreatePort(neutronV20.CreateCommand, UpdatePortSecGroupMixin,
parser.add_argument(
'--vnic-type',
metavar='<direct | direct-physical | macvtap '
'| normal | baremetal>',
'| normal | baremetal | smart-nic>',
choices=['direct', 'direct-physical', 'macvtap',
'normal', 'baremetal'],
'normal', 'baremetal', 'smart-nic'],
type=utils.convert_to_lowercase,
help=_('VNIC type for this port.'))
parser.add_argument(
'--vnic_type',
choices=['direct', 'direct-physical', 'macvtap',
'normal', 'baremetal'],
'normal', 'baremetal', 'smart-nic'],
type=utils.convert_to_lowercase,
help=argparse.SUPPRESS)
parser.add_argument(

View File

@@ -58,11 +58,11 @@ def _get_common_parser(parser):
enable_group.add_argument(
'--enable',
action='store_true',
help=_('Enable this log (default is disabled)'))
help=_('Enable this log'))
enable_group.add_argument(
'--disable',
action='store_true',
help=_('Disable this log'))
help=_('Disable this log (default is enabled)'))
return parser

View File

@@ -1,393 +0,0 @@
# Copyright 2016 ZTE 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.
#
"""Network trunk and subports action implementations"""
import logging
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils as osc_utils
from neutronclient._i18n import _
from neutronclient.osc import utils as nc_osc_utils
from neutronclient.osc.v2 import utils as v2_utils
LOG = logging.getLogger(__name__)
TRUNK = 'trunk'
TRUNKS = 'trunks'
SUB_PORTS = 'sub_ports'
class CreateNetworkTrunk(command.ShowOne):
"""Create a network trunk for a given project"""
def get_parser(self, prog_name):
parser = super(CreateNetworkTrunk, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<name>',
help=_("Name of the trunk to create")
)
parser.add_argument(
'--description',
metavar='<description>',
help=_("A description of the trunk")
)
parser.add_argument(
'--parent-port',
metavar='<parent-port>',
required=True,
help=_("Parent port belonging to this trunk (name or ID)")
)
parser.add_argument(
'--subport',
metavar='<port=,segmentation-type=,segmentation-id=>',
action=parseractions.MultiKeyValueAction, dest='add_subports',
optional_keys=['segmentation-id', 'segmentation-type'],
required_keys=['port'],
help=_("Subport to add. Subport is of form "
"\'port=<name or ID>,segmentation-type=,segmentation-ID=\' "
"(--subport) option can be repeated")
)
admin_group = parser.add_mutually_exclusive_group()
admin_group.add_argument(
'--enable',
action='store_true',
default=True,
help=_("Enable trunk (default)")
)
admin_group.add_argument(
'--disable',
action='store_true',
help=_("Disable trunk")
)
nc_osc_utils.add_project_owner_option_to_parser(parser)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.neutronclient
attrs = _get_attrs_for_trunk(self.app.client_manager,
parsed_args)
body = {TRUNK: attrs}
obj = client.create_trunk(body)
columns = _get_columns(obj[TRUNK])
data = osc_utils.get_dict_properties(obj[TRUNK], columns,
formatters=_formatters)
return columns, data
class DeleteNetworkTrunk(command.Command):
"""Delete a given network trunk"""
def get_parser(self, prog_name):
parser = super(DeleteNetworkTrunk, self).get_parser(prog_name)
parser.add_argument(
'trunk',
metavar="<trunk>",
nargs="+",
help=_("Trunk(s) to delete (name or ID)")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.neutronclient
result = 0
for trunk in parsed_args.trunk:
try:
trunk_id = _get_id(client, trunk, TRUNK)
client.delete_trunk(trunk_id)
except Exception as e:
result += 1
LOG.error(_("Failed to delete trunk with name "
"or ID '%(trunk)s': %(e)s"),
{'trunk': trunk, 'e': e})
if result > 0:
total = len(parsed_args.trunk)
msg = (_("%(result)s of %(total)s trunks failed "
"to delete.") % {'result': result, 'total': total})
raise exceptions.CommandError(msg)
class ListNetworkTrunk(command.Lister):
"""List all network trunks"""
def get_parser(self, prog_name):
parser = super(ListNetworkTrunk, self).get_parser(prog_name)
parser.add_argument(
'--long',
action='store_true',
default=False,
help=_("List additional fields in output")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.neutronclient
data = client.list_trunks()
headers = (
'ID',
'Name',
'Parent Port',
'Description'
)
columns = (
'id',
'name',
'port_id',
'description'
)
if parsed_args.long:
headers += (
'Status',
'State',
'Created At',
'Updated At',
)
columns += (
'status',
'admin_state_up',
'created_at',
'updated_at'
)
return (headers,
(osc_utils.get_dict_properties(
s, columns,
formatters=_formatters,
) for s in data[TRUNKS]))
class SetNetworkTrunk(command.Command):
"""Set network trunk properties"""
def get_parser(self, prog_name):
parser = super(SetNetworkTrunk, self).get_parser(prog_name)
parser.add_argument(
'trunk',
metavar="<trunk>",
help=_("Trunk to modify (name or ID)")
)
parser.add_argument(
'--name',
metavar="<name>",
help=_("Set trunk name")
)
parser.add_argument(
'--description',
metavar='<description>',
help=_("A description of the trunk")
)
parser.add_argument(
'--subport',
metavar='<port=,segmentation-type=,segmentation-id=>',
action=parseractions.MultiKeyValueAction, dest='set_subports',
optional_keys=['segmentation-id', 'segmentation-type'],
required_keys=['port'],
help=_("Subport to add. Subport is of form "
"\'port=<name or ID>,segmentation-type=,segmentation-ID=\'"
"(--subport) option can be repeated")
)
admin_group = parser.add_mutually_exclusive_group()
admin_group.add_argument(
'--enable',
action='store_true',
help=_("Enable trunk")
)
admin_group.add_argument(
'--disable',
action='store_true',
help=_("Disable trunk")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.neutronclient
trunk_id = _get_id(client, parsed_args.trunk, TRUNK)
attrs = _get_attrs_for_trunk(self.app.client_manager, parsed_args)
body = {TRUNK: attrs}
try:
client.update_trunk(trunk_id, body)
except Exception as e:
msg = (_("Failed to set trunk '%(t)s': %(e)s")
% {'t': parsed_args.trunk, 'e': e})
raise exceptions.CommandError(msg)
if parsed_args.set_subports:
subport_attrs = _get_attrs_for_subports(self.app.client_manager,
parsed_args)
try:
client.trunk_add_subports(trunk_id, subport_attrs)
except Exception as e:
msg = (_("Failed to add subports to trunk '%(t)s': %(e)s")
% {'t': parsed_args.trunk, 'e': e})
raise exceptions.CommandError(msg)
class ShowNetworkTrunk(command.ShowOne):
"""Show information of a given network trunk"""
def get_parser(self, prog_name):
parser = super(ShowNetworkTrunk, self).get_parser(prog_name)
parser.add_argument(
'trunk',
metavar="<trunk>",
help=_("Trunk to display (name or ID)")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.neutronclient
trunk_id = _get_id(client, parsed_args.trunk, TRUNK)
obj = client.show_trunk(trunk_id)
columns = _get_columns(obj[TRUNK])
data = osc_utils.get_dict_properties(obj[TRUNK], columns,
formatters=_formatters)
return columns, data
class ListNetworkSubport(command.Lister):
"""List all subports for a given network trunk"""
def get_parser(self, prog_name):
parser = super(ListNetworkSubport, self).get_parser(prog_name)
parser.add_argument(
'--trunk',
required=True,
metavar="<trunk>",
help=_("List subports belonging to this trunk (name or ID)")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.neutronclient
trunk_id = _get_id(client, parsed_args.trunk, TRUNK)
data = client.trunk_get_subports(trunk_id)
headers = ('Port', 'Segmentation Type', 'Segmentation ID')
columns = ('port_id', 'segmentation_type', 'segmentation_id')
return (headers,
(osc_utils.get_dict_properties(
s, columns,
) for s in data[SUB_PORTS]))
class UnsetNetworkTrunk(command.Command):
"""Unset subports from a given network trunk"""
def get_parser(self, prog_name):
parser = super(UnsetNetworkTrunk, self).get_parser(prog_name)
parser.add_argument(
'trunk',
metavar="<trunk>",
help=_("Unset subports from this trunk (name or ID)")
)
parser.add_argument(
'--subport',
metavar="<subport>",
required=True,
action='append', dest='unset_subports',
help=_("Subport to delete (name or ID of the port) "
"(--subport) option can be repeated")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.neutronclient
attrs = _get_attrs_for_subports(self.app.client_manager, parsed_args)
trunk_id = _get_id(client, parsed_args.trunk, TRUNK)
client.trunk_remove_subports(trunk_id, attrs)
_formatters = {
'admin_state_up': v2_utils.AdminStateColumn,
'sub_ports': format_columns.ListDictColumn,
}
def _get_columns(item):
return tuple(sorted(list(item.keys())))
def _get_attrs_for_trunk(client_manager, parsed_args):
attrs = {}
if parsed_args.name is not None:
attrs['name'] = str(parsed_args.name)
if parsed_args.description is not None:
attrs['description'] = str(parsed_args.description)
if parsed_args.enable:
attrs['admin_state_up'] = True
if parsed_args.disable:
attrs['admin_state_up'] = False
if 'parent_port' in parsed_args and parsed_args.parent_port is not None:
port_id = _get_id(client_manager.neutronclient,
parsed_args.parent_port, 'port')
attrs['port_id'] = port_id
if 'add_subports' in parsed_args and parsed_args.add_subports is not None:
attrs[SUB_PORTS] = _format_subports(client_manager,
parsed_args.add_subports)
# "trunk set" command doesn't support setting project.
if 'project' in parsed_args and parsed_args.project is not None:
identity_client = client_manager.identity
project_id = nc_osc_utils.find_project(
identity_client,
parsed_args.project,
parsed_args.project_domain,
).id
attrs['tenant_id'] = project_id
return attrs
def _format_subports(client_manager, subports):
attrs = []
for subport in subports:
subport_attrs = {}
if subport.get('port'):
port_id = _get_id(client_manager.neutronclient,
subport['port'], 'port')
subport_attrs['port_id'] = port_id
if subport.get('segmentation-id'):
try:
subport_attrs['segmentation_id'] = int(
subport['segmentation-id'])
except ValueError:
msg = (_("Segmentation-id '%s' is not an integer") %
subport['segmentation-id'])
raise exceptions.CommandError(msg)
if subport.get('segmentation-type'):
subport_attrs['segmentation_type'] = subport['segmentation-type']
attrs.append(subport_attrs)
return attrs
def _get_attrs_for_subports(client_manager, parsed_args):
attrs = {}
if 'set_subports' in parsed_args and parsed_args.set_subports is not None:
attrs[SUB_PORTS] = _format_subports(client_manager,
parsed_args.set_subports)
if ('unset_subports' in parsed_args and
parsed_args.unset_subports is not None):
subports_list = []
for subport in parsed_args.unset_subports:
port_id = _get_id(client_manager.neutronclient,
subport, 'port')
subports_list.append({'port_id': port_id})
attrs[SUB_PORTS] = subports_list
return attrs
def _get_id(client, id_or_name, resource):
return client.find_resource(resource, str(id_or_name))['id']

View File

@@ -637,7 +637,7 @@ class NeutronShell(app.App):
def main(argv=sys.argv[1:]):
try:
print(_("neutron CLI is deprecated and will be removed "
"in the future. Use openstack CLI instead."), file=sys.stderr)
"in the Z cycle. Use openstack CLI instead."), file=sys.stderr)
return NeutronShell(NEUTRON_API_VERSION).run(
list(map(encodeutils.safe_decode, argv)))
except KeyboardInterrupt:

View File

@@ -43,7 +43,7 @@ class TestCLIFormatter(base.ClientTestBase):
result = self._create_net('yaml', ['name', 'admin_state_up'])
self.assertDictEqual({'name': self.net_name,
'admin_state_up': True},
yaml.load(result))
yaml.safe_load(result))
def test_net_create_with_value_formatter(self):
# NOTE(amotoki): In 'value' formatter, there is no guarantee

View File

@@ -64,9 +64,13 @@ class SimpleReadOnlyNeutronClientTest(base.ClientTestBase):
self.neutron('floatingip-list')
def test_neutron_meter_label_list(self):
if not self.is_extension_enabled('metering'):
self.skipTest('metering is not enabled')
self.neutron('meter-label-list')
def test_neutron_meter_label_rule_list(self):
if not self.is_extension_enabled('metering'):
self.skipTest('metering is not enabled')
self.neutron('meter-label-rule-list')
def test_neutron_net_external_list(self):

View File

@@ -1,87 +0,0 @@
# 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 copy
from unittest import mock
from oslo_utils import uuidutils
class FakeTrunk(object):
"""Fake one or more trunks."""
@staticmethod
def create_one_trunk(attrs=None):
"""Create a fake trunk.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A Dictionary with id, name, description, admin_state_up, port_id,
sub_ports, status and project_id
"""
attrs = attrs or {}
# Set default attributes.
trunk_attrs = {
'id': 'trunk-id-' + uuidutils.generate_uuid(dashed=False),
'name': 'trunk-name-' + uuidutils.generate_uuid(dashed=False),
'description': '',
'port_id': 'port-' + uuidutils.generate_uuid(dashed=False),
'admin_state_up': True,
'project_id': 'project-id-' +
uuidutils.generate_uuid(dashed=False),
'status': 'ACTIVE',
'sub_ports': [{'port_id': 'subport-' +
uuidutils.generate_uuid(dashed=False),
'segmentation_type': 'vlan',
'segmentation_id': 100}],
}
# Overwrite default attributes.
trunk_attrs.update(attrs)
return copy.deepcopy(trunk_attrs)
@staticmethod
def create_trunks(attrs=None, count=2):
"""Create multiple fake trunks.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of routers to fake
:return:
A list of dictionaries faking the trunks
"""
trunks = []
for i in range(0, count):
trunks.append(FakeTrunk.create_one_trunk(attrs))
return trunks
@staticmethod
def get_trunks(trunks=None, count=2):
"""Get an iterable Mock object with a list of faked trunks.
If trunks list is provided, then initialize the Mock object with the
list. Otherwise create one.
:param List trunks:
A list of FakeResource objects faking trunks
:param int count:
The number of trunks to fake
:return:
An iterable Mock object with side_effect set to a list of faked
trunks
"""
if trunks is None:
trunks = FakeTrunk.create_trunks(count)
return mock.Mock(side_effect=trunks)

View File

@@ -1,769 +0,0 @@
# Copyright 2016 ZTE 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 argparse
import copy
from unittest import mock
from unittest.mock import call
from osc_lib.cli import format_columns
from osc_lib import exceptions
from osc_lib.tests import utils as tests_utils
import testtools
from neutronclient.osc.v2.trunk import network_trunk as trunk
from neutronclient.osc.v2 import utils as v2_utils
from neutronclient.tests.unit.osc.v2 import fakes as test_fakes
from neutronclient.tests.unit.osc.v2.trunk import fakes
def _get_id(client, id_or_name, resource):
return id_or_name
class TestCreateNetworkTrunk(test_fakes.TestNeutronClientOSCV2):
# The new trunk created
_trunk = fakes.FakeTrunk.create_one_trunk()
columns = (
'admin_state_up',
'description',
'id',
'name',
'port_id',
'project_id',
'status',
'sub_ports',
)
def get_data(self):
return (
v2_utils.AdminStateColumn(self._trunk['admin_state_up']),
self._trunk['description'],
self._trunk['id'],
self._trunk['name'],
self._trunk['port_id'],
self._trunk['project_id'],
self._trunk['status'],
format_columns.ListDictColumn(self._trunk['sub_ports']),
)
def setUp(self):
super(TestCreateNetworkTrunk, self).setUp()
mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id',
new=_get_id).start()
self.neutronclient.create_trunk = mock.Mock(
return_value={trunk.TRUNK: self._trunk})
self.data = self.get_data()
# Get the command object to test
self.cmd = trunk.CreateNetworkTrunk(self.app, self.namespace)
def test_create_no_options(self):
arglist = []
verifylist = []
self.assertRaises(tests_utils.ParserException, self.check_parser,
self.cmd, arglist, verifylist)
def test_create_default_options(self):
arglist = [
"--parent-port", self._trunk['port_id'],
self._trunk['name'],
]
verifylist = [
('parent_port', self._trunk['port_id']),
('name', self._trunk['name']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = (self.cmd.take_action(parsed_args))
self.neutronclient.create_trunk.assert_called_once_with({
trunk.TRUNK: {'name': self._trunk['name'],
'admin_state_up': self._trunk['admin_state_up'],
'port_id': self._trunk['port_id']}
})
self.assertEqual(self.columns, columns)
self.assertItemEqual(self.data, data)
def test_create_full_options(self):
self._trunk['description'] = 'foo description'
self.data = self.get_data()
subport = self._trunk['sub_ports'][0]
arglist = [
"--disable",
"--description", self._trunk['description'],
"--parent-port", self._trunk['port_id'],
"--subport", 'port=%(port)s,segmentation-type=%(seg_type)s,'
'segmentation-id=%(seg_id)s' % {
'seg_id': subport['segmentation_id'],
'seg_type': subport['segmentation_type'],
'port': subport['port_id']},
self._trunk['name'],
]
verifylist = [
('name', self._trunk['name']),
('description', self._trunk['description']),
('parent_port', self._trunk['port_id']),
('add_subports', [{
'port': subport['port_id'],
'segmentation-id': str(subport['segmentation_id']),
'segmentation-type': subport['segmentation_type']}]),
('disable', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = (self.cmd.take_action(parsed_args))
self.neutronclient.create_trunk.assert_called_once_with({
trunk.TRUNK: {'name': self._trunk['name'],
'description': self._trunk['description'],
'admin_state_up': False,
'sub_ports': [subport],
'port_id': self._trunk['port_id']}
})
self.assertEqual(self.columns, columns)
self.assertItemEqual(self.data, data)
def test_create_trunk_with_subport_invalid_segmentation_id_fail(self):
subport = self._trunk['sub_ports'][0]
arglist = [
"--parent-port", self._trunk['port_id'],
"--subport", "port=%(port)s,segmentation-type=%(seg_type)s,"
"segmentation-id=boom" % {
'seg_type': subport['segmentation_type'],
'port': subport['port_id']},
self._trunk['name'],
]
verifylist = [
('name', self._trunk['name']),
('parent_port', self._trunk['port_id']),
('add_subports', [{
'port': subport['port_id'],
'segmentation-id': 'boom',
'segmentation-type': subport['segmentation_type']}]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
with testtools.ExpectedException(exceptions.CommandError) as e:
self.cmd.take_action(parsed_args)
self.assertEqual("Segmentation-id 'boom' is not an integer",
str(e))
def test_create_network_trunk_subports_without_optional_keys(self):
subport = copy.copy(self._trunk['sub_ports'][0])
# Pop out the segmentation-id and segmentation-type
subport.pop('segmentation_type')
subport.pop('segmentation_id')
arglist = [
'--parent-port', self._trunk['port_id'],
'--subport', 'port=%(port)s' % {'port': subport['port_id']},
self._trunk['name'],
]
verifylist = [
('name', self._trunk['name']),
('parent_port', self._trunk['port_id']),
('add_subports', [{
'port': subport['port_id']}]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = (self.cmd.take_action(parsed_args))
self.neutronclient.create_trunk.assert_called_once_with({
trunk.TRUNK: {'name': self._trunk['name'],
'admin_state_up': True,
'sub_ports': [subport],
'port_id': self._trunk['port_id']}
})
self.assertEqual(self.columns, columns)
self.assertItemEqual(self.data, data)
def test_create_network_trunk_subports_without_required_key_fail(self):
subport = self._trunk['sub_ports'][0]
arglist = [
'--parent-port', self._trunk['port_id'],
'--subport', 'segmentation-type=%(seg_type)s,'
'segmentation-id=%(seg_id)s' % {
'seg_id': subport['segmentation_id'],
'seg_type': subport['segmentation_type']},
self._trunk['name'],
]
verifylist = [
('name', self._trunk['name']),
('parent_port', self._trunk['port_id']),
('add_subports', [{
'segmentation-id': str(subport['segmentation_id']),
'segmentation-type': subport['segmentation_type']}]),
]
with testtools.ExpectedException(argparse.ArgumentTypeError):
self.check_parser(self.cmd, arglist, verifylist)
class TestDeleteNetworkTrunk(test_fakes.TestNeutronClientOSCV2):
# The trunk to be deleted.
_trunks = fakes.FakeTrunk.create_trunks(count=2)
def setUp(self):
super(TestDeleteNetworkTrunk, self).setUp()
mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id',
new=_get_id).start()
self.neutronclient.delete_trunk = mock.Mock(return_value=None)
# Get the command object to test
self.cmd = trunk.DeleteNetworkTrunk(self.app, self.namespace)
def test_delete_trunk(self):
arglist = [
self._trunks[0]['name'],
]
verifylist = [
('trunk', [self._trunks[0]['name']]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.neutronclient.delete_trunk.assert_called_once_with(
self._trunks[0]['name'])
self.assertIsNone(result)
def test_delete_trunk_multiple(self):
arglist = []
verifylist = []
for t in self._trunks:
arglist.append(t['name'])
verifylist = [
('trunk', arglist),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
calls = []
for t in self._trunks:
calls.append(call(t['name']))
self.neutronclient.delete_trunk.assert_has_calls(calls)
self.assertIsNone(result)
def test_delete_trunk_multiple_with_exception(self):
arglist = [
self._trunks[0]['name'],
'unexist_trunk',
]
verifylist = [
('trunk',
[self._trunks[0]['name'], 'unexist_trunk']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
get_mock_result = [self._trunks[0], exceptions.CommandError]
trunk._get_id = (
mock.Mock(side_effect=get_mock_result)
)
with testtools.ExpectedException(exceptions.CommandError) as e:
self.cmd.take_action(parsed_args)
self.assertEqual('1 of 2 trunks failed to delete.', str(e))
self.neutronclient.delete_trunk.assert_called_once_with(
self._trunks[0]
)
class TestShowNetworkTrunk(test_fakes.TestNeutronClientOSCV2):
# The trunk to set.
_trunk = fakes.FakeTrunk.create_one_trunk()
columns = (
'admin_state_up',
'description',
'id',
'name',
'port_id',
'project_id',
'status',
'sub_ports',
)
data = (
v2_utils.AdminStateColumn(_trunk['admin_state_up']),
_trunk['description'],
_trunk['id'],
_trunk['name'],
_trunk['port_id'],
_trunk['project_id'],
_trunk['status'],
format_columns.ListDictColumn(_trunk['sub_ports']),
)
def setUp(self):
super(TestShowNetworkTrunk, self).setUp()
mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id',
new=_get_id).start()
self.neutronclient.show_trunk = mock.Mock(
return_value={trunk.TRUNK: self._trunk})
# Get the command object to test
self.cmd = trunk.ShowNetworkTrunk(self.app, self.namespace)
def test_show_no_options(self):
arglist = []
verifylist = []
self.assertRaises(tests_utils.ParserException, self.check_parser,
self.cmd, arglist, verifylist)
def test_show_all_options(self):
arglist = [
self._trunk['id'],
]
verifylist = [
('trunk', self._trunk['id']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.neutronclient.show_trunk.assert_called_once_with(
self._trunk['id'])
self.assertEqual(self.columns, columns)
self.assertItemEqual(self.data, data)
class TestListNetworkTrunk(test_fakes.TestNeutronClientOSCV2):
# Create trunks to be listed.
_trunks = fakes.FakeTrunk.create_trunks(
{'created_at': '2001-01-01 00:00:00',
'updated_at': '2001-01-01 00:00:00'}, count=3)
columns = (
'ID',
'Name',
'Parent Port',
'Description'
)
columns_long = columns + (
'Status',
'State',
'Created At',
'Updated At'
)
data = []
for t in _trunks:
data.append((
t['id'],
t['name'],
t['port_id'],
t['description']
))
data_long = []
for t in _trunks:
data_long.append((
t['id'],
t['name'],
t['port_id'],
t['description'],
t['status'],
v2_utils.AdminStateColumn(t['admin_state_up']),
'2001-01-01 00:00:00',
'2001-01-01 00:00:00',
))
def setUp(self):
super(TestListNetworkTrunk, self).setUp()
mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id',
new=_get_id).start()
self.neutronclient.list_trunks = mock.Mock(
return_value={trunk.TRUNKS: self._trunks})
# Get the command object to test
self.cmd = trunk.ListNetworkTrunk(self.app, self.namespace)
def test_trunk_list_no_option(self):
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.neutronclient.list_trunks.assert_called_once_with()
self.assertEqual(self.columns, columns)
self.assertListItemEqual(self.data, list(data))
def test_trunk_list_long(self):
arglist = [
'--long',
]
verifylist = [
('long', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.neutronclient.list_trunks.assert_called_once_with()
self.assertEqual(self.columns_long, columns)
self.assertListItemEqual(self.data_long, list(data))
class TestSetNetworkTrunk(test_fakes.TestNeutronClientOSCV2):
# Create trunks to be listed.
_trunk = fakes.FakeTrunk.create_one_trunk()
columns = (
'admin_state_up',
'id',
'name',
'description',
'port_id',
'project_id',
'status',
'sub_ports',
)
data = (
v2_utils.AdminStateColumn(_trunk['admin_state_up']),
_trunk['id'],
_trunk['name'],
_trunk['description'],
_trunk['port_id'],
_trunk['project_id'],
_trunk['status'],
format_columns.ListDictColumn(_trunk['sub_ports']),
)
def setUp(self):
super(TestSetNetworkTrunk, self).setUp()
mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id',
new=_get_id).start()
self.neutronclient.update_trunk = mock.Mock(
return_value={trunk.TRUNK: self._trunk})
self.neutronclient.trunk_add_subports = mock.Mock(
return_value=self._trunk)
# Get the command object to test
self.cmd = trunk.SetNetworkTrunk(self.app, self.namespace)
def _test_set_network_trunk_attr(self, attr, value):
arglist = [
'--%s' % attr, value,
self._trunk[attr],
]
verifylist = [
(attr, value),
('trunk', self._trunk[attr]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
attrs = {
attr: value,
}
self.neutronclient.update_trunk.assert_called_once_with(
self._trunk[attr], {trunk.TRUNK: attrs})
self.assertIsNone(result)
def test_set_network_trunk_name(self):
self._test_set_network_trunk_attr('name', 'trunky')
def test_test_set_network_trunk_description(self):
self._test_set_network_trunk_attr('description', 'description')
def test_set_network_trunk_admin_state_up_disable(self):
arglist = [
'--disable',
self._trunk['name'],
]
verifylist = [
('disable', True),
('trunk', self._trunk['name']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
attrs = {
'admin_state_up': False,
}
self.neutronclient.update_trunk.assert_called_once_with(
self._trunk['name'], {trunk.TRUNK: attrs})
self.assertIsNone(result)
def test_set_network_trunk_admin_state_up_enable(self):
arglist = [
'--enable',
self._trunk['name'],
]
verifylist = [
('enable', True),
('trunk', self._trunk['name']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
attrs = {
'admin_state_up': True,
}
self.neutronclient.update_trunk.assert_called_once_with(
self._trunk['name'], {trunk.TRUNK: attrs})
self.assertIsNone(result)
def test_set_network_trunk_nothing(self):
arglist = [self._trunk['name'], ]
verifylist = [('trunk', self._trunk['name']), ]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
attrs = {}
self.neutronclient.update_trunk.assert_called_once_with(
self._trunk['name'], {trunk.TRUNK: attrs})
self.assertIsNone(result)
def test_set_network_trunk_subports(self):
subport = self._trunk['sub_ports'][0]
arglist = [
'--subport', 'port=%(port)s,segmentation-type=%(seg_type)s,'
'segmentation-id=%(seg_id)s' % {
'seg_id': subport['segmentation_id'],
'seg_type': subport['segmentation_type'],
'port': subport['port_id']},
self._trunk['name'],
]
verifylist = [
('trunk', self._trunk['name']),
('set_subports', [{
'port': subport['port_id'],
'segmentation-id': str(subport['segmentation_id']),
'segmentation-type': subport['segmentation_type']}]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.neutronclient.trunk_add_subports.assert_called_once_with(
self._trunk['name'], {'sub_ports': [subport]}
)
self.assertIsNone(result)
def test_set_network_trunk_subports_without_optional_keys(self):
subport = copy.copy(self._trunk['sub_ports'][0])
# Pop out the segmentation-id and segmentation-type
subport.pop('segmentation_type')
subport.pop('segmentation_id')
arglist = [
'--subport', 'port=%(port)s' % {'port': subport['port_id']},
self._trunk['name'],
]
verifylist = [
('trunk', self._trunk['name']),
('set_subports', [{
'port': subport['port_id']}]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.neutronclient.trunk_add_subports.assert_called_once_with(
self._trunk['name'], {'sub_ports': [subport]}
)
self.assertIsNone(result)
def test_set_network_trunk_subports_without_required_key_fail(self):
subport = self._trunk['sub_ports'][0]
arglist = [
'--subport', 'segmentation-type=%(seg_type)s,'
'segmentation-id=%(seg_id)s' % {
'seg_id': subport['segmentation_id'],
'seg_type': subport['segmentation_type']},
self._trunk['name'],
]
verifylist = [
('trunk', self._trunk['name']),
('set_subports', [{
'segmentation-id': str(subport['segmentation_id']),
'segmentation-type': subport['segmentation_type']}]),
]
with testtools.ExpectedException(argparse.ArgumentTypeError):
self.check_parser(self.cmd, arglist, verifylist)
self.neutronclient.trunk_add_subports.assert_not_called()
def test_set_trunk_attrs_with_exception(self):
arglist = [
'--name', 'reallylongname',
self._trunk['name'],
]
verifylist = [
('trunk', self._trunk['name']),
('name', 'reallylongname'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.neutronclient.update_trunk = (
mock.Mock(side_effect=exceptions.CommandError)
)
with testtools.ExpectedException(exceptions.CommandError) as e:
self.cmd.take_action(parsed_args)
self.assertEqual(
"Failed to set trunk '%s': " % self._trunk['name'],
str(e))
attrs = {'name': 'reallylongname'}
self.neutronclient.update_trunk.assert_called_once_with(
self._trunk['name'], {trunk.TRUNK: attrs})
self.neutronclient.trunk_add_subports.assert_not_called()
def test_set_trunk_add_subport_with_exception(self):
arglist = [
'--subport', 'port=invalid_subport',
self._trunk['name'],
]
verifylist = [
('trunk', self._trunk['name']),
('set_subports', [{'port': 'invalid_subport'}]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.neutronclient.trunk_add_subports = (
mock.Mock(side_effect=exceptions.CommandError)
)
with testtools.ExpectedException(exceptions.CommandError) as e:
self.cmd.take_action(parsed_args)
self.assertEqual(
"Failed to add subports to trunk '%s': " % self._trunk['name'],
str(e))
self.neutronclient.update_trunk.assert_called_once_with(
self._trunk['name'], {trunk.TRUNK: {}})
self.neutronclient.trunk_add_subports.assert_called_once_with(
self._trunk['name'],
{'sub_ports': [{'port_id': 'invalid_subport'}]}
)
class TestListNetworkSubport(test_fakes.TestNeutronClientOSCV2):
_trunk = fakes.FakeTrunk.create_one_trunk()
_subports = _trunk['sub_ports']
columns = (
'Port',
'Segmentation Type',
'Segmentation ID',
)
data = []
for s in _subports:
data.append((
s['port_id'],
s['segmentation_type'],
s['segmentation_id'],
))
def setUp(self):
super(TestListNetworkSubport, self).setUp()
mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id',
new=_get_id).start()
self.neutronclient.trunk_get_subports = mock.Mock(
return_value={trunk.SUB_PORTS: self._subports})
# Get the command object to test
self.cmd = trunk.ListNetworkSubport(self.app, self.namespace)
def test_subport_list(self):
arglist = [
'--trunk', self._trunk['name'],
]
verifylist = [
('trunk', self._trunk['name']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.neutronclient.trunk_get_subports.assert_called_once_with(
self._trunk['name'])
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
class TestUnsetNetworkTrunk(test_fakes.TestNeutronClientOSCV2):
_trunk = fakes.FakeTrunk.create_one_trunk()
columns = (
'admin_state_up',
'id',
'name',
'port_id',
'project_id',
'status',
'sub_ports',
)
data = (
v2_utils.AdminStateColumn(_trunk['admin_state_up']),
_trunk['id'],
_trunk['name'],
_trunk['port_id'],
_trunk['project_id'],
_trunk['status'],
format_columns.ListDictColumn(_trunk['sub_ports']),
)
def setUp(self):
super(TestUnsetNetworkTrunk, self).setUp()
mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id',
new=_get_id).start()
self.neutronclient.trunk_remove_subports = mock.Mock(
return_value=None)
# Get the command object to test
self.cmd = trunk.UnsetNetworkTrunk(self.app, self.namespace)
def test_unset_network_trunk_subport(self):
subport = self._trunk['sub_ports'][0]
arglist = [
"--subport", subport['port_id'],
self._trunk['name'],
]
verifylist = [
('trunk', self._trunk['name']),
('unset_subports', [subport['port_id']]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.neutronclient.trunk_remove_subports.assert_called_once_with(
self._trunk['name'],
{trunk.SUB_PORTS: [{'port_id': subport['port_id']}]}
)
self.assertIsNone(result)
def test_unset_subport_no_arguments_fail(self):
arglist = [
self._trunk['name'],
]
verifylist = [
('trunk', self._trunk['name']),
]
self.assertRaises(tests_utils.ParserException,
self.check_parser, self.cmd, arglist, verifylist)

View File

@@ -1159,7 +1159,7 @@ class CLITestV20OutputFormatter(CLITestV20Base):
def test_create_resource_yaml(self):
self._test_create_resource_with_formatter('yaml')
data = yaml.load(self.fake_stdout.make_string())
data = yaml.safe_load(self.fake_stdout.make_string())
self.assertEqual('myname', data['name'])
self.assertEqual('myid', data['id'])
@@ -1184,7 +1184,7 @@ class CLITestV20OutputFormatter(CLITestV20Base):
def test_show_resource_yaml(self):
self._test_show_resource_with_formatter('yaml')
data = yaml.load(''.join(self.fake_stdout.content))
data = yaml.safe_load(''.join(self.fake_stdout.content))
self.assertEqual('myname', data['name'])
self.assertEqual('myid', data['id'])
@@ -1211,5 +1211,5 @@ class CLITestV20OutputFormatter(CLITestV20Base):
def test_list_resources_yaml(self):
self._test_list_resources_with_formatter('yaml')
data = yaml.load(''.join(self.fake_stdout.content))
data = yaml.safe_load(''.join(self.fake_stdout.content))
self.assertEqual(['myid1', 'myid2'], [d['id'] for d in data])

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env python
# Copyright 2012 Red Hat
# All Rights Reserved.
#

View File

@@ -214,6 +214,26 @@ class CLITestV20PortJSON(test_cli20.CLITestV20Base):
self._test_create_resource(resource, cmd, name, myid, args,
position_names, position_values)
def test_create_port_vnic_type_smart_nic(self):
# Create port: --vnic_type smart-nic netid.
resource = 'port'
cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None)
name = 'myname'
myid = 'myid'
netid = 'netid'
args = ['--vnic_type', 'smart-nic', netid]
position_names = ['binding:vnic_type', 'network_id']
position_values = ['smart-nic', netid]
self._test_create_resource(resource, cmd, name, myid, args,
position_names, position_values)
# Test dashed options
args = ['--vnic-type', 'smart-nic', netid]
position_names = ['binding:vnic_type', 'network_id']
position_values = ['smart-nic', netid]
self._test_create_resource(resource, cmd, name, myid, args,
position_names, position_values)
def test_create_port_with_binding_profile(self):
resource = 'port'
cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None)

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env python
# Copyright 2012 Red Hat
# All Rights Reserved.
#

View File

@@ -217,5 +217,5 @@ class CLITestV20ExtensionJSONChildResource(test_cli20.CLITestV20Base):
self.client.delete_parents_child,
self.client.create_parents_child)
for method in methods:
argspec = inspect.getargspec(method)
argspec = inspect.getfullargspec(method)
self.assertIn("parent_id", argspec.args)

View File

@@ -20,7 +20,6 @@
import logging
import testtools
from testtools import helpers
from neutronclient.neutron import v2_0 as neutronV20
@@ -30,7 +29,7 @@ class TestCommandMeta(testtools.TestCase):
class FakeCommand(neutronV20.NeutronCommand):
pass
self.assertTrue(helpers.safe_hasattr(FakeCommand, 'log'))
self.assertTrue(hasattr(FakeCommand, 'log'))
self.assertIsInstance(FakeCommand.log, logging.getLoggerClass())
self.assertEqual(__name__ + ".FakeCommand", FakeCommand.log.name)
@@ -38,5 +37,5 @@ class TestCommandMeta(testtools.TestCase):
class FakeCommand(neutronV20.NeutronCommand):
log = None
self.assertTrue(helpers.safe_hasattr(FakeCommand, 'log'))
self.assertTrue(hasattr(FakeCommand, 'log'))
self.assertIsNone(FakeCommand.log)

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env python
# Copyright (C) 2013 Yahoo! Inc.
# All Rights Reserved.
#

View File

@@ -357,10 +357,10 @@ class ShellTest(testtools.TestCase):
self.useFixture(fixtures.MockPatchObject(openstack_shell,
'COMMANDS', None))
openstack_shell.NeutronShell('2.0')
self.assertDictContainsSubset(
self.assertLessEqual(
{'net-create': network.CreateNetwork,
'net-delete': network.DeleteNetwork,
'net-list': network.ListNetwork,
'net-show': network.ShowNetwork,
'net-update': network.UpdateNetwork},
openstack_shell.COMMANDS['2.0'])
'net-update': network.UpdateNetwork}.items(),
openstack_shell.COMMANDS['2.0'].items())

View File

@@ -216,6 +216,10 @@ class ClientBase(object):
:param bool log_credentials: Allow for logging of passwords or not.
Defaults to False. (optional)
:param string ca_cert: SSL CA bundle file to use. (optional)
:param cert: A client certificate to pass to requests. These are of the
same form as requests expects. Either a single filename
containing both the certificate and key or a tuple containing
the path to the certificate then a path to the key. (optional)
:param integer retries: How many times idempotent (GET, PUT, DELETE)
requests to Neutron server should be retried if
they fail (default: 0).
@@ -511,6 +515,8 @@ class Client(ClientBase):
router_path = "/routers/%s"
floatingips_path = "/floatingips"
floatingip_path = "/floatingips/%s"
port_forwardings_path = "/floatingips/%s/port_forwardings"
port_forwarding_path = "/floatingips/%s/port_forwardings/%s"
security_groups_path = "/security-groups"
security_group_path = "/security-groups/%s"
security_group_rules_path = "/security-group-rules"
@@ -615,12 +621,20 @@ class Client(ClientBase):
qos_policy_path = "/qos/policies/%s"
qos_bandwidth_limit_rules_path = "/qos/policies/%s/bandwidth_limit_rules"
qos_bandwidth_limit_rule_path = "/qos/policies/%s/bandwidth_limit_rules/%s"
qos_packet_rate_limit_rules_path = \
"/qos/policies/%s/packet_rate_limit_rules"
qos_packet_rate_limit_rule_path = \
"/qos/policies/%s/packet_rate_limit_rules/%s"
qos_dscp_marking_rules_path = "/qos/policies/%s/dscp_marking_rules"
qos_dscp_marking_rule_path = "/qos/policies/%s/dscp_marking_rules/%s"
qos_minimum_bandwidth_rules_path = \
"/qos/policies/%s/minimum_bandwidth_rules"
qos_minimum_bandwidth_rule_path = \
"/qos/policies/%s/minimum_bandwidth_rules/%s"
qos_minimum_packet_rate_rules_path = \
"/qos/policies/%s/minimum_packet_rate_rules"
qos_minimum_packet_rate_rule_path = \
"/qos/policies/%s/minimum_packet_rate_rules/%s"
qos_rule_types_path = "/qos/rule-types"
qos_rule_type_path = "/qos/rule-types/%s"
flavors_path = "/flavors"
@@ -704,7 +718,9 @@ class Client(ClientBase):
'qos_policies': 'qos_policy',
'policies': 'policy',
'bandwidth_limit_rules': 'bandwidth_limit_rule',
'packet_rate_limit_rules': 'packet_rate_limit_rule',
'minimum_bandwidth_rules': 'minimum_bandwidth_rule',
'minimum_packet_rate_rules': 'minimum_packet_rate_rule',
'rules': 'rule',
'dscp_marking_rules': 'dscp_marking_rule',
'rule_types': 'rule_type',
@@ -1005,6 +1021,32 @@ class Client(ClientBase):
"""Deletes the specified floatingip."""
return self.delete(self.floatingip_path % (floatingip))
def show_port_forwarding(self, floatingip, portforwarding):
"""Fetches information of a certain portforwarding"""
return self.get(self.port_forwarding_path % (floatingip,
portforwarding))
def list_port_forwardings(self, floatingip, retrieve_all=True, **_params):
"""Fetches a list of all portforwardings for a floatingip."""
return self.list('port_forwardings',
self.port_forwardings_path % floatingip, retrieve_all,
**_params)
def create_port_forwarding(self, floatingip, body=None):
"""Creates a new portforwarding."""
return self.post(self.port_forwardings_path % floatingip, body=body)
def delete_port_forwarding(self, floatingip, portforwarding):
"""Deletes the specified portforwarding."""
return self.delete(self.port_forwarding_path % (floatingip,
portforwarding))
def update_port_forwarding(self, floatingip, portforwarding, body=None):
"""Updates a portforwarding."""
return self.put(self.port_forwarding_path % (floatingip,
portforwarding),
body=body)
def create_security_group(self, body=None):
"""Creates a new security group."""
return self.post(self.security_groups_path, body=body)
@@ -1968,6 +2010,35 @@ class Client(ClientBase):
return self.post(self.qos_minimum_bandwidth_rules_path % policy,
body=body)
def list_packet_rate_limit_rules(self, policy_id, retrieve_all=True,
**_params):
"""Fetches a list of all packet rate limit rules for the given policy
"""
return self.list('packet_rate_limit_rules',
self.qos_packet_rate_limit_rules_path %
policy_id, retrieve_all, **_params)
def show_packet_rate_limit_rule(self, rule, policy, body=None):
"""Fetches information of a certain packet rate limit rule."""
return self.get(self.qos_packet_rate_limit_rule_path %
(policy, rule), body=body)
def create_packet_rate_limit_rule(self, policy, body=None):
"""Creates a new packet rate limit rule."""
return self.post(self.qos_packet_rate_limit_rules_path % policy,
body=body)
def update_packet_rate_limit_rule(self, rule, policy, body=None):
"""Updates a packet rate limit rule."""
return self.put(self.qos_packet_rate_limit_rule_path %
(policy, rule), body=body)
def delete_packet_rate_limit_rule(self, rule, policy):
"""Deletes a packet rate limit rule."""
return self.delete(self.qos_packet_rate_limit_rule_path %
(policy, rule))
def update_minimum_bandwidth_rule(self, rule, policy, body=None):
"""Updates a minimum bandwidth rule."""
return self.put(self.qos_minimum_bandwidth_rule_path %
@@ -1978,6 +2049,35 @@ class Client(ClientBase):
return self.delete(self.qos_minimum_bandwidth_rule_path %
(policy, rule))
def list_minimum_packet_rate_rules(self, policy_id, retrieve_all=True,
**_params):
"""Fetches a list of all minimum packet rate rules for the given policy
"""
return self.list('minimum_packet_rate_rules',
self.qos_minimum_packet_rate_rules_path %
policy_id, retrieve_all, **_params)
def show_minimum_packet_rate_rule(self, rule, policy, body=None):
"""Fetches information of a certain minimum packet rate rule."""
return self.get(self.qos_minimum_packet_rate_rule_path %
(policy, rule), body=body)
def create_minimum_packet_rate_rule(self, policy, body=None):
"""Creates a new minimum packet rate rule."""
return self.post(self.qos_minimum_packet_rate_rules_path % policy,
body=body)
def update_minimum_packet_rate_rule(self, rule, policy, body=None):
"""Updates a minimum packet rate rule."""
return self.put(self.qos_minimum_packet_rate_rule_path %
(policy, rule), body=body)
def delete_minimum_packet_rate_rule(self, rule, policy):
"""Deletes a minimum packet rate rule."""
return self.delete(self.qos_minimum_packet_rate_rule_path %
(policy, rule))
def create_flavor(self, body=None):
"""Creates a new Neutron service flavor."""
return self.post(self.flavors_path, body=body)

View File

@@ -0,0 +1,4 @@
---
features:
- |
Add support to floating ip port forwarding.

View File

@@ -0,0 +1,5 @@
---
upgrade:
- |
Python 3.6 & 3.7 support has been dropped. The minimum version of Python now
supported is Python 3.8.

View File

@@ -0,0 +1,7 @@
---
features:
- |
Added new client methods for QoS minimum packet rate rule:
``list_minimum_packet_rate_rules``, ``show_minimum_packet_rate_rule``,
``create_minimum_packet_rate_rule``, ``update_minimum_packet_rate_rule``,
``delete_minimum_packet_rate_rule``.

View File

@@ -0,0 +1,10 @@
---
deprecations:
- |
``neutron`` CLI will be removed in 'Z' release.
While it has been marked as deprecated for removal for long,
all features in ``neutron`` CLI have been supported in ``openstack`` CLI
(OpenStackClient) as of Xena release and the neutron team plans to
remove it in 'Z' release. Consider using ``openstack`` CLI and
`Mapping Guide <https://docs.openstack.org/python-openstackclient/latest/cli/decoder.html#neutron-cli>`__
in the OSC documentation would help you.

View File

@@ -0,0 +1,7 @@
---
prelude: >
Openstack community decided to use one SDK for its services, that is
in ``openstacksdk`` repository. To avoid duplication, sooner or later the
python binding code in ``python-neutronclient`` will be deprecated, and
``Neutron`` team decided on the ``2023.1 (Antelope)`` PTG to not allow
new features\' bindings implemented here.

View File

@@ -0,0 +1,7 @@
---
features:
- |
Added new client methods for QoS packet rate limit rule:
``list_packet_rate_limit_rules``, ``show_packet_rate_limit_rule``,
``create_packet_rate_limit_rule``, ``update_packet_rate_limit_rule``,
``delete_packet_rate_limit_rule``.

View File

@@ -6,6 +6,10 @@
:maxdepth: 1
unreleased
zed
yoga
xena
wallaby
victoria
ussuri
train

View File

@@ -0,0 +1,6 @@
============================
Wallaby Series Release Notes
============================
.. release-notes::
:branch: stable/wallaby

View File

@@ -0,0 +1,6 @@
=========================
Xena Series Release Notes
=========================
.. release-notes::
:branch: stable/xena

View File

@@ -0,0 +1,6 @@
=========================
Yoga Series Release Notes
=========================
.. release-notes::
:branch: stable/yoga

View File

@@ -0,0 +1,6 @@
========================
Zed Series Release Notes
========================
.. release-notes::
:branch: stable/zed

View File

@@ -1,3 +1,7 @@
# Requirements lower bounds listed here are our best effort to keep them up to
# date but we do not test them so no guarantee of having them all correct. If
# you find any incorrect lower bounds, let us know or propose a fix.
# 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.
@@ -12,7 +16,7 @@ oslo.log>=3.36.0 # Apache-2.0
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0
os-client-config>=1.28.0 # Apache-2.0
keystoneauth1>=3.4.0 # Apache-2.0
keystoneauth1>=3.8.0 # Apache-2.0
# keystoneclient is used only by neutronclient.osc.utils
# TODO(amotoki): Drop this after osc.utils has no dependency on keystoneclient
python-keystoneclient>=3.8.0 # Apache-2.0

View File

@@ -1,12 +1,12 @@
[metadata]
name = python-neutronclient
summary = CLI and Client Library for OpenStack Networking
description-file =
description_file =
README.rst
author = OpenStack Networking Project
author-email = openstack-discuss@lists.openstack.org
home-page = https://docs.openstack.org/python-neutronclient/latest/
python-requires = >=3.6
author_email = openstack-discuss@lists.openstack.org
home_page = https://docs.openstack.org/python-neutronclient/latest/
python_requires = >=3.8
classifier =
Environment :: OpenStack
Intended Audience :: Developers
@@ -18,9 +18,8 @@ classifier =
Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
[files]
packages =
@@ -34,13 +33,6 @@ openstack.cli.extension =
neutronclient = neutronclient.osc.plugin
openstack.neutronclient.v2 =
network_subport_list = neutronclient.osc.v2.trunk.network_trunk:ListNetworkSubport
network_trunk_create = neutronclient.osc.v2.trunk.network_trunk:CreateNetworkTrunk
network_trunk_delete = neutronclient.osc.v2.trunk.network_trunk:DeleteNetworkTrunk
network_trunk_list = neutronclient.osc.v2.trunk.network_trunk:ListNetworkTrunk
network_trunk_set = neutronclient.osc.v2.trunk.network_trunk:SetNetworkTrunk
network_trunk_show = neutronclient.osc.v2.trunk.network_trunk:ShowNetworkTrunk
network_trunk_unset = neutronclient.osc.v2.trunk.network_trunk:UnsetNetworkTrunk
sfc_flow_classifier_create = neutronclient.osc.v2.sfc.sfc_flow_classifier:CreateSfcFlowClassifier
sfc_flow_classifier_delete = neutronclient.osc.v2.sfc.sfc_flow_classifier:DeleteSfcFlowClassifier
sfc_flow_classifier_list = neutronclient.osc.v2.sfc.sfc_flow_classifier:ListSfcFlowClassifier

24
tox.ini
View File

@@ -1,7 +1,7 @@
[tox]
envlist = py38,pep8
minversion = 2.3.2
skipsdist = True
envlist = py39,pep8
minversion = 3.18.0
skipsdist = False
ignore_basepython_conflict = True
[testenv]
@@ -12,18 +12,17 @@ setenv = VIRTUAL_ENV={envdir}
LC_ALL=C
PYTHONWARNINGS=default::DeprecationWarning
usedevelop = True
install_command = pip install {opts} {packages}
deps = -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
# Delete bytecodes from normal directories before running tests.
# Note that bytecodes in dot directories will not be deleted
# to keep bytecodes of python modules installed into virtualenvs.
commands = sh -c "find . -type d -name '.?*' -prune -o \
commands = bash -c "find . -type d -name '.?*' -prune -o \
\( -type d -name '__pycache__' -o -type f -name '*.py[co]' \) \
-print0 | xargs -0 rm -rf"
stestr run {posargs}
whitelist_externals = sh
allowlist_externals = bash
[testenv:pep8]
commands =
@@ -59,7 +58,7 @@ commands = sphinx-build -W -b html doc/source doc/build/html
[testenv:pdf-docs]
envdir = {toxworkdir}/docs
deps = {[testenv:docs]deps}
whitelist_externals =
allowlist_externals =
make
commands =
sphinx-build -W -b latex doc/source doc/build/pdf
@@ -81,11 +80,8 @@ enable-extensions=H904
[testenv:bandit]
# B303: blacklist calls: md5, sha1
# B105: The software contains a hard-coded password, which it uses for its own
# inbound authentication or for outbound communication to external
# components.
deps = -r{toxinidir}/test-requirements.txt
commands = bandit -r neutronclient -x tests -n5 -s B303
[testenv:lower-constraints]
deps =
-c{toxinidir}/lower-constraints.txt
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt
commands = bandit -r neutronclient -x tests -n5 -s B303,B105