././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2456641 python-neutronclient-11.2.0/0000775000175000017500000000000000000000000016026 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/.coveragerc0000664000175000017500000000014700000000000020151 0ustar00zuulzuul00000000000000[run] branch = True source = neutronclient omit = neutronclient/tests/* [report] ignore_errors = True ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/.pylintrc0000664000175000017500000000255300000000000017700 0ustar00zuulzuul00000000000000# The format of this file isn't really documented; just use --generate-rcfile [MASTER] # Add to the black list. It should be a base name, not a # path. You may set this option multiple times. ignore=test [Messages Control] # NOTE(justinsb): We might want to have a 2nd strict pylintrc in future # C0111: Don't require docstrings on every method # W0511: TODOs in code comments are fine. # W0142: *args and **kwargs are fine. # W0622: Redefining id is fine. disable=C0111,W0511,W0142,W0622 [Basic] # Variable names can be 1 to 31 characters long, with lowercase and underscores variable-rgx=[a-z_][a-z0-9_]{0,30}$ # Argument names can be 2 to 31 characters long, with lowercase and underscores argument-rgx=[a-z_][a-z0-9_]{1,30}$ # Method names should be at least 3 characters long # and be lowercased with underscores method-rgx=([a-z_][a-z0-9_]{2,50}|setUp|tearDown)$ # Module names matching quantum-* are ok (files in bin/) module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(quantum-[a-z0-9_-]+))$ # Don't require docstrings on tests. no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$ [Design] max-public-methods=100 min-public-methods=0 max-args=6 [Variables] # List of additional names supposed to be defined in builtins. Remember that # you should avoid to define new builtins when possible. # _ is used by our localization additional-builtins=_ ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/.stestr.conf0000664000175000017500000000011300000000000020272 0ustar00zuulzuul00000000000000[DEFAULT] test_path=${OS_TEST_PATH:-./neutronclient/tests/unit} top_dir=./ ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/.zuul.yaml0000664000175000017500000000250600000000000017772 0ustar00zuulzuul00000000000000- project: templates: - openstack-cover-jobs - openstack-python3-jobs - publish-openstack-docs-pti - check-requirements - lib-forward-testing-python3 - release-notes-jobs-python3 - openstackclient-plugin-jobs experimental: jobs: - neutronclient-grenade-neutron-lib: irrelevant-files: - ^(test-|)requirements.txt$ - ^setup.cfg$ - job: name: neutronclient-grenade-neutron-lib parent: grenade description: | neutron-lib grenade job. The version of this job on the current branch is py3 based, while any branch before ussuri needs to use the py2 version, which is defined in openstack-zuul-jobs with the old name (legacy-grenade-dsvm-neutron-libs). Users of this job needs to pay attention of the version used. Former names for this job were: * legacy-grenade-dsvm-neutron-libs * neutron-lib-grenade-dsvm required-projects: - openstack/keystoneauth - openstack/neutron - openstack/neutron-lib - openstack/os-client-config - openstack/python-cinderclient - openstack/python-glanceclient - openstack/python-ironicclient - openstack/python-keystoneclient - openstack/python-neutronclient - openstack/python-novaclient ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201317.0 python-neutronclient-11.2.0/AUTHORS0000664000175000017500000003202000000000000017073 0ustar00zuulzuul00000000000000Aaron Rosen Aaron Rosen Aaron-Zhang231 Abhishek Chanda Abhishek Kekane Abhishek Raut Abhishek Raut Adrien Vergé Akihiro MOTOKI Akihiro Motoki Akihiro Motoki Alessandro Pilotti Alessio Ababilov Alex Gaynor Amir Sadoughi Anand Shanmugam Andreas Jaeger Andreas Jaeger Andres Buraschi Andy McCrae Angus Lees Anindita Das Anita Kuno Ankur Gupta Armando Migliaccio Assaf Muller AvnishPal Ben Andrews Bence Romsics Bernard Cafarelli Bertrand Lallau Bhuvan Arumugam Bob Kukura Brad Hall Bradley Klein Brandon Logan Brandon Palm Brian Haley Brian Haley Brian Waldon Cao Xuan Hoang Carl Baldwin Carl Baldwin Carlos D. Garza Carlos Goncalves Cedric Brandily Chen Chris Krelle Chris Yeoh Christian Berendt Chuck Short Ciprian Cosma Clark Boylan Clenimar Filemon Clenimar Filemon Corey Bryant Craig Tracey Cyril Roelandt Daire Ní Chatháin Dan Prince Dan Wendlandt Danny Choi Darek Smigiel (dasm) Dariusz Smigiel Davanum Srinivas Dean Troyer Deepthi V V Dina Belova Dirk Mueller Dmitry Kulishenko Dmitry Tantsur Dongcan Ye Doug Fish Doug Hellmann Doug Hellmann Doug Wiegley Drew Thorstensen Duan Jiong Elena Ezhova Elod Illes Elvira García Eugene Nikanorov Evgeny Fedoruk Fei Long Wang Feng Xi Yan Flavio Percoco Frode Nordahl Gal Sagie Gary Kotton Gary Kotton German Eichberger Ghanshyam Mann Gleb Zimin Gábor Antal Haim Daniel Hangdong Zhang He Jie Xu He Yongli Henry Gessau Henry Gessau Hervé Beraud Hideki Saito Hirofumi Ichihara Hong Hui Xiao Hongbin Lu Hongbin Lu IWAMOTO Toshihiro Ian Wienand Igor Duarte Cardoso Ihar Hrachyshka Ilya Shakhat Inessa Vasilevskaya Ionuț Arțăriși Irina Isaku Yamahata Jakub Libosvar James Arendt James E. Blair Jamie Lennox Jason Zhang Jaspinder Jaume Devesa Jay Faulkner Jens Harbott Jeremy Liu Jeremy Stanley Jesse Proudman Jiajun Liu Joe Gordon John Davidge John Schwarz John Trowbridge Julien Danjou Justin Hammond Jyotsna K Jonathan Harker KATO Tomoyuki KC Wang Kenji Yasui Kevin Benton Kevin Benton Kim Bao Long Koteswara Rao Kelam Kyle Mestery Kyle Mestery LIU Yulong LIU Yulong Lokesh S Lucas H. Xu Lucian Petrut Luigi Toscano M V P Nitesh Madhav Puri Manjeet Singh Bhatia Marcos Lobo Mark McClain Mark Rawlings Maru Newby Maru Newby Matt Riedemann Matthew Treinish Michael Johnson Miguel Lavalle Ming Yang Mitsuru Kanabuchi Mohankumar Monty Taylor Mykola Yakovliev Na Nachi Ueno Nachi Ueno Nandini Tata Nguyen Hai Nikola Dipanov Nikolas Hermanns Oleg Bondarev Ondřej Nový OpenStack Release Bot Paul Michali Paul Michali Pedro Henrique Phil Day PhilippeJ Pritesh Kothari Przemyslaw Szczerbik Qin Zhao QunyingRan Rabi Mishra Rajesh Mohan Rakesh H S Ramanjaneya Reedip Reedip Banerjee Richard Theis Robert Collins Robert Li Rodion Tikunov Rodolfo Alonso Hernandez Rodolfo Alonso Hernandez Roman Podolyaka Rudrajit Tapadar Russell Bryant Ryan Tidwell Ryan Tidwell Saksham Varma Salvatore Orlando Salvatore Orlando Salvatore Orlando Samuel Barré Sascha Peilicke Sascha Peilicke Sean Dague Sean McGinnis Sean Winn Sergio Cazzolato Shih-Hao Li Slawek Kaplonski SongmingYan Sourabh Patwardhan Sridhar Gaddam Stanislav Kudriashev Stanislaw Pitucha Stephen Balukoff Stephen Finucane Stephen Ma Steve Martinelli Sudhakar Babu Gariganti Sudipta Biswas Sumit Naiksatam Sushil Kumar Swaminathan Vasudevan Swapnil Kulkarni (coolsvap) Sylvain Afchain Sławek Kapłoński Takashi Kajinami Takashi Kajinami Takashi NATSUME Tang Chen Tatyana Leontovich Terry Howe Thiago Morello Thierry Carrez Thomas Herve Thomas Herve Thomas Morin Tin Lam Toshiaki Higuchi Tovin Seven Ukesh Kumar Vasudevan Vic Howard Vieri <15050873171@163.com> Vikash082 Vikram Hosakote Vu Cong Tuan Wu Wenxiang XiaojueGuan Xu Han Peng Xuhan Peng Yaguang Tang Yalei Wang YangLei Yi Zhao Yohei Matsuhashi Yong Sheng Gong Yong Sheng Gong Yushiro FURUKAWA Yuuichi Fujioka Zang MingJie ZhaoBo Zhenguo Niu ZhiQiang Fan ZhiQiang Fan Zhongcheng Lao Zhongyue Luo armando-migliaccio arosen cao.yuan changzhi chenlx chenyaguang cshahani da52700 dekehn dengzhaosen dongwenshuai elajkat gaofei gecong1973 gong yong sheng gongysh gongysh guiyanxing hobo.kengo huang.zhiping huangtianhua ivan-zhu jacky06 jessegler ji-xuepeng jiasirui jichenjc kangyufei karthik s kavithahr likui lilintan linwwu liu-sheng liujingzte liuqing liushuobj liuweicai llg8212 mathieu-rohon melissaml mid_one minwang mohankumar_n nick.zhuyj nmagnezi preeti-mirji ptoohill1 qingszhao reedip ricolin ricolin ritesh.arya ronak ronak-c shenjibiao shihanzhang shreeduth-awasthi shu-mutou sri harsha mekala sridhargaddam sthakkar sunjia takanorimiyagishi venkatamahesh vikram.choudhary watanabe.isao watsalya wengjiangang wu.chunyang wu.shiming xiaosheng xiewj yong sheng gong yuyangbj zengfagao zhangboye zhanghao zhanghao2 zhaojingjing0067370 zheng yin zhurong Édouard Thuleau ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/CONTRIBUTING.rst0000664000175000017500000000107500000000000020472 0ustar00zuulzuul00000000000000If you would like to contribute to the development of OpenStack, you must follow the steps documented at: http://docs.openstack.org/infra/manual/developers.html#development-workflow 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-neutronclient ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201316.0 python-neutronclient-11.2.0/ChangeLog0000664000175000017500000013356700000000000017617 0ustar00zuulzuul00000000000000CHANGES ======= 11.2.0 ------ * reno: Update master for unmaintained/yoga * Bump hacking * Add note to prevent new features to be added (CLI and Python bindings) 11.1.0 ------ * Drop unused simplejson * Imported Translations from Zanata * OSC: Remove SFC V2 calls to neutronclient * OSC: Remove VPNAAS V2 calls to neutronclient * Update master for stable/2023.2 * OSC: Remove FWAAS V2 calls to neutronclient 11.0.0 ------ * BGPVPN: make resource\_association method calls logic simpler * OSC: Remove BGPVPN calls to neutronclient * Remove 'bgp speaker show dragents' 10.0.0 ------ * Remove the CLI code from the Neutron client * OSC: Remove BGP calls to neutronclient * Update master for stable/2023.1 9.0.0 ----- * Remove CLI warning message * Move network trunk commands from python-neutronclient * Tox4: add allowlist\_externals where necessary 8.2.1 ----- * Fix help sentence in network log create --enable 8.2.0 ----- * Add warning and reno for SDK * Switch to 2023.1 Python3 unit tests and generic template name * Update master for stable/zed 8.1.0 ----- * Add support to floating ip port forwarding 8.0.0 ----- * Update python testing as per zed cycle teting runtime * Drop lower-constraints.txt and its testing * Update master for stable/yoga * Skip B105 pep8 error: hardcoded passwords 7.8.0 ----- * Update python testing classifier * Add CURD actions for packet rate limit rule 7.7.0 ----- * Add support for minimum packet rate rule to the client * Fix lower-constraints and neutronclient-functional job * Add support for 'smart-nic' vnic-type * Add Python3 yoga unit tests * Update master for stable/xena * Replace deprecated assertDictContainsSubset 7.6.0 ----- * Use yaml.safe\_load instead of yaml.load * Set ML2/OVS backend explicitly for functional job * tests: change safe\_hasattr to hasattr * Ussuri+ is python3 only and update python to python3 7.5.0 ----- * Add a release note on deprecation for removal of neutron CLI * Changed minversion in tox to 3.18.0 * Set when deprecated neutron client CLI will be removed * Skip metering functional tests when metering extension is not enabled 7.4.0 ----- * setup.cfg: Replace dashes with underscores * Replace getargspec with getfullargspec * Fix lower constraints * Add Python3 xena unit tests * Update master for stable/wallaby * Support passing mTLS certificate/key to HTTPClient 7.3.0 ----- * remove unicode from code * Dep's should be restricted by tox-constraints * Update requirements URLs in tox config * Add Python3 wallaby unit tests * Update master for stable/victoria * Fix lower-constraints for Focal 7.2.1 ----- * Allow 4byte ASNs in dynamic routing client * Remove translation sections from setup.cfg * zuul: native Zuul v3 version of the grenade job * Fix description of bgp speaker set arg * lower-constraints: Drop os-testr, mox3 7.2.0 ----- * Use unittest.mock instead of mock * Stop to use the \_\_future\_\_ module * Use unittest.mock instead of third party mock * Add segments client code * Remove usage of six * Switch to newer openstackdocstheme and reno versions * Add aggressive negotiation mode for ikepolicy * Fix hacking min version to 3.0.1 * Bump default tox env from py37 to py38 * Add py38 package metadata * Remove Babel from requirements * Add Python3 victoria unit tests * Update master for stable/ussuri 7.1.1 ----- * Cleanup py27 support 7.1.0 ----- * Replace 'bgp speaker show dragents' with 'bgp dragent list' * Drop lib-forward-testing * Add support for port bindings 7.0.0 ----- * Convert exception to string before passing it in * Avoid py36 error when printing unicode chars in a stream * fix a typo * Fix pep8 errors with hacking 2.0.0 * Drop python 2.7 support * Drop python3 hack for XML serializer * Move grenade neutron-lib job to py3 and in python-neutronclient repo * Switch to Ussuri jobs * Remove 'public' and 'private' parameters in fwaas\_v2 * Update master for stable/train 6.14.0 ------ * Add router add/remove extra routes operations * PDF documentation build * Improve help text * Fix string in header * Use secure sha256 instead of sha1 6.13.0 ------ * Switch functional job to python3 * Convert legacy functional jobs to zuulv3 * Run functional test correctly * Add friendly event hints for logging * Add Python 3 Train unit tests * Blacklist bandit 1.6.0 due to directory exclusion bug * doc: Remove prompt from python binding examples * Replace git.openstack.org URLs with opendev.org URLs * OpenDev Migration Patch * Dropping the py35 testing * Replace openstack.org git:// URLs with https:// * Update master for stable/stein 6.12.0 ------ * Add subnet onboard CLI * Update json module to jsonutils * add python 3.7 unit test job * Remove basepython from [flake8] section * Update hacking version to 1.1 * Update mailinglist from dev to discuss * Add support for querying quotas with usage * Change openstack-dev to openstack-discuss * Add Python 3.6 classifier to setup.cfg * Support of the boolean advertise\_extra\_routes 6.11.0 ------ * Fix docstring in method list\_routers\_on\_l3\_agent * Fix docstring in method list\_networks\_on\_dhcp\_agent * Update min tox version to 2.3.2 * Fix api version handling, which completely breaks the client * Don't quote {posargs} in tox.ini * Adds the destination and source fwg to fwr * Use templates for cover and lower-constraints * Consolidate irrelevant files added for py3 project * Switch to stestr 6.10.0 ------ * Ensure API calls for subnets are in URL length limit * add lib-forward-testing-python3 test job * add python 3.6 unit test job * switch documentation job to new PTI * import zuul job settings from project-config * fix tox python3 overrides * [log] Add 'firewall\_group' as a loggable resource type for logging * Add B303 into list of skipped bandit plugins * Fix broken unittests * Update reno for stable/rocky * Add release note link in README * Add bandit to pep8 gate * Update links in README 6.9.0 ----- * Remove PyPI downloads * Trivial: Update pypi url to new url * Set or unset port pair group failed * Replace insecure function eval * Fix pep8 error * Fix list bgp speaker by agent ID * Add oslo.log to requirements.txt * Follow the new PTI for document build * Fix incompatible requirement in lower-constraints 6.8.0 ----- * Remove mox3 from test-requirements.txt * Remove mox/mox3 usage from test\_cli20.py * Remove mox/mox3 usage from lb modules * Remove mox/mox3 usage from fw modules * Remove mox/mox3 usage from bgp * Remove mox/mox3 from test\_cli20\_address\_scope.py * Remove mox/mox3 from test\_cli20\_agentschedulers.py * Rename python-openstacksdk to openstacksdk * Updated from global requirements * add lower-constraints job * Remove mox/mox3 usage from test\_cli20\_securitygroup.py * Remove mox/mox3 usage from test\_cli20\_subnet.py * Remove mox/mox3 usage from test\_cli20\_subnetpool.py * Remove mox/mox3 usage from test\_cli20\_network.py * Updated from global requirements * Remove mox/mox3 usage from test\_name\_or\_id.py * Remove mox/mox3 usage from test\_cli20\_port.py * Fix the assertion of standard error text * Remove mox/mox3 usage from test\_cli20\_tag * Remove mox/mox3 usage from test\_quota * Updated from global requirements * Remove bogus ID column from ListRoutesAdvertisedBySpeaker * Updated from global requirements * Drop neutronclient-specific cliff sphinx extension * Consume column utils from osc-lib * Update reno for stable/queens 6.7.0 ----- * Fix broken links * Updated from global requirements * Define IpAddressAlreadyAllocated exception * osc, bgpvpn: add support for 'local\_pref' BGPVPN attribute * Add commands to support BGP VPN route control new API extension * Updated from global requirements * VNI support in BGPVPN CLI * Updated from global requirements * Add VPNaaS commands for OSC plugin * Add Logging commands for OSC plugin * Add 'revision\_number' to update\_\* API * Pass headers to httpclient * Enable VPNaaS functional tests in the neutronclient gate * Updated from global requirements * Updated from global requirements * Remove a workaround for osc-lib in FWaaS UT 6.6.0 ----- * Avoid tox\_install.sh for constraints support * Remove setting of version/release from releasenotes * Added 'tap\_enabled' parameter for Port-pair-group * Consume tempest CLIClient keystone v3 support * Add correlation type "nsh" to both PPs and PCs * Add Service Graphs networking-sfc resource * Dynamic routing CLIs OSC transition * SFC plugin: preserve chain order in set/unset commands * SFC plugin: fix dictionary parameters * SFC plugin: fix port chain set commands * SFC plugin: fix all list commands * Use generic $USER variable for functional tests * Updated from global requirements * Make func test work with keystone v3 only * Updated from global requirements * Updated from global requirements * Updated from global requirements * Define shell.COMMANDS explicitly to avoid random UT failure * Add missing correlation type "mpls" to port pair * Updated from global requirements * Update reno for stable/pike 6.5.0 ----- * Populate shell.COMMANDS dict not to break CLI extension UT * [FWaaS] Migrate 'public' attribute to 'shared' * SFC plugin: fix flow classifier list display 6.4.0 ----- * Updated from global requirements * Update the documentation link for doc migration * Replace uuid.uuid4() with uuidutils.generate\_uuid() * Updated from global requirements * Updated from global requirements * Add SFC cli for OSC plugin * doc: autogenerate neutron CLI reference * doc: autogenerate OSC plugin command reference * doc: Improve network CLI page * Use flake8-import-order plugin * Enable warning-is-error in doc build * Use entry points to define neutron CLI commands * doc: use new config options of openstackdocstheme * Updated from global requirements * remove explicit global\_request\_id handling from session client * move existing content into the new standard structure * switch to openstackdocstheme * Updated from global requirements * CLI implementation should raise CommandError * Call mock.patch.stopall in OSC unit tests * BGP unit test 'auth-type' errors * Updated from global requirements * Updated from global requirements 6.3.0 ----- * Allow global\_request\_id in Client constructor * Updated from global requirements * Updated from global requirements * Machine-readable output for JSON/YAML format * FWaaS UT: Fake rule should return value returned from API * Drop deprecated neutronclient.i18n wrapper * Updated from global requirements * Now empty tags are not added to Networks * Be explicit about the identity plugin required in unit tests * Supports adding tags for port, router, subnet, subnetpool * Add optional\_keys and required\_keys to --subport argument * Updated from global requirements * Fix using wrong status code in some tests * Updated from global requirements 6.2.0 ----- * Do not append .json to sending URL * FWaaS OSC plugin: Use python logging instead of oslo.log * Allow to specify tenant\_id in subnetpool-create * Fix label of allowed-address-pair ip\_address * Remove log translations * Convert gate\_hook to devstack-tools * Don't sort the fw\_rule order in OSC * Python 3.4 support is removed * Updated from global requirements * Handle log message interpolation by the logger * [Fix gate]Update test requirement * Change documentation about UpdateQuota class * doc: Patch acceptance policy after neutron CLI deprecation * doc: Fix warning * Add profiling support to neutronclient * Drop MANIFEST.in - it's not needed by pbr * Trivial Fix:fix typo in .pylintrc file * Updated from global requirements * Add BGP VPN OSC commands * Updated from global requirements * Update reno for stable/ocata 6.1.0 ----- * FWaaSv2 - Enable to specify 'any' for protocol * FWaaS - Adds an argument into find\_resource * Add plug-in summary for osc doc * x-openstack-request-id logged twice in logs * Set project\_id column header to Project * Modify key for 'qos-minimum-bandwidth-rule-list' reponse * Updated from global requirements * Replace 'os' to 'openstack' for all command example * Add documentation for FWaaS v2 OSC plugin commands * The testcase's name may be inapposite. It is better to use 'delete', instead of 'delele' * Add FWaaS V2 commands for OSC plugin * Updated from global requirements * Decode exception parameters to expand exception message properly * Add common utilities for OSC plugin implementation * Clarify how to do client-side development for repos in neutron governance * Disable VPNaaS functional tests in the neutronclient gate * Show team and repo badges on README * Fix a typo * Refactor of Network tests * Added --enable-snat option for router-gateway-set * [VPNaaS] Add support for sha2-384 and sha2-512 * Devref: Transition to OSC update * Deprecate neutron CLI * Remove unused object * Updated from global requirements * Updated from global requirements * Updated from global requirements * Add rbac\_policy to quota resources * Use method is\_valid\_cidr from oslo.utils * OSC plugin: catch up with osc-lib 1.0 interface change * Updated from global requirements * Fix Quota Support for HMs * Enable release notes translation * Return proper error code for CLI failure * Replace 'MagicMock' with 'Mock' * Handle keystoneauth exceptions in retry logic * Revert "HAProxy uses milliseconds for its timeout values." * Replace lb\_method with lb\_algorithm * Update reno for stable/newton 6.0.0 ----- * Correct DisassociatingHealthmonitor help messages * Updated from global requirements * Sync tools/tox\_install.sh * Use correct cmd\_parser * Devref: Newton mid-cycle updates for transition to OSC * Make trunk commands handle description for trunk resources * quota-update to return an error msg for 0 args * Fix the problem of "qos-bandwidth-limit-rule-show" * fix one spelling mistake * Add flavor argument to router * Add QoS egress minimum bandwidth rule to neutronclient * Make trunk commands handle timestamps for trunk resources * Provide client bindings for DELETE method of auto-allocated-topology extension * Updated from global requirements * Move advanced service functional tests to functional-adv-svcs * Drop LBaaS v1 functional tests * Clean imports in code * Remove case dependancy for user inputs * Unable to add classless-static-route in extra\_dhcp\_opt extension * Updated from global requirements * Fix prompt message for qos-bandwidth-limit-rule-create * Add possible updatable options to net-update CLI * Remove admin-state-down from lbaas-member-update * Use upper constraints for all jobs in tox.ini * Improve Help message of VPN Update CLI * Updated from global requirements * Simplify clearing session-persistence * Enable DeprecationWarning in test environments * Do not check stderr output from shell * Fix problem of RBAC command arguments * Trivial correction in variable name * Add 'shared' option to neutron address-scope-update * Update OSC transition status 5.1.0 ----- * Update docs to use Identity v3 * Add support for Bulk Delete in NeutronClient * Don't decode empty response body * Remove environment defaults * Disallow specifying name for meter-label-rule * Add Python 3.5 classifier and venv * Make find\_resourceid\_by\_id public in python binding class * Updated from global requirements * Add documentation for OSC plugin commands * Add long option to network trunk list command * Add trunk commands to openstackclient * Move find\_resource family to API binding layer * Add quota support for LB and Listeners 5.0.0 ----- * Fix string interpolation at logging call * Add client exception for HostNotCompatibleWithFixedIps * Remove discover from test-requirements * Updated from global requirements * Log request-id for each api call * Add functional test hook for fwaas command * Add support to expose default quotas for tenants * Improve help messages for NeutronClient * remove unused LOG * HAProxy uses milliseconds for its timeout values * Base OSC plugin support * Updated from global requirements * Make USER\_AGENT variable global * Modify the help of connection-limit * Trivial: missing comma in the docs * Fixed --insecure not taking effect when specified * Fix the problem of mox in test\_shell.py * Updated from global requirements * Fix the problem of "qos-dscp-marking-rule-show" * Trivial Fix: Fix typo * Add segment as an attribute to subnet in client * improve readme contents * Add no-shared option to qos-policy-update command * Updated from global requirements * Add in missing translations * Trivial: ignore openstack/common in flake8 exclude list * Update for API bindings * Remove unnecessary executable permissions * Updated from global requirements * Update tempest\_lib to tempest.lib * Constraint tox targets with upper-constraints.txt * Make purge supports dvr router's interface * Switched from fixtures.MonkeyPatch to mock.patch * tests: removed mocking for Client.get\_attr\_metadata * Update the home-page with developer documentation * Address pairs help missing space * Devref: Add dynamic routing to OSC transition * Updated from global requirements * Updated from global requirements * Support sha256 for vpn-ikepolicy and vpn-ipsecpolicy * Fixes unclear error when no --pool-prefix given * Updated from global requirements * Added missing help text for 'purge' command * Fix random failure of security group unit test * Remove the last remaining vendor code 4.2.0 ----- * Change try..except to assertRaises in UT * Update help information for lbaasv2 CLIs * Updated from global requirements * Devref: Newton updates for transition to OSC * Change --no-gateway help text * Log SHA1 hash of X-Auth-Token value * Devref Update: Transition to OpenStack Client * Fix duplicate entries in list\_columns while extending the list * Remove APIParamsCall decorator * Fix assertNotEqual parameters * organize the release notes consistently * Update reno for stable/mitaka * Add parser options for description on resources * Use raw values when non-table formatter is used * Updated from global requirements 4.1.1 ----- * Add release note of critial TypeError fix * Fix TypeError with error message * Adding DSCP marking changes to neutronclient 4.1.0 ----- * Update relnote on fix of bug 1450414 * Support dry-run option for auto-allocated-topology * fix: can't get authentication with os-token and os-url * refactor: Merge all debug logging at the beginning of take\_action * refactor: Avoid overriding run() in cliff command * Add tags support * Fixed typos in securitygroup.py * Add commands for Network IP Availability * Support cleanup of tenant resources with a single API call * Reflecting L7 content rules capability in LBaaS * LBaaS updates to reflect shared pools feature * Fixed a bunch of spacing * Misleading output when network is not found * add rbac support for qos-policies * Devref Update: Transition to OpenStack Client * Add wrapper classes for return-request-id-to-caller * BGP Dynamic Routing: neutronclient changes * Add use\_default\_subnetpool to subnet create requests * Do not print 'Created' message when using non-table formatter * Ensure to use exception per status code for all cases * Use instanceof instead of type * Add DNS integration support to the client * Improve str2dict key validation to avoid wrong keys * Updated from global requirements * Fix the exception when ID/Name not found * Fix typo in the help of net-list * Fix typos in the docstrings * Updated from global requirements * Provide argument filtering in neutron \*-list * Client bindings for Get-me-a-network * "neutron help firewall-rule-update" info updated * Show all updatable options in (fw/fw-policy)-update CLI * Allow UPPER case in protocol/action for FW Rule * Make metavar usage consistent * Update translation setup * Remove unnecessary entry from old relnotes * Fix code-block for python code in doc * Show tenant\_id in \*-list by admin * Updated from global requirements * Trivial Update on ReleaseNotes * Remove inconsistency from vpn help text * Remove argparse from requirements * Add code for load balancer status tree * Add support for default subnetpools API * Updated from global requirements * Fix typo in docstrings * refactor: Get rid of usage of get\_data in favor of take\_action * refactor: Drop meaningless 'api' attribute from NeutronCommand class * refactor: Remove usage of useless command.command.OpenStackCommand * Convert remaining use of neutronclient.i18n to \_i18n * Updated from global requirements * Remove 'u' displayed before subnetpool-list's prefixes * Add support for ip\_version on AddressScope create * Enhance the help info of "neutron router-gateway-set" 4.0.0 ----- * Adding a lowercase converter in utils.py * Updated from global requirements * Add some items to the release notes * Devref: Transition to OpenStack Client * Updated from global requirements * Use six.python\_2\_unicode\_compatible for NeutronException.\_\_str\_\_ * port: Add 'direct-physical' as a valid vnic-type * Drop unused TableFormater code * Updated from global requirements * test: fix option in port test * Support pagination listing in client extension * Add protocol value options to sg-rule-create * improve tox -e cover * Use \_i18n instead of i18n * Add method to retrieve loadbalancer stats * Support for Name field in Members and HMs * Show availability\_zone info in CLI neutron agent-list * Delete python bytecode before every test run * Updated from global requirements * Reworded nargs='?' explanation for better clarity * Drop py33 support * Fixed connection\_limit and added UT * Add help information of 'firewall-rule-create' * Allow tenant\_id positional in quota syntax * Fix H405 violations * Updated from global requirements * Deprecated tox -downloadcache option removed * Remove nuage plugin from client * Adding missing headers to the devref documents * Allow lower case protocol values * Allow passing version as '2' as well as '2.0' * Remove XML support * Add availability\_zone CLI * Updated from global requirements * Remove extra space from VPN validator exception messages * Updated from global requirements * Add CLI option guideline * Add description of extra args in CLI * Add os-client-config to CLI usage * Add more contents about CLI usage * Setup for translation * Do not include reno releasenotes in normal documentation * Add release notes for changes since 3.0.0 release * Fix a column name "protocol/port" to "port/protocol" * Remove py26 support * Reorganize documentation structure * Updated from global requirements * Trivial: Fix a typo in class ListCommand * Use sphinx-build -W in [docs] target * Updated from global requirements * Add 'baremetal' as an allowed vnic type * Add reno for release notes management * Move the old release notes to a separate file * Do not allow name lookups on RBAC policies * Add route options to neutron router-update * Revert "Revert "Remove Cisco-specific neutron client commands"" * Improve neutron-client error message output * CLI support for VPNaaS multiple local subnets * Add flavor argument to loadbalancer v2 create * Drop cliff-tablib from test-requirements.txt * Add Neutron flavor framework CLI * Create floating IP on a specific subnet ID * Documentation error in show\_bandwidth\_limit\_rule * Use os-client-config and keystoneauth1 in shell * Updated from global requirements * Adding a generate\_default\_ethertype\_function * Use clouds.yaml from devstack for functional tests * Updated from global requirements * Updated from global requirements * Updated from global requirements * Revert parent\_id and obj\_id parameter order * Updated from global requirements * Fix arg order of assertEqual and use assertTrue * Let devstack-gate handle the gate hook timeout * Ensure to decode bytes or fail * Updated from global requirements * Add allowed-address-pairs to port-update * neutron v2 command module cleanup (2) * neutron v2 command module cleanup #1 * CRUD for VPN endpoint group API * Define non\_admin\_status\_resources in each test * Fix extend\_show parameter name * Py3k compliance: check for bytes when making a string * Enable VPN test cases 3.1.0 ----- * Updated from global requirements * Change ignore-errors to ignore\_errors * Revert "Remove Cisco-specific neutron client commands" * Updated from global requirements * Remove Cisco-specific neutron client commands 3.0.0 ----- * Remove NEC plugin specific commands * Update path to subunit2html in post\_test\_hook * Updated from global requirements * Add REJECT rule on FWaaS Client * Update tls\_container\_id to tls\_container\_ref * Updated from global requirements * Support CLI changes for QoS (2/2) * Support QoS neutron-client (1/2) * Clear the extension requirement * Updated from global requirements * Make subnetpool-list show correct address scope column * Fix find\_resourceid\_by\_name call for address scopes * Add extension name to extension's command help text line * Adding registration interface for non\_admin\_status\_resources * Add document for entry point in setup.cfg * Create hooks for running functional test * Support Command line changes for Address Scope * Remove --shared option from firewall-create * Disable failing vpn tests * Support RBAC neutron-client changes * Remove newlines from request and response log * Updated from global requirements * NSX gateway extension: allow more transport type values * Updated from global requirements * Devref documentation for client command extension support * Support CLI changes for associating subnetpools and address-scopes * Remove unused AlreadyAttachedClient * Avoid overwriting parsed\_args * Determine ip version during subnet create * Call UnsetStub/VerifyAll properly for tests with exceptions * Updated from global requirements * Support for child resource extensions * Support resource plurals not ending in 's' * Updated from global requirements * Revert "Add '--router:external' option to 'net-create'" * Updated from global requirements * Updated from global requirements * Fixes indentation for bash completion script * Allow bash completion script to work with BSD sed * Add alternative login description in neutronclient docs * Updated from global requirements * Raise user-friendly exceptions in str2dict * LBaaS v2: Fix listing pool members * Fix functional tests and tox 2.0 errors 2.6.0 ----- * Updated from global requirements * Allow setting router's external ip(s) * Add missing tenant\_id to lbaas-v2 resources creation * Add InvalidIpForSubnetClient exception * Drop use of 'oslo' namespace package * Updated from global requirements * Add functional test for subnet create * Fix Python client library for Neutron * Update README to work with release tools 2.5.0 ----- * Uncap library requirements for liberty * Add --binding-profile to port-create * Fix invalid error message in neutron-cli 2.4.0 ----- * Fix one remaining E125 error and remove it from ignore list * Add basic functional tests for client library * Add Neutron subnetpool API * Revert "Remove unused AlreadyAttachedClient" * Allow passing None for subnetpool * Add Neutron subnet-create with subnetpool * Adding VLAN Transparency support to neutronclient * 'neutron port-create' missing help info for --binding:vnic-type * Support fwaasrouterinsertion extension * Prefer argparse mutual exclusion * Add HA router state to l3-agent-list-hosting-router * Make secgroup rules more readable in security-group-show * Fix E265 block comment should start with '# ' * Remove author tag * Update hacking to 0.10 * Updated from global requirements * Fix failures when calling list operations using Python binding * Updates pool session persistence options * security-group-rule-list: show all info of rules briefly * Show rules in handy format in security-group-list * Add commands from extensions to available commands * Updating lbaas cli for TLS * Copy functional tests from tempest cli * Remove unused AlreadyAttachedClient * exec permission to port\_test\_hook.sh * Reinstate Max URI length checking to V2\_0 Client * Add post\_test\_hook for functional tests * First pass at tempest-lib based functional testing * Add OS\_TEST\_PATH to testr * "neutron help router-update" help info updated * Ignore order of query parameters when compared in MyUrlComparator * Fixed pool and health monitor create bugs * Added client calls for the lbaas v2 agent scheduler * Client command extension support * Fix lbaas-loadbalancer-create with no --name * Honor allow\_names in \*-update command * Updated from global requirements * Make some auth error messages more verbose 2.3.11 ------ * Updated from global requirements * Add unit tests for agentscheduler related commands * Fix for incorrect parameter in user-id error message in shell.py * Fix CSV formatting of fixed\_ips field in port-list command * Implement LBaaS object model v2 * Fix typo in test\_cli20\_agentschedulers filename * Add ip\_version to extra dhcp opts * Skip None id when getting security\_group\_ids * Reverse order of tests to avoid incompatibility * Utility method for boolean argument * Split base function of v2\_0.Client into a separate class * Updated from global requirements * Add parser options for port-update and port-create * Add floating-ip-address to floatingip-create * Fix KeyError when filtering SG rule listing * Updated from global requirements * Remove unreachable code from test\_cli20 class * Parse provider network attributes in net\_create * Parameter support both id and name * Add '--router:external' option to 'net-create' * Fix TypeError for six.text\_type * Add Python 3 classifiers * Namespace of arguments is incorrectly used * Fix True/False to accept Camel and Lower case * Use adapter from keystoneclient * Use requests\_mock instead of mox * Updated from global requirements 2.3.10 ------ * firewall policy update for a rule is not working * subnet: allow --enable-dhcp=False/True syntax, again * Fix columns setup base on csv formatter * Correct the bash completion of CLI * Workflow documentation is now in infra-manual * Router create distributed accepts lower case * Fix issues with Unicode compatibility for Py3 * Add unit tests for agent related commands * Make help for agent-update more verbose * Use discovery fixture * Cleanup copy and pasted token * fix the firewall rule arg split error * Updated from global requirements * Change Creates to Create in help text * Disable name support for lb-healthmonitor-\* commands * Fix mixed usage of \_ * Fixes neutronclient lb-member-show command * neutron port-list -f csv outputs poorly formatted JSON strings * Updated from global requirements * Don't allow update of ipv6-ra-mode and ipv6-address-mode * Updated from global requirements * Use graduated oslo libraries * Fix E113 hacking check * Fix E129 hacking check * Updated from global requirements * Add InvalidIpForNetworkClient exception * Add missing parameters to Client's docstring * Leverage neutronclient.openstack.common.importutils import\_class * Remove extraneous vim editor configuration comments * Fix E128 hacking check * Don't get keystone session if using noauth * Bump hacking to 0.9.x series * Change "healthmonitor" to "health monitor" in help info * Correct 4xx/5xx response management in SessionClient * Change ipsecpolicies to 2 separate words: IPsec policies * handles keyboard interrupt * Use six.moves cStringIO instead of cStringIO * Updated from global requirements * Replace httpretty with requests\_mock 2.3.9 ----- 2.3.8 ----- * Fix Py3 compatibility issues * Narrow down except clause * Correct Content-Type/Accept management in HTTPClient/SessionClient * Allow to specify policy by name in firewall-update * Silence iso8601 debug messages in verbose mode * Stop using intersphinx * Updated from global requirements * Replace utils.dumps with jsonutils.dumps * Fix to ensure endpoint\_type is used by make\_client() * Add L3 HA / VRRP support to CLI * Improve help strings * Isolate tests from HTTP\_PROXY, OS\_REGION\_NAME env vars * Leverage openstack.common.jsonutils * Work toward Python 3.4 support and testing * Clean-up shell run and run\_subcommand methods 2.3.7 ----- * Updated from global requirements * Remove unnecessary get\_status\_code wrapper function * Unify doc-strings format * Small improve of str2dict function * Fix CLI support for DVR, take 2 * Refactor CreateRouter to use update\_dict * Repeat add-tenant and remove-tenant option in cli * Rename --timeout param to --http-timeout * Fix typo in cli help * neutronclient shows low-level logs in console screen * Print exception when verbose is over DEBUG\_LEVEL * Adds tty password entry for neutronclient * Remove incorrect super() call * Avoid modifying default function arguments * Fix unit tests to succeed on any PYTHONHASHSEED * Provide support for nested objects * Add keystone v3 auth support * Updated from global requirements * Fix listing security group rules * Introduce shadow resources for NeutronCommands * setup logger name of NeutronCommand automatically 2.3.6 ----- * Add option for retry number of connection attempts * Remove strict checking of encryption type * Remove "--disabled" for firewall create rule * Improve the method find\_resourceid\_by\_name\_or\_id * Add a new timeout option to set the HTTP Timeout * Python 3: compatibility of StringIO() and dict.iterkeys() * Revert "Fix CLI support for DVR" * Update theme for docs * Add a tox job for generating docs * Add MacAddressInUseClient exception handling * Create new IPv6 attributes for Subnets by client * Python 3: use six.iteritems() * Fix for CLI message of agent disassociation * Fix CLI support for DVR * Warn on tiny subnet * Some edits for help strings * Changed 'json' to 'JSON' * Add CLI Support for DVR * Add CONTRIBUTING.rst * Pass timeout parameter to requests lib call * Found a useless comment * Suppress outputs in test\_cli20\_nsx\_networkgateway * Sync with oslo * Changed 'xml' to 'XML' * Switch over to mox3 2.3.5 ----- * Improve help strings * Ensure .status\_code is defined for all NeutronClientExceptions * Silences the output in CLI for connection info * debug level logs should not be translated * Updated from global requirements * Set firewall\_rules only after appending all rules * Make neutronclient parse keystone v3 endpoints correctly * removed usage of '... can be repeated.' * added new column binary to the listing of agents * Add ability to update certain attributes in a subnet * Removed now unnecesary workaround for PyPy * Add OverQuotaClient as exception to neutronclient * Synced jsonutils from oslo-incubator * enable sorting support for agent listing * Suppress expected help messages caused by wrong CLI inputs * Updated from global requirements * Remove httplib2 requirement * Updated from global requirements * Allow user ID for authentication * Use requests module for HTTP/HTTPS * Support packet\_filter extension in NEC plugin * Python3: fix syntax issue in \_encode\_item() * Updated from global requirements * Return response status reason on error * Improvements in neutron\_test sanity tests script * Adds support for os-auth-strategy=noauth * Show the unknown auth stratey in neutron client * Rearrange neutronclient exceptions for more easy use * Suppress stdout/stderr in test\_shell * Work around pypy testing issue * Empty file shouldn't contain copyright nor license * Updated from global requirements * CLI support for NSX gateway devices * Use six.moves.urllib.parse to replace urlparse * Updated from global requirements * New exception when auth\_url is not specified * Supporting Net-Partition as extension for Nuage plugin * Print human friendly string as an error message * Python 3: fix a call to ugettext() * Enable to select specific network service type * Replace assertEqual(None, \*) with assertIsNone in tests * Adds delete of extra-dhcp-opt to the client * Unexpected response in agent-list command * Remove unused imports * Enable hacking H233 rule 2.3.4 ----- * Don't reuse 'body' for response data * Work around for httplib2 retries on timeout * Modify quota-list descripton * Extending quota support neutron LBaaS entities * Fix net-gateway-create help message * Remove vi modelines * Support building wheels (PEP-427) * Fixed get\_auth\_info() for pre-authenticated clients * Fixed a minor typo in a docstring * Add shared parameter for metering labels * Rename Nicira NVP to VMware NSX in neutronclient * session\_persistence: invalid str2dict value: u'' * update coveragerc file * Adding weight column to Neutron lb member list CLI * Combine debug and verbose commandline options * Mention --fixed-ip subnet\_id=<..> in help message * Fix description of ListSubnet 2.3.3 ----- * Make compatible with Cliff (1.5.2) * Remove an unused imported module * Remove a debugging print statement * Remove start index 0 in range() 2.3.2 ----- * Pin Sphinx to <1.2 in test-requirements * Add -U to pip install command in tox.ini * Misc typo in neutronclient * Use assertIn where appropriate * Fix neutron port-create --no-security-groups * Fix i18n messages in neutronclient * Updates .gitignore * Convert xrange to range * Ignores swap files generated during file editing * Handle IpAddressInUse with client exception * Fix lb-healthmonitor-update to work with correct object * [fwaas] Can now create disabled firewall rules * Log reason for connection failed exception * Make HACKING.rst DRYer * Fix status\_code not passed in code * Add ability to reference pool by name in lb-pool-stats command * Updated from global requirements * Fix stable/grizzly gating for Neutron (aka Quantum) * Change copyright headers from LLC to Foundation * Forcibly clear connection pool after every request * Updated from global requirements * Adds ExternalIpAddressExhaustedClient exception * Fixes the display message for the insert/remove firewall rule CLI * Adds IpAddressGenerationFailureClient exception * Update tox.ini to use new features * Update help string to match API doc 2.3.1 ----- * Client for metering extension * Update cliff version to 1.4.3 in requirements.txt * Fix cisco n1kv plugin cli option and help * Add provider attribute to lb-pool-create command * Allow 'any' option for protocol in the firewall rule 2.3.0 ----- * The "arg\_value" was not getting checked for empty list * Use assertEqual instead of assertEquals * bp:pxeboot-ports, provide pxboot on ports * Move vpn unittest code to neutronclient.tests * Add 'distributed' option to router-create command * Remove openstack.common.exception usage * Makes client always use provided endpoint\_url * Make \_test\_update\_resource honor format * Sync test-requirements with global requirements * Added support for running the tests under PyPy with tox * Fix H202 hacking check in VPN client * neutron router-gateway-set failed for non-admin users * Add multi-segment and trunk support to N1KV Neutron client * VPN as a Service (VPNaaS) Client API * Move tests back to neutronclient package * Add credentials and profile support to Neutron client * Remove status field from the list of fields of Healthmonitor * Updated from global requirements * remove useless column in list\_columns 2.2.6 ----- * Add get\_attr for EXTED\_PLURALS 2.2.5 ----- * Sync with global requirements * Improve help message of loadbalancer commands * Don't log the credentials by default * FWaaS Client and Cli * Add command for listing available service providers * Remove repeated initialisation * Add commands related to loadbalancer agent scheduling * Handle host side SSL certificates validation * raise better exception for duplicate match * let cliff install the right pyparsing * Remove commented out code * Allow tenant ID for authentication * Add --security-group option to port-update * Don't convert httplib2 exceptions to status codes * Allow user to specify None value to attributes * Renamed quantum to neutron in .gitreview 2.2.4 ----- * Rename quantumclient to neutronclient 2.2.3 ----- * python3: Introduce py33 to tox.ini * Make --version option print a more detailed client version * Fix mocking of HTTPClient.request() method * Enables H404 check (multi line docstring) in flake8 * Support router-interface-add/delete by port\_id * Allow subnet name in lb-vip-create and lb-pool-create * Remove the monkey patching of \_ into the builtins 2.2.2 ----- * update to latest pbr & remove distribute from tox * Remove class-based import in the code repo * Remove explicit distribute depend * Add metavar for --fixed-ip * Rename README to README.rst * add readme for 2.2.2 * Rename requires files to standard names * Set default columns in ext-list * Migrate to pbr * Allow the HTTPClient consumer to pass endpoint\_type * CLI support for disabling SNAT * Add update method of security group name and description * Make flake8 deps consistent with other projects * Avoid error 414 when retrieving subnet cidrs for ListNetworks * Improve unit tests for python-quantumclient * Fix a comment formatting to make pep8 test pass * Enable automatic validation of many HACKING rules * Add custom TableFormater for keep same empty list behavior as prettytable 0.6 * Change variable name of admin\_state\_down to admin\_state * Fix xml request doesn't work with unicode * Switch to flake8 from pep8 * Exclude top level 'tests dir' from packages * Add public api to get authentication info from client * Move tests to project root 2.2.1 ----- * Add AUTHOR and .testrepository to .gitignore * Update --remote-group-id metavar to REMOTE\_GROUP * Handle auth\_token and endpoint\_url if passed to the http client constructor * Don't query the agent with name * remove remainder argument Bug #1160203 * Update tools/pip-requires for prettytable * Improve unit tests for python-quantumclient * Add exception & gettextutils to openstack.common * Reordering of optional and required args in lbaas commands help * add 2.2.0 release note in index.rst file * Add a missing command line option: --insecure * Improve unit tests for python-quantumclient 2.2.0 ----- * Fix a description of floatingip-id in (dis)associate commands * Add support for security group quotas * Rename source\_(group\_id/ip\_prefix) to remote\_(group\_id/ip\_prefix) * Add pagination support for client * rename port to port\_protocol for lbaas cli * Client for agent scheduler extension 2.1.2 ----- * Update cliff dependency (1.3.1) * quantumclient.common.serializer module cleanup 2.2.0a1 ------- * CLI support for network gateway feature * Allow known options after unknown ones in list and update command * Match other python-\*client prettytable dependency * Client for agent extension * Add nvp queue support to client * Add exceptions messages for authentication 3.0.a1 ------ * Add .coveragerc * Support XML request format * Allow ability to remove security groups from ports * Stored the quantum commands list to the variable * Remove gettext.install from quantumclient.\_\_init\_\_ * Migrate from nose to testr * The change implements LBaaS CLI commands * Delete network with id in sample code using API * Remove multiple white spaces * Fix quantum client example * Exception should raise with status code * Display security group name in security-group-rule-list * Migrate from unittest to testtools * Allow known options defined after position arguments * Display subnet cidr information in net-list * Make "quantum help" to show a list of subcommands * Fix import order nits * Add file 'ChangeLog' to MANIFEST.in * Add --security-group option to port-create * bug 1091028 * Support dash-style options for security-group commands * Add --dns-nameserver, --host-route, --disable-dhcp to subnet-create * Fix a wrong substition for '-h' in bash completion * Ensures that help alignment is not hard coded * Display columns in the order of -c options * Add --router and --floatingip to quota-update options * Correct the verbose output formatting when creating routers * Convenience cmds for l3 * Fix curl command for PUT and DELETE * Fixes setup compatibility issue on Windows * Adds securitygroup implementation * Add OpenStack trove classifier for PyPI * Generate bash\_completion string so that we can use bash completion * clean the descriptions for quota cli commands 2.1 --- * fix a minor comment error * Add document for using quantum client by python or cli invocation * Support shared option in CLI * Limit list command for router and floating ip * prevent floatingip-show and floatingip-delete from querying by "name" * Send all options with CreateFloatingIP * router/floating commands support resource reference by name * update error message to make clear that we were search for a name * \*-list command shows only limited fields normally * Fix printout of dns name servers and host routes * Change '\_' to '-' in options * initial client + CLI support for routers + floating ips * Add nosehtmloutput as a test dependency * Add install\_requires in setuptools.setup() * Fix warning when creating the sdist package * Support --no-gateway option 2.0 --- * add pyparsing to pip-requires * add ext list and show commands * remove cli.app in quantum client error message * enable -h | --help after command to show the command usage * deal with -c option when the list result is empty * Add quota commands to change quota of a tenant * Refreshes keystone token if a token is expired * update mailing list, etc in setup.py * Add name or id to quantum cli commands. Bug #1030180 * Allow to retrieve objects by name * Remove quantum client codes for API v1.0 Bug #1021546 * Use -h, --help to show help messages * Support allocation pools for subnet * Make quantum cli consistent with other cli's practice 0.1.1 ----- * Add post-tag versioning 0.1.0 ----- * add --fixed-ip argument to create port * add keystone support, new command interface, API v2.0 * Add initial docs * quit and print usage when unsupported version specified * Use --debug to enable printing HTTP message(s) between client and server, besides logging verbosely * Add HACKING.rst to generated tarballs * Align tox with standards * Clean up codebase in accordance with HACKING/PEP8 * Remove server-specific functionality * bug 963155: add some missing test files to the sdist tarball * Fix quantum client exception when server returns 500 error * Open Folsom * Add retry support to the quantum client * Remove generation of quantum/vcsversion.py * add LICENSE file to sdist tarball * Adds client side functions for quantum 'detail' actions * bp/quantum-client-1.1 * Bug 921930 remove depedency on webob from python-quantumclient * bug 933125 ensure cli.py executes from the shell * Enable log output to syslog * Add "quantum" package so that \_\_init\_\_.py is included * unexecutable lib files should not contain a shebang * Additional small release needs * Initial cut at removing unneeded dependencies * Added 501 exceptions to client package * move batch\_config.py to client library * Added README * Prepare for Jenkins gating job * Split quantumclient out * Second round of packaging changes ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/HACKING.rst0000664000175000017500000000227000000000000017625 0ustar00zuulzuul00000000000000Neutron Style Commandments ================================ - Step 1: Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/ - Step 2: Read on Running Tests ------------- The testing system is based on a combination of tox and testr. The canonical approach to running tests is to simply run the command `tox`. This will create virtual environments, populate them with depenedencies and run all of the tests that OpenStack CI systems run. Behind the scenes, tox is running `testr run --parallel`, but is set up such that you can supply any additional testr arguments that are needed to tox. For example, you can run: `tox -- --analyze-isolation` to cause tox to tell testr to add --analyze-isolation to its argument list. It is also possible to run the tests inside of a virtual environment you have created, or it is possible that you have all of the dependencies installed locally already. In this case, you can interact with the testr command directly. Running `testr run` will run the entire test suite. `testr run --parallel` will run it in parallel (this is the default incantation tox uses.) More information about testr can be found at: http://wiki.openstack.org/testr ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/LICENSE0000664000175000017500000002363700000000000017046 0ustar00zuulzuul00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2456641 python-neutronclient-11.2.0/PKG-INFO0000664000175000017500000000572100000000000017130 0ustar00zuulzuul00000000000000Metadata-Version: 1.2 Name: python-neutronclient Version: 11.2.0 Summary: CLI and Client Library for OpenStack Networking Home-page: https://docs.openstack.org/python-neutronclient/latest/ Author: OpenStack Networking Project Author-email: openstack-discuss@lists.openstack.org License: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: https://governance.openstack.org/tc/badges/python-neutronclient.svg :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on Python bindings to the Neutron API ================================== .. image:: https://img.shields.io/pypi/v/python-neutronclient.svg :target: https://pypi.org/project/python-neutronclient/ :alt: Latest Version This is a client library for Neutron built on the Neutron API. It provides a Python API (the ``neutronclient`` module). .. note:: This project has been deprecated. The CLI code has been deleted and is not accessible anymore. The Python bindings are still in use by other projects but no new features will be added to this project. Any new feature should be proposed to OpenStack SDK and OpenStack Client. * License: Apache License, Version 2.0 * `PyPi`_ - package installation * `Online Documentation`_ * `Launchpad project`_ - release management * `Blueprints`_ - feature specifications * `Bugs`_ - issue tracking * `Source`_ * `Developer's Guide`_ .. _PyPi: https://pypi.org/project/python-neutronclient .. _Online Documentation: https://docs.openstack.org/python-neutronclient/latest/ .. _Launchpad project: https://launchpad.net/python-neutronclient .. _Blueprints: https://blueprints.launchpad.net/python-neutronclient .. _Bugs: https://bugs.launchpad.net/python-neutronclient .. _Source: https://opendev.org/openstack/python-neutronclient .. _Developer's Guide: http://docs.openstack.org/infra/manual/developers.html .. _Release Notes: https://docs.openstack.org/releasenotes/python-neutronclient Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Requires-Python: >=3.8 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/README.rst0000664000175000017500000000325500000000000017522 0ustar00zuulzuul00000000000000======================== Team and repository tags ======================== .. image:: https://governance.openstack.org/tc/badges/python-neutronclient.svg :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on Python bindings to the Neutron API ================================== .. image:: https://img.shields.io/pypi/v/python-neutronclient.svg :target: https://pypi.org/project/python-neutronclient/ :alt: Latest Version This is a client library for Neutron built on the Neutron API. It provides a Python API (the ``neutronclient`` module). .. note:: This project has been deprecated. The CLI code has been deleted and is not accessible anymore. The Python bindings are still in use by other projects but no new features will be added to this project. Any new feature should be proposed to OpenStack SDK and OpenStack Client. * License: Apache License, Version 2.0 * `PyPi`_ - package installation * `Online Documentation`_ * `Launchpad project`_ - release management * `Blueprints`_ - feature specifications * `Bugs`_ - issue tracking * `Source`_ * `Developer's Guide`_ .. _PyPi: https://pypi.org/project/python-neutronclient .. _Online Documentation: https://docs.openstack.org/python-neutronclient/latest/ .. _Launchpad project: https://launchpad.net/python-neutronclient .. _Blueprints: https://blueprints.launchpad.net/python-neutronclient .. _Bugs: https://bugs.launchpad.net/python-neutronclient .. _Source: https://opendev.org/openstack/python-neutronclient .. _Developer's Guide: http://docs.openstack.org/infra/manual/developers.html .. _Release Notes: https://docs.openstack.org/releasenotes/python-neutronclient ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2056606 python-neutronclient-11.2.0/doc/0000775000175000017500000000000000000000000016573 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/requirements.txt0000664000175000017500000000051000000000000022053 0ustar00zuulzuul00000000000000# 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. 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 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2056606 python-neutronclient-11.2.0/doc/source/0000775000175000017500000000000000000000000020073 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2056606 python-neutronclient-11.2.0/doc/source/cli/0000775000175000017500000000000000000000000020642 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/index.rst0000664000175000017500000000406400000000000022507 0ustar00zuulzuul00000000000000.. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Convention for heading levels in Neutron devref: ======= Heading 0 (reserved for the title in a document) ------- Heading 1 ~~~~~~~ Heading 2 +++++++ Heading 3 ''''''' Heading 4 (Avoid deeper levels because they do not render well.) ========= Using CLI ========= There is `OpenStackClient (OSC) `__ which support the Networking API OpenStackClient --------------- OpenStackClient provides `the basic network commands `__ and python-neutronclient provides :doc:`extensions ` (aka OSC plugins) for advanced networking services. .. toctree:: :maxdepth: 1 Basic network commands Network commands for advanced networking services Mapping Guide from neutron CLI neutron CLI ----------- .. warning:: neutron CLI is removed. Use openstack CLI instead. See `openstack CLI command list `__ and :doc:`its extensions for advanced networking services `. The command mapping from neutron CLI to openstack CLI is available `here `__. ././@PaxHeader0000000000000000000000000000003200000000000011450 xustar000000000000000026 mtime=1709201317.19766 python-neutronclient-11.2.0/doc/source/cli/osc/0000775000175000017500000000000000000000000021426 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2056606 python-neutronclient-11.2.0/doc/source/cli/osc/v2/0000775000175000017500000000000000000000000021755 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc/v2/bgp-dynamic-routing.rst0000664000175000017500000000260500000000000026371 0ustar00zuulzuul00000000000000=================== BGP Dynamic Routing =================== BGP dynamic routing enables announcement of project subnet prefixes via BGP. Admins create BGP speakers and BGP peers. BGP peers can be associated with BGP speakers, thereby enabling peering sessions with operator infrastructure. BGP speakers can be associated with networks, which controls which routes are announced to peers. Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp speaker create .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp speaker delete .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp speaker list .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp speaker set .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp speaker show .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp speaker add network .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp speaker remove network .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp speaker add peer .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp speaker remove peer .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp speaker list advertised routes .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp peer * .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp dragent * ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc/v2/firewall-group.rst0000664000175000017500000000153100000000000025446 0ustar00zuulzuul00000000000000============== firewall group ============== A **firewall group** is a perimeter firewall management to Networking. Firewall group uses iptables to apply firewall policy to all VM ports and router ports within a project. Network v2 .. 'firewall group *' cannot be used below as it matches 'firewall group rule *' or 'firewall group policy *'. .. autoprogram-cliff:: openstack.neutronclient.v2 :command: firewall group create .. autoprogram-cliff:: openstack.neutronclient.v2 :command: firewall group delete .. autoprogram-cliff:: openstack.neutronclient.v2 :command: firewall group list .. autoprogram-cliff:: openstack.neutronclient.v2 :command: firewall group set .. autoprogram-cliff:: openstack.neutronclient.v2 :command: firewall group show .. autoprogram-cliff:: openstack.neutronclient.v2 :command: firewall group unset ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc/v2/firewall-policy.rst0000664000175000017500000000100000000000000025600 0ustar00zuulzuul00000000000000===================== firewall group policy ===================== A **firewall group policy** is an ordered collection of firewall rules. A firewall policy can be shared across projects. Thus it can also be made part of an audit workflow wherein the firewall_policy can be audited by the relevant entity that is authorized (and can be different from the projects which create or use the firewall group policy). Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: firewall group policy * ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc/v2/firewall-rule.rst0000664000175000017500000000054400000000000025264 0ustar00zuulzuul00000000000000=================== firewall group rule =================== A **firewall group rule** represents a collection of attributes like ports, IP addresses which define match criteria and action (allow, or deny) that needs to be taken on the matched data traffic. Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: firewall group rule * ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc/v2/network-log.rst0000664000175000017500000000060400000000000024757 0ustar00zuulzuul00000000000000=========== network log =========== A **network log** is a container to group security groups or ports for logging. Specified resources can be logged via these event (``ALL``, ``ACCEPT`` or ``DROP``). Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: network loggable resources list .. autoprogram-cliff:: openstack.neutronclient.v2 :command: network log * ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc/v2/networking-bgpvpn.rst0000664000175000017500000000206100000000000026167 0ustar00zuulzuul00000000000000====== bgpvpn ====== A **bgpvpn** resource contains a set of parameters to define a BGP-based VPN. BGP-based IP VPNs networks are widely used in the industry especially for enterprises. The networking BGP VPN project aims at supporting inter-connection between L3VPNs and Neutron resources, i.e. Networks, Routers and Ports. Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgpvpn create .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgpvpn delete .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgpvpn list .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgpvpn set .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgpvpn show .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgpvpn unset .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgpvpn network association * .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgpvpn router association * .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgpvpn port association * ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc/v2/networking-sfc.rst0000664000175000017500000000251400000000000025451 0ustar00zuulzuul00000000000000============== networking sfc ============== **Service Function Chaining** is a mechanism for overriding the basic destination based forwarding that is typical of IP networks. Service Function Chains consist of an ordered sequence of Service Functions (SFs). SFs are virtual machines (or potentially physical devices) that perform a network function such as firewall, content cache, packet inspection, or any other function that requires processing of packets in a flow from point A to point B even though the SFs are not literally between point A and B from a routing table perspective. Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: sfc flow classifier * .. autoprogram-cliff:: openstack.neutronclient.v2 :command: sfc port chain * .. autoprogram-cliff:: openstack.neutronclient.v2 :command: sfc port pair create .. autoprogram-cliff:: openstack.neutronclient.v2 :command: sfc port pair delete .. autoprogram-cliff:: openstack.neutronclient.v2 :command: sfc port pair list .. autoprogram-cliff:: openstack.neutronclient.v2 :command: sfc port pair set .. autoprogram-cliff:: openstack.neutronclient.v2 :command: sfc port pair show .. autoprogram-cliff:: openstack.neutronclient.v2 :command: sfc port pair group * .. autoprogram-cliff:: openstack.neutronclient.v2 :command: sfc service graph * ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc/v2/subnet-onboard.rst0000664000175000017500000000124600000000000025434 0ustar00zuulzuul00000000000000======================= network onboard subnets ======================= **network onboard subnets** enables a subnet to be adopted or "onboarded" into an existing subnet pool. The CIDR of the subnet is checked for uniqueness across any applicable address scopes and all subnets allocated from the target subnet pool. Once onboarded, the subnet CIDR is added to the prefix list of the subnet pool and the subnet appears as though it has been allocated from the subnet pool. The subnet also begins participating in the applicable address scope if the subnet pool belongs to one. Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: network onboard subnets ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc/v2/vpn-endpoint-group.rst0000664000175000017500000000037700000000000026271 0ustar00zuulzuul00000000000000================== VPN Endpoint Group ================== The **Endpoint Group** is used to configure multiple local and remote subnets in vpnservice object. Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: vpn endpoint group * ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc/v2/vpn-ike-policy.rst0000664000175000017500000000046300000000000025360 0ustar00zuulzuul00000000000000============== VPN IKE Policy ============== The **IKE Policy** is used for phases one and two negotiation of the VPN connection. You can specify both the authentication and encryption algorithms for connections. Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: vpn ike policy * ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc/v2/vpn-ipsec-policy.rst0000664000175000017500000000044100000000000025707 0ustar00zuulzuul00000000000000================ VPN IPsec Policy ================ The **IPsec Policy** specifies the authentication and encryption algorithms and encapsulation mode to use for the established VPN connection. Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: vpn ipsec policy * ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc/v2/vpn-ipsec-site-connection.rst0000664000175000017500000000037300000000000027515 0ustar00zuulzuul00000000000000========================= VPN IPsec Site Connection ========================= Creates a site-to-site **IPsec Site Connection** for a VPN service. Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: vpn ipsec site connection * ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc/v2/vpn-service.rst0000664000175000017500000000036700000000000024756 0ustar00zuulzuul00000000000000=========== VPN Service =========== The **VPN Service** is associated with a router. After you create the service, it can contain multiple VPN connections. Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: vpn service * ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/cli/osc_plugins.rst0000664000175000017500000000237500000000000023730 0ustar00zuulzuul00000000000000.. 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.) Advanced Network Commands in OpenStack Client ============================================= The following list covers the extended commands for advanced network 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 ``. .. toctree:: :glob: :maxdepth: 2 osc/v2/* ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/conf.py0000664000175000017500000000407100000000000021374 0ustar00zuulzuul00000000000000# -*- coding: utf-8 -*- # # -- General configuration --------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.autodoc', 'reno.sphinxext', 'openstackdocstheme', 'cliff.sphinxext', ] # openstackdocstheme options openstackdocs_repo_name = 'openstack/python-neutronclient' openstackdocs_pdf_link = True openstackdocs_bug_project = 'python-neutronclient' openstackdocs_bug_tag = 'doc' # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'index' # General information about the project. copyright = 'OpenStack Foundation' # If true, '()' will be appended to :func: etc. cross-reference text. add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). add_module_names = True # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # -- 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'. html_theme = 'openstackdocs' # Output file base name for HTML help builder. htmlhelp_basename = 'neutronclientdoc' # -- Options for LaTeX output ------------------------------------------------ latex_documents = [ ('index', 'doc-python-neutronclient.tex', 'python-neutronclient Documentation', 'Neutron Contributors', 'manual'), ] # Disable usage of xindy https://bugzilla.redhat.com/show_bug.cgi?id=1643664 latex_use_xindy = False latex_domain_indices = False latex_elements = { 'makeindex': '', 'printindex': '', 'preamble': r'\setcounter{tocdepth}{5}', } # -- Options for cliff.sphinxext plugin --------------------------------------- autoprogram_cliff_application = 'openstack' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2056606 python-neutronclient-11.2.0/doc/source/contributor/0000775000175000017500000000000000000000000022445 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/contributor/index.rst0000664000175000017500000000215100000000000024305 0ustar00zuulzuul00000000000000.. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Convention for heading levels in Neutron devref: ======= Heading 0 (reserved for the title in a document) ------- Heading 1 ~~~~~~~ Heading 2 +++++++ Heading 3 ''''''' Heading 4 (Avoid deeper levels because they do not render well.) ================= Contributor Guide ================= In the Contributor Guide, you will find information on neutronclient's lower level programming details or APIs as well as the transition to OpenStack client. .. toctree:: :maxdepth: 2 transition_to_osc ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/contributor/transition_to_osc.rst0000664000175000017500000003213600000000000026744 0ustar00zuulzuul00000000000000.. 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.) Transition to OpenStack Client ============================== This document details the transition roadmap for moving the neutron client's OpenStack Networking API support, both the Python library and the ``neutron`` command-line interface (CLI), to the `OpenStack Client (OSC) `_ and the `OpenStack Python SDK `_. This transition is being guided by the `Deprecate individual CLIs in favour of OSC `_ OpenStack spec. See the `Neutron RFE `_, `OSC neutron support etherpad `_ and details below for the overall progress of this transition. Overview -------- This transition will result in the neutron client's ``neutron`` CLI being deprecated and then eventually removed. The ``neutron`` CLI will be replaced by OSC's networking support available via the ``openstack`` CLI. This is similar to the deprecation and removal process for the `keystone client's `_ ``keystone`` CLI. The neutron client's Python library won't be deprecated. It will be available along side the networking support provided by the OpenStack Python SDK. Users of the neutron client's command extensions will need to transition to the `OSC plugin system `_ before the ``neutron`` CLI is removed. Such users will maintain their OSC plugin commands within their own project and will be responsible for deprecating and removing their ``neutron`` CLI extension. Transition Steps ---------------- 1. **Done:** OSC adds OpenStack Python SDK as a dependency. See the following patch set: https://review.opendev.org/#/c/138745/ 2. **Done:** OSC switches its networking support for the `network `_ command object to use the OpenStack Python SDK instead of the neutron client's Python library. See the following patch set: https://review.opendev.org/#/c/253348/ 3. **Done:** OSC removes its python-neutronclient dependency. See the following patch set: https://review.opendev.org/#/c/255545/ 4. **In Progress:** OpenStack Python SDK releases version 1.0 to guarantee backwards compatibility of its networking support and OSC updates its dependencies to include OpenStack Python SDK version 1.0 or later. See the following blueprint: https://blueprints.launchpad.net/python-openstackclient/+spec/network-command-sdk-support 5. **Done:** OSC switches its networking support for the `ip floating `_, `ip floating pool `_, `ip fixed `_, `security group `_, and `security group rule `_ command objects to use the OpenStack Python SDK instead of the nova client's Python library when neutron is enabled. When nova network is enabled, then the nova client's Python library will continue to be used. See the following OSC bugs: * **Done** `Floating IP CRUD `_ * **Done** `Port CRUD `_ * **Done** `Security Group CRUD `_ * **Done** `Security Group Rule CRUD `_ 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. **Done** Deprecate the ``neutron`` CLI. Running the CLI after it has been `deprecated `_ will issue a warning message: ``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. 8. **Done** Remove the ``neutron`` CLI after two deprecation cycles once the criteria below have been met. * The networking support provide by the ``openstack`` CLI is functionally equivalent to the ``neutron`` CLI and it contains sufficient functional and unit test coverage. * `Neutron Stadium `_ projects, Neutron documentation and `DevStack `_ use ``openstack`` CLI instead of ``neutron`` CLI. * Most users of the neutron client's command extensions have transitioned to the OSC plugin system and use the ``openstack`` CLI instead of the ``neutron`` CLI. Developer Guide --------------- The ``neutron`` CLI tool is now removed and all new CLI changes should be done in the ``OpenStackClient (OSC)`` and, if needed, also in the ``OpenStack SDK``. **Where does my CLI belong?** If you are developing an API in any of the `neutron repos `_ the client-side support must be generally located in either the openstackclient or neutronclient repos. Whether the actual code goes into one or the other repo it depends on the nature of the feature, its maturity level, and/or the depth of feedback required during the development. The table below provides an idea of what goes where. Generally speaking, we consider Core anything that is L2 and L3 related or that it has been located in the neutron repo for quite sometime, e.g. QoS or Metering, or that it is available in each neutron deployment irrespective of its configuration (e.g. auto-allocated-topology). Any client feature that falls into this categorization will need to be contributed in OSC. Any other that does not, will need to go into neutronclient, assuming that its server-side is located in a neutron controlled repo. This is a general guideline, when in doubt, please reach out to a member of the neutron core team for clarifications. +---------------------------+-------------------+-------------------------------------------------+ | Networking Commands | OSC Plugin | OpenStack Project for ``openstack`` Commands | +===========================+===================+=================================================+ | Core | No | python-openstackclient | +---------------------------+-------------------+-------------------------------------------------+ | Extension | Yes | python-neutronclient | | (i.e. neutron stadium) | | (``neutronclient/osc/v2/``) | +---------------------------+-------------------+-------------------------------------------------+ | Other | Yes | Applicable project owning networking resource | +---------------------------+-------------------+-------------------------------------------------+ When a repo stops being under neutron governance, its client-side counterpart will have to go through deprecation. Bear in mind that for grandfathered extensions like FWaaS v1, VPNaaS, and LBaaS v1, this is not required as the neutronclient is already deprecated on its own. **Which Python library do I change?** +-------------------------------------------------+-----------------------------------------------+ | OpenStack Project for ``openstack`` Commands | Python Library to Change | +=================================================+===============================================+ | python-openstackclient | openstacksdk | +-------------------------------------------------+-----------------------------------------------+ | Other | Applicable project owning network resource | +-------------------------------------------------+-----------------------------------------------+ **Important:** The actual name of the command object and/or action in OSC may differ from those used by neutron in order to follow the OSC command structure and to avoid name conflicts. The `network` prefix must be used to avoid name conflicts if the command object name is highly likely to have an ambiguous meaning. Developers should get new command objects and actions approved by the OSC team before proceeding with the implementation. The "Core" group includes network resources that provide core ``neutron`` project features (e.g. network, subnet, port, etc.) and not advanced features in the ``neutron`` project (e.g. trunk, etc.) or advanced services in separate projects (FWaaS, LBaaS, VPNaaS, dynamic routing, etc.). The "Other" group applies projects other than the core ``neutron`` project. Contact the neutron PTL or core team with questions on network resource classification. When adding or updating an ``openstack`` networking command to python-openstackclient, changes may first be required to the OpenStack Python SDK to support the underlying networking resource object, properties and/or actions. Once the OpenStack Python SDK changes are merged, the related OSC changes can be merged. The OSC changes may require an update to the OSC openstacksdk version in the `requirements.txt `_ file. When adding an ``openstack`` networking command to python-openstackclient, you can optionally propose an `OSC command spec `_ which documents the new command interface before proceeding with the implementation. Users of the neutron client's command extensions must adopt the `OSC plugin `_ system for this transition. Such users will maintain their OSC plugin within their own project and should follow the guidance in the table above to determine which command to change. Developer References -------------------- * See `OSC neutron support etherpad `_ to determine if an ``openstack`` command is in progress. * See `OSC command list `_ to determine if an ``openstack`` command exists. * See `OSC command spec list `_ to determine if an ``openstack`` command spec exists. * See `OSC plugin command list `_ to determine if an ``openstack`` plugin command exists. * See `OSC command structure `_ to determine the current ``openstack`` command objects, plugin objects and actions. * See `OSC human interface guide `_ for guidance on creating new OSC command interfaces. * See `OSC plugin `_ for information on the OSC plugin system to be used for ``neutron`` CLI extensions. * Create an OSC blueprint: https://blueprints.launchpad.net/python-openstackclient/ * Report an OSC bug: https://bugs.launchpad.net/python-openstackclient/+filebug * Report an OpenStack Python SDK bug: https://bugs.launchpad.net/python-openstacksdk/+filebug ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/index.rst0000664000175000017500000000370600000000000021742 0ustar00zuulzuul00000000000000.. 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.) ================================== python-neutronclient documentation ================================== This is a client for OpenStack Networking API. It provides :doc:`Python API bindings ` (the neutronclient module). There is `OpenStack Client (OSC) `__. CLI which support the Networking API. User Documentation ------------------ .. toctree:: :maxdepth: 2 cli/index reference/index Contributor Guide ----------------- In the :doc:`Contributor Guide `, you will find information on neutronclient's lower level programming details or APIs as well as the transition to OpenStack client. .. toctree:: :maxdepth: 2 contributor/index .. note:: neutron CLI has been deprecated from Ocata release. We do not add, change and drop any existing commands any more. We only accept changes on OSC plugin, neutronclient python bindings and bug fixes on the deprecated CLI (``neutron`` command). History ------- Release notes is available at http://docs.openstack.org/releasenotes/python-neutronclient/. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2056606 python-neutronclient-11.2.0/doc/source/reference/0000775000175000017500000000000000000000000022031 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/doc/source/reference/index.rst0000664000175000017500000000655100000000000023701 0ustar00zuulzuul00000000000000.. 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.) neutronclient Python API ======================== Basic Usage ----------- First create a client instance using a keystoneauth Session. For more information on this keystoneauth API, see `Using Sessions`_. .. _Using Sessions: https://docs.openstack.org/keystoneauth/latest/using-sessions.html .. code-block:: python from keystoneauth1 import identity from keystoneauth1 import session from neutronclient.v2_0 import client username='username' password='password' project_name='demo' project_domain_id='default' user_domain_id='default' auth_url='http://auth.example.com:5000/v3' auth = identity.Password(auth_url=auth_url, username=username, password=password, project_name=project_name, project_domain_id=project_domain_id, user_domain_id=user_domain_id) sess = session.Session(auth=auth) neutron = client.Client(session=sess) If you are using Identity v2.0 API (DEPRECATED), create an auth plugin using the appropriate parameters and `keystoneauth1.identity` will handle Identity API version discovery. Then you can create a Session and a Neutronclient just like the previous example. .. code-block:: python auth = identity.Password(auth_url=auth_url, username=username, password=password, project_name=project_name) # create a Session and a Neutronclient Now you can call various methods on the client instance. .. code-block:: python network = {'name': 'mynetwork', 'admin_state_up': True} neutron.create_network({'network':network}) networks = neutron.list_networks(name='mynetwork') print networks network_id = networks['networks'][0]['id'] neutron.delete_network(network_id) Alternatively, you can create a client instance using an auth token and a service endpoint URL directly. .. code-block:: python from neutronclient.v2_0 import client neutron = client.Client(endpoint_url='http://192.168.206.130:9696/', token='d3f9226f27774f338019aa2611112ef6') You can get ``X-Openstack-Request-Id`` as ``request_ids`` from the result. .. code-block:: python network = {'name': 'mynetwork', 'admin_state_up': True} neutron.create_network({'network':network}) networks = neutron.list_networks(name='mynetwork') print networks.request_ids # -> ['req-978a0160-7ab0-44f0-8a93-08e9a4e785fa'] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2056606 python-neutronclient-11.2.0/neutronclient/0000775000175000017500000000000000000000000020717 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/__init__.py0000664000175000017500000000000000000000000023016 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/_i18n.py0000664000175000017500000000177700000000000022223 0ustar00zuulzuul00000000000000# 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 oslo_i18n DOMAIN = 'neutronclient' _translators = oslo_i18n.TranslatorFactory(domain=DOMAIN) # The translation function using the well-known name "_" _ = _translators.primary # The contextual translation function using the name "_C" _C = _translators.contextual_form # The plural translation function using the name "_P" _P = _translators.plural_form def get_available_languages(): return oslo_i18n.get_available_languages(DOMAIN) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/client.py0000664000175000017500000004055300000000000022556 0ustar00zuulzuul00000000000000# Copyright 2012 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 logging import os import debtcollector.renames from keystoneauth1 import access from keystoneauth1 import adapter from oslo_serialization import jsonutils from oslo_utils import importutils import requests from neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils osprofiler_web = importutils.try_import("osprofiler.web") _logger = logging.getLogger(__name__) if os.environ.get('NEUTRONCLIENT_DEBUG'): ch = logging.StreamHandler() _logger.setLevel(logging.DEBUG) _logger.addHandler(ch) _requests_log_level = logging.DEBUG else: _requests_log_level = logging.WARNING logging.getLogger("requests").setLevel(_requests_log_level) MAX_URI_LEN = 8192 USER_AGENT = 'python-neutronclient' REQ_ID_HEADER = 'X-OpenStack-Request-ID' class HTTPClient(object): """Handles the REST calls and responses, include authn.""" CONTENT_TYPE = 'application/json' @debtcollector.renames.renamed_kwarg( 'tenant_id', 'project_id', replace=True) @debtcollector.renames.renamed_kwarg( 'tenant_name', 'project_name', replace=True) def __init__(self, username=None, user_id=None, project_name=None, project_id=None, password=None, auth_url=None, token=None, region_name=None, timeout=None, endpoint_url=None, insecure=False, endpoint_type='publicURL', 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 self.project_name = project_name self.project_id = project_id self.password = password self.auth_url = auth_url.rstrip('/') if auth_url else None self.service_type = service_type self.endpoint_type = endpoint_type self.region_name = region_name self.timeout = timeout self.auth_token = token self.auth_tenant_id = None self.auth_user_id = None self.endpoint_url = endpoint_url 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: self.verify_cert = ca_cert if ca_cert else True def _cs_request(self, *args, **kwargs): kargs = {} kargs.setdefault('headers', kwargs.get('headers', {})) kargs['headers']['User-Agent'] = USER_AGENT if 'body' in kwargs: kargs['body'] = kwargs['body'] if self.log_credentials: log_kargs = kargs else: log_kargs = self._strip_credentials(kargs) utils.http_log_req(_logger, args, log_kargs) try: resp, body = self.request(*args, **kargs) except requests.exceptions.SSLError as e: raise exceptions.SslCertificateValidationError(reason=str(e)) except Exception as e: # Wrap the low-level connection error (socket timeout, redirect # limit, decompression error, etc) into our custom high-level # connection exception (it is excepted in the upper layers of code) _logger.debug("throwing ConnectionFailed : %s", e) raise exceptions.ConnectionFailed(reason=str(e)) utils.http_log_resp(_logger, resp, body) # log request-id for each api call request_id = resp.headers.get('x-openstack-request-id') if request_id: _logger.debug('%(method)s call to neutron for ' '%(url)s used request id ' '%(response_request_id)s', {'method': resp.request.method, 'url': resp.url, 'response_request_id': request_id}) if resp.status_code == 401: raise exceptions.Unauthorized(message=body) return resp, body def _strip_credentials(self, kwargs): if kwargs.get('body') and self.password: log_kwargs = kwargs.copy() log_kwargs['body'] = kwargs['body'].replace(self.password, 'REDACTED') return log_kwargs else: return kwargs def authenticate_and_fetch_endpoint_url(self): if not self.auth_token: self.authenticate() elif not self.endpoint_url: self.endpoint_url = self._get_endpoint_url() def request(self, url, method, body=None, headers=None, **kwargs): """Request without authentication.""" content_type = kwargs.pop('content_type', None) or 'application/json' headers = headers or {} headers.setdefault('Accept', content_type) if body: headers.setdefault('Content-Type', content_type) if self.global_request_id: headers.setdefault(REQ_ID_HEADER, self.global_request_id) headers['User-Agent'] = USER_AGENT # NOTE(dbelova): osprofiler_web.get_trace_id_headers does not add any # headers in case if osprofiler is not initialized. if osprofiler_web: headers.update(osprofiler_web.get_trace_id_headers()) resp = requests.request( method, url, data=body, headers=headers, verify=self.verify_cert, cert=self.cert, timeout=self.timeout, **kwargs) return resp, resp.text def _check_uri_length(self, action): uri_len = len(self.endpoint_url) + len(action) if uri_len > MAX_URI_LEN: raise exceptions.RequestURITooLong( excess=uri_len - MAX_URI_LEN) def do_request(self, url, method, **kwargs): # Ensure client always has correct uri - do not guesstimate anything self.authenticate_and_fetch_endpoint_url() self._check_uri_length(url) # Perform the request once. If we get a 401 back then it # might be because the auth token expired, so try to # re-authenticate and try again. If it still fails, bail. try: kwargs['headers'] = kwargs.get('headers') or {} if self.auth_token is None: self.auth_token = "" kwargs['headers']['X-Auth-Token'] = self.auth_token resp, body = self._cs_request(self.endpoint_url + url, method, **kwargs) return resp, body except exceptions.Unauthorized: self.authenticate() kwargs['headers'] = kwargs.get('headers') or {} kwargs['headers']['X-Auth-Token'] = self.auth_token resp, body = self._cs_request( self.endpoint_url + url, method, **kwargs) return resp, body def _extract_service_catalog(self, body): """Set the client's service catalog from the response data.""" self.auth_ref = access.create(body=body) self.service_catalog = self.auth_ref.service_catalog self.auth_token = self.auth_ref.auth_token self.auth_tenant_id = self.auth_ref.tenant_id self.auth_user_id = self.auth_ref.user_id if not self.endpoint_url: self.endpoint_url = self.service_catalog.url_for( region_name=self.region_name, service_type=self.service_type, interface=self.endpoint_type) def _authenticate_keystone(self): if self.user_id: creds = {'userId': self.user_id, 'password': self.password} else: creds = {'username': self.username, 'password': self.password} if self.project_id: body = {'auth': {'passwordCredentials': creds, 'tenantId': self.project_id, }, } else: body = {'auth': {'passwordCredentials': creds, 'tenantName': self.project_name, }, } if self.auth_url is None: raise exceptions.NoAuthURLProvided() token_url = self.auth_url + "/tokens" resp, resp_body = self._cs_request(token_url, "POST", body=jsonutils.dumps(body), content_type="application/json", allow_redirects=True) if resp.status_code != 200: raise exceptions.Unauthorized(message=resp_body) if resp_body: try: resp_body = jsonutils.loads(resp_body) except ValueError: pass else: resp_body = None self._extract_service_catalog(resp_body) def _authenticate_noauth(self): if not self.endpoint_url: message = _('For "noauth" authentication strategy, the endpoint ' 'must be specified either in the constructor or ' 'using --os-url') raise exceptions.Unauthorized(message=message) def authenticate(self): if self.auth_strategy == 'keystone': self._authenticate_keystone() elif self.auth_strategy == 'noauth': self._authenticate_noauth() else: err_msg = _('Unknown auth strategy: %s') % self.auth_strategy raise exceptions.Unauthorized(message=err_msg) def _get_endpoint_url(self): if self.auth_url is None: raise exceptions.NoAuthURLProvided() url = self.auth_url + '/tokens/%s/endpoints' % self.auth_token try: resp, body = self._cs_request(url, "GET") except exceptions.Unauthorized: # rollback to authenticate() to handle case when neutron client # is initialized just before the token is expired self.authenticate() return self.endpoint_url body = jsonutils.loads(body) for endpoint in body.get('endpoints', []): if (endpoint['type'] == 'network' and endpoint.get('region') == self.region_name): if self.endpoint_type not in endpoint: raise exceptions.EndpointTypeNotFound( type_=self.endpoint_type) return endpoint[self.endpoint_type] raise exceptions.EndpointNotFound() def get_auth_info(self): return {'auth_token': self.auth_token, 'auth_tenant_id': self.auth_tenant_id, 'auth_user_id': self.auth_user_id, 'endpoint_url': self.endpoint_url} def get_auth_ref(self): return getattr(self, 'auth_ref', None) class SessionClient(adapter.Adapter): def request(self, *args, **kwargs): kwargs.setdefault('authenticated', False) kwargs.setdefault('raise_exc', False) content_type = kwargs.pop('content_type', None) or 'application/json' headers = kwargs.get('headers') or {} headers.setdefault('Accept', content_type) # NOTE(dbelova): osprofiler_web.get_trace_id_headers does not add any # headers in case if osprofiler is not initialized. if osprofiler_web: headers.update(osprofiler_web.get_trace_id_headers()) try: kwargs.setdefault('data', kwargs.pop('body')) except KeyError: pass if kwargs.get('data'): headers.setdefault('Content-Type', content_type) kwargs['headers'] = headers resp = super(SessionClient, self).request(*args, **kwargs) return resp, resp.text def _check_uri_length(self, url): uri_len = len(self.endpoint_url) + len(url) if uri_len > MAX_URI_LEN: raise exceptions.RequestURITooLong( excess=uri_len - MAX_URI_LEN) def do_request(self, url, method, **kwargs): kwargs.setdefault('authenticated', True) self._check_uri_length(url) return self.request(url, method, **kwargs) @property def endpoint_url(self): # NOTE(jamielennox): This is used purely by the CLI and should be # removed when the CLI gets smarter. return self.get_endpoint() @property def auth_token(self): # NOTE(jamielennox): This is used purely by the CLI and should be # removed when the CLI gets smarter. return self.get_token() def authenticate(self): # NOTE(jamielennox): This is used purely by the CLI and should be # removed when the CLI gets smarter. self.get_token() def get_auth_info(self): auth_info = {'auth_token': self.auth_token, 'endpoint_url': self.endpoint_url} # NOTE(jamielennox): This is the best we can do here. It will work # with identity plugins which is the primary case but we should # deprecate it's usage as much as possible. try: get_access = (self.auth or self.session.auth).get_access except AttributeError: pass else: auth_ref = get_access(self.session) auth_info['auth_tenant_id'] = auth_ref.project_id auth_info['auth_user_id'] = auth_ref.user_id return auth_info def get_auth_ref(self): return self.session.auth.get_auth_ref(self.session) # FIXME(bklei): Should refactor this to use kwargs and only # explicitly list arguments that are not None. @debtcollector.renames.renamed_kwarg('tenant_id', 'project_id', replace=True) @debtcollector.renames.renamed_kwarg( 'tenant_name', 'project_name', replace=True) def construct_http_client(username=None, user_id=None, project_name=None, project_id=None, password=None, auth_url=None, token=None, region_name=None, timeout=None, endpoint_url=None, insecure=False, endpoint_type='public', log_credentials=None, auth_strategy='keystone', ca_cert=None, cert=None, service_type='network', session=None, global_request_id=None, **kwargs): if session: kwargs.setdefault('user_agent', USER_AGENT) kwargs.setdefault('interface', endpoint_type) return SessionClient(session=session, service_type=service_type, region_name=region_name, global_request_id=global_request_id, **kwargs) else: # FIXME(bklei): username and password are now optional. Need # to test that they were provided in this mode. Should also # refactor to use kwargs. return HTTPClient(username=username, password=password, project_id=project_id, project_name=project_name, user_id=user_id, auth_url=auth_url, token=token, endpoint_url=endpoint_url, insecure=insecure, timeout=timeout, region_name=region_name, 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) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1709201317.209661 python-neutronclient-11.2.0/neutronclient/common/0000775000175000017500000000000000000000000022207 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/common/__init__.py0000664000175000017500000000000000000000000024306 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/common/clientmanager.py0000664000175000017500000001023400000000000025372 0ustar00zuulzuul00000000000000# Copyright 2012 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. # """Manage access to the clients, including authenticating when needed. """ import debtcollector.renames from neutronclient import client from neutronclient.neutron import client as neutron_client class ClientCache(object): """Descriptor class for caching created client handles.""" def __init__(self, factory): self.factory = factory self._handle = None def __get__(self, instance, owner): # Tell the ClientManager to login to keystone if self._handle is None: self._handle = self.factory(instance) return self._handle class ClientManager(object): """Manages access to API clients, including authentication.""" neutron = ClientCache(neutron_client.make_client) # Provide support for old quantum commands (for example # in stable versions) quantum = neutron @debtcollector.renames.renamed_kwarg( 'tenant_id', 'project_id', replace=True) @debtcollector.renames.renamed_kwarg( 'tenant_name', 'project_name', replace=True) def __init__(self, token=None, url=None, auth_url=None, endpoint_type=None, project_name=None, project_id=None, username=None, user_id=None, password=None, region_name=None, api_version=None, auth_strategy=None, insecure=False, ca_cert=None, log_credentials=False, service_type=None, service_name=None, timeout=None, retries=0, raise_errors=True, session=None, auth=None, ): self._token = token self._url = url self._auth_url = auth_url self._service_type = service_type self._service_name = service_name self._endpoint_type = endpoint_type self._project_name = project_name self._project_id = project_id self._username = username self._user_id = user_id self._password = password self._region_name = region_name self._api_version = api_version self._service_catalog = None self._auth_strategy = auth_strategy self._insecure = insecure self._ca_cert = ca_cert self._log_credentials = log_credentials self._timeout = timeout self._retries = retries self._raise_errors = raise_errors self._session = session self._auth = auth return def initialize(self): if not self._url: httpclient = client.construct_http_client( username=self._username, user_id=self._user_id, project_name=self._project_name, project_id=self._project_id, password=self._password, region_name=self._region_name, auth_url=self._auth_url, service_type=self._service_type, service_name=self._service_name, endpoint_type=self._endpoint_type, insecure=self._insecure, ca_cert=self._ca_cert, timeout=self._timeout, session=self._session, auth=self._auth, log_credentials=self._log_credentials) httpclient.authenticate() # Populate other password flow attributes self._token = httpclient.auth_token self._url = httpclient.endpoint_url ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/common/constants.py0000664000175000017500000000203500000000000024575 0ustar00zuulzuul00000000000000# Copyright (c) 2012 OpenStack Foundation. # # 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. TYPE_BOOL = "bool" TYPE_INT = "int" TYPE_LONG = "long" TYPE_FLOAT = "float" TYPE_LIST = "list" TYPE_DICT = "dict" PLURALS = {'networks': 'network', 'ports': 'port', 'subnets': 'subnet', 'subnetpools': 'subnetpool', 'dns_nameservers': 'dns_nameserver', 'host_routes': 'host_route', 'allocation_pools': 'allocation_pool', 'fixed_ips': 'fixed_ip', 'extensions': 'extension'} ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/common/exceptions.py0000664000175000017500000001513000000000000024742 0ustar00zuulzuul00000000000000# Copyright 2011 VMware, Inc # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from oslo_utils import encodeutils from neutronclient._i18n import _ """ Neutron base exception handling. Exceptions are classified into three categories: * Exceptions corresponding to exceptions from neutron server: This type of exceptions should inherit one of exceptions in HTTP_EXCEPTION_MAP. * Exceptions from client library: This type of exceptions should inherit NeutronClientException. * Exceptions from CLI code: This type of exceptions should inherit NeutronCLIError. """ # NOTE: This method is defined here to avoid # an import loop between common.utils and this module. def _safe_decode_dict(kwargs): for k, v in kwargs.items(): kwargs[k] = encodeutils.safe_decode(v) return kwargs class NeutronException(Exception): """Base Neutron Exception. To correctly use this class, inherit from it and define a 'message' property. That message will get printf'd with the keyword arguments provided to the constructor. """ message = _("An unknown exception occurred.") def __init__(self, message=None, **kwargs): if message: self.message = message try: self._error_string = self.message % _safe_decode_dict(kwargs) except Exception: # at least get the core message out if something happened self._error_string = self.message def __str__(self): return self._error_string class NeutronClientException(NeutronException): """Base exception which exceptions from Neutron are mapped into. NOTE: on the client side, we use different exception types in order to allow client library users to handle server exceptions in try...except blocks. The actual error message is the one generated on the server side. """ status_code = 0 req_ids_msg = _("Neutron server returns request_ids: %s") request_ids = [] def __init__(self, message=None, **kwargs): self.request_ids = kwargs.get('request_ids') if 'status_code' in kwargs: self.status_code = kwargs['status_code'] if self.request_ids: req_ids_msg = self.req_ids_msg % self.request_ids if message: message = _('%(msg)s\n%(id)s') % {'msg': message, 'id': req_ids_msg} else: message = req_ids_msg super(NeutronClientException, self).__init__(message, **kwargs) # Base exceptions from Neutron class BadRequest(NeutronClientException): status_code = 400 class Unauthorized(NeutronClientException): status_code = 401 message = _("Unauthorized: bad credentials.") class Forbidden(NeutronClientException): status_code = 403 message = _("Forbidden: your credentials don't give you access to this " "resource.") class NotFound(NeutronClientException): status_code = 404 class Conflict(NeutronClientException): status_code = 409 class InternalServerError(NeutronClientException): status_code = 500 class ServiceUnavailable(NeutronClientException): status_code = 503 HTTP_EXCEPTION_MAP = { 400: BadRequest, 401: Unauthorized, 403: Forbidden, 404: NotFound, 409: Conflict, 500: InternalServerError, 503: ServiceUnavailable, } # Exceptions mapped to Neutron server exceptions # These are defined if a user of client library needs specific exception. # Exception name should be + 'Client' # e.g., NetworkNotFound -> NetworkNotFoundClient class NetworkNotFoundClient(NotFound): pass class PortNotFoundClient(NotFound): pass class StateInvalidClient(BadRequest): pass class NetworkInUseClient(Conflict): pass class PortInUseClient(Conflict): pass class IpAddressInUseClient(Conflict): pass class IpAddressAlreadyAllocatedClient(Conflict): pass class InvalidIpForNetworkClient(BadRequest): pass class InvalidIpForSubnetClient(BadRequest): pass class OverQuotaClient(Conflict): pass class IpAddressGenerationFailureClient(Conflict): pass class MacAddressInUseClient(Conflict): pass class HostNotCompatibleWithFixedIpsClient(Conflict): pass class ExternalIpAddressExhaustedClient(BadRequest): pass # Exceptions from client library class NoAuthURLProvided(Unauthorized): message = _("auth_url was not provided to the Neutron client") class EndpointNotFound(NeutronClientException): message = _("Could not find Service or Region in Service Catalog.") class EndpointTypeNotFound(NeutronClientException): message = _("Could not find endpoint type %(type_)s in Service Catalog.") class AmbiguousEndpoints(NeutronClientException): message = _("Found more than one matching endpoint in Service Catalog: " "%(matching_endpoints)") class RequestURITooLong(NeutronClientException): """Raised when a request fails with HTTP error 414.""" def __init__(self, **kwargs): self.excess = kwargs.get('excess', 0) super(RequestURITooLong, self).__init__(**kwargs) class ConnectionFailed(NeutronClientException): message = _("Connection to neutron failed: %(reason)s") class SslCertificateValidationError(NeutronClientException): message = _("SSL certificate validation has failed: %(reason)s") class MalformedResponseBody(NeutronClientException): message = _("Malformed response body: %(reason)s") class InvalidContentType(NeutronClientException): message = _("Invalid content type %(content_type)s.") # Command line exceptions class NeutronCLIError(NeutronException): """Exception raised when command line parsing fails.""" pass class CommandError(NeutronCLIError): pass class UnsupportedVersion(NeutronCLIError): """Indicates usage of an unsupported API version Indicates that the user is trying to use an unsupported version of the API. """ pass class NeutronClientNoUniqueMatch(NeutronCLIError): message = _("Multiple %(resource)s matches found for name '%(name)s'," " use an ID to be more specific.") ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/common/extension.py0000664000175000017500000000655200000000000024605 0ustar00zuulzuul00000000000000# Copyright 2015 Rackspace Hosting Inc. # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from stevedore import extension from neutronclient.neutron import v2_0 as neutronV20 def _discover_via_entry_points(): emgr = extension.ExtensionManager('neutronclient.extension', invoke_on_load=False) return ((ext.name, ext.plugin) for ext in emgr) class NeutronClientExtension(neutronV20.NeutronCommand): pagination_support = False _formatters = {} sorting_support = False class ClientExtensionShow(NeutronClientExtension, neutronV20.ShowCommand): def take_action(self, parsed_args): # NOTE(mdietz): Calls 'execute' to provide a consistent pattern # for any implementers adding extensions with # regard to any other extension verb. return self.execute(parsed_args) def execute(self, parsed_args): return super(ClientExtensionShow, self).take_action(parsed_args) class ClientExtensionList(NeutronClientExtension, neutronV20.ListCommand): def take_action(self, parsed_args): # NOTE(mdietz): Calls 'execute' to provide a consistent pattern # for any implementers adding extensions with # regard to any other extension verb. return self.execute(parsed_args) def execute(self, parsed_args): return super(ClientExtensionList, self).take_action(parsed_args) class ClientExtensionDelete(NeutronClientExtension, neutronV20.DeleteCommand): def take_action(self, parsed_args): # NOTE(mdietz): Calls 'execute' to provide a consistent pattern # for any implementers adding extensions with # regard to any other extension verb. return self.execute(parsed_args) def execute(self, parsed_args): return super(ClientExtensionDelete, self).take_action(parsed_args) class ClientExtensionCreate(NeutronClientExtension, neutronV20.CreateCommand): def take_action(self, parsed_args): # NOTE(mdietz): Calls 'execute' to provide a consistent pattern # for any implementers adding extensions with # regard to any other extension verb. return self.execute(parsed_args) def execute(self, parsed_args): return super(ClientExtensionCreate, self).take_action(parsed_args) class ClientExtensionUpdate(NeutronClientExtension, neutronV20.UpdateCommand): def take_action(self, parsed_args): # NOTE(mdietz): Calls 'execute' to provide a consistent pattern # for any implementers adding extensions with # regard to any other extension verb. return self.execute(parsed_args) def execute(self, parsed_args): return super(ClientExtensionUpdate, self).take_action(parsed_args) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/common/serializer.py0000664000175000017500000000726400000000000024743 0ustar00zuulzuul00000000000000# Copyright 2013 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 oslo_serialization import jsonutils from neutronclient._i18n import _ from neutronclient.common import exceptions as exception class ActionDispatcher(object): """Maps method name to local methods through action name.""" def dispatch(self, *args, **kwargs): """Find and call local method.""" action = kwargs.pop('action', 'default') action_method = getattr(self, str(action), self.default) return action_method(*args, **kwargs) def default(self, data): raise NotImplementedError() class DictSerializer(ActionDispatcher): """Default request body serialization.""" def serialize(self, data, action='default'): return self.dispatch(data, action=action) def default(self, data): return "" class JSONDictSerializer(DictSerializer): """Default JSON request body serialization.""" def default(self, data): def sanitizer(obj): return str(obj) return jsonutils.dumps(data, default=sanitizer) class TextDeserializer(ActionDispatcher): """Default request body deserialization.""" def deserialize(self, datastring, action='default'): return self.dispatch(datastring, action=action) def default(self, datastring): return {} class JSONDeserializer(TextDeserializer): def _from_json(self, datastring): try: return jsonutils.loads(datastring) except ValueError: msg = _("Cannot understand JSON") raise exception.MalformedResponseBody(reason=msg) def default(self, datastring): return {'body': self._from_json(datastring)} # NOTE(maru): this class is duplicated from neutron.wsgi class Serializer(object): """Serializes and deserializes dictionaries to certain MIME types.""" def __init__(self, metadata=None): """Create a serializer based on the given WSGI environment. 'metadata' is an optional dict mapping MIME types to information needed to serialize a dictionary to that type. """ self.metadata = metadata or {} def _get_serialize_handler(self, content_type): handlers = { 'application/json': JSONDictSerializer(), } try: return handlers[content_type] except Exception: raise exception.InvalidContentType(content_type=content_type) def serialize(self, data): """Serialize a dictionary into the specified content type.""" return self._get_serialize_handler("application/json").serialize(data) def deserialize(self, datastring): """Deserialize a string to a dictionary. The string must be in the format of a supported MIME type. """ return self.get_deserialize_handler("application/json").deserialize( datastring) def get_deserialize_handler(self, content_type): handlers = { 'application/json': JSONDeserializer(), } try: return handlers[content_type] except Exception: raise exception.InvalidContentType(content_type=content_type) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/common/utils.py0000664000175000017500000001756700000000000023741 0ustar00zuulzuul00000000000000# Copyright 2011, VMware, Inc. # # 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. # # Borrowed from nova code base, more utilities will be added/borrowed as and # when needed. """Utilities and helper functions.""" import argparse import functools import hashlib import logging import os from oslo_utils import encodeutils from oslo_utils import importutils from neutronclient._i18n import _ from neutronclient.common import exceptions SENSITIVE_HEADERS = ('X-Auth-Token',) def env(*vars, **kwargs): """Returns the first environment variable set. If none are non-empty, defaults to '' or keyword arg default. """ for v in vars: value = os.environ.get(v) if value: return value return kwargs.get('default', '') def convert_to_uppercase(string): return string.upper() def convert_to_lowercase(string): return string.lower() def get_client_class(api_name, version, version_map): """Returns the client class for the requested API version. :param api_name: the name of the API, e.g. 'compute', 'image', etc :param version: the requested API version :param version_map: a dict of client classes keyed by version :rtype: a client class for the requested API version """ try: client_path = version_map[str(version)] except (KeyError, ValueError): msg = _("Invalid %(api_name)s client version '%(version)s'. must be " "one of: %(map_keys)s") msg = msg % {'api_name': api_name, 'version': version, 'map_keys': ', '.join(version_map.keys())} raise exceptions.UnsupportedVersion(msg) return importutils.import_class(client_path) def get_item_properties(item, fields, mixed_case_fields=(), formatters=None): """Return a tuple containing the item properties. :param item: a single item resource (e.g. Server, Tenant, etc) :param fields: tuple of strings with the desired field names :param mixed_case_fields: tuple of field names to preserve case :param formatters: dictionary mapping field names to callables to format the values """ if formatters is None: formatters = {} row = [] for field in fields: if field in formatters: row.append(formatters[field](item)) else: if field in mixed_case_fields: field_name = field.replace(' ', '_') else: field_name = field.lower().replace(' ', '_') if not hasattr(item, field_name) and isinstance(item, dict): data = item[field_name] else: data = getattr(item, field_name, '') if data is None: data = '' row.append(data) return tuple(row) def str2bool(strbool): if strbool is None: return None return strbool.lower() == 'true' def str2dict(strdict, required_keys=None, optional_keys=None): """Convert key1=value1,key2=value2,... string into dictionary. :param strdict: string in the form of key1=value1,key2=value2 :param required_keys: list of required keys. All keys in this list must be specified. Otherwise ArgumentTypeError will be raised. If this parameter is unspecified, no required key check will be done. :param optional_keys: list of optional keys. This parameter is used for valid key check. When at least one of required_keys and optional_keys, a key must be a member of either of required_keys or optional_keys. Otherwise, ArgumentTypeError will be raised. When both required_keys and optional_keys are unspecified, no valid key check will be done. """ result = {} if strdict: i = 0 kvlist = [] for kv in strdict.split(','): if '=' in kv: kvlist.append(kv) i += 1 elif i == 0: msg = _("missing value for key '%s'") raise argparse.ArgumentTypeError(msg % kv) else: kvlist[i - 1] = "%s,%s" % (kvlist[i - 1], kv) for kv in kvlist: key, sep, value = kv.partition('=') if not sep: msg = _("invalid key-value '%s', expected format: key=value") raise argparse.ArgumentTypeError(msg % kv) result[key] = value valid_keys = set(required_keys or []) | set(optional_keys or []) if valid_keys: invalid_keys = [k for k in result if k not in valid_keys] if invalid_keys: msg = _("Invalid key(s) '%(invalid_keys)s' specified. " "Valid key(s): '%(valid_keys)s'.") raise argparse.ArgumentTypeError( msg % {'invalid_keys': ', '.join(sorted(invalid_keys)), 'valid_keys': ', '.join(sorted(valid_keys))}) if required_keys: not_found_keys = [k for k in required_keys if k not in result] if not_found_keys: msg = _("Required key(s) '%s' not specified.") raise argparse.ArgumentTypeError(msg % ', '.join(not_found_keys)) return result def str2dict_type(optional_keys=None, required_keys=None): return functools.partial(str2dict, optional_keys=optional_keys, required_keys=required_keys) def http_log_req(_logger, args, kwargs): if not _logger.isEnabledFor(logging.DEBUG): return string_parts = ['curl -i'] for element in args: if element in ('GET', 'POST', 'DELETE', 'PUT'): string_parts.append(' -X %s' % element) else: string_parts.append(' %s' % element) for (key, value) in kwargs['headers'].items(): if key in SENSITIVE_HEADERS: v = value.encode('utf-8') h = hashlib.sha256(v) d = h.hexdigest() value = "{SHA256}%s" % d header = ' -H "%s: %s"' % (key, value) string_parts.append(header) if 'body' in kwargs and kwargs['body']: string_parts.append(" -d '%s'" % (kwargs['body'])) req = encodeutils.safe_encode("".join(string_parts)) _logger.debug("REQ: %s", req) def http_log_resp(_logger, resp, body): if not _logger.isEnabledFor(logging.DEBUG): return _logger.debug("RESP: %(code)s %(headers)s %(body)s", {'code': resp.status_code, 'headers': resp.headers, 'body': body}) def _safe_encode_without_obj(data): if isinstance(data, str): return encodeutils.safe_encode(data) return data def safe_encode_list(data): return list(map(_safe_encode_without_obj, data)) def safe_encode_dict(data): def _encode_item(item): k, v = item if isinstance(v, list): return (k, safe_encode_list(v)) elif isinstance(v, dict): return (k, safe_encode_dict(v)) return (k, _safe_encode_without_obj(v)) return dict(list(map(_encode_item, data.items()))) def add_boolean_argument(parser, name, **kwargs): for keyword in ('metavar', 'choices'): kwargs.pop(keyword, None) default = kwargs.pop('default', argparse.SUPPRESS) parser.add_argument( name, metavar='{True,False}', choices=['True', 'true', 'False', 'false'], default=default, **kwargs) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/common/validators.py0000664000175000017500000000504100000000000024731 0ustar00zuulzuul00000000000000# Copyright 2014 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 netaddr from neutronclient._i18n import _ from neutronclient.common import exceptions def validate_int_range(parsed_args, attr_name, min_value=None, max_value=None): val = getattr(parsed_args, attr_name, None) if val is None: return try: if not isinstance(val, int): int_val = int(val, 0) else: int_val = val if ((min_value is None or min_value <= int_val) and (max_value is None or int_val <= max_value)): return except (ValueError, TypeError): pass if min_value is not None and max_value is not None: msg = (_('%(attr_name)s "%(val)s" should be an integer ' '[%(min)i:%(max)i].') % {'attr_name': attr_name.replace('_', '-'), 'val': val, 'min': min_value, 'max': max_value}) elif min_value is not None: msg = (_('%(attr_name)s "%(val)s" should be an integer ' 'greater than or equal to %(min)i.') % {'attr_name': attr_name.replace('_', '-'), 'val': val, 'min': min_value}) elif max_value is not None: msg = (_('%(attr_name)s "%(val)s" should be an integer ' 'smaller than or equal to %(max)i.') % {'attr_name': attr_name.replace('_', '-'), 'val': val, 'max': max_value}) else: msg = (_('%(attr_name)s "%(val)s" should be an integer.') % {'attr_name': attr_name.replace('_', '-'), 'val': val}) raise exceptions.CommandError(msg) def validate_ip_subnet(parsed_args, attr_name): val = getattr(parsed_args, attr_name) if not val: return try: netaddr.IPNetwork(val) except (netaddr.AddrFormatError, ValueError): raise exceptions.CommandError( (_('%(attr_name)s "%(val)s" is not a valid CIDR.') % {'attr_name': attr_name.replace('_', '-'), 'val': val})) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1709201317.209661 python-neutronclient-11.2.0/neutronclient/neutron/0000775000175000017500000000000000000000000022411 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/__init__.py0000664000175000017500000000000000000000000024510 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/client.py0000664000175000017500000000431200000000000024241 0ustar00zuulzuul00000000000000# Copyright 2012 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 neutronclient.common import utils API_NAME = 'network' API_VERSIONS = { '2.0': 'neutronclient.v2_0.client.Client', '2': 'neutronclient.v2_0.client.Client', } def make_client(instance): """Returns an neutron client.""" neutron_client = utils.get_client_class( API_NAME, instance._api_version, API_VERSIONS, ) instance.initialize() url = instance._url url = url.rstrip("/") client = neutron_client(username=instance._username, project_name=instance._project_name, password=instance._password, region_name=instance._region_name, auth_url=instance._auth_url, endpoint_url=url, endpoint_type=instance._endpoint_type, token=instance._token, auth_strategy=instance._auth_strategy, insecure=instance._insecure, ca_cert=instance._ca_cert, retries=instance._retries, raise_errors=instance._raise_errors, session=instance._session, auth=instance._auth) return client def Client(api_version, *args, **kwargs): """Return an neutron client. @param api_version: only 2.0 is supported now """ neutron_client = utils.get_client_class( API_NAME, api_version, API_VERSIONS, ) return neutron_client(*args, **kwargs) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1709201317.209661 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/0000775000175000017500000000000000000000000023157 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/__init__.py0000664000175000017500000007427600000000000025310 0ustar00zuulzuul00000000000000# Copyright 2012 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 abc import argparse import functools import logging from cliff import command from cliff import lister from cliff import show from oslo_serialization import jsonutils from neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils HYPHEN_OPTS = ['tags_any', 'not_tags', 'not_tags_any'] def find_resource_by_id(client, resource, resource_id, cmd_resource=None, parent_id=None, fields=None): return client.find_resource_by_id(resource, resource_id, cmd_resource, parent_id, fields) def find_resourceid_by_id(client, resource, resource_id, cmd_resource=None, parent_id=None): return find_resource_by_id(client, resource, resource_id, cmd_resource, parent_id, fields='id')['id'] def find_resource_by_name_or_id(client, resource, name_or_id, project_id=None, cmd_resource=None, parent_id=None, fields=None): return client.find_resource(resource, name_or_id, project_id, cmd_resource, parent_id, fields) def find_resourceid_by_name_or_id(client, resource, name_or_id, project_id=None, cmd_resource=None, parent_id=None): return find_resource_by_name_or_id(client, resource, name_or_id, project_id, cmd_resource, parent_id, fields='id')['id'] def add_show_list_common_argument(parser): parser.add_argument( '-D', '--show-details', help=_('Show detailed information.'), action='store_true', default=False, ) parser.add_argument( '--show_details', action='store_true', help=argparse.SUPPRESS) parser.add_argument( '--fields', help=argparse.SUPPRESS, action='append', default=[]) parser.add_argument( '-F', '--field', dest='fields', metavar='FIELD', help=_('Specify the field(s) to be returned by server. You can ' 'repeat this option.'), action='append', default=[]) def add_pagination_argument(parser): parser.add_argument( '-P', '--page-size', dest='page_size', metavar='SIZE', type=int, help=_("Specify retrieve unit of each request, then split one request " "to several requests."), default=None) def add_sorting_argument(parser): parser.add_argument( '--sort-key', dest='sort_key', metavar='FIELD', action='append', help=_("Sorts the list by the specified fields in the specified " "directions. You can repeat this option, but you must " "specify an equal number of sort_dir and sort_key values. " "Extra sort_dir options are ignored. Missing sort_dir options " "use the default asc value."), default=[]) parser.add_argument( '--sort-dir', dest='sort_dir', metavar='{asc,desc}', help=_("Sorts the list in the specified direction. You can repeat " "this option."), action='append', default=[], choices=['asc', 'desc']) def is_number(s): try: float(s) # for int, long and float except ValueError: try: complex(s) # for complex except ValueError: return False return True def _process_previous_argument(current_arg, _value_number, current_type_str, _list_flag, _values_specs, _clear_flag, values_specs): if current_arg is not None: if _value_number == 0 and (current_type_str or _list_flag): # This kind of argument should have value raise exceptions.CommandError( _("Invalid values_specs %s") % ' '.join(values_specs)) if _value_number > 1 or _list_flag or current_type_str == 'list': current_arg.update({'nargs': '+'}) elif _value_number == 0: if _clear_flag: # if we have action=clear, we use argument's default # value None for argument _values_specs.pop() else: # We assume non value argument as bool one current_arg.update({'action': 'store_true'}) def parse_args_to_dict(values_specs): """It is used to analyze the extra command options to command. Besides known options and arguments, our commands also support user to put more options to the end of command line. For example, list_nets -- --tag x y --key1 value1, where '-- --tag x y --key1 value1' is extra options to our list_nets. This feature can support V2.0 API's fields selection and filters. For example, to list networks which has name 'test4', we can have list_nets -- --name=test4. value spec is: --key type=int|bool|... value. Type is one of Python built-in types. By default, type is string. The key without value is a bool option. Key with two values will be a list option. """ # values_specs for example: '-- --tag x y --key1 type=int value1' # -- is a pseudo argument values_specs_copy = values_specs[:] if values_specs_copy and values_specs_copy[0] == '--': del values_specs_copy[0] # converted ArgumentParser arguments for each of the options _options = {} # the argument part for current option in _options current_arg = None # the string after remove meta info in values_specs # for example, '--tag x y --key1 value1' _values_specs = [] # record the count of values for an option # for example: for '--tag x y', it is 2, while for '--key1 value1', it is 1 _value_number = 0 # list=true _list_flag = False # action=clear _clear_flag = False # the current item in values_specs current_item = None # the str after 'type=' current_type_str = None # dict of allowed types allowed_type_dict = { 'bool': utils.str2bool, 'dict': utils.str2dict, 'int': int, 'str': str, } for _item in values_specs_copy: if _item.startswith('--'): # Deal with previous argument if any _process_previous_argument( current_arg, _value_number, current_type_str, _list_flag, _values_specs, _clear_flag, values_specs) # Init variables for current argument current_item = _item _list_flag = False _clear_flag = False current_type_str = None if "=" in _item: _value_number = 1 _item = _item.split('=')[0] else: _value_number = 0 if _item in _options: raise exceptions.CommandError( _("Duplicated options %s") % ' '.join(values_specs)) else: _options.update({_item: {}}) current_arg = _options[_item] _item = current_item elif _item.startswith('type='): if current_arg is None: raise exceptions.CommandError( _("Invalid values_specs %s") % ' '.join(values_specs)) if 'type' not in current_arg: current_type_str = _item.split('=', 2)[1] if current_type_str in allowed_type_dict: current_arg['type'] = allowed_type_dict[current_type_str] continue else: raise exceptions.CommandError( _("Invalid value_specs {valspec}: type {curtypestr}" " is not supported").format( valspec=' '.join(values_specs), curtypestr=current_type_str)) elif _item == 'list=true': _list_flag = True continue elif _item == 'action=clear': _clear_flag = True continue if not _item.startswith('--'): # All others are value items # Make sure '--' occurs first and allow minus value if (not current_item or '=' in current_item or _item.startswith('-') and not is_number(_item)): raise exceptions.CommandError( _("Invalid values_specs %s") % ' '.join(values_specs)) _value_number += 1 if _item.startswith('---'): raise exceptions.CommandError( _("Invalid values_specs %s") % ' '.join(values_specs)) _values_specs.append(_item) # Deal with last one argument _process_previous_argument( current_arg, _value_number, current_type_str, _list_flag, _values_specs, _clear_flag, values_specs) # Populate the parser with arguments _parser = argparse.ArgumentParser(add_help=False) for opt, optspec in _options.items(): _parser.add_argument(opt, **optspec) _args = _parser.parse_args(_values_specs) result_dict = {} for opt in _options.keys(): _opt = opt.split('--', 2)[1] _opt = _opt.replace('-', '_') _value = getattr(_args, _opt) result_dict.update({_opt: _value}) return result_dict def _merge_args(qCmd, parsed_args, _extra_values, value_specs): """Merge arguments from _extra_values into parsed_args. If an argument value are provided in both and it is a list, the values in _extra_values will be merged into parsed_args. @param parsed_args: the parsed args from known options @param _extra_values: the other parsed arguments in unknown parts @param values_specs: the unparsed unknown parts """ temp_values = _extra_values.copy() for key, value in temp_values.items(): if hasattr(parsed_args, key): arg_value = getattr(parsed_args, key) if arg_value is not None and value is not None: if isinstance(arg_value, list): if value and isinstance(value, list): if (not arg_value or isinstance(arg_value[0], type(value[0]))): arg_value.extend(value) _extra_values.pop(key) def update_dict(obj, dict, attributes): """Update dict with fields from obj.attributes. :param obj: the object updated into dict :param dict: the result dictionary :param attributes: a list of attributes belonging to obj """ for attribute in attributes: if hasattr(obj, attribute) and getattr(obj, attribute) is not None: dict[attribute] = getattr(obj, attribute) # cliff.command.Command is abstract class so that metaclass of # subclass must be subclass of metaclass of all its base. # otherwise metaclass conflict exception is raised. class NeutronCommandMeta(abc.ABCMeta): def __new__(cls, name, bases, cls_dict): if 'log' not in cls_dict: cls_dict['log'] = logging.getLogger( cls_dict['__module__'] + '.' + name) return super(NeutronCommandMeta, cls).__new__(cls, name, bases, cls_dict) class NeutronCommand(command.Command, metaclass=NeutronCommandMeta): values_specs = [] json_indent = None resource = None shadow_resource = None parent_id = None def run(self, parsed_args): self.log.debug('run(%s)', parsed_args) return super(NeutronCommand, self).run(parsed_args) @property def cmd_resource(self): if self.shadow_resource: return self.shadow_resource return self.resource def get_client(self): return self.app.client_manager.neutron def get_parser(self, prog_name): parser = super(NeutronCommand, self).get_parser(prog_name) parser.add_argument( '--request-format', help=argparse.SUPPRESS, default='json', choices=['json', ], ) parser.add_argument( '--request_format', choices=['json', ], help=argparse.SUPPRESS) return parser def cleanup_output_data(self, data): pass def format_output_data(self, data): # Modify data to make it more readable if self.resource in data: for k, v in data[self.resource].items(): if isinstance(v, list): value = '\n'.join(jsonutils.dumps( i, indent=self.json_indent) if isinstance(i, dict) else str(i) for i in v) data[self.resource][k] = value elif isinstance(v, dict): value = jsonutils.dumps(v, indent=self.json_indent) data[self.resource][k] = value elif v is None: data[self.resource][k] = '' def add_known_arguments(self, parser): pass def set_extra_attrs(self, parsed_args): pass def args2body(self, parsed_args): return {} class CreateCommand(NeutronCommand, show.ShowOne): """Create a resource for a given tenant.""" log = None def get_parser(self, prog_name): parser = super(CreateCommand, self).get_parser(prog_name) parser.add_argument( '--tenant-id', metavar='TENANT_ID', help=_('The owner tenant ID.'), ) parser.add_argument( '--tenant_id', help=argparse.SUPPRESS) self.add_known_arguments(parser) return parser def take_action(self, parsed_args): self.set_extra_attrs(parsed_args) neutron_client = self.get_client() _extra_values = parse_args_to_dict(self.values_specs) _merge_args(self, parsed_args, _extra_values, self.values_specs) body = self.args2body(parsed_args) body[self.resource].update(_extra_values) obj_creator = getattr(neutron_client, "create_%s" % self.cmd_resource) if self.parent_id: data = obj_creator(self.parent_id, body) else: data = obj_creator(body) self.cleanup_output_data(data) if parsed_args.formatter == 'table': self.format_output_data(data) info = self.resource in data and data[self.resource] or None if info: if parsed_args.formatter == 'table': print(_('Created a new %s:') % self.resource, file=self.app.stdout) else: info = {'': ''} return zip(*sorted(info.items())) class UpdateCommand(NeutronCommand): """Update resource's information.""" log = None allow_names = True help_resource = None def get_parser(self, prog_name): parser = super(UpdateCommand, self).get_parser(prog_name) if self.allow_names: help_str = _('ID or name of %s to update.') else: help_str = _('ID of %s to update.') if not self.help_resource: self.help_resource = self.resource parser.add_argument( 'id', metavar=self.resource.upper(), help=help_str % self.help_resource) self.add_known_arguments(parser) return parser def take_action(self, parsed_args): self.set_extra_attrs(parsed_args) neutron_client = self.get_client() _extra_values = parse_args_to_dict(self.values_specs) _merge_args(self, parsed_args, _extra_values, self.values_specs) body = self.args2body(parsed_args) if self.resource in body: body[self.resource].update(_extra_values) else: body[self.resource] = _extra_values if not body[self.resource]: raise exceptions.CommandError( _("Must specify new values to update %s") % self.cmd_resource) if self.allow_names: _id = find_resourceid_by_name_or_id( neutron_client, self.resource, parsed_args.id, cmd_resource=self.cmd_resource, parent_id=self.parent_id) else: _id = find_resourceid_by_id( neutron_client, self.resource, parsed_args.id, self.cmd_resource, self.parent_id) obj_updater = getattr(neutron_client, "update_%s" % self.cmd_resource) if self.parent_id: obj_updater(_id, self.parent_id, body) else: obj_updater(_id, body) print((_('Updated %(resource)s: %(id)s') % {'id': parsed_args.id, 'resource': self.resource}), file=self.app.stdout) return class DeleteCommand(NeutronCommand): """Delete a given resource.""" log = None allow_names = True help_resource = None bulk_delete = True def get_parser(self, prog_name): parser = super(DeleteCommand, self).get_parser(prog_name) if not self.help_resource: self.help_resource = self.resource if self.allow_names: help_str = _('ID(s) or name(s) of %s to delete.') else: help_str = _('ID(s) of %s to delete.') parser.add_argument( 'id', metavar=self.resource.upper(), nargs='+' if self.bulk_delete else 1, help=help_str % self.help_resource) self.add_known_arguments(parser) return parser def take_action(self, parsed_args): self.set_extra_attrs(parsed_args) neutron_client = self.get_client() obj_deleter = getattr(neutron_client, "delete_%s" % self.cmd_resource) if self.bulk_delete: self._bulk_delete(obj_deleter, neutron_client, parsed_args.id) else: self.delete_item(obj_deleter, neutron_client, parsed_args.id) print((_('Deleted %(resource)s: %(id)s') % {'id': parsed_args.id, 'resource': self.resource}), file=self.app.stdout) return def _bulk_delete(self, obj_deleter, neutron_client, parsed_args_ids): successful_delete = [] non_existent = [] multiple_ids = [] for item_id in parsed_args_ids: try: self.delete_item(obj_deleter, neutron_client, item_id) successful_delete.append(item_id) except exceptions.NotFound: non_existent.append(item_id) except exceptions.NeutronClientNoUniqueMatch: multiple_ids.append(item_id) if successful_delete: print((_('Deleted %(resource)s(s): %(id)s')) % {'id': ", ".join(successful_delete), 'resource': self.cmd_resource}, file=self.app.stdout) if non_existent or multiple_ids: err_msgs = [] if non_existent: err_msgs.append((_("Unable to find %(resource)s(s) with id(s) " "'%(id)s'.") % {'resource': self.cmd_resource, 'id': ", ".join(non_existent)})) if multiple_ids: err_msgs.append((_("Multiple %(resource)s(s) matches found " "for name(s) '%(id)s'. Please use an ID " "to be more specific.") % {'resource': self.cmd_resource, 'id': ", ".join(multiple_ids)})) raise exceptions.NeutronCLIError(message='\n'.join(err_msgs)) def delete_item(self, obj_deleter, neutron_client, item_id): if self.allow_names: params = {'cmd_resource': self.cmd_resource, 'parent_id': self.parent_id} _id = find_resourceid_by_name_or_id(neutron_client, self.resource, item_id, **params) else: _id = item_id if self.parent_id: obj_deleter(_id, self.parent_id) else: obj_deleter(_id) return class ListCommand(NeutronCommand, lister.Lister): """List resources that belong to a given tenant.""" log = None _formatters = {} list_columns = [] unknown_parts_flag = True pagination_support = False sorting_support = False resource_plural = None # A list to define arguments for filtering by attribute value # CLI arguments are shown in the order of this list. # Each element must be either of a string of an attribute name # or a dict of a full attribute definitions whose format is: # {'name': attribute name, (mandatory) # 'help': help message for CLI (mandatory) # 'boolean': boolean parameter or not. (Default: False) (optional) # 'argparse_kwargs': a dict of parameters passed to # argparse add_argument() # (Default: {}) (optional) # } # For more details, see ListNetworks.filter_attrs. filter_attrs = [] default_attr_defs = { 'name': { 'help': _("Filter %s according to their name."), 'boolean': False, }, 'tenant_id': { 'help': _('Filter %s belonging to the given tenant.'), 'boolean': False, }, 'admin_state_up': { 'help': _('Filter and list the %s whose administrative ' 'state is active'), 'boolean': True, }, } def get_parser(self, prog_name): parser = super(ListCommand, self).get_parser(prog_name) add_show_list_common_argument(parser) if self.pagination_support: add_pagination_argument(parser) if self.sorting_support: add_sorting_argument(parser) self.add_known_arguments(parser) self.add_filtering_arguments(parser) return parser def add_filtering_arguments(self, parser): if not self.filter_attrs: return group_parser = parser.add_argument_group('filtering arguments') collection = self.resource_plural or '%ss' % self.resource for attr in self.filter_attrs: if isinstance(attr, str): # Use detail defined in default_attr_defs attr_name = attr attr_defs = self.default_attr_defs[attr] else: attr_name = attr['name'] attr_defs = attr option_name = '--%s' % attr_name.replace('_', '-') params = attr_defs.get('argparse_kwargs', {}) try: help_msg = attr_defs['help'] % collection except TypeError: help_msg = attr_defs['help'] if attr_defs.get('boolean', False): add_arg_func = functools.partial(utils.add_boolean_argument, group_parser) else: add_arg_func = group_parser.add_argument add_arg_func(option_name, help=help_msg, **params) def args2search_opts(self, parsed_args): search_opts = {} fields = parsed_args.fields if parsed_args.fields: search_opts.update({'fields': fields}) if parsed_args.show_details: search_opts.update({'verbose': 'True'}) filter_attrs = [field if isinstance(field, str) else field['name'] for field in self.filter_attrs] for attr in filter_attrs: val = getattr(parsed_args, attr, None) if attr in HYPHEN_OPTS: attr = attr.replace('_', '-') if val: search_opts[attr] = val return search_opts def call_server(self, neutron_client, search_opts, parsed_args): resource_plural = neutron_client.get_resource_plural(self.cmd_resource) obj_lister = getattr(neutron_client, "list_%s" % resource_plural) if self.parent_id: data = obj_lister(self.parent_id, **search_opts) else: data = obj_lister(**search_opts) return data def retrieve_list(self, parsed_args): """Retrieve a list of resources from Neutron server.""" neutron_client = self.get_client() _extra_values = parse_args_to_dict(self.values_specs) _merge_args(self, parsed_args, _extra_values, self.values_specs) search_opts = self.args2search_opts(parsed_args) search_opts.update(_extra_values) if self.pagination_support: page_size = parsed_args.page_size if page_size: search_opts.update({'limit': page_size}) if self.sorting_support: keys = parsed_args.sort_key if keys: search_opts.update({'sort_key': keys}) dirs = parsed_args.sort_dir len_diff = len(keys) - len(dirs) if len_diff > 0: dirs += ['asc'] * len_diff elif len_diff < 0: dirs = dirs[:len(keys)] if dirs: search_opts.update({'sort_dir': dirs}) data = self.call_server(neutron_client, search_opts, parsed_args) collection = neutron_client.get_resource_plural(self.resource) return data.get(collection, []) def extend_list(self, data, parsed_args): """Update a retrieved list. This method provides a way to modify an original list returned from the neutron server. For example, you can add subnet cidr information to a network list. """ pass def setup_columns(self, info, parsed_args): _columns = len(info) > 0 and sorted(info[0].keys()) or [] if not _columns: # clean the parsed_args.columns so that cliff will not break parsed_args.columns = [] elif parsed_args.columns: _columns = [x for x in parsed_args.columns if x in _columns] elif self.list_columns: # if no -c(s) by user and list_columns, we use columns in # both list_columns and returned resource. # Also Keep their order the same as in list_columns _columns = self._setup_columns_with_tenant_id(self.list_columns, _columns) if parsed_args.formatter == 'table': formatters = self._formatters elif (parsed_args.formatter == 'csv' and hasattr(self, '_formatters_csv')): formatters = self._formatters_csv else: # For other formatters, we use raw value returned from neutron formatters = {} return (_columns, (utils.get_item_properties( s, _columns, formatters=formatters, ) for s in info), ) def _setup_columns_with_tenant_id(self, display_columns, avail_columns): _columns = [x for x in display_columns if x in avail_columns] if 'tenant_id' in display_columns: return _columns if 'tenant_id' not in avail_columns: return _columns if not self.is_admin_role(): return _columns try: pos_id = _columns.index('id') except ValueError: pos_id = 0 try: pos_name = _columns.index('name') except ValueError: pos_name = 0 _columns.insert(max(pos_id, pos_name) + 1, 'tenant_id') return _columns def is_admin_role(self): client = self.get_client() auth_ref = client.httpclient.get_auth_ref() if not auth_ref: return False return 'admin' in auth_ref.role_names def take_action(self, parsed_args): self.set_extra_attrs(parsed_args) data = self.retrieve_list(parsed_args) self.extend_list(data, parsed_args) return self.setup_columns(data, parsed_args) class ShowCommand(NeutronCommand, show.ShowOne): """Show information of a given resource.""" log = None allow_names = True help_resource = None def get_parser(self, prog_name): parser = super(ShowCommand, self).get_parser(prog_name) add_show_list_common_argument(parser) if self.allow_names: help_str = _('ID or name of %s to look up.') else: help_str = _('ID of %s to look up.') if not self.help_resource: self.help_resource = self.resource parser.add_argument( 'id', metavar=self.resource.upper(), help=help_str % self.help_resource) self.add_known_arguments(parser) return parser def take_action(self, parsed_args): self.set_extra_attrs(parsed_args) neutron_client = self.get_client() params = {} if parsed_args.show_details: params = {'verbose': 'True'} if parsed_args.fields: params = {'fields': parsed_args.fields} if self.allow_names: _id = find_resourceid_by_name_or_id(neutron_client, self.resource, parsed_args.id, cmd_resource=self.cmd_resource, parent_id=self.parent_id) else: _id = parsed_args.id obj_shower = getattr(neutron_client, "show_%s" % self.cmd_resource) if self.parent_id: data = obj_shower(_id, self.parent_id, **params) else: data = obj_shower(_id, **params) self.cleanup_output_data(data) if parsed_args.formatter == 'table': self.format_output_data(data) resource = data[self.resource] if self.resource in data: return zip(*sorted(resource.items())) else: return None ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/address_scope.py0000664000175000017500000000545700000000000026362 0ustar00zuulzuul00000000000000# Copyright 2015 Huawei Technologies India Pvt. Ltd.. # 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 neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 class ListAddressScope(neutronV20.ListCommand): """List address scopes that belong to a given tenant.""" resource = 'address_scope' list_columns = ['id', 'name', 'ip_version'] pagination_support = True sorting_support = True class ShowAddressScope(neutronV20.ShowCommand): """Show information about an address scope.""" resource = 'address_scope' class CreateAddressScope(neutronV20.CreateCommand): """Create an address scope for a given tenant.""" resource = 'address_scope' def add_known_arguments(self, parser): parser.add_argument( '--shared', action='store_true', help=_('Set the address scope as shared.')) parser.add_argument( 'name', metavar='NAME', help=_('Specify the name of the address scope.')) parser.add_argument( 'ip_version', metavar='IP_VERSION', type=int, choices=[4, 6], help=_('Specify the address family of the address scope.')) def args2body(self, parsed_args): body = {'name': parsed_args.name, 'ip_version': parsed_args.ip_version} if parsed_args.shared: body['shared'] = True neutronV20.update_dict(parsed_args, body, ['tenant_id']) return {self.resource: body} class DeleteAddressScope(neutronV20.DeleteCommand): """Delete an address scope.""" resource = 'address_scope' class UpdateAddressScope(neutronV20.UpdateCommand): """Update an address scope.""" resource = 'address_scope' def add_known_arguments(self, parser): parser.add_argument('--name', help=_('Updated name of the address scope.')) utils.add_boolean_argument( parser, '--shared', help=_('Set sharing of address scope. ' '(True means shared)')) def args2body(self, parsed_args): body = {} neutronV20.update_dict(parsed_args, body, ['name', 'shared']) return {self.resource: body} ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/agent.py0000664000175000017500000000453500000000000024636 0ustar00zuulzuul00000000000000# Copyright 2013 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 neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 def _format_timestamp(component): try: return component['heartbeat_timestamp'].split(".", 2)[0] except (TypeError, KeyError): return '' class ListAgent(neutronV20.ListCommand): """List agents.""" resource = 'agent' list_columns = ['id', 'agent_type', 'host', 'availability_zone', 'alive', 'admin_state_up', 'binary'] _formatters = {'heartbeat_timestamp': _format_timestamp} sorting_support = True def extend_list(self, data, parsed_args): for agent in data: if 'alive' in agent: agent['alive'] = ":-)" if agent['alive'] else 'xxx' class ShowAgent(neutronV20.ShowCommand): """Show information of a given agent.""" resource = 'agent' allow_names = False json_indent = 5 class DeleteAgent(neutronV20.DeleteCommand): """Delete a given agent.""" resource = 'agent' allow_names = False class UpdateAgent(neutronV20.UpdateCommand): """Updates the admin status and description for a specified agent.""" resource = 'agent' allow_names = False def add_known_arguments(self, parser): parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up of the agent to false.')) parser.add_argument( '--description', help=_('Description for the agent.')) def args2body(self, parsed_args): body = {'admin_state_up': parsed_args.admin_state} neutronV20.update_dict(parsed_args, body, ['description']) return {self.resource: body} ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/agentscheduler.py0000664000175000017500000003020500000000000026526 0ustar00zuulzuul00000000000000# Copyright 2013 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 neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 from neutronclient.neutron.v2_0 import network from neutronclient.neutron.v2_0 import router PERFECT_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" class AddNetworkToDhcpAgent(neutronV20.NeutronCommand): """Add a network to a DHCP agent.""" def get_parser(self, prog_name): parser = super(AddNetworkToDhcpAgent, self).get_parser(prog_name) parser.add_argument( 'dhcp_agent', metavar='DHCP_AGENT', help=_('ID of the DHCP agent.')) parser.add_argument( 'network', metavar='NETWORK', help=_('Network to add.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() _net_id = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'network', parsed_args.network) neutron_client.add_network_to_dhcp_agent(parsed_args.dhcp_agent, {'network_id': _net_id}) print(_('Added network %s to DHCP agent') % parsed_args.network, file=self.app.stdout) class RemoveNetworkFromDhcpAgent(neutronV20.NeutronCommand): """Remove a network from a DHCP agent.""" def get_parser(self, prog_name): parser = super(RemoveNetworkFromDhcpAgent, self).get_parser(prog_name) parser.add_argument( 'dhcp_agent', metavar='DHCP_AGENT', help=_('ID of the DHCP agent.')) parser.add_argument( 'network', metavar='NETWORK', help=_('Network to remove.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() _net_id = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'network', parsed_args.network) neutron_client.remove_network_from_dhcp_agent( parsed_args.dhcp_agent, _net_id) print(_('Removed network %s from DHCP agent') % parsed_args.network, file=self.app.stdout) class ListNetworksOnDhcpAgent(network.ListNetwork): """List the networks on a DHCP agent.""" unknown_parts_flag = False def get_parser(self, prog_name): parser = super(ListNetworksOnDhcpAgent, self).get_parser(prog_name) parser.add_argument( 'dhcp_agent', metavar='DHCP_AGENT', help=_('ID of the DHCP agent.')) return parser def call_server(self, neutron_client, search_opts, parsed_args): data = neutron_client.list_networks_on_dhcp_agent( parsed_args.dhcp_agent, **search_opts) return data class ListDhcpAgentsHostingNetwork(neutronV20.ListCommand): """List DHCP agents hosting a network.""" resource = 'agent' _formatters = {} list_columns = ['id', 'host', 'admin_state_up', 'alive'] unknown_parts_flag = False def get_parser(self, prog_name): parser = super(ListDhcpAgentsHostingNetwork, self).get_parser(prog_name) parser.add_argument( 'network', metavar='NETWORK', help=_('Network to query.')) return parser def extend_list(self, data, parsed_args): for agent in data: agent['alive'] = ":-)" if agent['alive'] else 'xxx' def call_server(self, neutron_client, search_opts, parsed_args): _id = neutronV20.find_resourceid_by_name_or_id(neutron_client, 'network', parsed_args.network) search_opts['network'] = _id data = neutron_client.list_dhcp_agent_hosting_networks(**search_opts) return data class AddRouterToL3Agent(neutronV20.NeutronCommand): """Add a router to a L3 agent.""" def get_parser(self, prog_name): parser = super(AddRouterToL3Agent, self).get_parser(prog_name) parser.add_argument( 'l3_agent', metavar='L3_AGENT', help=_('ID of the L3 agent.')) parser.add_argument( 'router', metavar='ROUTER', help=_('Router to add.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() _id = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'router', parsed_args.router) neutron_client.add_router_to_l3_agent(parsed_args.l3_agent, {'router_id': _id}) print(_('Added router %s to L3 agent') % parsed_args.router, file=self.app.stdout) class RemoveRouterFromL3Agent(neutronV20.NeutronCommand): """Remove a router from a L3 agent.""" def get_parser(self, prog_name): parser = super(RemoveRouterFromL3Agent, self).get_parser(prog_name) parser.add_argument( 'l3_agent', metavar='L3_AGENT', help=_('ID of the L3 agent.')) parser.add_argument( 'router', metavar='ROUTER', help=_('Router to remove.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() _id = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'router', parsed_args.router) neutron_client.remove_router_from_l3_agent( parsed_args.l3_agent, _id) print(_('Removed router %s from L3 agent') % parsed_args.router, file=self.app.stdout) class ListRoutersOnL3Agent(neutronV20.ListCommand): """List the routers on a L3 agent.""" _formatters = {'external_gateway_info': router._format_external_gateway_info} list_columns = ['id', 'name', 'external_gateway_info'] resource = 'router' unknown_parts_flag = False def get_parser(self, prog_name): parser = super(ListRoutersOnL3Agent, self).get_parser(prog_name) parser.add_argument( 'l3_agent', metavar='L3_AGENT', help=_('ID of the L3 agent to query.')) return parser def call_server(self, neutron_client, search_opts, parsed_args): data = neutron_client.list_routers_on_l3_agent( parsed_args.l3_agent, **search_opts) return data class ListL3AgentsHostingRouter(neutronV20.ListCommand): """List L3 agents hosting a router.""" resource = 'agent' _formatters = {} list_columns = ['id', 'host', 'admin_state_up', 'alive'] unknown_parts_flag = False def get_parser(self, prog_name): parser = super(ListL3AgentsHostingRouter, self).get_parser(prog_name) parser.add_argument('router', metavar='ROUTER', help=_('Router to query.')) return parser def extend_list(self, data, parsed_args): # Show the ha_state column only if the server responds with it, # as some plugins do not support HA routers. if any('ha_state' in agent for agent in data): if 'ha_state' not in self.list_columns: self.list_columns.append('ha_state') for agent in data: agent['alive'] = ":-)" if agent['alive'] else 'xxx' def call_server(self, neutron_client, search_opts, parsed_args): _id = neutronV20.find_resourceid_by_name_or_id(neutron_client, 'router', parsed_args.router) search_opts['router'] = _id data = neutron_client.list_l3_agent_hosting_routers(**search_opts) return data class ListPoolsOnLbaasAgent(neutronV20.ListCommand): """List the pools on a loadbalancer agent.""" list_columns = ['id', 'name', 'lb_method', 'protocol', 'admin_state_up', 'status'] resource = 'pool' unknown_parts_flag = False def get_parser(self, prog_name): parser = super(ListPoolsOnLbaasAgent, self).get_parser(prog_name) parser.add_argument( 'lbaas_agent', metavar='LBAAS_AGENT', help=_('ID of the loadbalancer agent to query.')) return parser def call_server(self, neutron_client, search_opts, parsed_args): data = neutron_client.list_pools_on_lbaas_agent( parsed_args.lbaas_agent, **search_opts) return data class GetLbaasAgentHostingPool(neutronV20.ListCommand): """Get loadbalancer agent hosting a pool. Deriving from ListCommand though server will return only one agent to keep common output format for all agent schedulers """ resource = 'agent' list_columns = ['id', 'host', 'admin_state_up', 'alive'] unknown_parts_flag = False def get_parser(self, prog_name): parser = super(GetLbaasAgentHostingPool, self).get_parser(prog_name) parser.add_argument('pool', metavar='POOL', help=_('Pool to query.')) return parser def extend_list(self, data, parsed_args): for agent in data: agent['alive'] = ":-)" if agent['alive'] else 'xxx' def call_server(self, neutron_client, search_opts, parsed_args): _id = neutronV20.find_resourceid_by_name_or_id(neutron_client, 'pool', parsed_args.pool) search_opts['pool'] = _id agent = neutron_client.get_lbaas_agent_hosting_pool(**search_opts) data = {'agents': [agent['agent']]} return data class ListLoadBalancersOnLbaasAgent(neutronV20.ListCommand): """List the loadbalancers on a loadbalancer v2 agent.""" list_columns = ['id', 'name', 'admin_state_up', 'provisioning_status'] resource = 'loadbalancer' unknown_parts_flag = False def get_parser(self, prog_name): parser = super(ListLoadBalancersOnLbaasAgent, self).get_parser( prog_name) parser.add_argument( 'lbaas_agent', metavar='LBAAS_AGENT', help=_('ID of the loadbalancer agent to query.')) return parser def call_server(self, neutron_client, search_opts, parsed_args): data = neutron_client.list_loadbalancers_on_lbaas_agent( parsed_args.lbaas_agent, **search_opts) return data class GetLbaasAgentHostingLoadBalancer(neutronV20.ListCommand): """Get lbaas v2 agent hosting a loadbalancer. Deriving from ListCommand though server will return only one agent to keep common output format for all agent schedulers """ resource = 'agent' list_columns = ['id', 'host', 'admin_state_up', 'alive'] unknown_parts_flag = False def get_parser(self, prog_name): parser = super(GetLbaasAgentHostingLoadBalancer, self).get_parser(prog_name) parser.add_argument('loadbalancer', metavar='LOADBALANCER', help=_('LoadBalancer to query.')) return parser def extend_list(self, data, parsed_args): for agent in data: agent['alive'] = ":-)" if agent['alive'] else 'xxx' def call_server(self, neutron_client, search_opts, parsed_args): _id = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'loadbalancer', parsed_args.loadbalancer) search_opts['loadbalancer'] = _id agent = neutron_client.get_lbaas_agent_hosting_loadbalancer( **search_opts) data = {'agents': [agent['agent']]} return data ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/auto_allocated_topology.py0000664000175000017500000001057000000000000030450 0ustar00zuulzuul00000000000000# Copyright 2016 IBM # 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 from cliff import show from oslo_serialization import jsonutils from neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.neutron import v2_0 class ShowAutoAllocatedTopology(v2_0.NeutronCommand, show.ShowOne): """Show the auto-allocated topology of a given tenant.""" resource = 'auto_allocated_topology' def get_parser(self, prog_name): parser = super(ShowAutoAllocatedTopology, self).get_parser(prog_name) parser.add_argument( '--dry-run', help=_('Validate the requirements for auto-allocated-topology. ' '(Does not return a topology.)'), action='store_true') parser.add_argument( '--tenant-id', metavar='tenant-id', help=_('The owner tenant ID.')) # Allow people to do # neutron auto-allocated-topology-show # (Only useful to users who can look at other tenants' topologies.) # We use a different name for this arg because the default will # override whatever is in the named arg otherwise. parser.add_argument( 'pos_tenant_id', help=argparse.SUPPRESS, nargs='?') return parser def take_action(self, parsed_args): client = self.get_client() extra_values = v2_0.parse_args_to_dict(self.values_specs) if extra_values: raise exceptions.CommandError( _("Invalid argument(s): --%s") % ', --'.join(extra_values)) tenant_id = parsed_args.tenant_id or parsed_args.pos_tenant_id if parsed_args.dry_run: data = client.validate_auto_allocated_topology_requirements( tenant_id) else: data = client.get_auto_allocated_topology(tenant_id) if self.resource in data: for k, v in data[self.resource].items(): if isinstance(v, list): value = "" for _item in v: if value: value += "\n" if isinstance(_item, dict): value += jsonutils.dumps(_item) else: value += str(_item) data[self.resource][k] = value elif v == "dry-run=pass": return ("dry-run",), ("pass",) elif v is None: data[self.resource][k] = '' return zip(*sorted(data[self.resource].items())) else: return None class DeleteAutoAllocatedTopology(v2_0.NeutronCommand): """Delete the auto-allocated topology of a given tenant.""" resource = 'auto_allocated_topology' def get_parser(self, prog_name): parser = super(DeleteAutoAllocatedTopology, self).get_parser(prog_name) parser.add_argument( '--tenant-id', metavar='tenant-id', help=_('The owner tenant ID.')) # Allow people to do # neutron auto-allocated-topology-delete # (Only useful to users who can look at other tenants' topologies.) # We use a different name for this arg because the default will # override whatever is in the named arg otherwise. parser.add_argument( 'pos_tenant_id', help=argparse.SUPPRESS, nargs='?') return parser def take_action(self, parsed_args): client = self.get_client() tenant_id = parsed_args.tenant_id or parsed_args.pos_tenant_id client.delete_auto_allocated_topology(tenant_id) # It tenant is None, let's be clear on what it means. tenant_id = tenant_id or 'None (i.e. yours)' print(_('Deleted topology for tenant %s.') % tenant_id, file=self.app.stdout) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/availability_zone.py0000664000175000017500000000260200000000000027236 0ustar00zuulzuul00000000000000# 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 neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronv20 def add_az_hint_argument(parser, resource): parser.add_argument( '--availability-zone-hint', metavar='AVAILABILITY_ZONE', action='append', dest='availability_zone_hints', help=_('Availability Zone for the %s ' '(requires availability zone extension, ' 'this option can be repeated).') % resource) def args2body_az_hint(parsed_args, resource): if parsed_args.availability_zone_hints: resource['availability_zone_hints'] = ( parsed_args.availability_zone_hints) class ListAvailabilityZone(neutronv20.ListCommand): """List availability zones.""" resource = 'availability_zone' list_columns = ['name', 'resource', 'state'] pagination_support = True sorting_support = True ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2136614 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/bgp/0000775000175000017500000000000000000000000023727 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/bgp/__init__.py0000664000175000017500000000000000000000000026026 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/bgp/dragentscheduler.py0000664000175000017500000001074400000000000027632 0ustar00zuulzuul00000000000000# Copyright 2016 Huawei Technologies India Pvt. Ltd. # 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 neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 from neutronclient.neutron.v2_0.bgp import speaker as bgp_speaker def add_common_args(parser): parser.add_argument('dragent_id', metavar='BGP_DRAGENT_ID', help=_('ID of the Dynamic Routing agent.')) parser.add_argument('bgp_speaker', metavar='BGP_SPEAKER', help=_('ID or name of the BGP speaker.')) class AddBGPSpeakerToDRAgent(neutronV20.NeutronCommand): """Add a BGP speaker to a Dynamic Routing agent.""" def get_parser(self, prog_name): parser = super(AddBGPSpeakerToDRAgent, self).get_parser(prog_name) add_common_args(parser) return parser def take_action(self, parsed_args): neutron_client = self.get_client() _speaker_id = bgp_speaker.get_bgp_speaker_id(neutron_client, parsed_args.bgp_speaker) neutron_client.add_bgp_speaker_to_dragent( parsed_args.dragent_id, {'bgp_speaker_id': _speaker_id}) print(_('Associated BGP speaker %s to the Dynamic Routing agent.') % parsed_args.bgp_speaker, file=self.app.stdout) class RemoveBGPSpeakerFromDRAgent(neutronV20.NeutronCommand): """Removes a BGP speaker from a Dynamic Routing agent.""" def get_parser(self, prog_name): parser = super(RemoveBGPSpeakerFromDRAgent, self).get_parser( prog_name) add_common_args(parser) return parser def take_action(self, parsed_args): neutron_client = self.get_client() _speaker_id = bgp_speaker.get_bgp_speaker_id(neutron_client, parsed_args.bgp_speaker) neutron_client.remove_bgp_speaker_from_dragent(parsed_args.dragent_id, _speaker_id) print(_('Disassociated BGP speaker %s from the ' 'Dynamic Routing agent.') % parsed_args.bgp_speaker, file=self.app.stdout) class ListBGPSpeakersOnDRAgent(neutronV20.ListCommand): """List BGP speakers hosted by a Dynamic Routing agent.""" list_columns = ['id', 'name', 'local_as', 'ip_version'] resource = 'bgp_speaker' def get_parser(self, prog_name): parser = super(ListBGPSpeakersOnDRAgent, self).get_parser(prog_name) parser.add_argument( 'dragent_id', metavar='BGP_DRAGENT_ID', help=_('ID of the Dynamic Routing agent.')) return parser def call_server(self, neutron_client, search_opts, parsed_args): data = neutron_client.list_bgp_speaker_on_dragent( parsed_args.dragent_id, **search_opts) return data class ListDRAgentsHostingBGPSpeaker(neutronV20.ListCommand): """List Dynamic Routing agents hosting a BGP speaker.""" resource = 'agent' _formatters = {} list_columns = ['id', 'host', 'admin_state_up', 'alive'] unknown_parts_flag = False def get_parser(self, prog_name): parser = super(ListDRAgentsHostingBGPSpeaker, self).get_parser(prog_name) parser.add_argument('bgp_speaker', metavar='BGP_SPEAKER', help=_('ID or name of the BGP speaker.')) return parser def extend_list(self, data, parsed_args): for agent in data: agent['alive'] = ":-)" if agent['alive'] else 'xxx' def call_server(self, neutron_client, search_opts, parsed_args): _speaker_id = bgp_speaker.get_bgp_speaker_id(neutron_client, parsed_args.bgp_speaker) search_opts['bgp_speaker'] = _speaker_id data = neutron_client.list_dragents_hosting_bgp_speaker(**search_opts) return data ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/bgp/peer.py0000664000175000017500000001041600000000000025236 0ustar00zuulzuul00000000000000# Copyright 2016 Huawei Technologies India Pvt. Ltd. # 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 neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils from neutronclient.common import validators from neutronclient.neutron import v2_0 as neutronv20 def get_bgp_peer_id(client, id_or_name): return neutronv20.find_resourceid_by_name_or_id(client, 'bgp_peer', id_or_name) def validate_peer_attributes(parsed_args): # Validate AS number validators.validate_int_range(parsed_args, 'remote_as', neutronv20.bgp.speaker.MIN_AS_NUM, neutronv20.bgp.speaker.MAX_AS_NUM) # Validate password if parsed_args.auth_type != 'none' and parsed_args.password is None: raise exceptions.CommandError(_('Must provide password if auth-type ' 'is specified.')) if parsed_args.auth_type == 'none' and parsed_args.password: raise exceptions.CommandError(_('Must provide auth-type if password ' 'is specified.')) class ListPeers(neutronv20.ListCommand): """List BGP peers.""" resource = 'bgp_peer' list_columns = ['id', 'name', 'peer_ip', 'remote_as'] pagination_support = True sorting_support = True class ShowPeer(neutronv20.ShowCommand): """Show information of a given BGP peer.""" resource = 'bgp_peer' class CreatePeer(neutronv20.CreateCommand): """Create a BGP Peer.""" resource = 'bgp_peer' def add_known_arguments(self, parser): parser.add_argument( 'name', metavar='NAME', help=_('Name of the BGP peer to create.')) parser.add_argument( '--peer-ip', metavar='PEER_IP_ADDRESS', required=True, help=_('Peer IP address.')) parser.add_argument( '--remote-as', required=True, metavar='PEER_REMOTE_AS', help=_('Peer AS number. (Integer in [%(min_val)s, %(max_val)s] ' 'is allowed.)') % {'min_val': neutronv20.bgp.speaker.MIN_AS_NUM, 'max_val': neutronv20.bgp.speaker.MAX_AS_NUM}) parser.add_argument( '--auth-type', metavar='PEER_AUTH_TYPE', choices=['none', 'md5'], default='none', type=utils.convert_to_lowercase, help=_('Authentication algorithm. Supported algorithms: ' 'none(default), md5')) parser.add_argument( '--password', metavar='AUTH_PASSWORD', help=_('Authentication password.')) def args2body(self, parsed_args): body = {} validate_peer_attributes(parsed_args) neutronv20.update_dict(parsed_args, body, ['name', 'peer_ip', 'remote_as', 'auth_type', 'password']) return {self.resource: body} class UpdatePeer(neutronv20.UpdateCommand): """Update BGP Peer's information.""" resource = 'bgp_peer' def add_known_arguments(self, parser): parser.add_argument( '--name', help=_('Updated name of the BGP peer.')) parser.add_argument( '--password', metavar='AUTH_PASSWORD', help=_('Updated authentication password.')) def args2body(self, parsed_args): body = {} neutronv20.update_dict(parsed_args, body, ['name', 'password']) return {self.resource: body} class DeletePeer(neutronv20.DeleteCommand): """Delete a BGP peer.""" resource = 'bgp_peer' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/bgp/speaker.py0000664000175000017500000002377400000000000025750 0ustar00zuulzuul00000000000000# Copyright 2016 Huawei Technologies India Pvt. Ltd. # 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 neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.common import validators from neutronclient.neutron import v2_0 as neutronv20 from neutronclient.neutron.v2_0.bgp import peer as bgp_peer # Allowed BGP Autonomous number range MIN_AS_NUM = 1 MAX_AS_NUM = 4294967295 def get_network_id(client, id_or_name): return neutronv20.find_resourceid_by_name_or_id(client, 'network', id_or_name) def get_bgp_speaker_id(client, id_or_name): return neutronv20.find_resourceid_by_name_or_id(client, 'bgp_speaker', id_or_name) def validate_speaker_attributes(parsed_args): # Validate AS number validators.validate_int_range(parsed_args, 'local_as', MIN_AS_NUM, MAX_AS_NUM) def add_common_arguments(parser): utils.add_boolean_argument( parser, '--advertise-floating-ip-host-routes', help=_('Whether to enable or disable the advertisement ' 'of floating-ip host routes by the BGP speaker. ' 'By default floating ip host routes will be ' 'advertised by the BGP speaker.')) utils.add_boolean_argument( parser, '--advertise-tenant-networks', help=_('Whether to enable or disable the advertisement ' 'of tenant network routes by the BGP speaker. ' 'By default tenant network routes will be ' 'advertised by the BGP speaker.')) def args2body_common_arguments(body, parsed_args): neutronv20.update_dict(parsed_args, body, ['name', 'advertise_floating_ip_host_routes', 'advertise_tenant_networks']) class ListSpeakers(neutronv20.ListCommand): """List BGP speakers.""" resource = 'bgp_speaker' list_columns = ['id', 'name', 'local_as', 'ip_version'] pagination_support = True sorting_support = True class ShowSpeaker(neutronv20.ShowCommand): """Show information of a given BGP speaker.""" resource = 'bgp_speaker' class CreateSpeaker(neutronv20.CreateCommand): """Create a BGP Speaker.""" resource = 'bgp_speaker' def add_known_arguments(self, parser): parser.add_argument( 'name', metavar='NAME', help=_('Name of the BGP speaker to create.')) parser.add_argument( '--local-as', metavar='LOCAL_AS', required=True, help=_('Local AS number. (Integer in [%(min_val)s, %(max_val)s] ' 'is allowed.)') % {'min_val': MIN_AS_NUM, 'max_val': MAX_AS_NUM}) parser.add_argument( '--ip-version', type=int, choices=[4, 6], default=4, help=_('IP version for the BGP speaker (default is 4).')) add_common_arguments(parser) def args2body(self, parsed_args): body = {} validate_speaker_attributes(parsed_args) body['local_as'] = parsed_args.local_as body['ip_version'] = parsed_args.ip_version args2body_common_arguments(body, parsed_args) return {self.resource: body} class UpdateSpeaker(neutronv20.UpdateCommand): """Update BGP Speaker's information.""" resource = 'bgp_speaker' def add_known_arguments(self, parser): parser.add_argument( '--name', help=_('Name of the BGP speaker to update.')) add_common_arguments(parser) def args2body(self, parsed_args): body = {} args2body_common_arguments(body, parsed_args) return {self.resource: body} class DeleteSpeaker(neutronv20.DeleteCommand): """Delete a BGP speaker.""" resource = 'bgp_speaker' class AddPeerToSpeaker(neutronv20.NeutronCommand): """Add a peer to the BGP speaker.""" def get_parser(self, prog_name): parser = super(AddPeerToSpeaker, self).get_parser(prog_name) parser.add_argument( 'bgp_speaker', metavar='BGP_SPEAKER', help=_('ID or name of the BGP speaker.')) parser.add_argument( 'bgp_peer', metavar='BGP_PEER', help=_('ID or name of the BGP peer to add.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() _speaker_id = get_bgp_speaker_id(neutron_client, parsed_args.bgp_speaker) _peer_id = bgp_peer.get_bgp_peer_id(neutron_client, parsed_args.bgp_peer) neutron_client.add_peer_to_bgp_speaker(_speaker_id, {'bgp_peer_id': _peer_id}) print(_('Added BGP peer %(peer)s to BGP speaker %(speaker)s.') % {'peer': parsed_args.bgp_peer, 'speaker': parsed_args.bgp_speaker}, file=self.app.stdout) class RemovePeerFromSpeaker(neutronv20.NeutronCommand): """Remove a peer from the BGP speaker.""" def get_parser(self, prog_name): parser = super(RemovePeerFromSpeaker, self).get_parser(prog_name) parser.add_argument( 'bgp_speaker', metavar='BGP_SPEAKER', help=_('ID or name of the BGP speaker.')) parser.add_argument( 'bgp_peer', metavar='BGP_PEER', help=_('ID or name of the BGP peer to remove.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() _speaker_id = get_bgp_speaker_id(neutron_client, parsed_args.bgp_speaker) _peer_id = bgp_peer.get_bgp_peer_id(neutron_client, parsed_args.bgp_peer) neutron_client.remove_peer_from_bgp_speaker(_speaker_id, {'bgp_peer_id': _peer_id}) print(_('Removed BGP peer %(peer)s from BGP speaker %(speaker)s.') % {'peer': parsed_args.bgp_peer, 'speaker': parsed_args.bgp_speaker}, file=self.app.stdout) class AddNetworkToSpeaker(neutronv20.NeutronCommand): """Add a network to the BGP speaker.""" def get_parser(self, prog_name): parser = super(AddNetworkToSpeaker, self).get_parser(prog_name) parser.add_argument( 'bgp_speaker', metavar='BGP_SPEAKER', help=_('ID or name of the BGP speaker.')) parser.add_argument( 'network', metavar='NETWORK', help=_('ID or name of the network to add.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() _speaker_id = get_bgp_speaker_id(neutron_client, parsed_args.bgp_speaker) _net_id = get_network_id(neutron_client, parsed_args.network) neutron_client.add_network_to_bgp_speaker(_speaker_id, {'network_id': _net_id}) print(_('Added network %(net)s to BGP speaker %(speaker)s.') % {'net': parsed_args.network, 'speaker': parsed_args.bgp_speaker}, file=self.app.stdout) class RemoveNetworkFromSpeaker(neutronv20.NeutronCommand): """Remove a network from the BGP speaker.""" def get_parser(self, prog_name): parser = super(RemoveNetworkFromSpeaker, self).get_parser(prog_name) parser.add_argument( 'bgp_speaker', metavar='BGP_SPEAKER', help=_('ID or name of the BGP speaker.')) parser.add_argument( 'network', metavar='NETWORK', help=_('ID or name of the network to remove.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() _speaker_id = get_bgp_speaker_id(neutron_client, parsed_args.bgp_speaker) _net_id = get_network_id(neutron_client, parsed_args.network) neutron_client.remove_network_from_bgp_speaker(_speaker_id, {'network_id': _net_id}) print(_('Removed network %(net)s from BGP speaker %(speaker)s.') % {'net': parsed_args.network, 'speaker': parsed_args.bgp_speaker}, file=self.app.stdout) class ListRoutesAdvertisedBySpeaker(neutronv20.ListCommand): """List routes advertised by a given BGP speaker.""" list_columns = ['id', 'destination', 'next_hop'] resource = 'advertised_route' pagination_support = True sorting_support = True def get_parser(self, prog_name): parser = super(ListRoutesAdvertisedBySpeaker, self).get_parser(prog_name) parser.add_argument( 'bgp_speaker', metavar='BGP_SPEAKER', help=_('ID or name of the BGP speaker.')) return parser def call_server(self, neutron_client, search_opts, parsed_args): _speaker_id = get_bgp_speaker_id(neutron_client, parsed_args.bgp_speaker) data = neutron_client.list_route_advertised_from_bgp_speaker( _speaker_id, **search_opts) return data ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2136614 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/contrib/0000775000175000017500000000000000000000000024617 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/contrib/__init__.py0000664000175000017500000000000000000000000026716 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/contrib/_fox_sockets.py0000664000175000017500000000520400000000000027660 0ustar00zuulzuul00000000000000# Copyright 2015 Rackspace Hosting Inc. # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from neutronclient._i18n import _ from neutronclient.common import extension def _add_updatable_args(parser): parser.add_argument( 'name', help=_('Name of this fox socket.')) def _updatable_args2body(parsed_args, body, client): if parsed_args.name: body['name'] = parsed_args.name class FoxInSocket(extension.NeutronClientExtension): """Define required variables for resource operations.""" resource = 'fox_socket' resource_plural = '%ss' % resource object_path = '/%s' % resource_plural resource_path = '/%s/%%s' % resource_plural versions = ['2.0'] class FoxInSocketsList(extension.ClientExtensionList, FoxInSocket): """List fox sockets.""" shell_command = 'fox-sockets-list' list_columns = ['id', 'name'] pagination_support = True sorting_support = True class FoxInSocketsCreate(extension.ClientExtensionCreate, FoxInSocket): """Create a fox socket.""" shell_command = 'fox-sockets-create' list_columns = ['id', 'name'] def add_known_arguments(self, parser): _add_updatable_args(parser) def args2body(self, parsed_args): body = {} client = self.get_client() _updatable_args2body(parsed_args, body, client) return {'fox_socket': body} class FoxInSocketsUpdate(extension.ClientExtensionUpdate, FoxInSocket): """Update a fox socket.""" shell_command = 'fox-sockets-update' list_columns = ['id', 'name'] def add_known_arguments(self, parser): # _add_updatable_args(parser) parser.add_argument( '--name', help=_('Name of this fox socket.')) def args2body(self, parsed_args): body = {'name': parsed_args.name} return {'fox_socket': body} class FoxInSocketsDelete(extension.ClientExtensionDelete, FoxInSocket): """Delete a fox socket.""" shell_command = 'fox-sockets-delete' class FoxInSocketsShow(extension.ClientExtensionShow, FoxInSocket): """Show a fox socket.""" shell_command = 'fox-sockets-show' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/dns.py0000664000175000017500000000500300000000000024313 0ustar00zuulzuul00000000000000# Copyright (c) 2016 IBM # 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 neutronclient._i18n import _ def add_dns_argument_create(parser, resource, attribute): # Add dns_name and dns_domain support to network, port and floatingip # create argument = '--dns-%s' % attribute parser.add_argument( argument, help=_('Assign DNS %(attribute)s to the %(resource)s ' '(requires DNS integration ' 'extension)') % {'attribute': attribute, 'resource': resource}) def args2body_dns_create(parsed_args, resource, attribute): # Add dns_name and dns_domain support to network, port and floatingip # create destination = 'dns_%s' % attribute argument = getattr(parsed_args, destination) if argument: resource[destination] = argument def add_dns_argument_update(parser, resource, attribute): # Add dns_name and dns_domain support to network, port and floatingip # update argument = '--dns-%s' % attribute no_argument = '--no-dns-%s' % attribute dns_args = parser.add_mutually_exclusive_group() dns_args.add_argument( argument, help=_('Assign DNS %(attribute)s to the %(resource)s ' '(requires DNS integration ' 'extension.)') % {'attribute': attribute, 'resource': resource}) dns_args.add_argument( no_argument, action='store_true', help=_('Unassign DNS %(attribute)s from the %(resource)s ' '(requires DNS integration ' 'extension.)') % {'attribute': attribute, 'resource': resource}) def args2body_dns_update(parsed_args, resource, attribute): # Add dns_name and dns_domain support to network, port and floatingip # update destination = 'dns_%s' % attribute no_destination = 'no_dns_%s' % attribute argument = getattr(parsed_args, destination) no_argument = getattr(parsed_args, no_destination) if argument: resource[destination] = argument if no_argument: resource[destination] = "" ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/extension.py0000664000175000017500000000170300000000000025546 0ustar00zuulzuul00000000000000# Copyright 2012 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 neutronclient.neutron import v2_0 as cmd_base class ListExt(cmd_base.ListCommand): """List all extensions.""" resource = 'extension' list_columns = ['alias', 'name'] class ShowExt(cmd_base.ShowCommand): """Show information of a given resource.""" resource = "extension" allow_names = False ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2136614 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/flavor/0000775000175000017500000000000000000000000024450 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/flavor/__init__.py0000664000175000017500000000000000000000000026547 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/flavor/flavor.py0000664000175000017500000001307200000000000026316 0ustar00zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # 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 from neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 class ListFlavor(neutronV20.ListCommand): """List Neutron service flavors.""" resource = 'flavor' list_columns = ['id', 'name', 'service_type', 'enabled'] pagination_support = True sorting_support = True class ShowFlavor(neutronV20.ShowCommand): """Show information about a given Neutron service flavor.""" resource = 'flavor' class CreateFlavor(neutronV20.CreateCommand): """Create a Neutron service flavor.""" resource = 'flavor' def add_known_arguments(self, parser): parser.add_argument( 'name', metavar='NAME', help=_('Name for the flavor.')) parser.add_argument( 'service_type', metavar='SERVICE_TYPE', help=_('Service type to which the flavor applies to: e.g. VPN. ' '(See service-provider-list for loaded examples.)')) parser.add_argument( '--description', help=_('Description for the flavor.')) utils.add_boolean_argument( parser, '--enabled', default=argparse.SUPPRESS, help=_('Sets enabled flag.')) def args2body(self, parsed_args): body = {} neutronV20.update_dict(parsed_args, body, ['name', 'description', 'service_type', 'enabled']) return {self.resource: body} class DeleteFlavor(neutronV20.DeleteCommand): """Delete a given Neutron service flavor.""" resource = 'flavor' class UpdateFlavor(neutronV20.UpdateCommand): """Update a Neutron service flavor.""" resource = 'flavor' def add_known_arguments(self, parser): parser.add_argument( '--name', help=_('Name for the flavor.')) parser.add_argument( '--description', help=_('Description for the flavor.')) utils.add_boolean_argument( parser, '--enabled', default=argparse.SUPPRESS, help=_('Sets enabled flag.')) def args2body(self, parsed_args): body = {} neutronV20.update_dict(parsed_args, body, ['name', 'description', 'enabled']) return {self.resource: body} class AssociateFlavor(neutronV20.NeutronCommand): """Associate a Neutron service flavor with a flavor profile.""" resource = 'flavor' def get_parser(self, prog_name): parser = super(AssociateFlavor, self).get_parser(prog_name) parser.add_argument( 'flavor', metavar='FLAVOR', help=_('ID or name of the flavor to associate.')) parser.add_argument( 'flavor_profile', metavar='FLAVOR_PROFILE', help=_('ID of the flavor profile to be associated with the ' 'flavor.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() flavor_id = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'flavor', parsed_args.flavor) service_profile_id = neutronV20.find_resourceid_by_id( neutron_client, 'service_profile', parsed_args.flavor_profile) body = {'service_profile': {'id': service_profile_id}} neutron_client.associate_flavor(flavor_id, body) print((_('Associated flavor %(flavor)s with ' 'flavor_profile %(profile)s') % {'flavor': parsed_args.flavor, 'profile': parsed_args.flavor_profile}), file=self.app.stdout) class DisassociateFlavor(neutronV20.NeutronCommand): """Disassociate a Neutron service flavor from a flavor profile.""" resource = 'flavor' def get_parser(self, prog_name): parser = super(DisassociateFlavor, self).get_parser(prog_name) parser.add_argument( 'flavor', metavar='FLAVOR', help=_('ID or name of the flavor to be disassociated.')) parser.add_argument( 'flavor_profile', metavar='FLAVOR_PROFILE', help=_('ID of the flavor profile to be disassociated from the ' 'flavor.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() flavor_id = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'flavor', parsed_args.flavor) service_profile_id = neutronV20.find_resourceid_by_id( neutron_client, 'service_profile', parsed_args.flavor_profile) neutron_client.disassociate_flavor(flavor_id, service_profile_id) print((_('Disassociated flavor %(flavor)s from ' 'flavor_profile %(profile)s') % {'flavor': parsed_args.flavor, 'profile': parsed_args.flavor_profile}), file=self.app.stdout) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/flavor/flavor_profile.py0000664000175000017500000000624500000000000030042 0ustar00zuulzuul00000000000000# Copyright 2015 Hewlett-Packard Development Company, L.P. # 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 from neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 class ListFlavorProfile(neutronV20.ListCommand): """List Neutron service flavor profiles.""" resource = 'service_profile' list_columns = ['id', 'description', 'enabled', 'metainfo'] pagination_support = True sorting_support = True class ShowFlavorProfile(neutronV20.ShowCommand): """Show information about a given Neutron service flavor profile.""" resource = 'service_profile' class CreateFlavorProfile(neutronV20.CreateCommand): """Create a Neutron service flavor profile.""" resource = 'service_profile' def add_known_arguments(self, parser): parser.add_argument( '--description', help=_('Description for the flavor profile.')) parser.add_argument( '--driver', help=_('Python module path to driver.')) parser.add_argument( '--metainfo', help=_('Metainfo for the flavor profile.')) utils.add_boolean_argument( parser, '--enabled', default=argparse.SUPPRESS, help=_('Sets enabled flag.')) def args2body(self, parsed_args): body = {} neutronV20.update_dict(parsed_args, body, ['description', 'driver', 'enabled', 'metainfo']) return {self.resource: body} class DeleteFlavorProfile(neutronV20.DeleteCommand): """Delete a given Neutron service flavor profile.""" resource = 'service_profile' class UpdateFlavorProfile(neutronV20.UpdateCommand): """Update a given Neutron service flavor profile.""" resource = 'service_profile' def add_known_arguments(self, parser): parser.add_argument( '--description', help=_('Description for the flavor profile.')) parser.add_argument( '--driver', help=_('Python module path to driver.')) parser.add_argument( '--metainfo', help=_('Metainfo for the flavor profile.')) utils.add_boolean_argument( parser, '--enabled', default=argparse.SUPPRESS, help=_('Sets enabled flag.')) def args2body(self, parsed_args): body = {} neutronV20.update_dict(parsed_args, body, ['description', 'driver', 'enabled', 'metainfo']) return {self.resource: body} ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/floatingip.py0000664000175000017500000001262500000000000025673 0ustar00zuulzuul00000000000000# Copyright 2012 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 argparse from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 from neutronclient.neutron.v2_0 import dns class ListFloatingIP(neutronV20.ListCommand): """List floating IPs that belong to a given tenant.""" resource = 'floatingip' list_columns = ['id', 'fixed_ip_address', 'floating_ip_address', 'port_id'] pagination_support = True sorting_support = True class ShowFloatingIP(neutronV20.ShowCommand): """Show information of a given floating IP.""" resource = 'floatingip' allow_names = False class CreateFloatingIP(neutronV20.CreateCommand): """Create a floating IP for a given tenant.""" resource = 'floatingip' def add_known_arguments(self, parser): parser.add_argument( 'floating_network_id', metavar='FLOATING_NETWORK', help=_('ID or name of the network from which ' 'the floating IP is allocated.')) parser.add_argument( '--description', help=_('Description of the floating IP.')) parser.add_argument( '--port-id', help=_('ID of the port to be associated with the floating IP.')) parser.add_argument( '--port_id', help=argparse.SUPPRESS) parser.add_argument( '--fixed-ip-address', help=_('IP address on the port (only required if port has ' 'multiple IPs).')) parser.add_argument( '--fixed_ip_address', help=argparse.SUPPRESS) parser.add_argument( '--floating-ip-address', help=_('IP address of the floating IP')) parser.add_argument( '--subnet', dest='subnet_id', help=_('Subnet ID on which you want to create the floating IP.')) dns.add_dns_argument_create(parser, self.resource, 'domain') dns.add_dns_argument_create(parser, self.resource, 'name') def args2body(self, parsed_args): _network_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'network', parsed_args.floating_network_id) body = {'floating_network_id': _network_id} neutronV20.update_dict(parsed_args, body, ['port_id', 'tenant_id', 'fixed_ip_address', 'description', 'floating_ip_address', 'subnet_id']) dns.args2body_dns_create(parsed_args, body, 'domain') dns.args2body_dns_create(parsed_args, body, 'name') return {self.resource: body} class DeleteFloatingIP(neutronV20.DeleteCommand): """Delete a given floating IP.""" resource = 'floatingip' allow_names = False class AssociateFloatingIP(neutronV20.NeutronCommand): """Create a mapping between a floating IP and a fixed IP.""" resource = 'floatingip' def get_parser(self, prog_name): parser = super(AssociateFloatingIP, self).get_parser(prog_name) parser.add_argument( 'floatingip_id', metavar='FLOATINGIP_ID', help=_('ID of the floating IP to associate.')) parser.add_argument( 'port_id', metavar='PORT', help=_('ID or name of the port to be associated with the ' 'floating IP.')) parser.add_argument( '--fixed-ip-address', help=_('IP address on the port (only required if port has ' 'multiple IPs).')) parser.add_argument( '--fixed_ip_address', help=argparse.SUPPRESS) return parser def take_action(self, parsed_args): neutron_client = self.get_client() update_dict = {} neutronV20.update_dict(parsed_args, update_dict, ['port_id', 'fixed_ip_address']) neutron_client.update_floatingip(parsed_args.floatingip_id, {'floatingip': update_dict}) print(_('Associated floating IP %s') % parsed_args.floatingip_id, file=self.app.stdout) class DisassociateFloatingIP(neutronV20.NeutronCommand): """Remove a mapping from a floating IP to a fixed IP.""" resource = 'floatingip' def get_parser(self, prog_name): parser = super(DisassociateFloatingIP, self).get_parser(prog_name) parser.add_argument( 'floatingip_id', metavar='FLOATINGIP_ID', help=_('ID of the floating IP to disassociate.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() neutron_client.update_floatingip(parsed_args.floatingip_id, {'floatingip': {'port_id': None}}) print(_('Disassociated floating IP %s') % parsed_args.floatingip_id, file=self.app.stdout) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2136614 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/fw/0000775000175000017500000000000000000000000023573 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/fw/__init__.py0000664000175000017500000000000000000000000025672 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/fw/firewall.py0000664000175000017500000001016600000000000025756 0ustar00zuulzuul00000000000000# Copyright 2013 Big Switch Networks # 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 neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronv20 def add_common_args(parser): parser.add_argument( '--name', help=_('Name for the firewall.')) parser.add_argument( '--description', help=_('Description for the firewall.')) router = parser.add_mutually_exclusive_group() router.add_argument( '--router', dest='routers', metavar='ROUTER', action='append', help=_('ID or name of the router associated with the firewall ' '(requires FWaaS router insertion extension to be enabled). ' 'This option can be repeated.')) router.add_argument( '--no-routers', action='store_true', help=_('Associate no routers with the firewall (requires FWaaS ' 'router insertion extension).')) def parse_common_args(client, parsed_args): body = {} if parsed_args.policy: body['firewall_policy_id'] = neutronv20.find_resourceid_by_name_or_id( client, 'firewall_policy', parsed_args.policy) if parsed_args.routers: body['router_ids'] = [ neutronv20.find_resourceid_by_name_or_id(client, 'router', r) for r in parsed_args.routers] elif parsed_args.no_routers: body['router_ids'] = [] neutronv20.update_dict(parsed_args, body, ['name', 'description']) return body class ListFirewall(neutronv20.ListCommand): """List firewalls that belong to a given tenant.""" resource = 'firewall' list_columns = ['id', 'name', 'firewall_policy_id'] _formatters = {} pagination_support = True sorting_support = True class ShowFirewall(neutronv20.ShowCommand): """Show information of a given firewall.""" resource = 'firewall' class CreateFirewall(neutronv20.CreateCommand): """Create a firewall.""" resource = 'firewall' def add_known_arguments(self, parser): add_common_args(parser) parser.add_argument( 'policy', metavar='POLICY', help=_('ID or name of the firewall policy ' 'associated to this firewall.')) parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) def args2body(self, parsed_args): body = parse_common_args(self.get_client(), parsed_args) neutronv20.update_dict(parsed_args, body, ['tenant_id']) body['admin_state_up'] = parsed_args.admin_state return {self.resource: body} class UpdateFirewall(neutronv20.UpdateCommand): """Update a given firewall.""" resource = 'firewall' def add_known_arguments(self, parser): add_common_args(parser) parser.add_argument( '--policy', metavar='POLICY', help=_('ID or name of the firewall policy ' 'associated to this firewall.')) utils.add_boolean_argument( parser, '--admin-state-up', dest='admin_state_up', help=_('Update the admin state for the firewall ' '(True means UP).')) def args2body(self, parsed_args): body = parse_common_args(self.get_client(), parsed_args) neutronv20.update_dict(parsed_args, body, ['admin_state_up']) return {self.resource: body} class DeleteFirewall(neutronv20.DeleteCommand): """Delete a given firewall.""" resource = 'firewall' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/fw/firewallpolicy.py0000664000175000017500000002001700000000000027172 0ustar00zuulzuul00000000000000# Copyright 2013 Big Switch Networks # 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 from neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronv20 def _format_firewall_rules(firewall_policy): try: output = '[' + ',\n '.join([rule for rule in firewall_policy['firewall_rules']]) + ']' return output except (TypeError, KeyError): return '' def add_common_args(parser): parser.add_argument( '--description', help=_('Description for the firewall policy.')) parser.add_argument( '--firewall-rules', type=lambda x: x.split(), help=_('Ordered list of whitespace-delimited firewall rule ' 'names or IDs; e.g., --firewall-rules \"rule1 rule2\"')) def parse_common_args(client, parsed_args): if parsed_args.firewall_rules: _firewall_rules = [] for f in parsed_args.firewall_rules: _firewall_rules.append( neutronv20.find_resourceid_by_name_or_id( client, 'firewall_rule', f)) body = {'firewall_rules': _firewall_rules} else: body = {} neutronv20.update_dict(parsed_args, body, ['name', 'description', 'shared', 'audited', 'tenant_id']) return {'firewall_policy': body} class ListFirewallPolicy(neutronv20.ListCommand): """List firewall policies that belong to a given tenant.""" resource = 'firewall_policy' list_columns = ['id', 'name', 'firewall_rules'] _formatters = {'firewall_rules': _format_firewall_rules, } pagination_support = True sorting_support = True class ShowFirewallPolicy(neutronv20.ShowCommand): """Show information of a given firewall policy.""" resource = 'firewall_policy' class CreateFirewallPolicy(neutronv20.CreateCommand): """Create a firewall policy.""" resource = 'firewall_policy' def add_known_arguments(self, parser): parser.add_argument( 'name', metavar='NAME', help=_('Name for the firewall policy.')) parser.add_argument( '--shared', action='store_true', help=_('Create a shared policy.'), default=argparse.SUPPRESS) parser.add_argument( '--audited', action='store_true', help=_('Sets audited to True.'), default=argparse.SUPPRESS) add_common_args(parser) def args2body(self, parsed_args): return parse_common_args(self.get_client(), parsed_args) class UpdateFirewallPolicy(neutronv20.UpdateCommand): """Update a given firewall policy.""" resource = 'firewall_policy' def add_known_arguments(self, parser): add_common_args(parser) parser.add_argument( '--name', help=_('Name for the firewall policy.')) utils.add_boolean_argument( parser, '--shared', help=_('Update the sharing status of the policy. ' '(True means shared).')) utils.add_boolean_argument( parser, '--audited', help=_('Update the audit status of the policy. ' '(True means auditing is enabled).')) def args2body(self, parsed_args): return parse_common_args(self.get_client(), parsed_args) class DeleteFirewallPolicy(neutronv20.DeleteCommand): """Delete a given firewall policy.""" resource = 'firewall_policy' class FirewallPolicyInsertRule(neutronv20.UpdateCommand): """Insert a rule into a given firewall policy.""" resource = 'firewall_policy' def call_api(self, neutron_client, firewall_policy_id, body): return neutron_client.firewall_policy_insert_rule(firewall_policy_id, body) def args2body(self, parsed_args): _rule = '' if parsed_args.firewall_rule_id: _rule = neutronv20.find_resourceid_by_name_or_id( self.get_client(), 'firewall_rule', parsed_args.firewall_rule_id) _insert_before = '' if 'insert_before' in parsed_args: if parsed_args.insert_before: _insert_before = neutronv20.find_resourceid_by_name_or_id( self.get_client(), 'firewall_rule', parsed_args.insert_before) _insert_after = '' if 'insert_after' in parsed_args: if parsed_args.insert_after: _insert_after = neutronv20.find_resourceid_by_name_or_id( self.get_client(), 'firewall_rule', parsed_args.insert_after) body = {'firewall_rule_id': _rule, 'insert_before': _insert_before, 'insert_after': _insert_after} return body def get_parser(self, prog_name): parser = super(FirewallPolicyInsertRule, self).get_parser(prog_name) parser.add_argument( '--insert-before', metavar='FIREWALL_RULE', help=_('Insert before this rule.')) parser.add_argument( '--insert-after', metavar='FIREWALL_RULE', help=_('Insert after this rule.')) parser.add_argument( 'firewall_rule_id', metavar='FIREWALL_RULE', help=_('New rule to insert.')) self.add_known_arguments(parser) return parser def take_action(self, parsed_args): neutron_client = self.get_client() body = self.args2body(parsed_args) _id = neutronv20.find_resourceid_by_name_or_id(neutron_client, self.resource, parsed_args.id) self.call_api(neutron_client, _id, body) print((_('Inserted firewall rule in firewall policy %(id)s') % {'id': parsed_args.id}), file=self.app.stdout) class FirewallPolicyRemoveRule(neutronv20.UpdateCommand): """Remove a rule from a given firewall policy.""" resource = 'firewall_policy' def call_api(self, neutron_client, firewall_policy_id, body): return neutron_client.firewall_policy_remove_rule(firewall_policy_id, body) def args2body(self, parsed_args): _rule = '' if parsed_args.firewall_rule_id: _rule = neutronv20.find_resourceid_by_name_or_id( self.get_client(), 'firewall_rule', parsed_args.firewall_rule_id) body = {'firewall_rule_id': _rule} return body def get_parser(self, prog_name): parser = super(FirewallPolicyRemoveRule, self).get_parser(prog_name) parser.add_argument( 'firewall_rule_id', metavar='FIREWALL_RULE', help=_('ID or name of the firewall rule to be removed ' 'from the policy.')) self.add_known_arguments(parser) return parser def take_action(self, parsed_args): neutron_client = self.get_client() body = self.args2body(parsed_args) _id = neutronv20.find_resourceid_by_name_or_id(neutron_client, self.resource, parsed_args.id) self.call_api(neutron_client, _id, body) print((_('Removed firewall rule from firewall policy %(id)s') % {'id': parsed_args.id}), file=self.app.stdout) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/fw/firewallrule.py0000664000175000017500000001314200000000000026643 0ustar00zuulzuul00000000000000# Copyright 2013 Big Switch Networks # 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 from neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronv20 def _add_common_args(parser, is_create=True): """If is_create is True, protocol and action become mandatory arguments. CreateCommand = is_create : True UpdateCommand = is_create : False """ parser.add_argument( '--name', help=_('Name for the firewall rule.')) parser.add_argument( '--description', help=_('Description for the firewall rule.')) parser.add_argument( '--source-ip-address', help=_('Source IP address or subnet.')) parser.add_argument( '--destination-ip-address', help=_('Destination IP address or subnet.')) parser.add_argument( '--source-port', help=_('Source port (integer in [1, 65535] or range in a:b).')) parser.add_argument( '--destination-port', help=_('Destination port (integer in [1, 65535] or range in ' 'a:b).')) utils.add_boolean_argument( parser, '--enabled', dest='enabled', help=_('Whether to enable or disable this rule.')) parser.add_argument( '--protocol', choices=['tcp', 'udp', 'icmp', 'any'], required=is_create, type=utils.convert_to_lowercase, help=_('Protocol for the firewall rule.')) parser.add_argument( '--action', required=is_create, type=utils.convert_to_lowercase, choices=['allow', 'deny', 'reject'], help=_('Action for the firewall rule.')) def common_args2body(parsed_args): body = {} neutronv20.update_dict(parsed_args, body, ['name', 'description', 'shared', 'tenant_id', 'source_ip_address', 'destination_ip_address', 'source_port', 'destination_port', 'action', 'enabled', 'ip_version']) protocol = parsed_args.protocol if protocol: if protocol == 'any': protocol = None body['protocol'] = protocol return body class ListFirewallRule(neutronv20.ListCommand): """List firewall rules that belong to a given tenant.""" resource = 'firewall_rule' list_columns = ['id', 'name', 'firewall_policy_id', 'summary', 'enabled'] pagination_support = True sorting_support = True def extend_list(self, data, parsed_args): for d in data: val = [] if d.get('protocol'): protocol = d['protocol'].upper() else: protocol = 'no-protocol' val.append(protocol) if 'source_ip_address' in d and 'source_port' in d: src = 'source: ' + str(d['source_ip_address']).lower() src = src + '(' + str(d['source_port']).lower() + ')' else: src = 'source: none specified' val.append(src) if 'destination_ip_address' in d and 'destination_port' in d: dst = 'dest: ' + str(d['destination_ip_address']).lower() dst = dst + '(' + str(d['destination_port']).lower() + ')' else: dst = 'dest: none specified' val.append(dst) if 'action' in d: action = d['action'] else: action = 'no-action' val.append(action) d['summary'] = ',\n '.join(val) class ShowFirewallRule(neutronv20.ShowCommand): """Show information of a given firewall rule.""" resource = 'firewall_rule' class CreateFirewallRule(neutronv20.CreateCommand): """Create a firewall rule.""" resource = 'firewall_rule' def add_known_arguments(self, parser): parser.add_argument( '--shared', action='store_true', help=_('Set shared flag for the firewall rule.'), default=argparse.SUPPRESS) _add_common_args(parser) parser.add_argument( '--ip-version', type=int, choices=[4, 6], default=4, help=_('IP version for the firewall rule (default is 4).')) def args2body(self, parsed_args): return {self.resource: common_args2body(parsed_args)} class UpdateFirewallRule(neutronv20.UpdateCommand): """Update a given firewall rule.""" resource = 'firewall_rule' def add_known_arguments(self, parser): utils.add_boolean_argument( parser, '--shared', dest='shared', help=_('Update the shared flag for the firewall rule.'), default=argparse.SUPPRESS) parser.add_argument( '--ip-version', type=int, choices=[4, 6], help=_('Update IP version for the firewall rule.')) _add_common_args(parser, is_create=False) def args2body(self, parsed_args): return {self.resource: common_args2body(parsed_args)} class DeleteFirewallRule(neutronv20.DeleteCommand): """Delete a given firewall rule.""" resource = 'firewall_rule' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2136614 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/0000775000175000017500000000000000000000000023554 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/__init__.py0000664000175000017500000000000000000000000025653 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/healthmonitor.py0000664000175000017500000001413600000000000027010 0ustar00zuulzuul00000000000000# Copyright 2013 Mirantis Inc. # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 class ListHealthMonitor(neutronV20.ListCommand): """List health monitors that belong to a given tenant.""" resource = 'health_monitor' list_columns = ['id', 'type', 'admin_state_up'] pagination_support = True sorting_support = True class ShowHealthMonitor(neutronV20.ShowCommand): """Show information of a given health monitor.""" resource = 'health_monitor' allow_names = False class CreateHealthMonitor(neutronV20.CreateCommand): """Create a health monitor.""" resource = 'health_monitor' def add_known_arguments(self, parser): parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--expected-codes', help=_('The list of HTTP status codes expected in ' 'response from the member to declare it healthy. This ' 'attribute can contain one value, ' 'or a list of values separated by comma, ' 'or a range of values (e.g. "200-299"). If this attribute ' 'is not specified, it defaults to "200".')) parser.add_argument( '--http-method', help=_('The HTTP method used for requests by the monitor of type ' 'HTTP.')) parser.add_argument( '--url-path', help=_('The HTTP path used in the HTTP request used by the monitor' ' to test a member health. This must be a string ' 'beginning with a / (forward slash).')) parser.add_argument( '--delay', required=True, help=_('The time in seconds between sending probes to members.')) parser.add_argument( '--max-retries', required=True, help=_('Number of permissible connection failures before changing ' 'the member status to INACTIVE. [1..10]')) parser.add_argument( '--timeout', required=True, help=_('Maximum number of seconds for a monitor to wait for a ' 'connection to be established before it times out. The ' 'value must be less than the delay value.')) parser.add_argument( '--type', required=True, choices=['PING', 'TCP', 'HTTP', 'HTTPS'], help=_('One of the predefined health monitor types.')) def args2body(self, parsed_args): body = {'admin_state_up': parsed_args.admin_state, 'delay': parsed_args.delay, 'max_retries': parsed_args.max_retries, 'timeout': parsed_args.timeout, 'type': parsed_args.type} neutronV20.update_dict(parsed_args, body, ['expected_codes', 'http_method', 'url_path', 'tenant_id']) return {self.resource: body} class UpdateHealthMonitor(neutronV20.UpdateCommand): """Update a given health monitor.""" resource = 'health_monitor' allow_names = False class DeleteHealthMonitor(neutronV20.DeleteCommand): """Delete a given health monitor.""" resource = 'health_monitor' allow_names = False class AssociateHealthMonitor(neutronV20.NeutronCommand): """Create a mapping between a health monitor and a pool.""" resource = 'health_monitor' def get_parser(self, prog_name): parser = super(AssociateHealthMonitor, self).get_parser(prog_name) parser.add_argument( 'health_monitor_id', metavar='HEALTH_MONITOR_ID', help=_('Health monitor to associate.')) parser.add_argument( 'pool_id', metavar='POOL', help=_('ID of the pool to be associated with the health monitor.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() body = {'health_monitor': {'id': parsed_args.health_monitor_id}} pool_id = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'pool', parsed_args.pool_id) neutron_client.associate_health_monitor(pool_id, body) print((_('Associated health monitor ' '%s') % parsed_args.health_monitor_id), file=self.app.stdout) class DisassociateHealthMonitor(neutronV20.NeutronCommand): """Remove a mapping from a health monitor to a pool.""" resource = 'health_monitor' def get_parser(self, prog_name): parser = super(DisassociateHealthMonitor, self).get_parser(prog_name) parser.add_argument( 'health_monitor_id', metavar='HEALTH_MONITOR_ID', help=_('Health monitor to disassociate.')) parser.add_argument( 'pool_id', metavar='POOL', help=_('ID of the pool to be disassociated with the health ' 'monitor.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() pool_id = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'pool', parsed_args.pool_id) neutron_client.disassociate_health_monitor(pool_id, parsed_args .health_monitor_id) print((_('Disassociated health monitor ' '%s') % parsed_args.health_monitor_id), file=self.app.stdout) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/member.py0000664000175000017500000000525300000000000025402 0ustar00zuulzuul00000000000000# Copyright 2013 Mirantis Inc. # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 class ListMember(neutronV20.ListCommand): """List members that belong to a given tenant.""" resource = 'member' list_columns = [ 'id', 'address', 'protocol_port', 'weight', 'admin_state_up', 'status' ] pagination_support = True sorting_support = True class ShowMember(neutronV20.ShowCommand): """Show information of a given member.""" resource = 'member' allow_names = False class CreateMember(neutronV20.CreateCommand): """Create a member.""" resource = 'member' def add_known_arguments(self, parser): parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--weight', help=_('Weight of pool member in the pool (default:1, [0..256]).')) parser.add_argument( '--address', required=True, help=_('IP address of the pool member on the pool network.')) parser.add_argument( '--protocol-port', required=True, help=_('Port on which the pool member listens for requests or ' 'connections.')) parser.add_argument( 'pool_id', metavar='POOL', help=_('ID or name of the pool this vip belongs to.')) def args2body(self, parsed_args): _pool_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'pool', parsed_args.pool_id) body = {'pool_id': _pool_id, 'admin_state_up': parsed_args.admin_state} neutronV20.update_dict( parsed_args, body, ['address', 'protocol_port', 'weight', 'tenant_id'] ) return {self.resource: body} class UpdateMember(neutronV20.UpdateCommand): """Update a given member.""" resource = 'member' class DeleteMember(neutronV20.DeleteCommand): """Delete a given member.""" resource = 'member' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/pool.py0000664000175000017500000000750500000000000025106 0ustar00zuulzuul00000000000000# Copyright 2013 Mirantis Inc. # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 def _format_provider(pool): return pool.get('provider') or 'N/A' class ListPool(neutronV20.ListCommand): """List pools that belong to a given tenant.""" resource = 'pool' list_columns = ['id', 'name', 'provider', 'lb_method', 'protocol', 'admin_state_up', 'status'] _formatters = {'provider': _format_provider} pagination_support = True sorting_support = True class ShowPool(neutronV20.ShowCommand): """Show information of a given pool.""" resource = 'pool' class CreatePool(neutronV20.CreateCommand): """Create a pool.""" resource = 'pool' def add_known_arguments(self, parser): parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--description', help=_('Description of the pool.')) parser.add_argument( '--lb-method', required=True, choices=['ROUND_ROBIN', 'LEAST_CONNECTIONS', 'SOURCE_IP'], help=_('The algorithm used to distribute load between the members ' 'of the pool.')) parser.add_argument( '--name', required=True, help=_('The name of the pool.')) parser.add_argument( '--protocol', required=True, choices=['HTTP', 'HTTPS', 'TCP'], help=_('Protocol for balancing.')) parser.add_argument( '--subnet-id', metavar='SUBNET', required=True, help=_('The subnet on which the members of the pool will be ' 'located.')) parser.add_argument( '--provider', help=_('Provider name of the loadbalancer service.')) def args2body(self, parsed_args): _subnet_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'subnet', parsed_args.subnet_id) body = {'admin_state_up': parsed_args.admin_state, 'subnet_id': _subnet_id} neutronV20.update_dict(parsed_args, body, ['description', 'lb_method', 'name', 'protocol', 'tenant_id', 'provider']) return {self.resource: body} class UpdatePool(neutronV20.UpdateCommand): """Update a given pool.""" resource = 'pool' class DeletePool(neutronV20.DeleteCommand): """Delete a given pool.""" resource = 'pool' class RetrievePoolStats(neutronV20.ShowCommand): """Retrieve stats for a given pool.""" resource = 'pool' def take_action(self, parsed_args): neutron_client = self.get_client() pool_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'pool', parsed_args.id) params = {} if parsed_args.fields: params = {'fields': parsed_args.fields} data = neutron_client.retrieve_pool_stats(pool_id, **params) self.format_output_data(data) stats = data['stats'] if 'stats' in data: return zip(*sorted(stats.items())) else: return None ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2136614 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/v2/0000775000175000017500000000000000000000000024103 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/v2/__init__.py0000664000175000017500000000000000000000000026202 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/v2/healthmonitor.py0000664000175000017500000001234600000000000027340 0ustar00zuulzuul00000000000000# Copyright 2013 Mirantis Inc. # Copyright 2014 Blue Box Group, Inc. # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 def _add_common_args(parser, is_create=True): parser.add_argument( '--delay', required=is_create, help=_('The time in seconds between sending probes to members.')) parser.add_argument( '--name', help=_('Name of the health monitor.')) parser.add_argument( '--timeout', required=is_create, help=_('Maximum number of seconds for a monitor to wait for a ' 'connection to be established before it times out. The ' 'value must be less than the delay value.')) parser.add_argument( '--http-method', type=utils.convert_to_uppercase, help=_('The HTTP method used for requests by the monitor of type ' 'HTTP.')) parser.add_argument( '--url-path', help=_('The HTTP path used in the HTTP request used by the monitor ' 'to test a member health. This must be a string ' 'beginning with a / (forward slash).')) parser.add_argument( '--max-retries', required=is_create, help=_('Number of permissible connection failures before changing ' 'the member status to INACTIVE. [1..10].')) parser.add_argument( '--expected-codes', help=_('The list of HTTP status codes expected in ' 'response from the member to declare it healthy. This ' 'attribute can contain one value, ' 'or a list of values separated by comma, ' 'or a range of values (e.g. "200-299"). If this attribute ' 'is not specified, it defaults to "200".')) def _parse_common_args(body, parsed_args): neutronV20.update_dict(parsed_args, body, ['expected_codes', 'http_method', 'url_path', 'timeout', 'name', 'delay', 'max_retries']) class ListHealthMonitor(neutronV20.ListCommand): """LBaaS v2 List healthmonitors that belong to a given tenant.""" resource = 'healthmonitor' shadow_resource = 'lbaas_healthmonitor' list_columns = ['id', 'name', 'type', 'admin_state_up'] pagination_support = True sorting_support = True class ShowHealthMonitor(neutronV20.ShowCommand): """LBaaS v2 Show information of a given healthmonitor.""" resource = 'healthmonitor' shadow_resource = 'lbaas_healthmonitor' class CreateHealthMonitor(neutronV20.CreateCommand): """LBaaS v2 Create a healthmonitor.""" resource = 'healthmonitor' shadow_resource = 'lbaas_healthmonitor' def add_known_arguments(self, parser): _add_common_args(parser) parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--type', required=True, choices=['PING', 'TCP', 'HTTP', 'HTTPS'], help=_('One of the predefined health monitor types.')) parser.add_argument( '--pool', required=True, help=_('ID or name of the pool that this healthmonitor will ' 'monitor.')) def args2body(self, parsed_args): pool_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'pool', parsed_args.pool, cmd_resource='lbaas_pool') body = {'admin_state_up': parsed_args.admin_state, 'type': parsed_args.type, 'pool_id': pool_id} neutronV20.update_dict(parsed_args, body, ['tenant_id']) _parse_common_args(body, parsed_args) return {self.resource: body} class UpdateHealthMonitor(neutronV20.UpdateCommand): """LBaaS v2 Update a given healthmonitor.""" resource = 'healthmonitor' shadow_resource = 'lbaas_healthmonitor' def add_known_arguments(self, parser): _add_common_args(parser, is_create=False) utils.add_boolean_argument( parser, '--admin-state-up', help=_('Update the administrative state of ' 'the health monitor (True meaning "Up").')) def args2body(self, parsed_args): body = {} _parse_common_args(body, parsed_args) neutronV20.update_dict(parsed_args, body, ['admin_state_up']) return {self.resource: body} class DeleteHealthMonitor(neutronV20.DeleteCommand): """LBaaS v2 Delete a given healthmonitor.""" resource = 'healthmonitor' shadow_resource = 'lbaas_healthmonitor' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/v2/l7policy.py0000664000175000017500000001247000000000000026223 0ustar00zuulzuul00000000000000# Copyright 2016 Radware LTD. # 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 neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 def _get_listener_id(client, listener_id_or_name): return neutronV20.find_resourceid_by_name_or_id( client, 'listener', listener_id_or_name) def _get_pool_id(client, pool_id_or_name): return neutronV20.find_resourceid_by_name_or_id( client, 'pool', pool_id_or_name, cmd_resource='lbaas_pool') def _add_common_args(parser, is_create=True): parser.add_argument( '--name', help=_('Name of the policy.')) parser.add_argument( '--description', help=_('Description of the policy.')) parser.add_argument( '--action', required=is_create, metavar='ACTION', type=utils.convert_to_uppercase, choices=['REJECT', 'REDIRECT_TO_POOL', 'REDIRECT_TO_URL'], help=_('Action type of the policy.')) parser.add_argument( '--redirect-pool', help=_('ID or name of the pool for REDIRECT_TO_POOL action type.')) parser.add_argument( '--redirect-url', help=_('URL for REDIRECT_TO_URL action type. ' 'This should be a valid URL string.')) parser.add_argument( '--position', type=int, help=_('L7 policy position in ordered policies list. ' 'This must be an integer starting from 1. ' 'Not specifying the position will place the policy ' 'at the tail of existing policies list.')) def _common_args2body(client, parsed_args, is_create=True): if parsed_args.redirect_url: if parsed_args.action != 'REDIRECT_TO_URL': raise exceptions.CommandError(_('Action must be REDIRECT_TO_URL')) if parsed_args.redirect_pool: if parsed_args.action != 'REDIRECT_TO_POOL': raise exceptions.CommandError(_('Action must be REDIRECT_TO_POOL')) parsed_args.redirect_pool_id = _get_pool_id( client, parsed_args.redirect_pool) if (parsed_args.action == 'REDIRECT_TO_URL' and not parsed_args.redirect_url): raise exceptions.CommandError(_('Redirect URL must be specified')) if (parsed_args.action == 'REDIRECT_TO_POOL' and not parsed_args.redirect_pool): raise exceptions.CommandError(_('Redirect pool must be specified')) attributes = ['name', 'description', 'action', 'redirect_pool_id', 'redirect_url', 'position', 'admin_state_up'] if is_create: parsed_args.listener_id = _get_listener_id( client, parsed_args.listener) attributes.extend(['listener_id', 'tenant_id']) body = {} neutronV20.update_dict(parsed_args, body, attributes) return {'l7policy': body} class ListL7Policy(neutronV20.ListCommand): """LBaaS v2 List L7 policies that belong to a given listener.""" resource = 'l7policy' shadow_resource = 'lbaas_l7policy' pagination_support = True sorting_support = True list_columns = [ 'id', 'name', 'action', 'redirect_pool_id', 'redirect_url', 'position', 'admin_state_up', 'status' ] class ShowL7Policy(neutronV20.ShowCommand): """LBaaS v2 Show information of a given L7 policy.""" resource = 'l7policy' shadow_resource = 'lbaas_l7policy' class CreateL7Policy(neutronV20.CreateCommand): """LBaaS v2 Create L7 policy.""" resource = 'l7policy' shadow_resource = 'lbaas_l7policy' def add_known_arguments(self, parser): _add_common_args(parser) parser.add_argument( '--admin-state-down', dest='admin_state_up', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--listener', required=True, metavar='LISTENER', help=_('ID or name of the listener this policy belongs to.')) def args2body(self, parsed_args): return _common_args2body(self.get_client(), parsed_args) class UpdateL7Policy(neutronV20.UpdateCommand): """LBaaS v2 Update a given L7 policy.""" resource = 'l7policy' shadow_resource = 'lbaas_l7policy' def add_known_arguments(self, parser): _add_common_args(parser, is_create=False) utils.add_boolean_argument( parser, '--admin-state-up', help=_('Specify the administrative state of the policy' ' (True meaning "Up").')) def args2body(self, parsed_args): return _common_args2body(self.get_client(), parsed_args, False) class DeleteL7Policy(neutronV20.DeleteCommand): """LBaaS v2 Delete a given L7 policy.""" resource = 'l7policy' shadow_resource = 'lbaas_l7policy' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/v2/l7rule.py0000664000175000017500000001125000000000000025666 0ustar00zuulzuul00000000000000# Copyright 2016 Radware LTD. # 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 neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 def _get_policy_id(client, policy_id_or_name): return neutronV20.find_resourceid_by_name_or_id( client, 'l7policy', policy_id_or_name, cmd_resource='lbaas_l7policy') class LbaasL7RuleMixin(object): def set_extra_attrs(self, parsed_args): self.parent_id = _get_policy_id(self.get_client(), parsed_args.l7policy) def add_known_arguments(self, parser): parser.add_argument( 'l7policy', metavar='L7POLICY', help=_('ID or name of L7 policy this rule belongs to.')) def _add_common_args(parser, is_create=True): parser.add_argument( '--type', required=is_create, type=utils.convert_to_uppercase, choices=['HOST_NAME', 'PATH', 'FILE_TYPE', 'HEADER', 'COOKIE'], help=_('Rule type.')) parser.add_argument( '--compare-type', required=is_create, type=utils.convert_to_uppercase, choices=['REGEX', 'STARTS_WITH', 'ENDS_WITH', 'CONTAINS', 'EQUAL_TO'], help=_('Rule compare type.')) parser.add_argument( '--invert-compare', dest='invert', action='store_true', help=_('Invert the compare type.')) parser.add_argument( '--key', help=_('Key to compare.' ' Relevant for HEADER and COOKIE types only.')) parser.add_argument( '--value', required=is_create, help=_('Value to compare.')) def _common_args2body(client, parsed_args, is_create=True): attributes = ['type', 'compare_type', 'invert', 'key', 'value', 'admin_state_up'] if is_create: attributes.append('tenant_id') body = {} neutronV20.update_dict(parsed_args, body, attributes) return {'rule': body} class ListL7Rule(LbaasL7RuleMixin, neutronV20.ListCommand): """LBaaS v2 List L7 rules that belong to a given L7 policy.""" resource = 'rule' shadow_resource = 'lbaas_l7rule' pagination_support = True sorting_support = True list_columns = [ 'id', 'type', 'compare_type', 'invert', 'key', 'value', 'admin_state_up', 'status' ] def take_action(self, parsed_args): self.parent_id = _get_policy_id(self.get_client(), parsed_args.l7policy) self.values_specs.append('--l7policy_id=%s' % self.parent_id) return super(ListL7Rule, self).take_action(parsed_args) class ShowL7Rule(LbaasL7RuleMixin, neutronV20.ShowCommand): """LBaaS v2 Show information of a given rule.""" resource = 'rule' shadow_resource = 'lbaas_l7rule' class CreateL7Rule(LbaasL7RuleMixin, neutronV20.CreateCommand): """LBaaS v2 Create L7 rule.""" resource = 'rule' shadow_resource = 'lbaas_l7rule' def add_known_arguments(self, parser): super(CreateL7Rule, self).add_known_arguments(parser) _add_common_args(parser) parser.add_argument( '--admin-state-down', dest='admin_state_up', action='store_false', help=_('Set admin state up to false')) def args2body(self, parsed_args): return _common_args2body(self.get_client(), parsed_args) class UpdateL7Rule(LbaasL7RuleMixin, neutronV20.UpdateCommand): """LBaaS v2 Update a given L7 rule.""" resource = 'rule' shadow_resource = 'lbaas_l7rule' def add_known_arguments(self, parser): super(UpdateL7Rule, self).add_known_arguments(parser) _add_common_args(parser, False) utils.add_boolean_argument( parser, '--admin-state-up', help=_('Specify the administrative state of the rule' ' (True meaning "Up").')) def args2body(self, parsed_args): return _common_args2body(self.get_client(), parsed_args, False) class DeleteL7Rule(LbaasL7RuleMixin, neutronV20.DeleteCommand): """LBaaS v2 Delete a given L7 rule.""" resource = 'rule' shadow_resource = 'lbaas_l7rule' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/v2/listener.py0000664000175000017500000001364000000000000026306 0ustar00zuulzuul00000000000000# Copyright 2014 Blue Box Group, Inc. # Copyright 2015 Hewlett-Packard Development Company, L.P. # 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 neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 def _get_loadbalancer_id(client, lb_id_or_name): return neutronV20.find_resourceid_by_name_or_id( client, 'loadbalancer', lb_id_or_name, cmd_resource='lbaas_loadbalancer') def _get_pool(client, pool_id_or_name): return neutronV20.find_resource_by_name_or_id( client, 'pool', pool_id_or_name, cmd_resource='lbaas_pool') def _get_pool_id(client, pool_id_or_name): return neutronV20.find_resourceid_by_name_or_id( client, 'pool', pool_id_or_name, cmd_resource='lbaas_pool') def _add_common_args(parser): parser.add_argument( '--description', help=_('Description of the listener.')) parser.add_argument( '--connection-limit', type=int, help=_('The maximum number of connections per second allowed for ' 'the listener. Positive integer or -1 ' 'for unlimited (default).')) parser.add_argument( '--default-pool', help=_('Default pool for the listener.')) def _parse_common_args(body, parsed_args, client): neutronV20.update_dict(parsed_args, body, ['name', 'description', 'connection_limit']) if parsed_args.default_pool: default_pool_id = _get_pool_id( client, parsed_args.default_pool) body['default_pool_id'] = default_pool_id class ListListener(neutronV20.ListCommand): """LBaaS v2 List listeners that belong to a given tenant.""" resource = 'listener' list_columns = ['id', 'default_pool_id', 'name', 'protocol', 'protocol_port', 'admin_state_up', 'status'] pagination_support = True sorting_support = True class ShowListener(neutronV20.ShowCommand): """LBaaS v2 Show information of a given listener.""" resource = 'listener' class CreateListener(neutronV20.CreateCommand): """LBaaS v2 Create a listener.""" resource = 'listener' def add_known_arguments(self, parser): _add_common_args(parser) parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--name', help=_('The name of the listener. At least one of --default-pool ' 'or --loadbalancer must be specified.')) parser.add_argument( '--default-tls-container-ref', dest='default_tls_container_ref', help=_('Default TLS container reference' ' to retrieve TLS information.')) parser.add_argument( '--sni-container-refs', dest='sni_container_refs', nargs='+', help=_('List of TLS container references for SNI.')) parser.add_argument( '--loadbalancer', metavar='LOADBALANCER', help=_('ID or name of the load balancer.')) parser.add_argument( '--protocol', required=True, choices=['TCP', 'HTTP', 'HTTPS', 'TERMINATED_HTTPS'], type=utils.convert_to_uppercase, help=_('Protocol for the listener.')) parser.add_argument( '--protocol-port', dest='protocol_port', required=True, metavar='PORT', help=_('Protocol port for the listener.')) def args2body(self, parsed_args): if not parsed_args.loadbalancer and not parsed_args.default_pool: message = _('Either --default-pool or --loadbalancer must be ' 'specified.') raise exceptions.CommandError(message) body = { 'protocol': parsed_args.protocol, 'protocol_port': parsed_args.protocol_port, 'admin_state_up': parsed_args.admin_state } if parsed_args.loadbalancer: loadbalancer_id = _get_loadbalancer_id( self.get_client(), parsed_args.loadbalancer) body['loadbalancer_id'] = loadbalancer_id neutronV20.update_dict(parsed_args, body, ['default_tls_container_ref', 'sni_container_refs', 'tenant_id']) _parse_common_args(body, parsed_args, self.get_client()) return {self.resource: body} class UpdateListener(neutronV20.UpdateCommand): """LBaaS v2 Update a given listener.""" resource = 'listener' def add_known_arguments(self, parser): _add_common_args(parser) parser.add_argument( '--name', help=_('Name of the listener.')) utils.add_boolean_argument( parser, '--admin-state-up', dest='admin_state_up', help=_('Specify the administrative state of the listener. ' '(True meaning "Up")')) def args2body(self, parsed_args): body = {} neutronV20.update_dict(parsed_args, body, ['admin_state_up']) _parse_common_args(body, parsed_args, self.get_client()) return {self.resource: body} class DeleteListener(neutronV20.DeleteCommand): """LBaaS v2 Delete a given listener.""" resource = 'listener' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/v2/loadbalancer.py0000664000175000017500000001437500000000000027076 0ustar00zuulzuul00000000000000# Copyright 2014 Blue Box Group, Inc. # Copyright 2015 Hewlett-Packard Development Company, L.P. # 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 oslo_serialization import jsonutils from neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 def _add_common_args(parser): parser.add_argument( '--description', help=_('Description of the load balancer.')) parser.add_argument( '--name', metavar='NAME', help=_('Name of the load balancer.')) def _parse_common_args(body, parsed_args): neutronV20.update_dict(parsed_args, body, ['name', 'description']) class ListLoadBalancer(neutronV20.ListCommand): """LBaaS v2 List loadbalancers that belong to a given tenant.""" resource = 'loadbalancer' list_columns = ['id', 'name', 'vip_address', 'provisioning_status', 'provider'] pagination_support = True sorting_support = True class ShowLoadBalancer(neutronV20.ShowCommand): """LBaaS v2 Show information of a given loadbalancer.""" resource = 'loadbalancer' class CreateLoadBalancer(neutronV20.CreateCommand): """LBaaS v2 Create a loadbalancer.""" resource = 'loadbalancer' def add_known_arguments(self, parser): _add_common_args(parser) parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--provider', help=_('Provider name of the load balancer service.')) parser.add_argument( '--flavor', help=_('ID or name of the flavor.')) parser.add_argument( '--vip-address', help=_('VIP address for the load balancer.')) parser.add_argument( 'vip_subnet', metavar='VIP_SUBNET', help=_('Load balancer VIP subnet.')) def args2body(self, parsed_args): _subnet_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'subnet', parsed_args.vip_subnet) body = {'vip_subnet_id': _subnet_id, 'admin_state_up': parsed_args.admin_state} if parsed_args.flavor: _flavor_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'flavor', parsed_args.flavor) body['flavor_id'] = _flavor_id neutronV20.update_dict(parsed_args, body, ['provider', 'vip_address', 'tenant_id']) _parse_common_args(body, parsed_args) return {self.resource: body} class UpdateLoadBalancer(neutronV20.UpdateCommand): """LBaaS v2 Update a given loadbalancer.""" resource = 'loadbalancer' def add_known_arguments(self, parser): utils.add_boolean_argument( parser, '--admin-state-up', help=_('Update the administrative state of ' 'the load balancer (True meaning "Up").')) _add_common_args(parser) def args2body(self, parsed_args): body = {} _parse_common_args(body, parsed_args) neutronV20.update_dict(parsed_args, body, ['admin_state_up']) return {self.resource: body} class DeleteLoadBalancer(neutronV20.DeleteCommand): """LBaaS v2 Delete a given loadbalancer.""" resource = 'loadbalancer' class RetrieveLoadBalancerStats(neutronV20.ShowCommand): """Retrieve stats for a given loadbalancer.""" resource = 'loadbalancer' def take_action(self, parsed_args): neutron_client = self.get_client() loadbalancer_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'loadbalancer', parsed_args.id) params = {} if parsed_args.fields: params = {'fields': parsed_args.fields} data = neutron_client.retrieve_loadbalancer_stats(loadbalancer_id, **params) self.format_output_data(data) stats = data['stats'] if 'stats' in data: # To render the output table like: # +--------------------+-------+ # | Field | Value | # +--------------------+-------+ # | field1 | value1| # | field2 | value2| # | field3 | value3| # | ... | ... | # +--------------------+-------+ # it has two columns and the Filed column is alphabetical, # here convert the data dict to the 1-1 vector format below: # [(field1, field2, field3, ...), (value1, value2, value3, ...)] return list(zip(*sorted(stats.items()))) class RetrieveLoadBalancerStatus(neutronV20.NeutronCommand): """Retrieve status for a given loadbalancer. The only output is a formatted JSON tree, and the table format does not support this type of data. """ resource = 'loadbalancer' def get_parser(self, prog_name): parser = super(RetrieveLoadBalancerStatus, self).get_parser(prog_name) parser.add_argument( self.resource, metavar=self.resource.upper(), help=_('ID or name of %s to show.') % self.resource) return parser def take_action(self, parsed_args): self.log.debug('run(%s)', parsed_args) neutron_client = self.get_client() lb_id = neutronV20.find_resourceid_by_name_or_id( neutron_client, self.resource, parsed_args.loadbalancer) params = {} data = neutron_client.retrieve_loadbalancer_status(lb_id, **params) res = data['statuses'] if 'statuses' in data: print(jsonutils.dumps(res, indent=4)) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/v2/member.py0000664000175000017500000001227400000000000025732 0ustar00zuulzuul00000000000000# Copyright 2013 Mirantis Inc. # Copyright 2014 Blue Box Group, Inc. # Copyright 2015 Hewlett-Packard Development Company, L.P. # 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 neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 def _get_pool_id(client, pool_id_or_name): return neutronV20.find_resourceid_by_name_or_id(client, 'pool', pool_id_or_name, cmd_resource='lbaas_pool') class LbaasMemberMixin(object): def set_extra_attrs(self, parsed_args): self.parent_id = _get_pool_id(self.get_client(), parsed_args.pool) def add_known_arguments(self, parser): parser.add_argument( 'pool', metavar='POOL', help=_('ID or name of the pool that this member belongs to.')) def _add_common_args(parser): parser.add_argument( '--name', help=_('Name of the member.')) parser.add_argument( '--weight', help=_('Weight of the member in the pool (default:1, [0..256]).')) def _parse_common_args(body, parsed_args): neutronV20.update_dict(parsed_args, body, ['weight', 'name']) class ListMember(LbaasMemberMixin, neutronV20.ListCommand): """LBaaS v2 List members that belong to a given pool.""" resource = 'member' shadow_resource = 'lbaas_member' list_columns = [ 'id', 'name', 'address', 'protocol_port', 'weight', 'subnet_id', 'admin_state_up', 'status' ] pagination_support = True sorting_support = True def take_action(self, parsed_args): self.parent_id = _get_pool_id(self.get_client(), parsed_args.pool) self.values_specs.append('--pool_id=%s' % self.parent_id) return super(ListMember, self).take_action(parsed_args) class ShowMember(LbaasMemberMixin, neutronV20.ShowCommand): """LBaaS v2 Show information of a given member.""" resource = 'member' shadow_resource = 'lbaas_member' class CreateMember(neutronV20.CreateCommand): """LBaaS v2 Create a member.""" resource = 'member' shadow_resource = 'lbaas_member' def add_known_arguments(self, parser): _add_common_args(parser) parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--subnet', required=True, help=_('Subnet ID or name for the member.')) parser.add_argument( '--address', required=True, help=_('IP address of the pool member in the pool.')) parser.add_argument( '--protocol-port', required=True, help=_('Port on which the pool member listens for requests or ' 'connections.')) parser.add_argument( 'pool', metavar='POOL', help=_('ID or name of the pool that this member belongs to.')) def args2body(self, parsed_args): self.parent_id = _get_pool_id(self.get_client(), parsed_args.pool) _subnet_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'subnet', parsed_args.subnet) body = {'subnet_id': _subnet_id, 'admin_state_up': parsed_args.admin_state, 'protocol_port': parsed_args.protocol_port, 'address': parsed_args.address} neutronV20.update_dict(parsed_args, body, ['subnet_id', 'tenant_id']) _parse_common_args(body, parsed_args) return {self.resource: body} class UpdateMember(neutronV20.UpdateCommand): """LBaaS v2 Update a given member.""" resource = 'member' shadow_resource = 'lbaas_member' def add_known_arguments(self, parser): parser.add_argument( 'pool', metavar='POOL', help=_('ID or name of the pool that this member belongs to.')) utils.add_boolean_argument( parser, '--admin-state-up', help=_('Update the administrative state of ' 'the member (True meaning "Up").')) _add_common_args(parser) def args2body(self, parsed_args): self.parent_id = _get_pool_id(self.get_client(), parsed_args.pool) body = {} if hasattr(parsed_args, "admin_state_up"): body['admin_state_up'] = parsed_args.admin_state_up _parse_common_args(body, parsed_args) return {self.resource: body} class DeleteMember(LbaasMemberMixin, neutronV20.DeleteCommand): """LBaaS v2 Delete a given member.""" resource = 'member' shadow_resource = 'lbaas_member' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/v2/pool.py0000664000175000017500000001542700000000000025437 0ustar00zuulzuul00000000000000# Copyright 2013 Mirantis Inc. # Copyright 2014 Blue Box Group, Inc. # Copyright 2015 Hewlett-Packard Development Company, L.P. # Copyright 2015 Blue Box, an IBM Company # 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 neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 def _get_loadbalancer_id(client, lb_id_or_name): return neutronV20.find_resourceid_by_name_or_id( client, 'loadbalancer', lb_id_or_name, cmd_resource='lbaas_loadbalancer') def _get_listener(client, listener_id_or_name): return neutronV20.find_resource_by_name_or_id( client, 'listener', listener_id_or_name) def _get_listener_id(client, listener_id_or_name): return neutronV20.find_resourceid_by_name_or_id( client, 'listener', listener_id_or_name) def _add_common_args(parser, is_create=True): parser.add_argument( '--description', help=_('Description of the pool.')) parser.add_argument( '--name', help=_('The name of the pool.')) parser.add_argument( '--lb-algorithm', required=is_create, type=utils.convert_to_uppercase, choices=['ROUND_ROBIN', 'LEAST_CONNECTIONS', 'SOURCE_IP'], help=_('The algorithm used to distribute load between the members ' 'of the pool.')) def _parse_common_args(parsed_args): body = {} neutronV20.update_dict(parsed_args, body, ['description', 'lb_algorithm', 'name']) return body class ListPool(neutronV20.ListCommand): """LBaaS v2 List pools that belong to a given tenant.""" resource = 'pool' shadow_resource = 'lbaas_pool' list_columns = ['id', 'name', 'lb_algorithm', 'protocol', 'admin_state_up'] pagination_support = True sorting_support = True class ShowPool(neutronV20.ShowCommand): """LBaaS v2 Show information of a given pool.""" resource = 'pool' shadow_resource = 'lbaas_pool' def cleanup_output_data(self, data): if 'members' not in data['pool']: return [] member_info = [] for member in data['pool']['members']: member_info.append(member['id']) data['pool']['members'] = member_info class CreatePool(neutronV20.CreateCommand): """LBaaS v2 Create a pool.""" resource = 'pool' shadow_resource = 'lbaas_pool' def add_known_arguments(self, parser): _add_common_args(parser) parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--listener', help=_('Listener whose default-pool should be set to this pool. ' 'At least one of --listener or --loadbalancer must be ' 'specified.')) parser.add_argument( '--loadbalancer', help=_('Loadbalancer with which this pool should be associated. ' 'At least one of --listener or --loadbalancer must be ' 'specified.')) parser.add_argument( '--protocol', type=utils.convert_to_uppercase, required=True, choices=['HTTP', 'HTTPS', 'TCP'], help=_('Protocol for balancing.')) parser.add_argument( '--session-persistence', metavar='type=TYPE[,cookie_name=COOKIE_NAME]', type=utils.str2dict_type(required_keys=['type'], optional_keys=['cookie_name']), help=_('The type of session persistence to use and associated ' 'cookie name.')) def args2body(self, parsed_args): if not parsed_args.listener and not parsed_args.loadbalancer: message = _('At least one of --listener or --loadbalancer must be ' 'specified.') raise exceptions.CommandError(message) body = _parse_common_args(parsed_args) if parsed_args.listener: listener_id = _get_listener_id( self.get_client(), parsed_args.listener) body['listener_id'] = listener_id if parsed_args.loadbalancer: loadbalancer_id = _get_loadbalancer_id( self.get_client(), parsed_args.loadbalancer) body['loadbalancer_id'] = loadbalancer_id body['admin_state_up'] = parsed_args.admin_state neutronV20.update_dict(parsed_args, body, ['tenant_id', 'protocol', 'session_persistence']) return {self.resource: body} class UpdatePool(neutronV20.UpdateCommand): """LBaaS v2 Update a given pool.""" resource = 'pool' shadow_resource = 'lbaas_pool' def add_known_arguments(self, parser): utils.add_boolean_argument( parser, '--admin-state-up', help=_('Update the administrative state of ' 'the pool (True meaning "Up").')) session_group = parser.add_mutually_exclusive_group() session_group.add_argument( '--session-persistence', metavar='type=TYPE[,cookie_name=COOKIE_NAME]', type=utils.str2dict_type(required_keys=['type'], optional_keys=['cookie_name']), help=_('The type of session persistence to use and associated ' 'cookie name.')) session_group.add_argument( '--no-session-persistence', action='store_true', help=_('Clear session persistence for the pool.')) _add_common_args(parser, False) def args2body(self, parsed_args): body = _parse_common_args(parsed_args) if parsed_args.no_session_persistence: body['session_persistence'] = None elif parsed_args.session_persistence: body['session_persistence'] = parsed_args.session_persistence neutronV20.update_dict(parsed_args, body, ['admin_state_up']) return {self.resource: body} class DeletePool(neutronV20.DeleteCommand): """LBaaS v2 Delete a given pool.""" resource = 'pool' shadow_resource = 'lbaas_pool' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/lb/vip.py0000664000175000017500000000704700000000000024734 0ustar00zuulzuul00000000000000# Copyright 2013 Mirantis Inc. # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 class ListVip(neutronV20.ListCommand): """List vips that belong to a given tenant.""" resource = 'vip' list_columns = ['id', 'name', 'algorithm', 'address', 'protocol', 'admin_state_up', 'status'] pagination_support = True sorting_support = True class ShowVip(neutronV20.ShowCommand): """Show information of a given vip.""" resource = 'vip' class CreateVip(neutronV20.CreateCommand): """Create a vip.""" resource = 'vip' def add_known_arguments(self, parser): parser.add_argument( 'pool_id', metavar='POOL', help=_('ID or name of the pool to which this vip belongs.')) parser.add_argument( '--address', help=_('IP address of the vip.')) parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--connection-limit', help=_('The maximum number of connections per second allowed for ' 'the vip. Valid values: a positive integer or -1 ' 'for unlimited (default).')) parser.add_argument( '--description', help=_('Description of the vip to be created.')) parser.add_argument( '--name', required=True, help=_('Name of the vip to be created.')) parser.add_argument( '--protocol-port', required=True, help=_('TCP port on which to listen for client traffic that is ' 'associated with the vip address.')) parser.add_argument( '--protocol', required=True, choices=['TCP', 'HTTP', 'HTTPS'], help=_('Protocol for balancing.')) parser.add_argument( '--subnet-id', metavar='SUBNET', required=True, help=_('The subnet on which to allocate the vip address.')) def args2body(self, parsed_args): _pool_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'pool', parsed_args.pool_id) _subnet_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'subnet', parsed_args.subnet_id) body = {'pool_id': _pool_id, 'admin_state_up': parsed_args.admin_state, 'subnet_id': _subnet_id} neutronV20.update_dict(parsed_args, body, ['address', 'connection_limit', 'description', 'name', 'protocol_port', 'protocol', 'tenant_id']) return {self.resource: body} class UpdateVip(neutronV20.UpdateCommand): """Update a given vip.""" resource = 'vip' class DeleteVip(neutronV20.DeleteCommand): """Delete a given vip.""" resource = 'vip' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/metering.py0000664000175000017500000000774500000000000025360 0ustar00zuulzuul00000000000000# Copyright (C) 2013 eNovance SAS # # 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 neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronv20 class ListMeteringLabel(neutronv20.ListCommand): """List metering labels that belong to a given tenant.""" resource = 'metering_label' list_columns = ['id', 'name', 'description', 'shared'] pagination_support = True sorting_support = True class ShowMeteringLabel(neutronv20.ShowCommand): """Show information of a given metering label.""" resource = 'metering_label' allow_names = True class CreateMeteringLabel(neutronv20.CreateCommand): """Create a metering label for a given tenant.""" resource = 'metering_label' def add_known_arguments(self, parser): parser.add_argument( 'name', metavar='NAME', help=_('Name of the metering label to be created.')) parser.add_argument( '--description', help=_('Description of the metering label to be created.')) parser.add_argument( '--shared', action='store_true', help=_('Set the label as shared.')) def args2body(self, parsed_args): body = {'name': parsed_args.name} neutronv20.update_dict(parsed_args, body, ['tenant_id', 'description', 'shared']) return {'metering_label': body} class DeleteMeteringLabel(neutronv20.DeleteCommand): """Delete a given metering label.""" resource = 'metering_label' allow_names = True class ListMeteringLabelRule(neutronv20.ListCommand): """List metering labels that belong to a given label.""" resource = 'metering_label_rule' list_columns = ['id', 'excluded', 'direction', 'remote_ip_prefix'] pagination_support = True sorting_support = True class ShowMeteringLabelRule(neutronv20.ShowCommand): """Show information of a given metering label rule.""" resource = 'metering_label_rule' allow_names = False class CreateMeteringLabelRule(neutronv20.CreateCommand): """Create a metering label rule for a given label.""" resource = 'metering_label_rule' def add_known_arguments(self, parser): parser.add_argument( 'label_id', metavar='LABEL', help=_('ID or name of the label.')) parser.add_argument( 'remote_ip_prefix', metavar='REMOTE_IP_PREFIX', help=_('CIDR to match on.')) parser.add_argument( '--direction', default='ingress', choices=['ingress', 'egress'], type=utils.convert_to_lowercase, help=_('Direction of traffic, default: ingress.')) parser.add_argument( '--excluded', action='store_true', help=_('Exclude this CIDR from the label, default: not excluded.')) def args2body(self, parsed_args): neutron_client = self.get_client() label_id = neutronv20.find_resourceid_by_name_or_id( neutron_client, 'metering_label', parsed_args.label_id) body = {'metering_label_id': label_id, 'remote_ip_prefix': parsed_args.remote_ip_prefix} neutronv20.update_dict(parsed_args, body, ['direction', 'excluded']) return {'metering_label_rule': body} class DeleteMeteringLabelRule(neutronv20.DeleteCommand): """Delete a given metering label.""" resource = 'metering_label_rule' allow_names = False ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/network.py0000664000175000017500000002216600000000000025231 0ustar00zuulzuul00000000000000# Copyright 2012 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 argparse from neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 from neutronclient.neutron.v2_0 import availability_zone from neutronclient.neutron.v2_0 import dns from neutronclient.neutron.v2_0.qos import policy as qos_policy def _format_subnets(network): try: return '\n'.join([' '.join([s['id'], s.get('cidr', '')]) for s in network['subnets']]) except (TypeError, KeyError): return '' def args2body_common(body, parsed_args): neutronV20.update_dict(parsed_args, body, ['name', 'description']) class ListNetwork(neutronV20.ListCommand): """List networks that belong to a given tenant.""" # Length of a query filter on subnet id # id=& (with len(uuid)=36) subnet_id_filter_len = 40 # Length of a marker in pagination # &marker= (with len(uuid)=36) marker_len = 44 resource = 'network' _formatters = {'subnets': _format_subnets, } list_columns = ['id', 'name', 'subnets'] pagination_support = True sorting_support = True filter_attrs = [ 'tenant_id', 'name', 'admin_state_up', {'name': 'status', 'help': _("Filter %s according to their operation status." "(For example: ACTIVE, ERROR etc)"), 'boolean': False, 'argparse_kwargs': {'type': utils.convert_to_uppercase}}, {'name': 'shared', 'help': _('Filter and list the networks which are shared.'), 'boolean': True}, {'name': 'router:external', 'help': _('Filter and list the networks which are external.'), 'boolean': True}, {'name': 'tags', 'help': _("Filter and list %s which has all given tags. " "Multiple tags can be set like --tags "), 'boolean': False, 'argparse_kwargs': {'metavar': 'TAG'}}, {'name': 'tags_any', 'help': _("Filter and list %s which has any given tags. " "Multiple tags can be set like --tags-any "), 'boolean': False, 'argparse_kwargs': {'metavar': 'TAG'}}, {'name': 'not_tags', 'help': _("Filter and list %s which does not have all given tags. " "Multiple tags can be set like --not-tags "), 'boolean': False, 'argparse_kwargs': {'metavar': 'TAG'}}, {'name': 'not_tags_any', 'help': _("Filter and list %s which does not have any given tags. " "Multiple tags can be set like --not-tags-any " ""), 'boolean': False, 'argparse_kwargs': {'metavar': 'TAG'}}, ] def extend_list(self, data, parsed_args): """Add subnet information to a network list.""" neutron_client = self.get_client() search_opts = {'fields': ['id', 'cidr']} if self.pagination_support: page_size = parsed_args.page_size if page_size: search_opts.update({'limit': page_size}) subnet_ids = [] for n in data: if 'subnets' in n: subnet_ids.extend(n['subnets']) def _get_subnet_list(sub_ids): search_opts['id'] = sub_ids return neutron_client.list_subnets( **search_opts).get('subnets', []) try: subnets = _get_subnet_list(subnet_ids) except exceptions.RequestURITooLong as uri_len_exc: # The URI is too long because of too many subnet_id filters # Use the excess attribute of the exception to know how many # subnet_id filters can be inserted into a single request subnet_count = len(subnet_ids) max_size = ((self.subnet_id_filter_len * subnet_count) - uri_len_exc.excess) if self.pagination_support: max_size -= self.marker_len chunk_size = max_size // self.subnet_id_filter_len subnets = [] for i in range(0, subnet_count, chunk_size): subnets.extend( _get_subnet_list(subnet_ids[i: i + chunk_size])) subnet_dict = dict([(s['id'], s) for s in subnets]) for n in data: if 'subnets' in n: n['subnets'] = [(subnet_dict.get(s) or {"id": s}) for s in n['subnets']] class ListExternalNetwork(ListNetwork): """List external networks that belong to a given tenant.""" pagination_support = True sorting_support = True def retrieve_list(self, parsed_args): external = '--router:external=True' if external not in self.values_specs: self.values_specs.append('--router:external=True') return super(ListExternalNetwork, self).retrieve_list(parsed_args) class ShowNetwork(neutronV20.ShowCommand): """Show information of a given network.""" resource = 'network' class CreateNetwork(neutronV20.CreateCommand, qos_policy.CreateQosPolicyMixin): """Create a network for a given tenant.""" resource = 'network' def add_known_arguments(self, parser): parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--admin_state_down', dest='admin_state', action='store_false', help=argparse.SUPPRESS) parser.add_argument( '--shared', action='store_true', help=_('Set the network as shared.'), default=argparse.SUPPRESS) parser.add_argument( '--provider:network_type', metavar='', help=_('The physical mechanism by which the virtual network' ' is implemented.')) parser.add_argument( '--provider:physical_network', metavar='', help=_('Name of the physical network over which the virtual ' 'network is implemented.')) parser.add_argument( '--provider:segmentation_id', metavar='', help=_('VLAN ID for VLAN networks or tunnel-id for GRE/VXLAN ' 'networks.')) utils.add_boolean_argument( parser, '--vlan-transparent', default=argparse.SUPPRESS, help=_('Create a VLAN transparent network.')) parser.add_argument( 'name', metavar='NAME', help=_('Name of the network to be created.')) parser.add_argument( '--description', help=_('Description of network.')) self.add_arguments_qos_policy(parser) availability_zone.add_az_hint_argument(parser, self.resource) dns.add_dns_argument_create(parser, self.resource, 'domain') def args2body(self, parsed_args): body = {'admin_state_up': parsed_args.admin_state} args2body_common(body, parsed_args) neutronV20.update_dict(parsed_args, body, ['shared', 'tenant_id', 'vlan_transparent', 'provider:network_type', 'provider:physical_network', 'provider:segmentation_id', 'description']) self.args2body_qos_policy(parsed_args, body) availability_zone.args2body_az_hint(parsed_args, body) dns.args2body_dns_create(parsed_args, body, 'domain') return {'network': body} class DeleteNetwork(neutronV20.DeleteCommand): """Delete a given network.""" resource = 'network' class UpdateNetwork(neutronV20.UpdateCommand, qos_policy.UpdateQosPolicyMixin): """Update network's information.""" resource = 'network' def add_known_arguments(self, parser): parser.add_argument( '--name', help=_('Name of the network.')) parser.add_argument( '--description', help=_('Description of this network.')) self.add_arguments_qos_policy(parser) dns.add_dns_argument_update(parser, self.resource, 'domain') def args2body(self, parsed_args): body = {} args2body_common(body, parsed_args) self.args2body_qos_policy(parsed_args, body) dns.args2body_dns_update(parsed_args, body, 'domain') return {'network': body} ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/network_ip_availability.py0000664000175000017500000000520300000000000030444 0ustar00zuulzuul00000000000000# 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 cliff import show from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 class ListIpAvailability(neutronV20.ListCommand): """List IP usage of networks""" resource = 'network_ip_availability' resource_plural = 'network_ip_availabilities' list_columns = ['network_id', 'network_name', 'total_ips', 'used_ips'] paginations_support = True sorting_support = True filter_attrs = [ {'name': 'ip_version', 'help': _('Returns IP availability for the network subnets ' 'with a given IP version. Default: 4'), 'argparse_kwargs': {'type': int, 'choices': [4, 6], 'default': 4} }, {'name': 'network_id', 'help': _('Returns IP availability for the network ' 'matching a given network ID.')}, {'name': 'network_name', 'help': _('Returns IP availability for the network ' 'matching a given name.')}, {'name': 'tenant_id', 'help': _('Returns IP availability for the networks ' 'with a given tenant ID.')}, ] class ShowIpAvailability(neutronV20.NeutronCommand, show.ShowOne): """Show IP usage of specific network""" resource = 'network_ip_availability' def get_parser(self, prog_name): parser = super(ShowIpAvailability, self).get_parser(prog_name) parser.add_argument( 'network_id', metavar='NETWORK', help=_('ID or name of network to look up.')) return parser def take_action(self, parsed_args): self.log.debug('run(%s)', parsed_args) neutron_client = self.get_client() _id = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'network', parsed_args.network_id) data = neutron_client.show_network_ip_availability(_id) self.format_output_data(data) resource = data[self.resource] if self.resource in data: return zip(*sorted(resource.items())) else: return None ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/port.py0000664000175000017500000003123400000000000024520 0ustar00zuulzuul00000000000000# Copyright 2012 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 argparse from oslo_serialization import jsonutils from neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 from neutronclient.neutron.v2_0 import dns from neutronclient.neutron.v2_0.qos import policy as qos_policy def _format_fixed_ips(port): try: return '\n'.join([jsonutils.dumps(ip) for ip in port['fixed_ips']]) except (TypeError, KeyError): return '' def _add_updatable_args(parser): parser.add_argument( '--name', help=_('Name of this port.')) parser.add_argument( '--description', help=_('Description of this port.')) parser.add_argument( '--fixed-ip', metavar='subnet_id=SUBNET,ip_address=IP_ADDR', action='append', type=utils.str2dict_type(optional_keys=['subnet_id', 'ip_address']), help=_('Desired IP and/or subnet for this port: ' 'subnet_id=,ip_address=. ' 'You can repeat this option.')) parser.add_argument( '--fixed_ip', action='append', help=argparse.SUPPRESS) parser.add_argument( '--device-id', help=_('Device ID of this port.')) parser.add_argument( '--device_id', help=argparse.SUPPRESS) parser.add_argument( '--device-owner', help=_('Device owner of this port.')) parser.add_argument( '--device_owner', help=argparse.SUPPRESS) def _updatable_args2body(parsed_args, body, client): neutronV20.update_dict(parsed_args, body, ['device_id', 'device_owner', 'name', 'description']) ips = [] if parsed_args.fixed_ip: for ip_spec in parsed_args.fixed_ip: if 'subnet_id' in ip_spec: subnet_name_id = ip_spec['subnet_id'] _subnet_id = neutronV20.find_resourceid_by_name_or_id( client, 'subnet', subnet_name_id) ip_spec['subnet_id'] = _subnet_id ips.append(ip_spec) if ips: body['fixed_ips'] = ips class ListPort(neutronV20.ListCommand): """List ports that belong to a given tenant.""" resource = 'port' _formatters = {'fixed_ips': _format_fixed_ips, } list_columns = ['id', 'name', 'mac_address', 'fixed_ips'] pagination_support = True sorting_support = True class ListRouterPort(neutronV20.ListCommand): """List ports that belong to a given tenant, with specified router.""" resource = 'port' _formatters = {'fixed_ips': _format_fixed_ips, } list_columns = ['id', 'name', 'mac_address', 'fixed_ips'] pagination_support = True sorting_support = True def get_parser(self, prog_name): parser = super(ListRouterPort, self).get_parser(prog_name) parser.add_argument( 'id', metavar='ROUTER', help=_('ID or name of the router to look up.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() _id = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'router', parsed_args.id) self.values_specs.append('--device_id=%s' % _id) return super(ListRouterPort, self).take_action(parsed_args) class ShowPort(neutronV20.ShowCommand): """Show information of a given port.""" resource = 'port' class UpdatePortSecGroupMixin(object): def add_arguments_secgroup(self, parser): group_sg = parser.add_mutually_exclusive_group() group_sg.add_argument( '--security-group', metavar='SECURITY_GROUP', default=[], action='append', dest='security_groups', help=_('Security group associated with the port. You can ' 'repeat this option.')) group_sg.add_argument( '--no-security-groups', action='store_true', help=_('Associate no security groups with the port.')) def _resolv_sgid(self, secgroup): return neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'security_group', secgroup) def args2body_secgroup(self, parsed_args, port): if parsed_args.security_groups: port['security_groups'] = [self._resolv_sgid(sg) for sg in parsed_args.security_groups] elif parsed_args.no_security_groups: port['security_groups'] = [] class UpdateExtraDhcpOptMixin(object): def add_arguments_extradhcpopt(self, parser): group_sg = parser.add_mutually_exclusive_group() group_sg.add_argument( '--extra-dhcp-opt', default=[], action='append', dest='extra_dhcp_opts', type=utils.str2dict_type( required_keys=['opt_name'], optional_keys=['opt_value', 'ip_version']), help=_('Extra dhcp options to be assigned to this port: ' 'opt_name=,opt_value=,' 'ip_version={4,6}. You can repeat this option.')) def args2body_extradhcpopt(self, parsed_args, port): ops = [] if parsed_args.extra_dhcp_opts: # the extra_dhcp_opt params (opt_name & opt_value) # must come in pairs, if there is a parm error # both must be thrown out. opt_ele = {} edo_err_msg = _("Invalid --extra-dhcp-opt option, can only be: " "opt_name=,opt_value=," "ip_version={4,6}. " "You can repeat this option.") for opt in parsed_args.extra_dhcp_opts: opt_ele.update(opt) if ('opt_name' in opt_ele and ('opt_value' in opt_ele or 'ip_version' in opt_ele)): if opt_ele.get('opt_value') == 'null': opt_ele['opt_value'] = None ops.append(opt_ele) opt_ele = {} else: raise exceptions.CommandError(edo_err_msg) if ops: port['extra_dhcp_opts'] = ops class UpdatePortAllowedAddressPair(object): """Update Port for allowed_address_pairs""" def add_arguments_allowedaddresspairs(self, parser): group_aap = parser.add_mutually_exclusive_group() group_aap.add_argument( '--allowed-address-pair', metavar='ip_address=IP_ADDR|CIDR[,mac_address=MAC_ADDR]', default=[], action='append', dest='allowed_address_pairs', type=utils.str2dict_type( required_keys=['ip_address'], optional_keys=['mac_address']), help=_('Allowed address pair associated with the port. ' '"ip_address" parameter is required. IP address or ' 'CIDR can be specified for "ip_address". ' '"mac_address" parameter is optional. ' 'You can repeat this option.')) group_aap.add_argument( '--no-allowed-address-pairs', action='store_true', help=_('Associate no allowed address pairs with the port.')) def args2body_allowedaddresspairs(self, parsed_args, port): if parsed_args.allowed_address_pairs: port['allowed_address_pairs'] = parsed_args.allowed_address_pairs elif parsed_args.no_allowed_address_pairs: port['allowed_address_pairs'] = [] class CreatePort(neutronV20.CreateCommand, UpdatePortSecGroupMixin, UpdateExtraDhcpOptMixin, qos_policy.CreateQosPolicyMixin, UpdatePortAllowedAddressPair): """Create a port for a given tenant.""" resource = 'port' def add_known_arguments(self, parser): _add_updatable_args(parser) parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--admin_state_down', dest='admin_state', action='store_false', help=argparse.SUPPRESS) parser.add_argument( '--mac-address', help=_('MAC address of this port.')) parser.add_argument( '--mac_address', help=argparse.SUPPRESS) parser.add_argument( '--vnic-type', metavar='', choices=['direct', 'direct-physical', 'macvtap', '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', 'smart-nic'], type=utils.convert_to_lowercase, help=argparse.SUPPRESS) parser.add_argument( '--binding-profile', help=_('Custom data to be passed as binding:profile.')) parser.add_argument( '--binding_profile', help=argparse.SUPPRESS) self.add_arguments_secgroup(parser) self.add_arguments_extradhcpopt(parser) self.add_arguments_qos_policy(parser) self.add_arguments_allowedaddresspairs(parser) parser.add_argument( 'network_id', metavar='NETWORK', help=_('ID or name of the network this port belongs to.')) dns.add_dns_argument_create(parser, self.resource, 'name') def args2body(self, parsed_args): client = self.get_client() _network_id = neutronV20.find_resourceid_by_name_or_id( client, 'network', parsed_args.network_id) body = {'admin_state_up': parsed_args.admin_state, 'network_id': _network_id, } _updatable_args2body(parsed_args, body, client) neutronV20.update_dict(parsed_args, body, ['mac_address', 'tenant_id']) if parsed_args.vnic_type: body['binding:vnic_type'] = parsed_args.vnic_type if parsed_args.binding_profile: body['binding:profile'] = jsonutils.loads( parsed_args.binding_profile) self.args2body_secgroup(parsed_args, body) self.args2body_extradhcpopt(parsed_args, body) self.args2body_qos_policy(parsed_args, body) self.args2body_allowedaddresspairs(parsed_args, body) dns.args2body_dns_create(parsed_args, body, 'name') return {'port': body} class DeletePort(neutronV20.DeleteCommand): """Delete a given port.""" resource = 'port' class UpdatePort(neutronV20.UpdateCommand, UpdatePortSecGroupMixin, UpdateExtraDhcpOptMixin, qos_policy.UpdateQosPolicyMixin, UpdatePortAllowedAddressPair): """Update port's information.""" resource = 'port' def add_known_arguments(self, parser): _add_updatable_args(parser) parser.add_argument( '--admin-state-up', choices=['True', 'False'], help=_('Set admin state up for the port.')) parser.add_argument( '--admin_state_up', choices=['True', 'False'], help=argparse.SUPPRESS) self.add_arguments_secgroup(parser) self.add_arguments_extradhcpopt(parser) self.add_arguments_qos_policy(parser) self.add_arguments_allowedaddresspairs(parser) dns.add_dns_argument_update(parser, self.resource, 'name') def args2body(self, parsed_args): body = {} client = self.get_client() _updatable_args2body(parsed_args, body, client) if parsed_args.admin_state_up: body['admin_state_up'] = parsed_args.admin_state_up self.args2body_secgroup(parsed_args, body) self.args2body_extradhcpopt(parsed_args, body) self.args2body_qos_policy(parsed_args, body) self.args2body_allowedaddresspairs(parsed_args, body) dns.args2body_dns_update(parsed_args, body, 'name') return {'port': body} ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/purge.py0000664000175000017500000001371200000000000024657 0ustar00zuulzuul00000000000000# Copyright 2016 Cisco Systems # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # import sys from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 class Purge(neutronV20.NeutronCommand): """Delete all resources that belong to a given tenant.""" def _pluralize(self, string): return string + 's' def _get_resources(self, neutron_client, resource_types, tenant_id): resources = [] for resource_type in resource_types: resources.append([]) resource_type_plural = self._pluralize(resource_type) opts = {'fields': ['id', 'tenant_id']} if resource_type_plural == 'ports': opts['fields'].append('device_id') opts['fields'].append('device_owner') function = getattr(neutron_client, 'list_%s' % resource_type_plural) if callable(function): returned_resources = function(**opts).get(resource_type_plural, []) for resource in returned_resources: if resource['tenant_id'] == tenant_id: index = resource_types.index(resource_type) resources[index].append(resource) self.total_resources += 1 return resources def _delete_resource(self, neutron_client, resource_type, resource): resource_id = resource['id'] if resource_type == 'port': router_interface_owners = ['network:router_interface', 'network:router_interface_distributed'] if resource.get('device_owner', '') in router_interface_owners: body = {'port_id': resource_id} neutron_client.remove_interface_router(resource['device_id'], body) return function = getattr(neutron_client, 'delete_%s' % resource_type) if callable(function): function(resource_id) def _purge_resources(self, neutron_client, resource_types, tenant_resources): deleted = {} failed = {} failures = False for resources in tenant_resources: index = tenant_resources.index(resources) resource_type = resource_types[index] failed[resource_type] = 0 deleted[resource_type] = 0 for resource in resources: try: self._delete_resource(neutron_client, resource_type, resource) deleted[resource_type] += 1 self.deleted_resources += 1 except Exception: failures = True failed[resource_type] += 1 self.total_resources -= 1 percent_complete = 100 if self.total_resources > 0: percent_complete = (self.deleted_resources / float(self.total_resources)) * 100 sys.stdout.write("\rPurging resources: %d%% complete." % percent_complete) sys.stdout.flush() return (deleted, failed, failures) def _build_message(self, deleted, failed, failures): msg = '' deleted_msg = [] for resource, value in deleted.items(): if value: if not msg: msg = 'Deleted' if not value == 1: resource = self._pluralize(resource) deleted_msg.append(" %d %s" % (value, resource)) if deleted_msg: msg += ','.join(deleted_msg) failed_msg = [] if failures: if msg: msg += '. ' msg += 'The following resources could not be deleted:' for resource, value in failed.items(): if value: if not value == 1: resource = self._pluralize(resource) failed_msg.append(" %d %s" % (value, resource)) msg += ','.join(failed_msg) if msg: msg += '.' else: msg = _('Tenant has no supported resources.') return msg def get_parser(self, prog_name): parser = super(Purge, self).get_parser(prog_name) parser.add_argument( 'tenant', metavar='TENANT', help=_('ID of Tenant owning the resources to be deleted.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() self.any_failures = False # A list of the types of resources supported in the order in which # they should be deleted. resource_types = ['floatingip', 'port', 'router', 'network', 'security_group'] deleted = {} failed = {} self.total_resources = 0 self.deleted_resources = 0 resources = self._get_resources(neutron_client, resource_types, parsed_args.tenant) deleted, failed, failures = self._purge_resources(neutron_client, resource_types, resources) print('\n%s' % self._build_message(deleted, failed, failures)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2176616 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/qos/0000775000175000017500000000000000000000000023761 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/qos/__init__.py0000664000175000017500000000000000000000000026060 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/qos/bandwidth_limit_rule.py0000664000175000017500000000660700000000000030535 0ustar00zuulzuul00000000000000# Copyright 2015 Huawei Technologies India Pvt Ltd, Inc. # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.neutron import v2_0 as neutronv20 from neutronclient.neutron.v2_0.qos import rule as qos_rule BANDWIDTH_LIMIT_RULE_RESOURCE = 'bandwidth_limit_rule' def add_bandwidth_limit_arguments(parser): parser.add_argument( '--max-kbps', help=_('Maximum bandwidth in kbps.')) parser.add_argument( '--max-burst-kbps', help=_('Maximum burst bandwidth in kbps.')) def update_bandwidth_limit_args2body(parsed_args, body): max_kbps = parsed_args.max_kbps max_burst_kbps = parsed_args.max_burst_kbps if not (max_kbps or max_burst_kbps): raise exceptions.CommandError(_("Must provide max-kbps" " or max-burst-kbps option.")) neutronv20.update_dict(parsed_args, body, ['max_kbps', 'max_burst_kbps', 'tenant_id']) class CreateQoSBandwidthLimitRule(qos_rule.QosRuleMixin, neutronv20.CreateCommand): """Create a qos bandwidth limit rule.""" resource = BANDWIDTH_LIMIT_RULE_RESOURCE def add_known_arguments(self, parser): super(CreateQoSBandwidthLimitRule, self).add_known_arguments(parser) add_bandwidth_limit_arguments(parser) def args2body(self, parsed_args): body = {} update_bandwidth_limit_args2body(parsed_args, body) return {self.resource: body} class ListQoSBandwidthLimitRules(qos_rule.QosRuleMixin, neutronv20.ListCommand): """List all qos bandwidth limit rules belonging to the specified policy.""" resource = BANDWIDTH_LIMIT_RULE_RESOURCE _formatters = {} pagination_support = True sorting_support = True class ShowQoSBandwidthLimitRule(qos_rule.QosRuleMixin, neutronv20.ShowCommand): """Show information about the given qos bandwidth limit rule.""" resource = BANDWIDTH_LIMIT_RULE_RESOURCE allow_names = False class UpdateQoSBandwidthLimitRule(qos_rule.QosRuleMixin, neutronv20.UpdateCommand): """Update the given qos bandwidth limit rule.""" resource = BANDWIDTH_LIMIT_RULE_RESOURCE allow_names = False def add_known_arguments(self, parser): super(UpdateQoSBandwidthLimitRule, self).add_known_arguments(parser) add_bandwidth_limit_arguments(parser) def args2body(self, parsed_args): body = {} update_bandwidth_limit_args2body(parsed_args, body) return {self.resource: body} class DeleteQoSBandwidthLimitRule(qos_rule.QosRuleMixin, neutronv20.DeleteCommand): """Delete a given qos bandwidth limit rule.""" resource = BANDWIDTH_LIMIT_RULE_RESOURCE allow_names = False ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/qos/dscp_marking_rule.py0000664000175000017500000000745200000000000030033 0ustar00zuulzuul00000000000000# Copyright 2016 Comcast, Inc. # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.neutron import v2_0 as neutronv20 from neutronclient.neutron.v2_0.qos import rule as qos_rule DSCP_MARKING_RESOURCE = 'dscp_marking_rule' # DSCP DETAILS # 0 - none | 8 - cs1 | 10 - af11 | 12 - af12 | 14 - af13 | # 16 - cs2 | 18 - af21 | 20 - af22 | 22 - af23 | 24 - cs3 | # 26 - af31 | 28 - af32 | 30 - af33 | 32 - cs4 | 34 - af41 | # 36 - af42 | 38 - af43 | 40 - cs5 | 46 - ef | 48 - cs6 | # 56 - cs7 DSCP_VALID_MARKS = [0, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 46, 48, 56] def add_dscp_marking_arguments(parser): parser.add_argument( '--dscp-mark', required=True, type=str, help=_('DSCP mark: value can be 0, even numbers from 8-56, \ excluding 42, 44, 50, 52, and 54.')) def update_dscp_args2body(parsed_args, body): dscp_mark = parsed_args.dscp_mark if int(dscp_mark) not in DSCP_VALID_MARKS: raise exceptions.CommandError(_("DSCP mark: %s not supported. " "Please note value can either be 0 " "or any even number from 8-56 " "excluding 42, 44, 50, 52 and " "54.") % dscp_mark) neutronv20.update_dict(parsed_args, body, ['dscp_mark']) class CreateQoSDscpMarkingRule(qos_rule.QosRuleMixin, neutronv20.CreateCommand): """Create a QoS DSCP marking rule.""" resource = DSCP_MARKING_RESOURCE def add_known_arguments(self, parser): super(CreateQoSDscpMarkingRule, self).add_known_arguments(parser) add_dscp_marking_arguments(parser) def args2body(self, parsed_args): body = {} update_dscp_args2body(parsed_args, body) return {self.resource: body} class ListQoSDscpMarkingRules(qos_rule.QosRuleMixin, neutronv20.ListCommand): """List all QoS DSCP marking rules belonging to the specified policy.""" _formatters = {} pagination_support = True sorting_support = True resource = DSCP_MARKING_RESOURCE class ShowQoSDscpMarkingRule(qos_rule.QosRuleMixin, neutronv20.ShowCommand): """Show information about the given qos dscp marking rule.""" resource = DSCP_MARKING_RESOURCE allow_names = False class UpdateQoSDscpMarkingRule(qos_rule.QosRuleMixin, neutronv20.UpdateCommand): """Update the given QoS DSCP marking rule.""" allow_names = False resource = DSCP_MARKING_RESOURCE def add_known_arguments(self, parser): super(UpdateQoSDscpMarkingRule, self).add_known_arguments(parser) add_dscp_marking_arguments(parser) def args2body(self, parsed_args): body = {} update_dscp_args2body(parsed_args, body) return {self.resource: body} class DeleteQoSDscpMarkingRule(qos_rule.QosRuleMixin, neutronv20.DeleteCommand): """Delete a given qos dscp marking rule.""" allow_names = False resource = DSCP_MARKING_RESOURCE ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/qos/minimum_bandwidth_rule.py0000664000175000017500000000740400000000000031066 0ustar00zuulzuul00000000000000# Copyright (c) 2016 Intel Corporation. # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronv20 from neutronclient.neutron.v2_0.qos import rule as qos_rule MINIMUM_BANDWIDTH_RULE_RESOURCE = 'minimum_bandwidth_rule' def add_minimum_bandwidth_arguments(parser): parser.add_argument( '--min-kbps', required=True, type=str, help=_('QoS minimum bandwidth assurance, expressed in kilobits ' 'per second.')) # NOTE(ralonsoh): the only direction implemented is "egress". Please, # refer to the spec (https://review.opendev.org/#/c/316082/). parser.add_argument( '--direction', # NOTE(ihrachys): though server picks the default for us (egress), it's # better to require the argument to make the UI more explicit and the # intentions more clear in the future when we add other values for the # attribute on server side. required=True, type=utils.convert_to_lowercase, choices=['egress'], help=_('Traffic direction.')) def update_minimum_bandwidth_args2body(parsed_args, body): neutronv20.update_dict(parsed_args, body, ['min_kbps', 'direction']) class CreateQoSMinimumBandwidthRule(qos_rule.QosRuleMixin, neutronv20.CreateCommand): """Create a qos minimum bandwidth rule.""" resource = MINIMUM_BANDWIDTH_RULE_RESOURCE def add_known_arguments(self, parser): super(CreateQoSMinimumBandwidthRule, self).add_known_arguments( parser) add_minimum_bandwidth_arguments(parser) def args2body(self, parsed_args): body = {} update_minimum_bandwidth_args2body(parsed_args, body) return {self.resource: body} class ListQoSMinimumBandwidthRules(qos_rule.QosRuleMixin, neutronv20.ListCommand): """List all qos minimum bandwidth rules belonging to the specified policy. """ resource = MINIMUM_BANDWIDTH_RULE_RESOURCE _formatters = {} pagination_support = True sorting_support = True class ShowQoSMinimumBandwidthRule(qos_rule.QosRuleMixin, neutronv20.ShowCommand): """Show information about the given qos minimum bandwidth rule.""" resource = MINIMUM_BANDWIDTH_RULE_RESOURCE allow_names = False class UpdateQoSMinimumBandwidthRule(qos_rule.QosRuleMixin, neutronv20.UpdateCommand): """Update the given qos minimum bandwidth rule.""" resource = MINIMUM_BANDWIDTH_RULE_RESOURCE allow_names = False def add_known_arguments(self, parser): super(UpdateQoSMinimumBandwidthRule, self).add_known_arguments( parser) add_minimum_bandwidth_arguments(parser) def args2body(self, parsed_args): body = {} update_minimum_bandwidth_args2body(parsed_args, body) return {self.resource: body} class DeleteQoSMinimumBandwidthRule(qos_rule.QosRuleMixin, neutronv20.DeleteCommand): """Delete a given qos minimum bandwidth rule.""" resource = MINIMUM_BANDWIDTH_RULE_RESOURCE allow_names = False ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/qos/policy.py0000664000175000017500000001251400000000000025635 0ustar00zuulzuul00000000000000# Copyright 2015 Huawei Technologies India Pvt Ltd, Inc. # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # import os from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronv20 def get_qos_policy_id(client, policy_id_or_name): _policy_id = neutronv20.find_resourceid_by_name_or_id( client, 'policy', policy_id_or_name, cmd_resource='qos_policy') return _policy_id class CreateQosPolicyMixin(object): def add_arguments_qos_policy(self, parser): qos_policy_args = parser.add_mutually_exclusive_group() qos_policy_args.add_argument( '--qos-policy', help=_('ID or name of the QoS policy that should' 'be attached to the resource.')) return qos_policy_args def args2body_qos_policy(self, parsed_args, resource): if parsed_args.qos_policy: _policy_id = get_qos_policy_id(self.get_client(), parsed_args.qos_policy) resource['qos_policy_id'] = _policy_id class UpdateQosPolicyMixin(CreateQosPolicyMixin): def add_arguments_qos_policy(self, parser): qos_policy_args = (super(UpdateQosPolicyMixin, self). add_arguments_qos_policy(parser)) qos_policy_args.add_argument( '--no-qos-policy', action='store_true', help=_('Detach QoS policy from the resource.')) return qos_policy_args def args2body_qos_policy(self, parsed_args, resource): super(UpdateQosPolicyMixin, self).args2body_qos_policy(parsed_args, resource) if parsed_args.no_qos_policy: resource['qos_policy_id'] = None class ListQoSPolicy(neutronv20.ListCommand): """List QoS policies that belong to a given tenant connection.""" resource = 'policy' shadow_resource = 'qos_policy' list_columns = ['id', 'name'] pagination_support = True sorting_support = True class ShowQoSPolicy(neutronv20.ShowCommand): """Show information of a given qos policy.""" resource = 'policy' shadow_resource = 'qos_policy' def format_output_data(self, data): rules = [] for rule in data['policy'].get('rules', []): rules.append("%s (type: %s)" % (rule['id'], rule['type'])) data['policy']['rules'] = os.linesep.join(rules) super(ShowQoSPolicy, self).format_output_data(data) class CreateQoSPolicy(neutronv20.CreateCommand): """Create a qos policy.""" resource = 'policy' shadow_resource = 'qos_policy' def add_known_arguments(self, parser): parser.add_argument( 'name', metavar='NAME', help=_('Name of the QoS policy to be created.')) parser.add_argument( '--description', help=_('Description of the QoS policy to be created.')) parser.add_argument( '--shared', action='store_true', help=_('Accessible by other tenants. ' 'Set shared to True (default is False).')) def args2body(self, parsed_args): body = {'name': parsed_args.name} if parsed_args.description: body['description'] = parsed_args.description if parsed_args.shared: body['shared'] = parsed_args.shared if parsed_args.tenant_id: body['tenant_id'] = parsed_args.tenant_id return {self.resource: body} class UpdateQoSPolicy(neutronv20.UpdateCommand): """Update a given qos policy.""" resource = 'policy' shadow_resource = 'qos_policy' def add_known_arguments(self, parser): parser.add_argument( '--name', help=_('Name of the QoS policy.')) parser.add_argument( '--description', help=_('Description of the QoS policy.')) shared_group = parser.add_mutually_exclusive_group() shared_group.add_argument( '--shared', action='store_true', help=_('Accessible by other tenants. ' 'Set shared to True (default is False).')) shared_group.add_argument( '--no-shared', action='store_true', help=_('Not accessible by other tenants. ' 'Set shared to False.')) def args2body(self, parsed_args): body = {} if parsed_args.name: body['name'] = parsed_args.name if parsed_args.description: body['description'] = parsed_args.description if parsed_args.shared: body['shared'] = True if parsed_args.no_shared: body['shared'] = False return {self.resource: body} class DeleteQoSPolicy(neutronv20.DeleteCommand): """Delete a given qos policy.""" resource = 'policy' shadow_resource = 'qos_policy' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/qos/rule.py0000664000175000017500000000364700000000000025314 0ustar00zuulzuul00000000000000# Copyright 2015 Huawei Technologies India Pvt Ltd, Inc. # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronv20 from neutronclient.neutron.v2_0.qos import policy as qos_policy def add_policy_argument(parser): parser.add_argument( 'policy', metavar='QOS_POLICY', help=_('ID or name of the QoS policy.')) def add_rule_argument(parser): parser.add_argument( 'rule', metavar='QOS_RULE', help=_('ID of the QoS rule.')) def update_policy_args2body(parsed_args, body): neutronv20.update_dict(parsed_args, body, ['policy']) def update_rule_args2body(parsed_args, body): neutronv20.update_dict(parsed_args, body, ['rule']) class QosRuleMixin(object): def add_known_arguments(self, parser): add_policy_argument(parser) def set_extra_attrs(self, parsed_args): self.parent_id = qos_policy.get_qos_policy_id(self.get_client(), parsed_args.policy) def args2body(self, parsed_args): body = {} update_policy_args2body(parsed_args, body) return {'qos_rule': body} class ListQoSRuleTypes(neutronv20.ListCommand): """List available qos rule types.""" resource = 'rule_type' shadow_resource = 'qos_rule_type' pagination_support = True sorting_support = True ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/quota.py0000664000175000017500000002233500000000000024667 0ustar00zuulzuul00000000000000# Copyright 2012 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 abc import argparse from cliff import lister from cliff import show from oslo_serialization import jsonutils from neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 def get_tenant_id(args, client): return (args.pos_tenant_id or args.tenant_id or client.get_quotas_tenant()['tenant']['tenant_id']) class DeleteQuota(neutronV20.NeutronCommand): """Delete defined quotas of a given tenant.""" resource = 'quota' def get_parser(self, prog_name): parser = super(DeleteQuota, self).get_parser(prog_name) parser.add_argument( '--tenant-id', metavar='tenant-id', help=_('The owner tenant ID.')) parser.add_argument( '--tenant_id', help=argparse.SUPPRESS) parser.add_argument( 'pos_tenant_id', help=argparse.SUPPRESS, nargs='?') return parser def take_action(self, parsed_args): neutron_client = self.get_client() tenant_id = get_tenant_id(parsed_args, neutron_client) obj_deleter = getattr(neutron_client, "delete_%s" % self.resource) obj_deleter(tenant_id) print((_('Deleted %(resource)s: %(tenant_id)s') % {'tenant_id': tenant_id, 'resource': self.resource}), file=self.app.stdout) return class ListQuota(neutronV20.NeutronCommand, lister.Lister): """List quotas of all tenants who have non-default quota values.""" resource = 'quota' def get_parser(self, prog_name): parser = super(ListQuota, self).get_parser(prog_name) return parser def take_action(self, parsed_args): neutron_client = self.get_client() search_opts = {} self.log.debug('search options: %s', search_opts) obj_lister = getattr(neutron_client, "list_%ss" % self.resource) data = obj_lister(**search_opts) info = [] collection = self.resource + "s" if collection in data: info = data[collection] _columns = len(info) > 0 and sorted(info[0].keys()) or [] return (_columns, (utils.get_item_properties(s, _columns) for s in info)) class ShowQuotaBase(neutronV20.NeutronCommand, show.ShowOne): """Base class to show quotas of a given tenant.""" resource = "quota" @abc.abstractmethod def retrieve_data(self, tenant_id, neutron_client): """Retrieve data using neutron client for the given tenant.""" def get_parser(self, prog_name): parser = super(ShowQuotaBase, self).get_parser(prog_name) parser.add_argument( '--tenant-id', metavar='tenant-id', help=_('The owner tenant ID.')) parser.add_argument( '--tenant_id', help=argparse.SUPPRESS) # allow people to do neutron quota-show . # we use a different name for this because the default will # override whatever is in the named arg otherwise. parser.add_argument( 'pos_tenant_id', help=argparse.SUPPRESS, nargs='?') return parser def take_action(self, parsed_args): neutron_client = self.get_client() tenant_id = get_tenant_id(parsed_args, neutron_client) data = self.retrieve_data(tenant_id, neutron_client) if self.resource in data: return zip(*sorted(data[self.resource].items())) return class ShowQuota(ShowQuotaBase): """Show quotas for a given tenant.""" def retrieve_data(self, tenant_id, neutron_client): return neutron_client.show_quota(tenant_id) class ShowQuotaDefault(ShowQuotaBase): """Show default quotas for a given tenant.""" def retrieve_data(self, tenant_id, neutron_client): return neutron_client.show_quota_default(tenant_id) class UpdateQuota(neutronV20.NeutronCommand, show.ShowOne): """Update a given tenant's quotas.""" resource = 'quota' def get_parser(self, prog_name): parser = super(UpdateQuota, self).get_parser(prog_name) parser.add_argument( '--tenant-id', metavar='tenant-id', help=_('The owner tenant ID.')) parser.add_argument( '--tenant_id', help=argparse.SUPPRESS) parser.add_argument( '--network', metavar='networks', help=_('The limit of networks.')) parser.add_argument( '--subnet', metavar='subnets', help=_('The limit of subnets.')) parser.add_argument( '--port', metavar='ports', help=_('The limit of ports.')) parser.add_argument( '--router', metavar='routers', help=_('The limit of routers.')) parser.add_argument( '--floatingip', metavar='floatingips', help=_('The limit of floating IPs.')) parser.add_argument( '--security-group', metavar='security_groups', help=_('The limit of security groups.')) parser.add_argument( '--security-group-rule', metavar='security_group_rules', help=_('The limit of security groups rules.')) parser.add_argument( '--vip', metavar='vips', help=_('The limit of vips.')) parser.add_argument( '--pool', metavar='pools', help=_('The limit of pools.')) parser.add_argument( '--member', metavar='members', help=_('The limit of pool members.')) parser.add_argument( '--health-monitor', metavar='health_monitors', dest='healthmonitor', help=_('The limit of health monitors.')) parser.add_argument( '--loadbalancer', metavar='loadbalancers', help=_('The limit of load balancers.')) parser.add_argument( '--listener', metavar='listeners', help=_('The limit of listeners.')) parser.add_argument( '--rbac-policy', metavar='rbac_policies', help=_('The limit of RBAC policies.')) parser.add_argument( 'pos_tenant_id', help=argparse.SUPPRESS, nargs='?') return parser def _validate_int(self, name, value): try: return_value = int(value) except Exception: message = (_('Quota limit for %(name)s must be an integer') % {'name': name}) raise exceptions.CommandError(message=message) return return_value def args2body(self, parsed_args): quota = {} for resource in ('network', 'subnet', 'port', 'router', 'floatingip', 'security_group', 'security_group_rule', 'vip', 'pool', 'member', 'healthmonitor', 'loadbalancer', 'listener', 'rbac_policy'): if getattr(parsed_args, resource): quota[resource] = self._validate_int( resource, getattr(parsed_args, resource)) if not quota: raise exceptions.CommandError( message=_('Must specify a valid resource with new quota ' 'value')) return {self.resource: quota} def take_action(self, parsed_args): neutron_client = self.get_client() _extra_values = neutronV20.parse_args_to_dict(self.values_specs) neutronV20._merge_args(self, parsed_args, _extra_values, self.values_specs) body = self.args2body(parsed_args) if self.resource in body: body[self.resource].update(_extra_values) else: body[self.resource] = _extra_values obj_updator = getattr(neutron_client, "update_%s" % self.resource) tenant_id = get_tenant_id(parsed_args, neutron_client) data = obj_updator(tenant_id, body) if self.resource in data: for k, v in data[self.resource].items(): if isinstance(v, list): value = "" for _item in v: if value: value += "\n" if isinstance(_item, dict): value += jsonutils.dumps(_item) else: value += str(_item) data[self.resource][k] = value elif v is None: data[self.resource][k] = '' return zip(*sorted(data[self.resource].items())) else: return ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/rbac.py0000664000175000017500000000760700000000000024452 0ustar00zuulzuul00000000000000# Copyright 2015 Huawei Technologies India Pvt Ltd. # 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 neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 # key=object_type: value={key=resource, value=cmd_resource} RBAC_OBJECTS = {'network': {'network': 'network'}, 'qos-policy': {'policy': 'qos_policy'}} def _get_cmd_resource(obj_type): resource = list(RBAC_OBJECTS[obj_type])[0] cmd_resource = RBAC_OBJECTS[obj_type][resource] return resource, cmd_resource def get_rbac_obj_params(client, obj_type, obj_id_or_name): resource, cmd_resource = _get_cmd_resource(obj_type) obj_id = neutronV20.find_resourceid_by_name_or_id( client=client, resource=resource, name_or_id=obj_id_or_name, cmd_resource=cmd_resource) return obj_id, cmd_resource class ListRBACPolicy(neutronV20.ListCommand): """List RBAC policies that belong to a given tenant.""" resource = 'rbac_policy' list_columns = ['id', 'object_type', 'object_id'] pagination_support = True sorting_support = True allow_names = False class ShowRBACPolicy(neutronV20.ShowCommand): """Show information of a given RBAC policy.""" resource = 'rbac_policy' allow_names = False class CreateRBACPolicy(neutronV20.CreateCommand): """Create a RBAC policy for a given tenant.""" resource = 'rbac_policy' def add_known_arguments(self, parser): parser.add_argument( 'name', metavar='RBAC_OBJECT', help=_('ID or name of the RBAC object.')) parser.add_argument( '--type', choices=RBAC_OBJECTS.keys(), required=True, type=utils.convert_to_lowercase, help=_('Type of the object that RBAC policy affects.')) parser.add_argument( '--target-tenant', default='*', help=_('ID of the tenant to which the RBAC ' 'policy will be enforced.')) parser.add_argument( '--action', choices=['access_as_external', 'access_as_shared'], type=utils.convert_to_lowercase, required=True, help=_('Action for the RBAC policy.')) def args2body(self, parsed_args): neutron_client = self.get_client() _object_id, _object_type = get_rbac_obj_params(neutron_client, parsed_args.type, parsed_args.name) body = { 'object_id': _object_id, 'object_type': _object_type, 'target_tenant': parsed_args.target_tenant, 'action': parsed_args.action, } return {self.resource: body} class UpdateRBACPolicy(neutronV20.UpdateCommand): """Update RBAC policy for given tenant.""" resource = 'rbac_policy' allow_names = False def add_known_arguments(self, parser): parser.add_argument( '--target-tenant', help=_('ID of the tenant to which the RBAC ' 'policy will be enforced.')) def args2body(self, parsed_args): body = {'target_tenant': parsed_args.target_tenant} return {self.resource: body} class DeleteRBACPolicy(neutronV20.DeleteCommand): """Delete a RBAC policy.""" resource = 'rbac_policy' allow_names = False ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/router.py0000664000175000017500000002642400000000000025061 0ustar00zuulzuul00000000000000# Copyright 2012 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 argparse from oslo_serialization import jsonutils from neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 from neutronclient.neutron.v2_0 import availability_zone def _format_external_gateway_info(router): try: return jsonutils.dumps(router['external_gateway_info']) except (TypeError, KeyError): return '' class ListRouter(neutronV20.ListCommand): """List routers that belong to a given tenant.""" resource = 'router' _formatters = {'external_gateway_info': _format_external_gateway_info, } list_columns = ['id', 'name', 'external_gateway_info', 'distributed', 'ha'] pagination_support = True sorting_support = True class ShowRouter(neutronV20.ShowCommand): """Show information of a given router.""" resource = 'router' class CreateRouter(neutronV20.CreateCommand): """Create a router for a given tenant.""" resource = 'router' _formatters = {'external_gateway_info': _format_external_gateway_info, } def add_known_arguments(self, parser): parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--admin_state_down', dest='admin_state', action='store_false', help=argparse.SUPPRESS) parser.add_argument( 'name', metavar='NAME', help=_('Name of the router to be created.')) parser.add_argument( '--description', help=_('Description of router.')) parser.add_argument( '--flavor', help=_('ID or name of flavor.')) utils.add_boolean_argument( parser, '--distributed', dest='distributed', help=_('Create a distributed router.')) utils.add_boolean_argument( parser, '--ha', dest='ha', help=_('Create a highly available router.')) availability_zone.add_az_hint_argument(parser, self.resource) def args2body(self, parsed_args): body = {'admin_state_up': parsed_args.admin_state} if parsed_args.flavor: _flavor_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'flavor', parsed_args.flavor) body['flavor_id'] = _flavor_id neutronV20.update_dict(parsed_args, body, ['name', 'tenant_id', 'distributed', 'ha', 'description']) availability_zone.args2body_az_hint(parsed_args, body) return {self.resource: body} class DeleteRouter(neutronV20.DeleteCommand): """Delete a given router.""" resource = 'router' class UpdateRouter(neutronV20.UpdateCommand): """Update router's information.""" resource = 'router' def add_known_arguments(self, parser): parser.add_argument( '--name', help=_('Updated name of the router.')) parser.add_argument( '--description', help=_('Description of router.')) utils.add_boolean_argument( parser, '--admin-state-up', dest='admin_state', help=_('Specify the administrative state of the router ' '(True means "Up").')) utils.add_boolean_argument( parser, '--admin_state_up', dest='admin_state', help=argparse.SUPPRESS) utils.add_boolean_argument( parser, '--distributed', dest='distributed', help=_('True means this router should operate in ' 'distributed mode.')) routes_group = parser.add_mutually_exclusive_group() routes_group.add_argument( '--route', metavar='destination=CIDR,nexthop=IP_ADDR', action='append', dest='routes', type=utils.str2dict_type(required_keys=['destination', 'nexthop']), help=_('Route to associate with the router.' ' You can repeat this option.')) routes_group.add_argument( '--no-routes', action='store_true', help=_('Remove routes associated with the router.')) def args2body(self, parsed_args): body = {} if hasattr(parsed_args, 'admin_state'): body['admin_state_up'] = parsed_args.admin_state neutronV20.update_dict(parsed_args, body, ['name', 'distributed', 'description']) if parsed_args.no_routes: body['routes'] = None elif parsed_args.routes: body['routes'] = parsed_args.routes return {self.resource: body} class RouterInterfaceCommand(neutronV20.NeutronCommand): """Based class to Add/Remove router interface.""" resource = 'router' def call_api(self, neutron_client, router_id, body): raise NotImplementedError() def success_message(self, router_id, portinfo): raise NotImplementedError() def get_parser(self, prog_name): parser = super(RouterInterfaceCommand, self).get_parser(prog_name) parser.add_argument( 'router', metavar='ROUTER', help=_('ID or name of the router.')) parser.add_argument( 'interface', metavar='INTERFACE', help=_('The format is "SUBNET|subnet=SUBNET|port=PORT". ' 'Either a subnet or port must be specified. ' 'Both ID and name are accepted as SUBNET or PORT. ' 'Note that "subnet=" can be omitted when specifying a ' 'subnet.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() if '=' in parsed_args.interface: resource, value = parsed_args.interface.split('=', 1) if resource not in ['subnet', 'port']: exceptions.CommandError(_('You must specify either subnet or ' 'port for INTERFACE parameter.')) else: resource = 'subnet' value = parsed_args.interface _router_id = neutronV20.find_resourceid_by_name_or_id( neutron_client, self.resource, parsed_args.router) _interface_id = neutronV20.find_resourceid_by_name_or_id( neutron_client, resource, value) body = {'%s_id' % resource: _interface_id} portinfo = self.call_api(neutron_client, _router_id, body) print(self.success_message(parsed_args.router, portinfo), file=self.app.stdout) class AddInterfaceRouter(RouterInterfaceCommand): """Add an internal network interface to a router.""" def call_api(self, neutron_client, router_id, body): return neutron_client.add_interface_router(router_id, body) def success_message(self, router_id, portinfo): return (_('Added interface %(port)s to router %(router)s.') % {'router': router_id, 'port': portinfo['port_id']}) class RemoveInterfaceRouter(RouterInterfaceCommand): """Remove an internal network interface from a router.""" def call_api(self, neutron_client, router_id, body): return neutron_client.remove_interface_router(router_id, body) def success_message(self, router_id, portinfo): # portinfo is not used since it is None for router-interface-delete. return _('Removed interface from router %s.') % router_id class SetGatewayRouter(neutronV20.NeutronCommand): """Set the external network gateway for a router.""" resource = 'router' def get_parser(self, prog_name): parser = super(SetGatewayRouter, self).get_parser(prog_name) parser.add_argument( 'router', metavar='ROUTER', help=_('ID or name of the router.')) parser.add_argument( 'external_network', metavar='EXTERNAL-NETWORK', help=_('ID or name of the external network for the gateway.')) parser.add_argument( '--enable-snat', action='store_true', help=_('Enable source NAT on the router gateway.')) parser.add_argument( '--disable-snat', action='store_true', help=_('Disable source NAT on the router gateway.')) parser.add_argument( '--fixed-ip', metavar='subnet_id=SUBNET,ip_address=IP_ADDR', action='append', type=utils.str2dict_type(optional_keys=['subnet_id', 'ip_address']), help=_('Desired IP and/or subnet on external network: ' 'subnet_id=,ip_address=. ' 'You can specify both of subnet_id and ip_address or ' 'specify one of them as well. ' 'You can repeat this option.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() _router_id = neutronV20.find_resourceid_by_name_or_id( neutron_client, self.resource, parsed_args.router) _ext_net_id = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'network', parsed_args.external_network) router_dict = {'network_id': _ext_net_id} if parsed_args.enable_snat: router_dict['enable_snat'] = True if parsed_args.disable_snat: router_dict['enable_snat'] = False if parsed_args.fixed_ip: ips = [] for ip_spec in parsed_args.fixed_ip: subnet_name_id = ip_spec.get('subnet_id') if subnet_name_id: subnet_id = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'subnet', subnet_name_id) ip_spec['subnet_id'] = subnet_id ips.append(ip_spec) router_dict['external_fixed_ips'] = ips neutron_client.add_gateway_router(_router_id, router_dict) print(_('Set gateway for router %s') % parsed_args.router, file=self.app.stdout) class RemoveGatewayRouter(neutronV20.NeutronCommand): """Remove an external network gateway from a router.""" resource = 'router' def get_parser(self, prog_name): parser = super(RemoveGatewayRouter, self).get_parser(prog_name) parser.add_argument( 'router', metavar='ROUTER', help=_('ID or name of the router.')) return parser def take_action(self, parsed_args): neutron_client = self.get_client() _router_id = neutronV20.find_resourceid_by_name_or_id( neutron_client, self.resource, parsed_args.router) neutron_client.remove_gateway_router(_router_id) print(_('Removed gateway from router %s') % parsed_args.router, file=self.app.stdout) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/securitygroup.py0000664000175000017500000003337000000000000026463 0ustar00zuulzuul00000000000000# Copyright 2012 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 argparse from neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 def _get_remote(rule): if rule['remote_ip_prefix']: remote = '%s (CIDR)' % rule['remote_ip_prefix'] elif rule['remote_group_id']: remote = '%s (group)' % rule['remote_group_id'] else: remote = None return remote def _get_protocol_port(rule): proto = rule['protocol'] port_min = rule['port_range_min'] port_max = rule['port_range_max'] if proto in ('tcp', 'udp'): if (port_min and port_min == port_max): protocol_port = '%s/%s' % (port_min, proto) elif port_min: protocol_port = '%s-%s/%s' % (port_min, port_max, proto) else: protocol_port = proto elif proto == 'icmp': icmp_opts = [] if port_min is not None: icmp_opts.append('type:%s' % port_min) if port_max is not None: icmp_opts.append('code:%s' % port_max) if icmp_opts: protocol_port = 'icmp (%s)' % ', '.join(icmp_opts) else: protocol_port = 'icmp' elif proto is not None: # port_range_min/max are not recognized for protocol # other than TCP, UDP and ICMP. protocol_port = proto else: protocol_port = None return protocol_port def _format_sg_rule(rule): formatted = [] for field in ['direction', 'ethertype', ('protocol_port', _get_protocol_port), 'remote_ip_prefix', 'remote_group_id']: if isinstance(field, tuple): field, get_method = field data = get_method(rule) else: data = rule[field] if not data: continue if field in ('remote_ip_prefix', 'remote_group_id'): data = '%s: %s' % (field, data) formatted.append(data) return ', '.join(formatted) def _format_sg_rules(secgroup): try: return '\n'.join(sorted([_format_sg_rule(rule) for rule in secgroup['security_group_rules']])) except Exception: return '' def generate_default_ethertype(protocol): if protocol == 'icmpv6': return 'IPv6' return 'IPv4' class ListSecurityGroup(neutronV20.ListCommand): """List security groups that belong to a given tenant.""" resource = 'security_group' list_columns = ['id', 'name', 'security_group_rules'] _formatters = {'security_group_rules': _format_sg_rules} pagination_support = True sorting_support = True class ShowSecurityGroup(neutronV20.ShowCommand): """Show information of a given security group.""" resource = 'security_group' allow_names = True json_indent = 5 class CreateSecurityGroup(neutronV20.CreateCommand): """Create a security group.""" resource = 'security_group' def add_known_arguments(self, parser): parser.add_argument( 'name', metavar='NAME', help=_('Name of the security group to be created.')) parser.add_argument( '--description', help=_('Description of the security group to be created.')) def args2body(self, parsed_args): body = {'name': parsed_args.name} neutronV20.update_dict(parsed_args, body, ['description', 'tenant_id']) return {'security_group': body} class DeleteSecurityGroup(neutronV20.DeleteCommand): """Delete a given security group.""" resource = 'security_group' allow_names = True class UpdateSecurityGroup(neutronV20.UpdateCommand): """Update a given security group.""" resource = 'security_group' def add_known_arguments(self, parser): parser.add_argument( '--name', help=_('Updated name of the security group.')) parser.add_argument( '--description', help=_('Updated description of the security group.')) def args2body(self, parsed_args): body = {} neutronV20.update_dict(parsed_args, body, ['name', 'description']) return {'security_group': body} class ListSecurityGroupRule(neutronV20.ListCommand): """List security group rules that belong to a given tenant.""" resource = 'security_group_rule' list_columns = ['id', 'security_group_id', 'direction', 'ethertype', 'port/protocol', 'remote'] # replace_rules: key is an attribute name in Neutron API and # corresponding value is a display name shown by CLI. replace_rules = {'security_group_id': 'security_group', 'remote_group_id': 'remote_group'} digest_fields = { # The entry 'protocol/port' is left deliberately for backwards # compatibility. 'remote': { 'method': _get_remote, 'depends_on': ['remote_ip_prefix', 'remote_group_id']}, 'port/protocol': { 'method': _get_protocol_port, 'depends_on': ['protocol', 'port_range_min', 'port_range_max']}, 'protocol/port': { 'method': _get_protocol_port, 'depends_on': ['protocol', 'port_range_min', 'port_range_max']}} pagination_support = True sorting_support = True def get_parser(self, prog_name): parser = super(ListSecurityGroupRule, self).get_parser(prog_name) parser.add_argument( '--no-nameconv', action='store_true', help=_('Do not convert security group ID to its name.')) return parser @staticmethod def replace_columns(cols, rules, reverse=False): if reverse: rules = dict((rules[k], k) for k in rules.keys()) return [rules.get(col, col) for col in cols] def get_required_fields(self, fields): fields = self.replace_columns(fields, self.replace_rules, reverse=True) for field, digest_fields in self.digest_fields.items(): if field in fields: fields += digest_fields['depends_on'] fields.remove(field) return fields def retrieve_list(self, parsed_args): parsed_args.fields = self.get_required_fields(parsed_args.fields) return super(ListSecurityGroupRule, self).retrieve_list(parsed_args) def _get_sg_name_dict(self, data, page_size, no_nameconv): """Get names of security groups referred in the retrieved rules. :return: a dict from secgroup ID to secgroup name """ if no_nameconv: return {} neutron_client = self.get_client() search_opts = {'fields': ['id', 'name']} if self.pagination_support: if page_size: search_opts.update({'limit': page_size}) sec_group_ids = set() for rule in data: for key in self.replace_rules: if rule.get(key): sec_group_ids.add(rule[key]) sec_group_ids = list(sec_group_ids) def _get_sec_group_list(sec_group_ids): search_opts['id'] = sec_group_ids return neutron_client.list_security_groups( **search_opts).get('security_groups', []) try: secgroups = _get_sec_group_list(sec_group_ids) except exceptions.RequestURITooLong as uri_len_exc: # Length of a query filter on security group rule id # id=& (with len(uuid)=36) sec_group_id_filter_len = 40 # The URI is too long because of too many sec_group_id filters # Use the excess attribute of the exception to know how many # sec_group_id filters can be inserted into a single request sec_group_count = len(sec_group_ids) max_size = ((sec_group_id_filter_len * sec_group_count) - uri_len_exc.excess) chunk_size = max_size // sec_group_id_filter_len secgroups = [] for i in range(0, sec_group_count, chunk_size): secgroups.extend( _get_sec_group_list(sec_group_ids[i: i + chunk_size])) return dict([(sg['id'], sg['name']) for sg in secgroups if sg['name']]) @staticmethod def _has_fields(rule, required_fields): return all([key in rule for key in required_fields]) def extend_list(self, data, parsed_args): sg_dict = self._get_sg_name_dict(data, parsed_args.page_size, parsed_args.no_nameconv) for rule in data: # Replace security group UUID with its name. for key in self.replace_rules: if key in rule: rule[key] = sg_dict.get(rule[key], rule[key]) for field, digest_rule in self.digest_fields.items(): if self._has_fields(rule, digest_rule['depends_on']): rule[field] = digest_rule['method'](rule) or 'any' def setup_columns(self, info, parsed_args): # Translate the specified columns from the command line # into field names used in "info". parsed_args.columns = self.replace_columns(parsed_args.columns, self.replace_rules, reverse=True) # NOTE(amotoki): 2nd element of the tuple returned by setup_columns() # is a generator, so if you need to create a look using the generator # object, you need to recreate a generator to show a list expectedly. info = super(ListSecurityGroupRule, self).setup_columns(info, parsed_args) cols = info[0] if not parsed_args.no_nameconv: # Replace column names in the header line (in info[0]) cols = self.replace_columns(info[0], self.replace_rules) parsed_args.columns = cols return (cols, info[1]) class ShowSecurityGroupRule(neutronV20.ShowCommand): """Show information of a given security group rule.""" resource = 'security_group_rule' allow_names = False class CreateSecurityGroupRule(neutronV20.CreateCommand): """Create a security group rule.""" resource = 'security_group_rule' def add_known_arguments(self, parser): parser.add_argument( '--description', help=_('Description of security group rule.')) parser.add_argument( 'security_group_id', metavar='SECURITY_GROUP', help=_('ID or name of the security group to ' 'which the rule is added.')) parser.add_argument( '--direction', type=utils.convert_to_lowercase, default='ingress', choices=['ingress', 'egress'], help=_('Direction of traffic: ingress/egress.')) parser.add_argument( '--ethertype', help=_('IPv4/IPv6')) parser.add_argument( '--protocol', type=utils.convert_to_lowercase, help=_('Protocol of packet. Allowed values are ' '[icmp, icmpv6, tcp, udp] and ' 'integer representations [0-255].')) parser.add_argument( '--port-range-min', help=_('Starting port range. For ICMP it is type.')) parser.add_argument( '--port_range_min', help=argparse.SUPPRESS) parser.add_argument( '--port-range-max', help=_('Ending port range. For ICMP it is code.')) parser.add_argument( '--port_range_max', help=argparse.SUPPRESS) parser.add_argument( '--remote-ip-prefix', help=_('CIDR to match on.')) parser.add_argument( '--remote_ip_prefix', help=argparse.SUPPRESS) parser.add_argument( '--remote-group-id', metavar='REMOTE_GROUP', help=_('ID or name of the remote security group ' 'to which the rule is applied.')) parser.add_argument( '--remote_group_id', help=argparse.SUPPRESS) def args2body(self, parsed_args): _security_group_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'security_group', parsed_args.security_group_id) body = {'security_group_id': _security_group_id, 'direction': parsed_args.direction, 'ethertype': parsed_args.ethertype or generate_default_ethertype(parsed_args.protocol)} neutronV20.update_dict(parsed_args, body, ['protocol', 'port_range_min', 'port_range_max', 'remote_ip_prefix', 'tenant_id', 'description']) if parsed_args.remote_group_id: _remote_group_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'security_group', parsed_args.remote_group_id) body['remote_group_id'] = _remote_group_id return {'security_group_rule': body} class DeleteSecurityGroupRule(neutronV20.DeleteCommand): """Delete a given security group rule.""" resource = 'security_group_rule' allow_names = False ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/servicetype.py0000664000175000017500000000166200000000000026100 0ustar00zuulzuul00000000000000# Copyright 2013 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 neutronclient.neutron import v2_0 as neutronV20 class ListServiceProvider(neutronV20.ListCommand): """List service providers.""" resource = 'service_provider' list_columns = ['service_type', 'name', 'default'] _formatters = {} pagination_support = True sorting_support = True ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/subnet.py0000664000175000017500000002440100000000000025032 0ustar00zuulzuul00000000000000# Copyright 2012 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 argparse from oslo_serialization import jsonutils from neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 def _format_allocation_pools(subnet): try: return '\n'.join([jsonutils.dumps(pool) for pool in subnet['allocation_pools']]) except (TypeError, KeyError): return '' def _format_dns_nameservers(subnet): try: return '\n'.join([jsonutils.dumps(server) for server in subnet['dns_nameservers']]) except (TypeError, KeyError): return '' def _format_host_routes(subnet): try: return '\n'.join([jsonutils.dumps(route) for route in subnet['host_routes']]) except (TypeError, KeyError): return '' def add_updatable_arguments(parser): parser.add_argument( '--name', help=_('Name of this subnet.')) parser.add_argument( '--description', help=_('Description of this subnet.')) gateway_sg = parser.add_mutually_exclusive_group() gateway_sg.add_argument( '--gateway', metavar='GATEWAY_IP', help=_('Gateway IP of this subnet.')) gateway_sg.add_argument( '--no-gateway', action='store_true', help=_('Do not configure a gateway for this subnet.')) parser.add_argument( '--allocation-pool', metavar='start=IP_ADDR,end=IP_ADDR', action='append', dest='allocation_pools', type=utils.str2dict_type(required_keys=['start', 'end']), help=_('Allocation pool IP addresses for this subnet ' '(This option can be repeated).')) parser.add_argument( '--allocation_pool', action='append', dest='allocation_pools', type=utils.str2dict_type(required_keys=['start', 'end']), help=argparse.SUPPRESS) parser.add_argument( '--host-route', metavar='destination=CIDR,nexthop=IP_ADDR', action='append', dest='host_routes', type=utils.str2dict_type(required_keys=['destination', 'nexthop']), help=_('Additional route (This option can be repeated).')) parser.add_argument( '--dns-nameserver', metavar='DNS_NAMESERVER', action='append', dest='dns_nameservers', help=_('DNS name server for this subnet ' '(This option can be repeated).')) parser.add_argument( '--disable-dhcp', action='store_true', help=_('Disable DHCP for this subnet.')) parser.add_argument( '--enable-dhcp', action='store_true', help=_('Enable DHCP for this subnet.')) # NOTE(ihrachys): yes, that's awful, but should be left as-is for # backwards compatibility for versions <=2.3.4 that passed the # boolean values through to the server without any argument # validation. parser.add_argument( '--enable-dhcp=True', action='store_true', dest='enable_dhcp', help=argparse.SUPPRESS) parser.add_argument( '--enable-dhcp=False', action='store_true', dest='disable_dhcp', help=argparse.SUPPRESS) def updatable_args2body(parsed_args, body, for_create=True, ip_version=None): if parsed_args.disable_dhcp and parsed_args.enable_dhcp: raise exceptions.CommandError(_( "You cannot enable and disable DHCP at the same time.")) neutronV20.update_dict(parsed_args, body, ['name', 'allocation_pools', 'host_routes', 'dns_nameservers', 'description']) if parsed_args.no_gateway: body['gateway_ip'] = None elif parsed_args.gateway: body['gateway_ip'] = parsed_args.gateway if parsed_args.disable_dhcp: body['enable_dhcp'] = False if parsed_args.enable_dhcp: body['enable_dhcp'] = True if for_create and parsed_args.ipv6_ra_mode: if ip_version == 4: raise exceptions.CommandError(_("--ipv6-ra-mode is invalid " "when --ip-version is 4")) body['ipv6_ra_mode'] = parsed_args.ipv6_ra_mode if for_create and parsed_args.ipv6_address_mode: if ip_version == 4: raise exceptions.CommandError(_("--ipv6-address-mode is " "invalid when --ip-version " "is 4")) body['ipv6_address_mode'] = parsed_args.ipv6_address_mode class ListSubnet(neutronV20.ListCommand): """List subnets that belong to a given tenant.""" resource = 'subnet' _formatters = {'allocation_pools': _format_allocation_pools, 'dns_nameservers': _format_dns_nameservers, 'host_routes': _format_host_routes, } list_columns = ['id', 'name', 'cidr', 'allocation_pools'] pagination_support = True sorting_support = True class ShowSubnet(neutronV20.ShowCommand): """Show information of a given subnet.""" resource = 'subnet' class CreateSubnet(neutronV20.CreateCommand): """Create a subnet for a given tenant.""" resource = 'subnet' def add_known_arguments(self, parser): add_updatable_arguments(parser) parser.add_argument( '--ip-version', type=int, default=4, choices=[4, 6], help=_('IP version to use, default is 4. ' 'Note that when subnetpool is specified, ' 'IP version is determined from the subnetpool ' 'and this option is ignored.')) parser.add_argument( '--ip_version', type=int, choices=[4, 6], help=argparse.SUPPRESS) parser.add_argument( 'network_id', metavar='NETWORK', help=_('Network ID or name this subnet belongs to.')) parser.add_argument( 'cidr', nargs='?', metavar='CIDR', help=_('CIDR of subnet to create.')) parser.add_argument( '--ipv6-ra-mode', type=utils.convert_to_lowercase, choices=['dhcpv6-stateful', 'dhcpv6-stateless', 'slaac'], help=_('IPv6 RA (Router Advertisement) mode.')) parser.add_argument( '--ipv6-address-mode', type=utils.convert_to_lowercase, choices=['dhcpv6-stateful', 'dhcpv6-stateless', 'slaac'], help=_('IPv6 address mode.')) parser.add_argument( '--subnetpool', metavar='SUBNETPOOL', help=_('ID or name of subnetpool from which this subnet ' 'will obtain a CIDR.')) parser.add_argument( '--use-default-subnetpool', action='store_true', help=_('Use default subnetpool for ip_version, if it exists.')) parser.add_argument( '--prefixlen', metavar='PREFIX_LENGTH', help=_('Prefix length for subnet allocation from subnetpool.')) parser.add_argument( '--segment', metavar='SEGMENT', help=_('ID of segment with which this subnet will be associated.')) def args2body(self, parsed_args): _network_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'network', parsed_args.network_id) body = {'network_id': _network_id} if parsed_args.prefixlen: body['prefixlen'] = parsed_args.prefixlen ip_version = parsed_args.ip_version if parsed_args.use_default_subnetpool: body['use_default_subnetpool'] = True if parsed_args.segment: body['segment_id'] = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'segment', parsed_args.segment) if parsed_args.subnetpool: if parsed_args.subnetpool == 'None': _subnetpool_id = None else: _subnetpool = neutronV20.find_resource_by_name_or_id( self.get_client(), 'subnetpool', parsed_args.subnetpool) _subnetpool_id = _subnetpool['id'] # Now that we have the pool_id - let's just have a check on the # ip version used in the pool ip_version = _subnetpool['ip_version'] body['subnetpool_id'] = _subnetpool_id # IP version needs to be set as IP version can be # determined by subnetpool. body['ip_version'] = ip_version if parsed_args.cidr: # With subnetpool, cidr is now optional for creating subnet. cidr = parsed_args.cidr body['cidr'] = cidr unusable_cidr = '/32' if ip_version == 4 else '/128' if cidr.endswith(unusable_cidr): self.log.warning(_("An IPv%(ip)d subnet with a %(cidr)s CIDR " "will have only one usable IP address so " "the device attached to it will not have " "any IP connectivity."), {"ip": ip_version, "cidr": unusable_cidr}) updatable_args2body(parsed_args, body, ip_version=ip_version) if parsed_args.tenant_id: body['tenant_id'] = parsed_args.tenant_id return {'subnet': body} class DeleteSubnet(neutronV20.DeleteCommand): """Delete a given subnet.""" resource = 'subnet' class UpdateSubnet(neutronV20.UpdateCommand): """Update subnet's information.""" resource = 'subnet' def add_known_arguments(self, parser): add_updatable_arguments(parser) def args2body(self, parsed_args): body = {} updatable_args2body(parsed_args, body, for_create=False) return {'subnet': body} ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/subnetpool.py0000664000175000017500000001310200000000000025720 0ustar00zuulzuul00000000000000# Copyright 2015 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 neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronV20 def _format_prefixes(subnetpool): try: return '\n'.join(pool for pool in subnetpool['prefixes']) except (TypeError, KeyError): return subnetpool['prefixes'] def add_updatable_arguments(parser, for_create=False): parser.add_argument( '--description', help=_('Description of subnetpool.')) parser.add_argument( '--min-prefixlen', type=int, help=_('Subnetpool minimum prefix length.')) parser.add_argument( '--max-prefixlen', type=int, help=_('Subnetpool maximum prefix length.')) parser.add_argument( '--default-prefixlen', type=int, help=_('Subnetpool default prefix length.')) parser.add_argument( '--pool-prefix', action='append', dest='prefixes', required=for_create, help=_('Subnetpool prefixes (This option can be repeated).')) utils.add_boolean_argument( parser, '--is-default', help=_('Specify whether this should be the default subnetpool ' '(True meaning default).')) def updatable_args2body(parsed_args, body): neutronV20.update_dict(parsed_args, body, ['name', 'prefixes', 'default_prefixlen', 'min_prefixlen', 'max_prefixlen', 'is_default', 'description']) class ListSubnetPool(neutronV20.ListCommand): """List subnetpools that belong to a given tenant.""" _formatters = {'prefixes': _format_prefixes, } resource = 'subnetpool' list_columns = ['id', 'name', 'prefixes', 'default_prefixlen', 'address_scope_id', 'is_default'] pagination_support = True sorting_support = True class ShowSubnetPool(neutronV20.ShowCommand): """Show information of a given subnetpool.""" resource = 'subnetpool' class CreateSubnetPool(neutronV20.CreateCommand): """Create a subnetpool for a given tenant.""" resource = 'subnetpool' def add_known_arguments(self, parser): add_updatable_arguments(parser, for_create=True) parser.add_argument( '--shared', action='store_true', help=_('Set the subnetpool as shared.')) parser.add_argument( 'name', metavar='NAME', help=_('Name of the subnetpool to be created.')) parser.add_argument( '--address-scope', metavar='ADDRSCOPE', help=_('ID or name of the address scope with which the subnetpool ' 'is associated. Prefixes must be unique across address ' 'scopes.')) def args2body(self, parsed_args): body = {'prefixes': parsed_args.prefixes} updatable_args2body(parsed_args, body) neutronV20.update_dict(parsed_args, body, ['tenant_id']) if parsed_args.shared: body['shared'] = True # Parse and update for "address-scope" option if parsed_args.address_scope: _addrscope_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'address_scope', parsed_args.address_scope) body['address_scope_id'] = _addrscope_id return {'subnetpool': body} class DeleteSubnetPool(neutronV20.DeleteCommand): """Delete a given subnetpool.""" resource = 'subnetpool' class UpdateSubnetPool(neutronV20.UpdateCommand): """Update subnetpool's information.""" resource = 'subnetpool' def add_known_arguments(self, parser): add_updatable_arguments(parser) parser.add_argument('--name', help=_('Updated name of the subnetpool.')) addrscope_args = parser.add_mutually_exclusive_group() addrscope_args.add_argument('--address-scope', metavar='ADDRSCOPE', help=_('ID or name of the address scope ' 'with which the subnetpool is ' 'associated. Prefixes must be ' 'unique across address scopes.')) addrscope_args.add_argument('--no-address-scope', action='store_true', help=_('Detach subnetpool from the ' 'address scope.')) def args2body(self, parsed_args): body = {} updatable_args2body(parsed_args, body) # Parse and update for "address-scope" option/s if parsed_args.no_address_scope: body['address_scope_id'] = None elif parsed_args.address_scope: _addrscope_id = neutronV20.find_resourceid_by_name_or_id( self.get_client(), 'address_scope', parsed_args.address_scope) body['address_scope_id'] = _addrscope_id return {'subnetpool': body} ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/tag.py0000664000175000017500000001017600000000000024311 0ustar00zuulzuul00000000000000# 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 neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.neutron import v2_0 as neutronv20 # List of resources can be set tag TAG_RESOURCES = ['network', 'subnet', 'port', 'router', 'subnetpool'] def _convert_resource_args(client, parsed_args): resource_type = client.get_resource_plural(parsed_args.resource_type) resource_id = neutronv20.find_resourceid_by_name_or_id( client, parsed_args.resource_type, parsed_args.resource) return resource_type, resource_id def _add_common_arguments(parser): parser.add_argument('--resource-type', choices=TAG_RESOURCES, dest='resource_type', required=True, help=_('Resource Type.')) parser.add_argument('--resource', required=True, help=_('Resource name or ID.')) class AddTag(neutronv20.NeutronCommand): """Add a tag into the resource.""" def get_parser(self, prog_name): parser = super(AddTag, self).get_parser(prog_name) _add_common_arguments(parser) parser.add_argument('--tag', required=True, help=_('Tag to be added.')) return parser def take_action(self, parsed_args): client = self.get_client() if not parsed_args.tag: raise exceptions.CommandError( _('Cannot add an empty value as tag')) resource_type, resource_id = _convert_resource_args(client, parsed_args) client.add_tag(resource_type, resource_id, parsed_args.tag) class ReplaceTag(neutronv20.NeutronCommand): """Replace all tags on the resource.""" def get_parser(self, prog_name): parser = super(ReplaceTag, self).get_parser(prog_name) _add_common_arguments(parser) parser.add_argument('--tag', metavar='TAG', action='append', dest='tags', required=True, help=_('Tag (This option can be repeated).')) return parser def take_action(self, parsed_args): client = self.get_client() resource_type, resource_id = _convert_resource_args(client, parsed_args) body = {'tags': parsed_args.tags} client.replace_tag(resource_type, resource_id, body) class RemoveTag(neutronv20.NeutronCommand): """Remove a tag on the resource.""" def get_parser(self, prog_name): parser = super(RemoveTag, self).get_parser(prog_name) _add_common_arguments(parser) tag_opt = parser.add_mutually_exclusive_group() tag_opt.add_argument('--all', action='store_true', help=_('Remove all tags on the resource.')) tag_opt.add_argument('--tag', help=_('Tag to be removed.')) return parser def take_action(self, parsed_args): if not parsed_args.all and not parsed_args.tag: raise exceptions.CommandError( _("--all or --tag must be specified")) client = self.get_client() resource_type, resource_id = _convert_resource_args(client, parsed_args) if parsed_args.all: client.remove_tag_all(resource_type, resource_id) else: client.remove_tag(resource_type, resource_id, parsed_args.tag) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2176616 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/vpn/0000775000175000017500000000000000000000000023762 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/vpn/__init__.py0000664000175000017500000000000000000000000026061 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/vpn/endpoint_group.py0000664000175000017500000000632600000000000027377 0ustar00zuulzuul00000000000000# (c) Copyright 2015 Cisco Systems, Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronv20 def add_known_endpoint_group_arguments(parser, is_create=True): parser.add_argument( '--name', help=_('Set a name for the endpoint group.')) parser.add_argument( '--description', help=_('Set a description for the endpoint group.')) if is_create: parser.add_argument( '--type', required=is_create, help=_('Type of endpoints in group (e.g. subnet, cidr, vlan).')) parser.add_argument( '--value', action='append', dest='endpoints', required=is_create, help=_('Endpoint(s) for the group. Must all be of the same type.')) class ListEndpointGroup(neutronv20.ListCommand): """List VPN endpoint groups that belong to a given tenant.""" resource = 'endpoint_group' list_columns = ['id', 'name', 'type', 'endpoints'] _formatters = {} pagination_support = True sorting_support = True class ShowEndpointGroup(neutronv20.ShowCommand): """Show a specific VPN endpoint group.""" resource = 'endpoint_group' class CreateEndpointGroup(neutronv20.CreateCommand): """Create a VPN endpoint group.""" resource = 'endpoint_group' def add_known_arguments(self, parser): add_known_endpoint_group_arguments(parser) def subnet_name2id(self, endpoint): return neutronv20.find_resourceid_by_name_or_id(self.get_client(), 'subnet', endpoint) def args2body(self, parsed_args): if parsed_args.type == 'subnet': endpoints = [self.subnet_name2id(ep) for ep in parsed_args.endpoints] else: endpoints = parsed_args.endpoints body = {'endpoints': endpoints} neutronv20.update_dict(parsed_args, body, ['name', 'description', 'tenant_id', 'type']) return {self.resource: body} class UpdateEndpointGroup(neutronv20.UpdateCommand): """Update a given VPN endpoint group.""" resource = 'endpoint_group' def add_known_arguments(self, parser): add_known_endpoint_group_arguments(parser, is_create=False) def args2body(self, parsed_args): body = {} neutronv20.update_dict(parsed_args, body, ['name', 'description']) return {self.resource: body} class DeleteEndpointGroup(neutronv20.DeleteCommand): """Delete a given VPN endpoint group.""" resource = 'endpoint_group' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/vpn/ikepolicy.py0000664000175000017500000001043100000000000026323 0ustar00zuulzuul00000000000000# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. # 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 from neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronv20 from neutronclient.neutron.v2_0.vpn import utils as vpn_utils def add_common_args(parser, is_create=True): parser.add_argument( '--description', help=_('Description of the IKE policy.')) parser.add_argument( '--auth-algorithm', type=utils.convert_to_lowercase, default='sha1' if is_create else argparse.SUPPRESS, choices=['sha1', 'sha256', 'sha384', 'sha512'], help=_('Authentication algorithm, default:sha1.')) parser.add_argument( '--encryption-algorithm', default='aes-128' if is_create else argparse.SUPPRESS, type=utils.convert_to_lowercase, help=_('Encryption algorithm, default:aes-128.')) parser.add_argument( '--phase1-negotiation-mode', default='main' if is_create else argparse.SUPPRESS, choices=['main'], type=utils.convert_to_lowercase, help=_('IKE Phase1 negotiation mode, default:main.')) parser.add_argument( '--ike-version', default='v1' if is_create else argparse.SUPPRESS, choices=['v1', 'v2'], type=utils.convert_to_lowercase, help=_('IKE version for the policy, default:v1.')) parser.add_argument( '--pfs', default='group5' if is_create else argparse.SUPPRESS, type=utils.convert_to_lowercase, help=_('Perfect Forward Secrecy, default:group5.')) parser.add_argument( '--lifetime', metavar="units=UNITS,value=VALUE", type=utils.str2dict_type(optional_keys=['units', 'value']), help=vpn_utils.lifetime_help("IKE")) def parse_common_args2body(parsed_args, body): neutronv20.update_dict(parsed_args, body, ['auth_algorithm', 'encryption_algorithm', 'phase1_negotiation_mode', 'ike_version', 'pfs', 'name', 'description', 'tenant_id']) if parsed_args.lifetime: vpn_utils.validate_lifetime_dict(parsed_args.lifetime) body['lifetime'] = parsed_args.lifetime return body class ListIKEPolicy(neutronv20.ListCommand): """List IKE policies that belong to a tenant.""" resource = 'ikepolicy' list_columns = ['id', 'name', 'auth_algorithm', 'encryption_algorithm', 'ike_version', 'pfs'] _formatters = {} pagination_support = True sorting_support = True class ShowIKEPolicy(neutronv20.ShowCommand): """Show information of a given IKE policy.""" resource = 'ikepolicy' help_resource = 'IKE policy' class CreateIKEPolicy(neutronv20.CreateCommand): """Create an IKE policy.""" resource = 'ikepolicy' def add_known_arguments(self, parser): parser.add_argument( 'name', metavar='NAME', help=_('Name of the IKE policy.')) add_common_args(parser) def args2body(self, parsed_args): return {'ikepolicy': parse_common_args2body(parsed_args, body={})} class UpdateIKEPolicy(neutronv20.UpdateCommand): """Update a given IKE policy.""" resource = 'ikepolicy' help_resource = 'IKE policy' def add_known_arguments(self, parser): parser.add_argument( '--name', help=_('Updated name of the IKE policy.')) add_common_args(parser, is_create=False) def args2body(self, parsed_args): return {'ikepolicy': parse_common_args2body(parsed_args, body={})} class DeleteIKEPolicy(neutronv20.DeleteCommand): """Delete a given IKE policy.""" resource = 'ikepolicy' help_resource = 'IKE policy' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/vpn/ipsec_site_connection.py0000664000175000017500000002163200000000000030706 0ustar00zuulzuul00000000000000# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. # 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 from oslo_serialization import jsonutils from neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronv20 from neutronclient.neutron.v2_0.vpn import utils as vpn_utils def _format_peer_cidrs(ipsec_site_connection): try: return '\n'.join([jsonutils.dumps(cidrs) for cidrs in ipsec_site_connection['peer_cidrs']]) except (TypeError, KeyError): return '' class ListIPsecSiteConnection(neutronv20.ListCommand): """List IPsec site connections that belong to a given tenant.""" resource = 'ipsec_site_connection' _formatters = {'peer_cidrs': _format_peer_cidrs} list_columns = [ 'id', 'name', 'peer_address', 'auth_mode', 'status'] pagination_support = True sorting_support = True class ShowIPsecSiteConnection(neutronv20.ShowCommand): """Show information of a given IPsec site connection.""" resource = 'ipsec_site_connection' help_resource = 'IPsec site connection' class IPsecSiteConnectionMixin(object): def add_known_arguments(self, parser, is_create=True): parser.add_argument( '--name', help=_('Set friendly name for the connection.')) parser.add_argument( '--description', help=_('Set a description for the connection.')) parser.add_argument( '--dpd', metavar="action=ACTION,interval=INTERVAL,timeout=TIMEOUT", type=utils.str2dict_type( optional_keys=['action', 'interval', 'timeout']), help=vpn_utils.dpd_help("IPsec connection.")) parser.add_argument( '--local-ep-group', help=_('Local endpoint group ID/name with subnet(s) for ' 'IPSec connection.')) parser.add_argument( '--peer-ep-group', help=_('Peer endpoint group ID/name with CIDR(s) for ' 'IPSec connection.')) parser.add_argument( '--peer-cidr', action='append', dest='peer_cidrs', help=_('[DEPRECATED in Mitaka] Remote subnet(s) in CIDR format. ' 'Cannot be specified when using endpoint groups. Only ' 'applicable, if subnet provided for VPN service.')) parser.add_argument( '--peer-id', required=is_create, help=_('Peer router identity for authentication. Can be ' 'IPv4/IPv6 address, e-mail address, key id, or FQDN.')) parser.add_argument( '--peer-address', required=is_create, help=_('Peer gateway public IPv4/IPv6 address or FQDN.')) parser.add_argument( '--psk', required=is_create, help=_('Pre-shared key string.')) parser.add_argument( '--mtu', default='1500' if is_create else argparse.SUPPRESS, help=_('MTU size for the connection, default:1500.')) parser.add_argument( '--initiator', default='bi-directional' if is_create else argparse.SUPPRESS, choices=['bi-directional', 'response-only'], help=_('Initiator state in lowercase, default:bi-directional')) def args2body(self, parsed_args, body=None): """Add in conditional args and then return all conn info.""" if body is None: body = {} if parsed_args.dpd: vpn_utils.validate_dpd_dict(parsed_args.dpd) body['dpd'] = parsed_args.dpd if parsed_args.local_ep_group: _local_epg = neutronv20.find_resourceid_by_name_or_id( self.get_client(), 'endpoint_group', parsed_args.local_ep_group) body['local_ep_group_id'] = _local_epg if parsed_args.peer_ep_group: _peer_epg = neutronv20.find_resourceid_by_name_or_id( self.get_client(), 'endpoint_group', parsed_args.peer_ep_group) body['peer_ep_group_id'] = _peer_epg if hasattr(parsed_args, 'mtu') and int(parsed_args.mtu) < 68: message = _("Invalid MTU value: MTU must be " "greater than or equal to 68.") raise exceptions.CommandError(message) # ToDo (Reedip) : Remove below check when peer-cidr is removed if parsed_args.peer_cidrs and parsed_args.local_ep_group: message = _("You cannot specify both endpoint groups and peer " "CIDR(s).") raise exceptions.CommandError(message) neutronv20.update_dict(parsed_args, body, ['peer_id', 'mtu', 'initiator', 'psk', 'peer_address', 'name', 'description', 'peer_cidrs']) return {self.resource: body} class CreateIPsecSiteConnection(IPsecSiteConnectionMixin, neutronv20.CreateCommand): """Create an IPsec site connection.""" resource = 'ipsec_site_connection' def add_known_arguments(self, parser): parser.add_argument( '--admin-state-down', default=True, action='store_false', help=_('Set admin state up to false.')) parser.add_argument( '--vpnservice-id', metavar='VPNSERVICE', required=True, help=_('VPN service instance ID associated with this connection.')) parser.add_argument( '--ikepolicy-id', metavar='IKEPOLICY', required=True, help=_('IKE policy ID associated with this connection.')) parser.add_argument( '--ipsecpolicy-id', metavar='IPSECPOLICY', required=True, help=_('IPsec policy ID associated with this connection.')) super(CreateIPsecSiteConnection, self).add_known_arguments(parser) def args2body(self, parsed_args): _vpnservice_id = neutronv20.find_resourceid_by_name_or_id( self.get_client(), 'vpnservice', parsed_args.vpnservice_id) _ikepolicy_id = neutronv20.find_resourceid_by_name_or_id( self.get_client(), 'ikepolicy', parsed_args.ikepolicy_id) _ipsecpolicy_id = neutronv20.find_resourceid_by_name_or_id( self.get_client(), 'ipsecpolicy', parsed_args.ipsecpolicy_id) body = { 'vpnservice_id': _vpnservice_id, 'ikepolicy_id': _ikepolicy_id, 'ipsecpolicy_id': _ipsecpolicy_id, 'admin_state_up': parsed_args.admin_state_down, } if parsed_args.tenant_id: body['tenant_id'] = parsed_args.tenant_id if (bool(parsed_args.local_ep_group) != bool(parsed_args.peer_ep_group)): message = _("You must specify both local and peer endpoint " "groups.") raise exceptions.CommandError(message) if not parsed_args.peer_cidrs and not parsed_args.local_ep_group: message = _("You must specify endpoint groups or peer CIDR(s).") raise exceptions.CommandError(message) return super(CreateIPsecSiteConnection, self).args2body(parsed_args, body) class UpdateIPsecSiteConnection(IPsecSiteConnectionMixin, neutronv20.UpdateCommand): """Update a given IPsec site connection.""" resource = 'ipsec_site_connection' help_resource = 'IPsec site connection' def add_known_arguments(self, parser): utils.add_boolean_argument( parser, '--admin-state-up', help=_('Update the administrative state. (True meaning "Up")')) super(UpdateIPsecSiteConnection, self).add_known_arguments(parser, False) def args2body(self, parsed_args): body = {} neutronv20.update_dict(parsed_args, body, ['admin_state_up']) return super(UpdateIPsecSiteConnection, self).args2body(parsed_args, body) class DeleteIPsecSiteConnection(neutronv20.DeleteCommand): """Delete a given IPsec site connection.""" resource = 'ipsec_site_connection' help_resource = 'IPsec site connection' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/vpn/ipsecpolicy.py0000664000175000017500000001072600000000000026665 0ustar00zuulzuul00000000000000# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. # 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 from neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronv20 from neutronclient.neutron.v2_0.vpn import utils as vpn_utils def add_common_args(parser, is_create=True): parser.add_argument( '--auth-algorithm', default='sha1' if is_create else argparse.SUPPRESS, type=utils.convert_to_lowercase, choices=['sha1', 'sha256', 'sha384', 'sha512'], help=_('Authentication algorithm for IPsec policy, default:sha1.')) parser.add_argument( '--description', help=_('Description of the IPsec policy.')) parser.add_argument( '--encapsulation-mode', default='tunnel' if is_create else argparse.SUPPRESS, choices=['tunnel', 'transport'], type=utils.convert_to_lowercase, help=_('Encapsulation mode for IPsec policy, default:tunnel.')) parser.add_argument( '--encryption-algorithm', default='aes-128' if is_create else argparse.SUPPRESS, type=utils.convert_to_lowercase, help=_('Encryption algorithm for IPsec policy, default:aes-128.')) parser.add_argument( '--lifetime', metavar="units=UNITS,value=VALUE", type=utils.str2dict_type(optional_keys=['units', 'value']), help=vpn_utils.lifetime_help("IPsec")) parser.add_argument( '--pfs', default='group5' if is_create else argparse.SUPPRESS, type=utils.convert_to_lowercase, help=_('Perfect Forward Secrecy for IPsec policy, default:group5.')) parser.add_argument( '--transform-protocol', default='esp' if is_create else argparse.SUPPRESS, type=utils.convert_to_lowercase, choices=['esp', 'ah', 'ah-esp'], help=_('Transform protocol for IPsec policy, default:esp.')) def parse_common_args2body(parsed_args, body): neutronv20.update_dict(parsed_args, body, ['auth_algorithm', 'encryption_algorithm', 'encapsulation_mode', 'transform_protocol', 'pfs', 'name', 'description', 'tenant_id']) if parsed_args.lifetime: vpn_utils.validate_lifetime_dict(parsed_args.lifetime) body['lifetime'] = parsed_args.lifetime return body class ListIPsecPolicy(neutronv20.ListCommand): """List IPsec policies that belong to a given tenant connection.""" resource = 'ipsecpolicy' list_columns = ['id', 'name', 'auth_algorithm', 'encryption_algorithm', 'pfs'] _formatters = {} pagination_support = True sorting_support = True class ShowIPsecPolicy(neutronv20.ShowCommand): """Show information of a given IPsec policy.""" resource = 'ipsecpolicy' help_resource = 'IPsec policy' class CreateIPsecPolicy(neutronv20.CreateCommand): """Create an IPsec policy.""" resource = 'ipsecpolicy' help_resource = 'IPsec policy' def add_known_arguments(self, parser): parser.add_argument( 'name', metavar='NAME', help=_('Name of the IPsec policy.')) add_common_args(parser) def args2body(self, parsed_args): return {'ipsecpolicy': parse_common_args2body(parsed_args, body={})} class UpdateIPsecPolicy(neutronv20.UpdateCommand): """Update a given IPsec policy.""" resource = 'ipsecpolicy' help_resource = 'IPsec policy' def add_known_arguments(self, parser): parser.add_argument( '--name', help=_('Updated name of the IPsec policy.')) add_common_args(parser, is_create=False) def args2body(self, parsed_args): return {'ipsecpolicy': parse_common_args2body(parsed_args, body={})} class DeleteIPsecPolicy(neutronv20.DeleteCommand): """Delete a given IPsec policy.""" resource = 'ipsecpolicy' help_resource = 'IPsec policy' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/vpn/utils.py0000664000175000017500000001036600000000000025502 0ustar00zuulzuul00000000000000# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. # 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. # """VPN Utilities and helper functions.""" from neutronclient._i18n import _ from neutronclient.common import exceptions dpd_supported_actions = ['hold', 'clear', 'restart', 'restart-by-peer', 'disabled'] dpd_supported_keys = ['action', 'interval', 'timeout'] lifetime_keys = ['units', 'value'] lifetime_units = ['seconds'] def validate_dpd_dict(dpd_dict): for key, value in dpd_dict.items(): if key not in dpd_supported_keys: message = _( "DPD Dictionary KeyError: " "Reason-Invalid DPD key : " "'%(key)s' not in %(supported_key)s") % { 'key': key, 'supported_key': dpd_supported_keys} raise exceptions.CommandError(message) if key == 'action' and value not in dpd_supported_actions: message = _( "DPD Dictionary ValueError: " "Reason-Invalid DPD action : " "'%(key_value)s' not in %(supported_action)s") % { 'key_value': value, 'supported_action': dpd_supported_actions} raise exceptions.CommandError(message) if key in ('interval', 'timeout'): try: if int(value) <= 0: raise ValueError() except ValueError: message = _( "DPD Dictionary ValueError: " "Reason-Invalid positive integer value: " "'%(key)s' = %(value)s") % { 'key': key, 'value': value} raise exceptions.CommandError(message) else: dpd_dict[key] = int(value) return def validate_lifetime_dict(lifetime_dict): for key, value in lifetime_dict.items(): if key not in lifetime_keys: message = _( "Lifetime Dictionary KeyError: " "Reason-Invalid unit key : " "'%(key)s' not in %(supported_key)s") % { 'key': key, 'supported_key': lifetime_keys} raise exceptions.CommandError(message) if key == 'units' and value not in lifetime_units: message = _( "Lifetime Dictionary ValueError: " "Reason-Invalid units : " "'%(key_value)s' not in %(supported_units)s") % { 'key_value': key, 'supported_units': lifetime_units} raise exceptions.CommandError(message) if key == 'value': try: if int(value) < 60: raise ValueError() except ValueError: message = _( "Lifetime Dictionary ValueError: " "Reason-Invalid value should be at least 60:" "'%(key_value)s' = %(value)s") % { 'key_value': key, 'value': value} raise exceptions.CommandError(message) else: lifetime_dict['value'] = int(value) return def lifetime_help(policy): lifetime = _("%s lifetime attributes. " "'units'-seconds, default:seconds. " "'value'-non negative integer, default:3600.") % policy return lifetime def dpd_help(policy): dpd = _(" %s Dead Peer Detection attributes." " 'action'-hold,clear,disabled,restart,restart-by-peer." " 'interval' and 'timeout' are non negative integers. " " 'interval' should be less than 'timeout' value. " " 'action', default:hold 'interval', default:30, " " 'timeout', default:120.") % policy.capitalize() return dpd ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/neutron/v2_0/vpn/vpnservice.py0000664000175000017500000000734300000000000026527 0ustar00zuulzuul00000000000000# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. # 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 neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.neutron import v2_0 as neutronv20 def add_common_args(parser): parser.add_argument( '--name', help=_('Name for the VPN service.')) parser.add_argument( '--description', help=_('Description for the VPN service.')) def common_args2body(parsed_args, body): neutronv20.update_dict(parsed_args, body, ['name', 'description']) class ListVPNService(neutronv20.ListCommand): """List VPN service configurations that belong to a given tenant.""" resource = 'vpnservice' list_columns = [ 'id', 'name', 'router_id', 'status' ] _formatters = {} pagination_support = True sorting_support = True class ShowVPNService(neutronv20.ShowCommand): """Show information of a given VPN service.""" resource = 'vpnservice' help_resource = 'VPN service' class CreateVPNService(neutronv20.CreateCommand): """Create a VPN service.""" resource = 'vpnservice' def add_known_arguments(self, parser): parser.add_argument( '--admin-state-down', dest='admin_state', action='store_false', help=_('Set admin state up to false.')) parser.add_argument( 'router', metavar='ROUTER', help=_('Router unique identifier for the VPN service.')) parser.add_argument( 'subnet', nargs='?', metavar='SUBNET', help=_('[DEPRECATED in Mitaka] Unique identifier for the local ' 'private subnet.')) add_common_args(parser) def args2body(self, parsed_args): if parsed_args.subnet: _subnet_id = neutronv20.find_resourceid_by_name_or_id( self.get_client(), 'subnet', parsed_args.subnet) else: _subnet_id = None _router_id = neutronv20.find_resourceid_by_name_or_id( self.get_client(), 'router', parsed_args.router) body = {'subnet_id': _subnet_id, 'router_id': _router_id, 'admin_state_up': parsed_args.admin_state} neutronv20.update_dict(parsed_args, body, ['tenant_id']) common_args2body(parsed_args, body) return {self.resource: body} class UpdateVPNService(neutronv20.UpdateCommand): """Update a given VPN service.""" resource = 'vpnservice' help_resource = 'VPN service' def add_known_arguments(self, parser): add_common_args(parser) utils.add_boolean_argument( parser, '--admin-state-up', help=_('Update the admin state for the VPN Service.' '(True means UP)')) def args2body(self, parsed_args): body = {} common_args2body(parsed_args, body) neutronv20.update_dict(parsed_args, body, ['admin_state_up']) return {self.resource: body} class DeleteVPNService(neutronv20.DeleteCommand): """Delete a given VPN service.""" resource = 'vpnservice' help_resource = 'VPN service' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2176616 python-neutronclient-11.2.0/neutronclient/osc/0000775000175000017500000000000000000000000021503 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/__init__.py0000664000175000017500000000000000000000000023602 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/plugin.py0000664000175000017500000000427200000000000023360 0ustar00zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # """OpenStackClient plugin for advanced Networking service.""" import logging # TODO(rtheis/amotoki): Add functional test infrastructure for OSC # plugin commands. # TODO(amotoki): Add and update document on OSC plugin. from osc_lib import utils LOG = logging.getLogger(__name__) DEFAULT_API_VERSION = '2.0' API_VERSION_OPTION = 'os_network_api_version' # NOTE(rtheis): API_NAME must NOT be set to 'network' since # 'network' is owned by OSC! The OSC 'network' client uses # the OpenStack SDK. API_NAME = 'neutronclient' API_VERSIONS = { '2.0': 'neutronclient.v2_0.client.Client', '2': 'neutronclient.v2_0.client.Client', } def make_client(instance): """Returns an neutron client.""" neutron_client = utils.get_client_class( API_NAME, instance._api_version[API_NAME], API_VERSIONS) LOG.debug('Instantiating neutron client: %s', neutron_client) # TODO(amotoki): Check the following arguments need to be passed # to neutronclient class. Check keystoneauth code. # - endpoint_type (do we need to specify it explicitly?) # - auth (session object contains auth. Is it required?) client = neutron_client(session=instance.session, region_name=instance.region_name, endpoint_type=instance.interface, insecure=not instance.verify, ca_cert=instance.cacert) return client def build_option_parser(parser): """Hook to add global options""" # NOTE(amotoki): At now we register no option. # OSC itself has an option for Network API version # and we refer to it. return parser ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/utils.py0000664000175000017500000001105100000000000023213 0ustar00zuulzuul00000000000000# Copyright 2016 NEC Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """This module should contain OSC plugin generic methods. Methods in this module are candidates adopted to osc-lib. Stuffs specific to neutronclient OSC plugin should not be added to this module. They should go to neutronclient.osc.v2.utils. """ from keystoneclient import exceptions as identity_exc from keystoneclient.v3 import domains from keystoneclient.v3 import projects from osc_lib import utils from neutronclient._i18n import _ # TODO(amotoki): Use osc-lib version once osc-lib provides this. def add_project_owner_option_to_parser(parser): """Register project and project domain options. :param parser: argparse.Argument parser object. """ parser.add_argument( '--project', metavar='', help=_("Owner's project (name or ID)") ) # Borrowed from openstackclient.identity.common # as it is not exposed officially. parser.add_argument( '--project-domain', metavar='', help=_('Domain the project belongs to (name or ID). ' 'This can be used in case collisions between project names ' 'exist.'), ) # The following methods are borrowed from openstackclient.identity.common # as it is not exposed officially. # TODO(amotoki): Use osc-lib version once osc-lib provides this. def find_domain(identity_client, name_or_id): return _find_identity_resource(identity_client.domains, name_or_id, domains.Domain) def find_project(identity_client, name_or_id, domain_name_or_id=None): domain_id = _get_domain_id_if_requested(identity_client, domain_name_or_id) if not domain_id: return _find_identity_resource(identity_client.projects, name_or_id, projects.Project) else: return _find_identity_resource(identity_client.projects, name_or_id, projects.Project, domain_id=domain_id) def _get_domain_id_if_requested(identity_client, domain_name_or_id): if not domain_name_or_id: return None domain = find_domain(identity_client, domain_name_or_id) return domain.id def _find_identity_resource(identity_client_manager, name_or_id, resource_type, **kwargs): """Find a specific identity resource. Using keystoneclient's manager, attempt to find a specific resource by its name or ID. If Forbidden to find the resource (a common case if the user does not have permission), then return the resource by creating a local instance of keystoneclient's Resource. The parameter identity_client_manager is a keystoneclient manager, for example: keystoneclient.v3.users or keystoneclient.v3.projects. The parameter resource_type is a keystoneclient resource, for example: keystoneclient.v3.users.User or keystoneclient.v3.projects.Project. :param identity_client_manager: the manager that contains the resource :type identity_client_manager: `keystoneclient.base.CrudManager` :param name_or_id: the resources's name or ID :type name_or_id: string :param resource_type: class that represents the resource type :type resource_type: `keystoneclient.base.Resource` :returns: the resource in question :rtype: `keystoneclient.base.Resource` """ try: identity_resource = utils.find_resource(identity_client_manager, name_or_id, **kwargs) if identity_resource is not None: return identity_resource except identity_exc.Forbidden: pass return resource_type(None, {'id': name_or_id, 'name': name_or_id}) # The above are borrowed from openstackclient.identity.common. # DO NOT ADD original methods in neutronclient repo to the above area. def _get_columns(item): column_map = {} hidden_columns = ['location', 'tenant_id'] return utils.get_osc_show_columns_for_sdk_resource( item, column_map, hidden_columns ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2176616 python-neutronclient-11.2.0/neutronclient/osc/v2/0000775000175000017500000000000000000000000022032 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/__init__.py0000664000175000017500000000000000000000000024131 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2176616 python-neutronclient-11.2.0/neutronclient/osc/v2/dynamic_routing/0000775000175000017500000000000000000000000025225 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/dynamic_routing/__init__.py0000664000175000017500000000000000000000000027324 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py0000664000175000017500000000723700000000000030064 0ustar00zuulzuul00000000000000# 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 neutronclient._i18n import _ def _format_alive_state(item): return ':-)' if item else 'XXX' _formatters = { 'alive': _format_alive_state } def add_common_args(parser): parser.add_argument('dragent_id', metavar='', help=_("ID of the dynamic routing agent")) parser.add_argument('bgp_speaker', metavar='', help=_("ID or name of the BGP speaker")) class AddBgpSpeakerToDRAgent(command.Command): """Add a BGP speaker to a dynamic routing agent""" def get_parser(self, prog_name): parser = super(AddBgpSpeakerToDRAgent, self).get_parser(prog_name) add_common_args(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker).id client.add_bgp_speaker_to_dragent(parsed_args.dragent_id, speaker_id) class RemoveBgpSpeakerFromDRAgent(command.Command): """Removes a BGP speaker from a dynamic routing agent""" def get_parser(self, prog_name): parser = super(RemoveBgpSpeakerFromDRAgent, self).get_parser( prog_name) add_common_args(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker).id client.remove_bgp_speaker_from_dragent(parsed_args.dragent_id, speaker_id) class ListDRAgent(command.Lister): """List dynamic routing agents""" resource = 'agent' list_columns = ['id', 'host', 'admin_state_up', 'alive'] unknown_parts_flag = False def get_parser(self, prog_name): parser = super(ListDRAgent, self).get_parser(prog_name) parser.add_argument('--bgp-speaker', metavar='', help=_("List dynamic routing agents hosting a " "BGP speaker (name or ID)")) return parser def take_action(self, parsed_args): client = self.app.client_manager.network if parsed_args.bgp_speaker is not None: speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker).id data = client.get_bgp_dragents_hosting_speaker(speaker_id) else: attrs = {'agent_type': 'BGP dynamic routing agent'} data = client.agents(**attrs) columns = ( 'id', 'agent_type', 'host', 'availability_zone', 'is_alive', 'is_admin_state_up', 'binary' ) column_headers = ( 'ID', 'Agent Type', 'Host', 'Availability Zone', 'Alive', 'State', 'Binary' ) return (column_headers, (utils.get_item_properties( s, columns,) for s in data)) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/dynamic_routing/bgp_peer.py0000664000175000017500000001471400000000000027371 0ustar00zuulzuul00000000000000# 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 neutronclient._i18n import _ from neutronclient.common import exceptions from neutronclient.common import utils as nc_utils from neutronclient.osc import utils as nc_osc_utils from neutronclient.osc.v2.dynamic_routing import constants def _get_attrs(client_manager, parsed_args): attrs = {} # Validate password if 'auth_type' in parsed_args: if parsed_args.auth_type != 'none': if 'password' not in parsed_args or parsed_args.password is None: raise exceptions.CommandError(_('Must provide password if ' 'auth-type is specified.')) if ( parsed_args.auth_type == 'none' and parsed_args.password is not None ): raise exceptions.CommandError(_('Must provide auth-type if ' 'password is specified.')) attrs['auth_type'] = parsed_args.auth_type if parsed_args.name is not None: attrs['name'] = parsed_args.name if 'remote_as' in parsed_args: attrs['remote_as'] = parsed_args.remote_as if 'peer_ip' in parsed_args: attrs['peer_ip'] = parsed_args.peer_ip if 'password' in parsed_args: attrs['password'] = parsed_args.password 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 class CreateBgpPeer(command.ShowOne): _description = _("Create a BGP peer") def get_parser(self, prog_name): parser = super(CreateBgpPeer, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_("Name of the BGP peer to create")) parser.add_argument( '--peer-ip', metavar='', required=True, help=_("Peer IP address")) parser.add_argument( '--remote-as', required=True, metavar='', help=_("Peer AS number. (Integer in [%(min_val)s, %(max_val)s] " "is allowed)") % {'min_val': constants.MIN_AS_NUM, 'max_val': constants.MAX_AS_NUM}) parser.add_argument( '--auth-type', metavar='', choices=['none', 'md5'], type=nc_utils.convert_to_lowercase, default='none', help=_("Authentication algorithm. Supported algorithms: " "none (default), md5")) parser.add_argument( '--password', metavar='', help=_("Authentication password")) nc_osc_utils.add_project_owner_option_to_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_attrs(self.app.client_manager, parsed_args) obj = client.create_bgp_peer(**attrs) display_columns, columns = nc_osc_utils._get_columns(obj) data = utils.get_dict_properties(obj, columns) return display_columns, data class DeleteBgpPeer(command.Command): _description = _("Delete a BGP peer") def get_parser(self, prog_name): parser = super(DeleteBgpPeer, self).get_parser(prog_name) parser.add_argument( 'bgp_peer', metavar="", help=_("BGP peer to delete (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network id = client.find_bgp_peer(parsed_args.bgp_peer)['id'] client.delete_bgp_peer(id) class ListBgpPeer(command.Lister): _description = _("List BGP peers") def take_action(self, parsed_args): data = self.app.client_manager.network.bgp_peers(retrieve_all=True) headers = ('ID', 'Name', 'Peer IP', 'Remote AS') columns = ('id', 'name', 'peer_ip', 'remote_as') return (headers, (utils.get_dict_properties(s, columns,) for s in data)) class SetBgpPeer(command.Command): _description = _("Update a BGP peer") resource = constants.BGP_PEER def get_parser(self, prog_name): parser = super(SetBgpPeer, self).get_parser(prog_name) parser.add_argument( '--name', help=_("Updated name of the BGP peer")) parser.add_argument( '--password', metavar='', help=_("Updated authentication password")) parser.add_argument( 'bgp_peer', metavar="", help=_("BGP peer to update (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network id = client.find_bgp_peer(parsed_args.bgp_peer)['id'] attrs = _get_attrs(self.app.client_manager, parsed_args) client.update_bgp_peer(id, **attrs) class ShowBgpPeer(command.ShowOne): _description = _("Show information for a BGP peer") def get_parser(self, prog_name): parser = super(ShowBgpPeer, self).get_parser(prog_name) parser.add_argument( 'bgp_peer', metavar="", help=_("BGP peer to display (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network id = client.find_bgp_peer(parsed_args.bgp_peer, ignore_missing=False).id obj = client.get_bgp_peer(id) display_columns, columns = nc_osc_utils._get_columns(obj) data = utils.get_dict_properties(obj, columns) return display_columns, data ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/dynamic_routing/bgp_speaker.py0000664000175000017500000002616000000000000030066 0ustar00zuulzuul00000000000000# 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 neutronclient._i18n import _ from neutronclient.osc import utils as nc_osc_utils from neutronclient.osc.v2.dynamic_routing import constants def _get_attrs(client_manager, parsed_args): attrs = {} if parsed_args.name is not None: attrs['name'] = str(parsed_args.name) if 'local_as' in parsed_args: attrs['local_as'] = parsed_args.local_as if 'ip_version' in parsed_args: attrs['ip_version'] = parsed_args.ip_version if parsed_args.advertise_tenant_networks: attrs['advertise_tenant_networks'] = True if parsed_args.no_advertise_tenant_networks: attrs['advertise_tenant_networks'] = False if parsed_args.advertise_floating_ip_host_routes: attrs['advertise_floating_ip_host_routes'] = True if parsed_args.no_advertise_floating_ip_host_routes: attrs['advertise_floating_ip_host_routes'] = False 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 add_common_arguments(parser): parser.add_argument( '--advertise-floating-ip-host-routes', action='store_true', help=_("Enable the advertisement of floating IP host routes " "by the BGP speaker. (default)")) parser.add_argument( '--no-advertise-floating-ip-host-routes', action='store_true', help=_("Disable the advertisement of floating IP host routes " "by the BGP speaker.")) parser.add_argument( '--advertise-tenant-networks', action='store_true', help=_("Enable the advertisement of tenant network routes " "by the BGP speaker. (default)")) parser.add_argument( '--no-advertise-tenant-networks', action='store_true', help=_("Disable the advertisement of tenant network routes " "by the BGP speaker.")) class AddNetworkToSpeaker(command.Command): _description = _("Add a network to a BGP speaker") def get_parser(self, prog_name): parser = super(AddNetworkToSpeaker, self).get_parser(prog_name) parser.add_argument( 'bgp_speaker', metavar='', help=_("BGP speaker (name or ID)")) parser.add_argument( 'network', metavar='', help=_("Network to add (name or ID)")) return parser def take_action(self, parsed_args): client = self.app.client_manager.network speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker, ignore_missing=False).id net_id = client.find_network(parsed_args.network, ignore_missing=False).id client.add_gateway_network_to_speaker(speaker_id, net_id) class AddPeerToSpeaker(command.Command): _description = _("Add a peer to a BGP speaker") def get_parser(self, prog_name): parser = super(AddPeerToSpeaker, self).get_parser(prog_name) parser.add_argument( 'bgp_speaker', metavar='', help=_("BGP speaker (name or ID)")) parser.add_argument( 'bgp_peer', metavar='', help=_("BGP Peer to add (name or ID)")) return parser def take_action(self, parsed_args): client = self.app.client_manager.network speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker)['id'] peer_id = client.find_bgp_peer(parsed_args.bgp_peer)['id'] client.add_bgp_peer_to_speaker(speaker_id, peer_id) class CreateBgpSpeaker(command.ShowOne): _description = _("Create a BGP speaker") def get_parser(self, prog_name): parser = super(CreateBgpSpeaker, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_("Name of the BGP speaker to create")) parser.add_argument( '--local-as', metavar='', required=True, help=_("Local AS number. (Integer in [%(min_val)s, %(max_val)s] " "is allowed.)") % {'min_val': constants.MIN_AS_NUM, 'max_val': constants.MAX_AS_NUM}) parser.add_argument( '--ip-version', type=int, choices=[4, 6], default=4, help=_("IP version for the BGP speaker (default is 4)")) add_common_arguments(parser) nc_osc_utils.add_project_owner_option_to_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_attrs(self.app.client_manager, parsed_args) obj = client.create_bgp_speaker(**attrs) display_columns, columns = nc_osc_utils._get_columns(obj) data = utils.get_dict_properties(obj, columns) return display_columns, data class DeleteBgpSpeaker(command.Command): _description = _("Delete a BGP speaker") def get_parser(self, prog_name): parser = super(DeleteBgpSpeaker, self).get_parser(prog_name) parser.add_argument( 'bgp_speaker', metavar="", help=_("BGP speaker to delete (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network id = client.find_bgp_speaker(parsed_args.bgp_speaker)['id'] client.delete_bgp_speaker(id) class ListBgpSpeaker(command.Lister): _description = _("List BGP speakers") def get_parser(self, prog_name): parser = super(ListBgpSpeaker, self).get_parser(prog_name) parser.add_argument( '--agent', metavar='', help=_("List BGP speakers hosted by an agent (ID only)")) return parser def take_action(self, parsed_args): client = self.app.client_manager.network if parsed_args.agent is not None: data = client.get_bgp_speakers_hosted_by_dragent(parsed_args.agent) else: data = client.bgp_speakers(retrieve_all=True) headers = ('ID', 'Name', 'Local AS', 'IP Version') columns = ('id', 'name', 'local_as', 'ip_version') return (headers, (utils.get_dict_properties(s, columns) for s in data)) class ListRoutesAdvertisedBySpeaker(command.Lister): _description = _("List routes advertised") def get_parser(self, prog_name): parser = super(ListRoutesAdvertisedBySpeaker, self).get_parser(prog_name) parser.add_argument( 'bgp_speaker', metavar='', help=_("BGP speaker (name or ID)")) return parser def take_action(self, parsed_args): client = self.app.client_manager.network speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker)['id'] data = client.get_advertised_routes_of_speaker(speaker_id) headers = ('Destination', 'Nexthop') columns = ('destination', 'next_hop') return (headers, (utils.get_dict_properties(s, columns) for s in data['advertised_routes'])) class RemoveNetworkFromSpeaker(command.Command): _description = _("Remove a network from a BGP speaker") def get_parser(self, prog_name): parser = super(RemoveNetworkFromSpeaker, self).get_parser(prog_name) parser.add_argument( 'bgp_speaker', metavar='', help=_("BGP speaker (name or ID)")) parser.add_argument( 'network', metavar='', help=_("Network to remove (name or ID)")) return parser def take_action(self, parsed_args): client = self.app.client_manager.network speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker)['id'] net_id = client.find_network(parsed_args.network)['id'] client.remove_gateway_network_from_speaker(speaker_id, net_id) class RemovePeerFromSpeaker(command.Command): _description = _("Remove a peer from a BGP speaker") def get_parser(self, prog_name): parser = super(RemovePeerFromSpeaker, self).get_parser(prog_name) parser.add_argument( 'bgp_speaker', metavar='', help=_("BGP speaker (name or ID)")) parser.add_argument( 'bgp_peer', metavar='', help=_("BGP Peer to remove (name or ID)")) return parser def take_action(self, parsed_args): client = self.app.client_manager.network speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker)['id'] peer_id = client.find_bgp_peer(parsed_args.bgp_peer)['id'] client.remove_bgp_peer_from_speaker(speaker_id, peer_id) class SetBgpSpeaker(command.Command): _description = _("Set BGP speaker properties") resource = constants.BGP_SPEAKER def get_parser(self, prog_name): parser = super(SetBgpSpeaker, self).get_parser(prog_name) parser.add_argument( 'bgp_speaker', metavar="", help=_("BGP speaker to update (name or ID)") ) parser.add_argument( '--name', help=_("New name for the BGP speaker")) add_common_arguments(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network id = client.find_bgp_speaker(parsed_args.bgp_speaker)['id'] attrs = _get_attrs(self.app.client_manager, parsed_args) client.update_bgp_speaker(id, **attrs) class ShowBgpSpeaker(command.ShowOne): _description = _("Show a BGP speaker") def get_parser(self, prog_name): parser = super(ShowBgpSpeaker, self).get_parser(prog_name) parser.add_argument( 'bgp_speaker', metavar="", help=_("BGP speaker to display (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network id = client.find_bgp_speaker(parsed_args.bgp_speaker, ignore_missing=False).id obj = client.get_bgp_speaker(id) display_columns, columns = nc_osc_utils._get_columns(obj) data = utils.get_dict_properties(obj, columns) return display_columns, data ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/dynamic_routing/constants.py0000664000175000017500000000131400000000000027612 0ustar00zuulzuul00000000000000# 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. BGP_SPEAKERS = 'bgp_speakers' BGP_SPEAKER = 'bgp_speaker' BGP_PEERS = 'bgp_peers' BGP_PEER = 'bgp_peer' MIN_AS_NUM = 1 MAX_AS_NUM = 4294967295 ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1709201317.221662 python-neutronclient-11.2.0/neutronclient/osc/v2/fwaas/0000775000175000017500000000000000000000000023133 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/fwaas/__init__.py0000664000175000017500000000000000000000000025232 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/fwaas/constants.py0000664000175000017500000000153100000000000025521 0ustar00zuulzuul00000000000000# Copyright 2016-2017 FUJITSU LIMITED # 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. # FWG = 'firewall_group' FWGS = 'firewall_groups' FWP = 'firewall_policy' FWPS = 'firewall_policies' FWR = 'firewall_rule' FWRS = 'firewall_rules' CMD_FWG = 'fwaas_' + FWG CMD_FWP = 'fwaas_' + FWP CMD_FWR = 'fwaas_' + FWR ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/fwaas/firewallgroup.py0000664000175000017500000003472100000000000026376 0ustar00zuulzuul00000000000000# Copyright 2016-2017 FUJITSU LIMITED # 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 logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from neutronclient._i18n import _ from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.fwaas import constants as const from neutronclient.osc.v2 import utils as v2_utils LOG = logging.getLogger(__name__) _formatters = { 'admin_state_up': v2_utils.AdminStateColumn, } _attr_map_dict = { 'id': 'ID', 'name': 'Name', 'ingress_firewall_policy_id': 'Ingress Policy ID', 'egress_firewall_policy_id': 'Egress Policy ID', 'description': 'Description', 'status': 'Status', 'ports': 'Ports', 'admin_state_up': 'State', 'shared': 'Shared', 'tenant_id': 'Project', 'project_id': 'Project', } _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('ingress_firewall_policy_id', 'Ingress Policy ID', column_util.LIST_BOTH), ('egress_firewall_policy_id', 'Egress Policy ID', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), ('status', 'Status', column_util.LIST_LONG_ONLY), ('ports', 'Ports', column_util.LIST_LONG_ONLY), ('admin_state_up', 'State', column_util.LIST_LONG_ONLY), ('shared', 'Shared', column_util.LIST_LONG_ONLY), ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), ) def _get_common_parser(parser): parser.add_argument( '--name', help=_('Name for the firewall group')) parser.add_argument( '--description', metavar='', help=_('Description of the firewall group')) ingress_group = parser.add_mutually_exclusive_group() ingress_group.add_argument( '--ingress-firewall-policy', metavar='', dest='ingress_firewall_policy', help=_('Ingress firewall policy (name or ID)')) ingress_group.add_argument( '--no-ingress-firewall-policy', dest='no_ingress_firewall_policy', action='store_true', help=_('Detach ingress firewall policy from the firewall group')) egress_group = parser.add_mutually_exclusive_group() egress_group.add_argument( '--egress-firewall-policy', metavar='', dest='egress_firewall_policy', help=_('Egress firewall policy (name or ID)')) egress_group.add_argument( '--no-egress-firewall-policy', dest='no_egress_firewall_policy', action='store_true', help=_('Detach egress firewall policy from the firewall group')) shared_group = parser.add_mutually_exclusive_group() shared_group.add_argument( '--share', action='store_true', help=_('Share the firewall group to be used in all projects ' '(by default, it is restricted to be used by the ' 'current project).')) shared_group.add_argument( '--no-share', action='store_true', help=_('Restrict use of the firewall group to the ' 'current project')) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', help=_('Enable firewall group')) admin_group.add_argument( '--disable', action='store_true', help=_('Disable firewall group')) return parser def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} client = client_manager.network if is_create: if 'project' in parsed_args and parsed_args.project is not None: attrs['tenant_id'] = osc_utils.find_project( client_manager.identity, parsed_args.project, parsed_args.project_domain, ).id if (parsed_args.ingress_firewall_policy and parsed_args.no_ingress_firewall_policy): attrs['ingress_firewall_policy_id'] = client.find_firewall_policy( parsed_args.ingress_firewall_policy)['id'] elif parsed_args.ingress_firewall_policy: attrs['ingress_firewall_policy_id'] = client.find_firewall_policy( parsed_args.ingress_firewall_policy)['id'] elif parsed_args.no_ingress_firewall_policy: attrs['ingress_firewall_policy_id'] = None if (parsed_args.egress_firewall_policy and parsed_args.no_egress_firewall_policy): attrs['egress_firewall_policy_id'] = client.find_firewall_policy( parsed_args.egress_firewall_policy)['id'] elif parsed_args.egress_firewall_policy: attrs['egress_firewall_policy_id'] = client.find_firewall_policy( parsed_args.egress_firewall_policy)['id'] elif parsed_args.no_egress_firewall_policy: attrs['egress_firewall_policy_id'] = None if parsed_args.share: attrs['shared'] = True if parsed_args.no_share: attrs['shared'] = False if parsed_args.enable: attrs['admin_state_up'] = True if parsed_args.disable: attrs['admin_state_up'] = False if parsed_args.name: attrs['name'] = str(parsed_args.name) if parsed_args.description: attrs['description'] = str(parsed_args.description) if parsed_args.port and parsed_args.no_port: attrs['ports'] = sorted([client.find_port( p)['id'] for p in set(parsed_args.port)]) elif parsed_args.port: ports = [] for p in set(parsed_args.port): ports.append(client.find_port(p)['id']) if not is_create: ports += client.find_firewall_group( parsed_args.firewall_group)['ports'] attrs['ports'] = sorted(set(ports)) elif parsed_args.no_port: attrs['ports'] = [] return attrs class CreateFirewallGroup(command.ShowOne): _description = _("Create a new firewall group") def get_parser(self, prog_name): parser = super(CreateFirewallGroup, self).get_parser(prog_name) _get_common_parser(parser) osc_utils.add_project_owner_option_to_parser(parser) port_group = parser.add_mutually_exclusive_group() port_group.add_argument( '--port', metavar='', action='append', help=_('Port(s) (name or ID) to apply firewall group. This ' 'option can be repeated')) port_group.add_argument( '--no-port', dest='no_port', action='store_true', help=_('Detach all port from the firewall group')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) obj = client.create_firewall_group(**attrs) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return (display_columns, data) class DeleteFirewallGroup(command.Command): _description = _("Delete firewall group(s)") def get_parser(self, prog_name): parser = super(DeleteFirewallGroup, self).get_parser(prog_name) parser.add_argument( const.FWG, metavar='', nargs='+', help=_('Firewall group(s) to delete (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for fwg in parsed_args.firewall_group: try: fwg_id = client.find_firewall_group(fwg)['id'] client.delete_firewall_group(fwg_id) except Exception as e: result += 1 LOG.error(_("Failed to delete firewall group with " "name or ID '%(firewall_group)s': %(e)s"), {const.FWG: fwg, 'e': e}) if result > 0: total = len(parsed_args.firewall_group) msg = (_("%(result)s of %(total)s firewall group(s) " "failed to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListFirewallGroup(command.Lister): _description = _("List firewall groups") def get_parser(self, prog_name): parser = super(ListFirewallGroup, 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.network obj = client.firewall_groups() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties( s, columns, formatters=_formatters) for s in obj)) class SetFirewallGroup(command.Command): _description = _("Set firewall group properties") def get_parser(self, prog_name): parser = super(SetFirewallGroup, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( const.FWG, metavar='', help=_('Firewall group to update (name or ID)')) parser.add_argument( '--port', metavar='', action='append', help=_('Port(s) (name or ID) to apply firewall group. This ' 'option can be repeated')) parser.add_argument( '--no-port', dest='no_port', action='store_true', help=_('Detach all port from the firewall group')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network fwg_id = client.find_firewall_group(parsed_args.firewall_group)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) try: client.update_firewall_group(fwg_id, **attrs) except Exception as e: msg = (_("Failed to set firewall group '%(group)s': %(e)s") % {'group': parsed_args.firewall_group, 'e': e}) raise exceptions.CommandError(msg) class ShowFirewallGroup(command.ShowOne): _description = _("Display firewall group details") def get_parser(self, prog_name): parser = super(ShowFirewallGroup, self).get_parser(prog_name) parser.add_argument( const.FWG, metavar='', help=_('Firewall group to show (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network fwg_id = client.find_firewall_group(parsed_args.firewall_group)['id'] obj = client.get_firewall_group(fwg_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return (display_columns, data) class UnsetFirewallGroup(command.Command): _description = _("Unset firewall group properties") def get_parser(self, prog_name): parser = super(UnsetFirewallGroup, self).get_parser(prog_name) parser.add_argument( const.FWG, metavar='', help=_('Firewall group to unset (name or ID)')) port_group = parser.add_mutually_exclusive_group() port_group.add_argument( '--port', metavar='', action='append', help=_('Port(s) (name or ID) to apply firewall group. This ' 'option can be repeated')) port_group.add_argument( '--all-port', action='store_true', help=_('Remove all ports for this firewall group')) parser.add_argument( '--ingress-firewall-policy', action='store_true', help=_('Ingress firewall policy (name or ID) to delete')) parser.add_argument( '--egress-firewall-policy', action='store_true', dest='egress_firewall_policy', help=_('Egress firewall policy (name or ID) to delete')) shared_group = parser.add_mutually_exclusive_group() shared_group.add_argument( '--share', action='store_true', help=_('Restrict use of the firewall group to the ' 'current project')) parser.add_argument( '--enable', action='store_true', help=_('Disable firewall group')) return parser def _get_attrs(self, client, parsed_args): attrs = {} if parsed_args.ingress_firewall_policy: attrs['ingress_firewall_policy_id'] = None if parsed_args.egress_firewall_policy: attrs['egress_firewall_policy_id'] = None if parsed_args.share: attrs['shared'] = False if parsed_args.enable: attrs['admin_state_up'] = False if parsed_args.port: old = client.find_firewall_group( parsed_args.firewall_group)['ports'] new = [client.find_port(r)['id'] for r in parsed_args.port] attrs['ports'] = sorted(list(set(old) - set(new))) if parsed_args.all_port: attrs['ports'] = [] return attrs def take_action(self, parsed_args): client = self.app.client_manager.network fwg_id = client.find_firewall_group(parsed_args.firewall_group)['id'] attrs = self._get_attrs(client, parsed_args) try: client.update_firewall_group(fwg_id, **attrs) except Exception as e: msg = (_("Failed to unset firewall group '%(group)s': %(e)s") % {'group': parsed_args.firewall_group, 'e': e}) raise exceptions.CommandError(msg) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/fwaas/firewallpolicy.py0000664000175000017500000003727300000000000026546 0ustar00zuulzuul00000000000000# Copyright 2016-2017 FUJITSU LIMITED # 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 logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from neutronclient._i18n import _ from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.fwaas import constants as const LOG = logging.getLogger(__name__) _formatters = {} _attr_map_dict = { 'id': 'ID', 'name': 'Name', 'description': 'Description', 'firewall_rules': 'Firewall Rules', 'audited': 'Audited', 'shared': 'Shared', 'tenant_id': 'Project', 'project_id': 'Project', } _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('firewall_rules', 'Firewall Rules', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), ('audited', 'Audited', column_util.LIST_LONG_ONLY), ('shared', 'Shared', column_util.LIST_LONG_ONLY), ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), ) def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} client = client_manager.network if is_create: if 'project' in parsed_args and parsed_args.project is not None: attrs['tenant_id'] = osc_utils.find_project( client_manager.identity, parsed_args.project, parsed_args.project_domain, ).id if parsed_args.firewall_rule and parsed_args.no_firewall_rule: _firewall_rules = [] for f in parsed_args.firewall_rule: _firewall_rules.append(client.find_firewall_rule(f)['id']) attrs[const.FWRS] = _firewall_rules elif parsed_args.firewall_rule: rules = [] if not is_create: foobar = client.find_firewall_policy( parsed_args.firewall_policy) rules += foobar[const.FWRS] for f in parsed_args.firewall_rule: rules.append(client.find_firewall_rule(f)['id']) attrs[const.FWRS] = rules elif parsed_args.no_firewall_rule: attrs[const.FWRS] = [] if parsed_args.audited: attrs['audited'] = True if parsed_args.no_audited: attrs['audited'] = False if parsed_args.name: attrs['name'] = str(parsed_args.name) if parsed_args.description: attrs['description'] = str(parsed_args.description) if parsed_args.share: attrs['shared'] = True if parsed_args.no_share: attrs['shared'] = False return attrs def _get_common_parser(parser): parser.add_argument( '--description', help=_('Description of the firewall policy')) audited_group = parser.add_mutually_exclusive_group() audited_group.add_argument( '--audited', action='store_true', help=_('Enable auditing for the policy')) audited_group.add_argument( '--no-audited', action='store_true', help=_('Disable auditing for the policy')) shared_group = parser.add_mutually_exclusive_group() shared_group.add_argument( '--share', action='store_true', help=_('Share the firewall policy to be used in all projects ' '(by default, it is restricted to be used by the ' 'current project).')) shared_group.add_argument( '--no-share', action='store_true', help=_('Restrict use of the firewall policy to the ' 'current project')) return parser class CreateFirewallPolicy(command.ShowOne): _description = _("Create a new firewall policy") def get_parser(self, prog_name): parser = super(CreateFirewallPolicy, self).get_parser(prog_name) _get_common_parser(parser) osc_utils.add_project_owner_option_to_parser(parser) parser.add_argument( 'name', metavar='', help=_('Name for the firewall policy')) fwr_group = parser.add_mutually_exclusive_group() fwr_group.add_argument( '--firewall-rule', action='append', metavar='', help=_('Firewall rule(s) to apply (name or ID)')) fwr_group.add_argument( '--no-firewall-rule', action='store_true', help=_('Unset all firewall rules from firewall policy')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) obj = client.create_firewall_policy(**attrs) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return (display_columns, data) class DeleteFirewallPolicy(command.Command): _description = _("Delete firewall policy(s)") def get_parser(self, prog_name): parser = super(DeleteFirewallPolicy, self).get_parser(prog_name) parser.add_argument( const.FWP, metavar='', nargs='+', help=_('Firewall policy(s) to delete (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for fwp in parsed_args.firewall_policy: try: fwp_id = client.find_firewall_policy(fwp)['id'] client.delete_firewall_policy(fwp_id) except Exception as e: result += 1 LOG.error(_("Failed to delete Firewall policy with " "name or ID '%(firewall_policy)s': %(e)s"), {const.FWP: fwp, 'e': e}) if result > 0: total = len(parsed_args.firewall_policy) msg = (_("%(result)s of %(total)s firewall policy(s) " "failed to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class FirewallPolicyInsertRule(command.Command): _description = _("Insert a rule into a given firewall policy") def get_parser(self, prog_name): parser = super(FirewallPolicyInsertRule, self).get_parser(prog_name) parser.add_argument( const.FWP, metavar='', help=_('Firewall policy to insert rule (name or ID)')) parser.add_argument( '--insert-before', metavar='', help=_('Insert the new rule before this existing rule ' '(name or ID)')) parser.add_argument( '--insert-after', metavar='', help=_('Insert the new rule after this existing rule ' '(name or ID)')) parser.add_argument( const.FWR, metavar='', help=_('Firewall rule to be inserted (name or ID)')) return parser def args2body(self, parsed_args): client = self.app.client_manager.network _rule_id = _get_required_firewall_rule(client, parsed_args) _insert_before = '' if 'insert_before' in parsed_args: if parsed_args.insert_before: _insert_before = client.find_firewall_rule( parsed_args.insert_before)['id'] _insert_after = '' if 'insert_after' in parsed_args: if parsed_args.insert_after: _insert_after = client.find_firewall_rule( parsed_args.insert_after)['id'] return {'firewall_rule_id': _rule_id, 'insert_before': _insert_before, 'insert_after': _insert_after} def take_action(self, parsed_args): client = self.app.client_manager.network policy_id = client.find_firewall_policy( parsed_args.firewall_policy)['id'] body = self.args2body(parsed_args) client.insert_rule_into_policy(policy_id, body) rule_id = body['firewall_rule_id'] policy = parsed_args.firewall_policy print((_('Inserted firewall rule %(rule)s in firewall policy ' '%(policy)s') % {'rule': rule_id, 'policy': policy}), file=self.app.stdout) class FirewallPolicyRemoveRule(command.Command): _description = _("Remove a rule from a given firewall policy") def get_parser(self, prog_name): parser = super(FirewallPolicyRemoveRule, self).get_parser(prog_name) parser.add_argument( const.FWP, metavar='', help=_('Firewall policy to remove rule (name or ID)')) parser.add_argument( const.FWR, metavar='', help=_('Firewall rule to remove from policy (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network policy_id = client.find_firewall_policy( parsed_args.firewall_policy)['id'] fwr_id = _get_required_firewall_rule(client, parsed_args) body = {'firewall_rule_id': fwr_id} client.remove_rule_from_policy(policy_id, body) rule_id = body['firewall_rule_id'] policy = parsed_args.firewall_policy print((_('Removed firewall rule %(rule)s from firewall policy ' '%(policy)s') % {'rule': rule_id, 'policy': policy}), file=self.app.stdout) class ListFirewallPolicy(command.Lister): _description = _("List firewall policies") def get_parser(self, prog_name): parser = super(ListFirewallPolicy, 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.network obj = client.firewall_policies() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties( s, columns, formatters=_formatters) for s in obj)) class SetFirewallPolicy(command.Command): _description = _("Set firewall policy properties") def get_parser(self, prog_name): parser = super(SetFirewallPolicy, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( const.FWP, metavar='', help=_('Firewall policy to update (name or ID)')) parser.add_argument( '--name', metavar='', help=_('Name for the firewall policy')) parser.add_argument( '--firewall-rule', action='append', metavar='', help=_('Firewall rule(s) to apply (name or ID)')) parser.add_argument( '--no-firewall-rule', action='store_true', help=_('Remove all firewall rules from firewall policy')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network fwp_id = client.find_firewall_policy( parsed_args.firewall_policy)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) try: client.update_firewall_policy(fwp_id, **attrs) except Exception as e: msg = (_("Failed to set firewall policy '%(policy)s': %(e)s") % {'policy': parsed_args.firewall_policy, 'e': e}) raise exceptions.CommandError(msg) class ShowFirewallPolicy(command.ShowOne): _description = _("Display firewall policy details") def get_parser(self, prog_name): parser = super(ShowFirewallPolicy, self).get_parser(prog_name) parser.add_argument( const.FWP, metavar='', help=_('Firewall policy to show (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network fwp_id = client.find_firewall_policy( parsed_args.firewall_policy)['id'] obj = client.get_firewall_policy(fwp_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return (display_columns, data) def _get_required_firewall_rule(client, parsed_args): if not parsed_args.firewall_rule: msg = (_("Firewall rule (name or ID) is required.")) raise exceptions.CommandError(msg) return client.find_firewall_rule(parsed_args.firewall_rule)['id'] class UnsetFirewallPolicy(command.Command): _description = _("Unset firewall policy properties") def get_parser(self, prog_name): parser = super(UnsetFirewallPolicy, self).get_parser(prog_name) parser.add_argument( const.FWP, metavar='', help=_('Firewall policy to unset (name or ID)')) firewall_rule_group = parser.add_mutually_exclusive_group() firewall_rule_group.add_argument( '--firewall-rule', action='append', metavar='', help=_('Remove firewall rule(s) from the firewall policy ' '(name or ID)')) firewall_rule_group.add_argument( '--all-firewall-rule', action='store_true', help=_('Remove all firewall rules from the firewall policy')) parser.add_argument( '--audited', action='store_true', help=_('Disable auditing for the policy')) parser.add_argument( '--share', action='store_true', help=_('Restrict use of the firewall policy to the ' 'current project')) return parser def _get_attrs(self, client_manager, parsed_args): attrs = {} client = client_manager.network if parsed_args.firewall_rule: current = client.find_firewall_policy( parsed_args.firewall_policy)[const.FWRS] removed = [] for f in set(parsed_args.firewall_rule): removed.append(client.find_firewall_rule(f)['id']) attrs[const.FWRS] = [r for r in current if r not in removed] if parsed_args.all_firewall_rule: attrs[const.FWRS] = [] if parsed_args.audited: attrs['audited'] = False if parsed_args.share: attrs['shared'] = False return attrs def take_action(self, parsed_args): client = self.app.client_manager.network fwp_id = client.find_firewall_policy( parsed_args.firewall_policy)['id'] attrs = self._get_attrs(self.app.client_manager, parsed_args) try: client.update_firewall_policy(fwp_id, **attrs) except Exception as e: msg = (_("Failed to unset firewall policy '%(policy)s': %(e)s") % {'policy': parsed_args.firewall_policy, 'e': e}) raise exceptions.CommandError(msg) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/fwaas/firewallrule.py0000664000175000017500000004363600000000000026216 0ustar00zuulzuul00000000000000# Copyright 2016-2017 FUJITSU LIMITED # 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 logging from cliff import columns as cliff_columns from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from neutronclient._i18n import _ from neutronclient.common import utils as nc_utils from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.fwaas import constants as const LOG = logging.getLogger(__name__) _attr_map_dict = { 'id': 'ID', 'name': 'Name', 'enabled': 'Enabled', 'summary': 'Summary', 'description': 'Description', 'firewall_policy_id': 'Firewall Policy', 'ip_version': 'IP Version', 'action': 'Action', 'protocol': 'Protocol', 'source_ip_address': 'Source IP Address', 'source_port': 'Source Port', 'destination_ip_address': 'Destination IP Address', 'destination_port': 'Destination Port', 'shared': 'Shared', 'source_firewall_group_id': 'Source Firewall Group ID', 'destination_firewall_group_id': 'Destination Firewall Group ID', 'tenant_id': 'Project', 'project_id': 'Project', } _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('enabled', 'Enabled', column_util.LIST_BOTH), ('summary', 'Summary', column_util.LIST_SHORT_ONLY), ('description', 'Description', column_util.LIST_LONG_ONLY), ('firewall_policy_id', 'Firewall Policy', column_util.LIST_BOTH), ('ip_version', 'IP Version', column_util.LIST_LONG_ONLY), ('action', 'Action', column_util.LIST_LONG_ONLY), ('protocol', 'Protocol', column_util.LIST_LONG_ONLY), ('source_ip_address', 'Source IP Address', column_util.LIST_LONG_ONLY), ('source_port', 'Source Port', column_util.LIST_LONG_ONLY), ('destination_ip_address', 'Destination IP Address', column_util.LIST_LONG_ONLY), ('destination_port', 'Destination Port', column_util.LIST_LONG_ONLY), ('shared', 'Shared', column_util.LIST_LONG_ONLY), ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), ('source_firewall_group_id', 'Source Firewall Group ID', column_util.LIST_LONG_ONLY), ('destination_firewall_group_id', 'Destination Firewall Group ID', column_util.LIST_LONG_ONLY), ) def _get_common_parser(parser): parser.add_argument( '--name', metavar='', help=_('Name of the firewall rule')) parser.add_argument( '--description', metavar='', help=_('Description of the firewall rule')) parser.add_argument( '--protocol', choices=['tcp', 'udp', 'icmp', 'any'], type=nc_utils.convert_to_lowercase, help=_('Protocol for the firewall rule')) parser.add_argument( '--action', choices=['allow', 'deny', 'reject'], type=nc_utils.convert_to_lowercase, help=_('Action for the firewall rule')) parser.add_argument( '--ip-version', metavar='', choices=['4', '6'], help=_('Set IP version 4 or 6 (default is 4)')) src_ip_group = parser.add_mutually_exclusive_group() src_ip_group.add_argument( '--source-ip-address', metavar='', help=_('Source IP address or subnet')) src_ip_group.add_argument( '--no-source-ip-address', action='store_true', help=_('Detach source IP address')) dst_ip_group = parser.add_mutually_exclusive_group() dst_ip_group.add_argument( '--destination-ip-address', metavar='', help=_('Destination IP address or subnet')) dst_ip_group.add_argument( '--no-destination-ip-address', action='store_true', help=_('Detach destination IP address')) src_port_group = parser.add_mutually_exclusive_group() src_port_group.add_argument( '--source-port', metavar='', help=_('Source port number or range' '(integer in [1, 65535] or range like 123:456)')) src_port_group.add_argument( '--no-source-port', action='store_true', help=_('Detach source port number or range')) dst_port_group = parser.add_mutually_exclusive_group() dst_port_group.add_argument( '--destination-port', metavar='', help=_('Destination port number or range' '(integer in [1, 65535] or range like 123:456)')) dst_port_group.add_argument( '--no-destination-port', action='store_true', help=_('Detach destination port number or range')) shared_group = parser.add_mutually_exclusive_group() shared_group.add_argument( '--share', action='store_true', help=_('Share the firewall rule to be used in all projects ' '(by default, it is restricted to be used by the ' 'current project).')) shared_group.add_argument( '--no-share', action='store_true', help=_('Restrict use of the firewall rule to the current project')) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable-rule', action='store_true', help=_('Enable this rule (default is enabled)')) enable_group.add_argument( '--disable-rule', action='store_true', help=_('Disable this rule')) src_fwg_group = parser.add_mutually_exclusive_group() src_fwg_group.add_argument( '--source-firewall-group', metavar='', help=_('Source firewall group (name or ID)')) src_fwg_group.add_argument( '--no-source-firewall-group', action='store_true', help=_('No associated destination firewall group')) dst_fwg_group = parser.add_mutually_exclusive_group() dst_fwg_group.add_argument( '--destination-firewall-group', metavar='', help=_('Destination firewall group (name or ID)')) dst_fwg_group.add_argument( '--no-destination-firewall-group', action='store_true', help=_('No associated destination firewall group')) return parser def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} client = client_manager.network if is_create: if 'project' in parsed_args and parsed_args.project is not None: attrs['tenant_id'] = osc_utils.find_project( client_manager.identity, parsed_args.project, parsed_args.project_domain, ).id if parsed_args.name: attrs['name'] = str(parsed_args.name) if parsed_args.description: attrs['description'] = str(parsed_args.description) if parsed_args.protocol: protocol = parsed_args.protocol attrs['protocol'] = None if protocol == 'any' else protocol if parsed_args.action: attrs['action'] = parsed_args.action if parsed_args.ip_version: attrs['ip_version'] = str(parsed_args.ip_version) if parsed_args.source_port: attrs['source_port'] = parsed_args.source_port if parsed_args.no_source_port: attrs['source_port'] = None if parsed_args.source_ip_address: attrs['source_ip_address'] = parsed_args.source_ip_address if parsed_args.no_source_ip_address: attrs['source_ip_address'] = None if parsed_args.destination_port: attrs['destination_port'] = str(parsed_args.destination_port) if parsed_args.no_destination_port: attrs['destination_port'] = None if parsed_args.destination_ip_address: attrs['destination_ip_address'] = str( parsed_args.destination_ip_address) if parsed_args.no_destination_ip_address: attrs['destination_ip_address'] = None if parsed_args.enable_rule: attrs['enabled'] = True if parsed_args.disable_rule: attrs['enabled'] = False if parsed_args.share: attrs['shared'] = True if parsed_args.no_share: attrs['shared'] = False if parsed_args.source_firewall_group: attrs['source_firewall_group_id'] = client.find_firewall_group( parsed_args.source_firewall_group)['id'] if parsed_args.no_source_firewall_group: attrs['source_firewall_group_id'] = None if parsed_args.destination_firewall_group: attrs['destination_firewall_group_id'] = client.find_firewall_group( parsed_args.destination_firewall_group)['id'] if parsed_args.no_destination_firewall_group: attrs['destination_firewall_group_id'] = None return attrs class ProtocolColumn(cliff_columns.FormattableColumn): def human_readable(self): return self._value if self._value else 'any' _formatters = {'protocol': ProtocolColumn} class CreateFirewallRule(command.ShowOne): _description = _("Create a new firewall rule") def get_parser(self, prog_name): parser = super(CreateFirewallRule, self).get_parser(prog_name) _get_common_parser(parser) osc_utils.add_project_owner_option_to_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) obj = client.create_firewall_rule(**attrs) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return display_columns, data class DeleteFirewallRule(command.Command): _description = _("Delete firewall rule(s)") def get_parser(self, prog_name): parser = super(DeleteFirewallRule, self).get_parser(prog_name) parser.add_argument( const.FWR, metavar='', nargs='+', help=_('Firewall rule(s) to delete (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for fwr in parsed_args.firewall_rule: try: fwr_id = client.find_firewall_rule(fwr)['id'] client.delete_firewall_rule(fwr_id) except Exception as e: result += 1 LOG.error(_("Failed to delete Firewall rule with " "name or ID '%(firewall_rule)s': %(e)s"), {const.FWR: fwr, 'e': e}) if result > 0: total = len(parsed_args.firewall_rule) msg = (_("%(result)s of %(total)s firewall rule(s) failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListFirewallRule(command.Lister): _description = _("List firewall rules that belong to a given tenant") def get_parser(self, prog_name): parser = super(ListFirewallRule, self).get_parser(prog_name) parser.add_argument( '--long', action='store_true', default=False, help=_("List additional fields in output") ) return parser def extend_list(self, data, parsed_args): ext_data = [] for d in data: protocol = d['protocol'].upper() if d['protocol'] else 'ANY' src_ip = 'none specified' dst_ip = 'none specified' src_port = '(none specified)' dst_port = '(none specified)' if 'source_ip_address' in d and d['source_ip_address']: src_ip = str(d['source_ip_address']).lower() if 'source_port' in d and d['source_port']: src_port = '(' + str(d['source_port']).lower() + ')' if 'destination_ip_address' in d and d['destination_ip_address']: dst_ip = str(d['destination_ip_address']).lower() if 'destination_port' in d and d['destination_port']: dst_port = '(' + str(d['destination_port']).lower() + ')' action = d['action'] if d.get('action') else 'no-action' src = 'source(port): ' + src_ip + src_port dst = 'dest(port): ' + dst_ip + dst_port d['summary'] = ',\n '.join([protocol, src, dst, action]) ext_data.append(d) return ext_data def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.firewall_rules() obj_extend = self.extend_list(obj, parsed_args) headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties( s, columns, formatters=_formatters) for s in obj_extend)) class SetFirewallRule(command.Command): _description = _("Set firewall rule properties") def get_parser(self, prog_name): parser = super(SetFirewallRule, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( const.FWR, metavar='', help=_('Firewall rule to set (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) fwr_id = client.find_firewall_rule(parsed_args.firewall_rule)['id'] try: client.update_firewall_rule(fwr_id, **attrs) except Exception as e: msg = (_("Failed to set firewall rule '%(rule)s': %(e)s") % {'rule': parsed_args.firewall_rule, 'e': e}) raise exceptions.CommandError(msg) class ShowFirewallRule(command.ShowOne): _description = _("Display firewall rule details") def get_parser(self, prog_name): parser = super(ShowFirewallRule, self).get_parser(prog_name) parser.add_argument( const.FWR, metavar='', help=_('Firewall rule to display (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network fwr_id = client.find_firewall_rule(parsed_args.firewall_rule)['id'] obj = client.get_firewall_rule(fwr_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return (display_columns, data) class UnsetFirewallRule(command.Command): _description = _("Unset firewall rule properties") def get_parser(self, prog_name): parser = super(UnsetFirewallRule, self).get_parser(prog_name) parser.add_argument( const.FWR, metavar='', help=_('Firewall rule to unset (name or ID)')) parser.add_argument( '--source-ip-address', action='store_true', help=_('Source IP address or subnet')) parser.add_argument( '--destination-ip-address', action='store_true', help=_('Destination IP address or subnet')) parser.add_argument( '--source-port', action='store_true', help=_('Source port number or range' '(integer in [1, 65535] or range like 123:456)')) parser.add_argument( '--destination-port', action='store_true', help=_('Destination port number or range' '(integer in [1, 65535] or range like 123:456)')) parser.add_argument( '--share', action='store_true', help=_('Restrict use of the firewall rule to the current project')) parser.add_argument( '--enable-rule', action='store_true', help=_('Disable this rule')) parser.add_argument( '--source-firewall-group', action='store_true', help=_('Source firewall group (name or ID)')) parser.add_argument( '--destination-firewall-group', action='store_true', help=_('Destination firewall group (name or ID)')) return parser def _get_attrs(self, client_manager, parsed_args): attrs = {} if parsed_args.source_ip_address: attrs['source_ip_address'] = None if parsed_args.source_port: attrs['source_port'] = None if parsed_args.destination_ip_address: attrs['destination_ip_address'] = None if parsed_args.destination_port: attrs['destination_port'] = None if parsed_args.share: attrs['shared'] = False if parsed_args.enable_rule: attrs['enabled'] = False if parsed_args.source_firewall_group: attrs['source_firewall_group_id'] = None if parsed_args.source_firewall_group: attrs['destination_firewall_group_id'] = None return attrs def take_action(self, parsed_args): client = self.app.client_manager.network attrs = self._get_attrs(self.app.client_manager, parsed_args) fwr_id = client.find_firewall_rule(parsed_args.firewall_rule)['id'] try: client.update_firewall_rule(fwr_id, **attrs) except Exception as e: msg = (_("Failed to unset firewall rule '%(rule)s': %(e)s") % {'rule': parsed_args.firewall_rule, 'e': e}) raise exceptions.CommandError(msg) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1709201317.221662 python-neutronclient-11.2.0/neutronclient/osc/v2/lbaas/0000775000175000017500000000000000000000000023114 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/lbaas/__init__.py0000664000175000017500000000000000000000000025213 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1709201317.221662 python-neutronclient-11.2.0/neutronclient/osc/v2/logging/0000775000175000017500000000000000000000000023460 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/logging/__init__.py0000664000175000017500000000000000000000000025557 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/logging/network_log.py0000664000175000017500000002643600000000000026377 0ustar00zuulzuul00000000000000# Copyright 2017-2018 FUJTISU LIMITED. # 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 copy from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from oslo_log import log as logging from neutronclient._i18n import _ from neutronclient.common import utils as nc_utils from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.fwaas import constants as fwaas_const LOG = logging.getLogger(__name__) _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), ('enabled', 'Enabled', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('target_id', 'Target', column_util.LIST_LONG_ONLY), ('project_id', 'Project', column_util.LIST_LONG_ONLY), ('resource_id', 'Resource', column_util.LIST_LONG_ONLY), ('resource_type', 'Type', column_util.LIST_BOTH), ('event', 'Event', column_util.LIST_LONG_ONLY), ('summary', 'Summary', column_util.LIST_SHORT_ONLY), ) _attr_map_for_loggable = ( ('type', 'Supported types', column_util.LIST_BOTH), ) NET_LOG = 'network_log' def _get_common_parser(parser): parser.add_argument( '--description', metavar='', help=_('Description of the network log')) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable this log')) enable_group.add_argument( '--disable', action='store_true', help=_('Disable this log (default is enabled)')) return parser def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} client = client_manager.neutronclient if is_create: if 'project' in parsed_args and parsed_args.project is not None: attrs['project_id'] = osc_utils.find_project( client_manager.identity, parsed_args.project, parsed_args.project_domain, ).id resource_type = parsed_args.resource_type attrs['resource_type'] = resource_type if parsed_args.resource: cmd_resource = None if resource_type == fwaas_const.FWG: cmd_resource = fwaas_const.CMD_FWG attrs['resource_id'] = client.find_resource( resource_type, parsed_args.resource, cmd_resource=cmd_resource)['id'] if parsed_args.target: # NOTE(yushiro) Currently, we're supporting only port attrs['target_id'] = client.find_resource( 'port', parsed_args.target)['id'] if parsed_args.event: attrs['event'] = parsed_args.event if parsed_args.enable: attrs['enabled'] = True if parsed_args.disable: attrs['enabled'] = False if parsed_args.name: attrs['name'] = parsed_args.name if parsed_args.description: attrs['description'] = parsed_args.description return attrs class CreateNetworkLog(command.ShowOne): _description = _("Create a new network log") def get_parser(self, prog_name): parser = super(CreateNetworkLog, self).get_parser(prog_name) _get_common_parser(parser) osc_utils.add_project_owner_option_to_parser(parser) parser.add_argument( 'name', metavar='', help=_('Name for the network log')) parser.add_argument( '--event', metavar='{ALL,ACCEPT,DROP}', choices=['ALL', 'ACCEPT', 'DROP'], type=nc_utils.convert_to_uppercase, help=_('An event to store with log')) # NOTE(yushiro) '--resource-type' is managed by following command: # "openstack network loggable resources list". Therefore, this option # shouldn't have "choices" like ['security_group', 'firewall_group'] parser.add_argument( '--resource-type', metavar='', required=True, type=nc_utils.convert_to_lowercase, help=_('Network log type(s). ' 'You can see supported type(s) with following command:\n' '$ openstack network loggable resources list')) parser.add_argument( '--resource', metavar='', help=_('Name or ID of resource (security group or firewall group) ' 'that used for logging. You can control for logging target ' 'combination with --target option.')) parser.add_argument( '--target', metavar='', help=_('Port (name or ID) for logging. You can control ' 'for logging target combination with --resource option.')) return parser def take_action(self, parsed_args): client = self.app.client_manager.neutronclient attrs = _get_common_attrs(self.app.client_manager, parsed_args) obj = client.create_network_log({'log': attrs})['log'] columns, display_columns = column_util.get_columns(obj, _attr_map) data = utils.get_dict_properties(obj, columns) return (display_columns, data) class DeleteNetworkLog(command.Command): _description = _("Delete network log(s)") def get_parser(self, prog_name): parser = super(DeleteNetworkLog, self).get_parser(prog_name) parser.add_argument( 'network_log', metavar='', nargs='+', help=_('Network log(s) to delete (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.neutronclient result = 0 for log_res in parsed_args.network_log: try: log_id = client.find_resource( 'log', log_res, cmd_resource=NET_LOG)['id'] client.delete_network_log(log_id) except Exception as e: result += 1 LOG.error(_("Failed to delete network log with " "name or ID '%(network_log)s': %(e)s"), {'network_log': log_res, 'e': e}) if result > 0: total = len(parsed_args.network_log) msg = (_("%(result)s of %(total)s network log(s) " "failed to delete") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListLoggableResource(command.Lister): _description = _("List supported loggable resources") def get_parser(self, prog_name): parser = super(ListLoggableResource, 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.neutronclient obj = client.list_network_loggable_resources()['loggable_resources'] headers, columns = column_util.get_column_definitions( _attr_map_for_loggable, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties(s, columns) for s in obj)) class ListNetworkLog(command.Lister): _description = _("List network logs") def get_parser(self, prog_name): parser = super(ListNetworkLog, self).get_parser(prog_name) parser.add_argument( '--long', action='store_true', help=_("List additional fields in output") ) # TODO(yushiro): We'll support filtering in the future. return parser def _extend_list(self, data, parsed_args): ext_data = copy.deepcopy(data) for d in ext_data: e_prefix = 'Event: ' if d['event']: event = e_prefix + d['event'].upper() port = '(port) ' + d['target_id'] if d['target_id'] else '' resource_type = d['resource_type'] if d['resource_id']: res = '(%s) %s' % (resource_type, d['resource_id']) else: res = '' t_prefix = 'Logged: ' if port and res: t = '%s on %s' % (res, port) else: # Either of res and port is empty, so concatenation works fine t = res + port target = t_prefix + t if t else t_prefix + '(None specified)' d['summary'] = ',\n'.join([event, target]) return ext_data def take_action(self, parsed_args): client = self.app.client_manager.neutronclient obj = client.list_network_logs()['logs'] obj_extend = self._extend_list(obj, parsed_args) headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, ( utils.get_dict_properties(s, columns) for s in obj_extend)) class SetNetworkLog(command.Command): _description = _("Set network log properties") def get_parser(self, prog_name): parser = super(SetNetworkLog, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( 'network_log', metavar='', help=_('Network log to set (name or ID)')) parser.add_argument( '--name', metavar='', help=_('Name of the network log')) return parser def take_action(self, parsed_args): client = self.app.client_manager.neutronclient log_id = client.find_resource( 'log', parsed_args.network_log, cmd_resource=NET_LOG)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) try: client.update_network_log(log_id, {'log': attrs}) except Exception as e: msg = (_("Failed to set network log '%(logging)s': %(e)s") % {'logging': parsed_args.network_log, 'e': e}) raise exceptions.CommandError(msg) class ShowNetworkLog(command.ShowOne): _description = _("Display network log details") def get_parser(self, prog_name): parser = super(ShowNetworkLog, self).get_parser(prog_name) parser.add_argument( 'network_log', metavar='', help=_('Network log to show (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.neutronclient log_id = client.find_resource( 'log', parsed_args.network_log, cmd_resource=NET_LOG)['id'] obj = client.show_network_log(log_id)['log'] columns, display_columns = column_util.get_columns(obj, _attr_map) data = utils.get_dict_properties(obj, columns) return (display_columns, data) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1709201317.221662 python-neutronclient-11.2.0/neutronclient/osc/v2/networking_bgpvpn/0000775000175000017500000000000000000000000025575 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/networking_bgpvpn/__init__.py0000664000175000017500000000000000000000000027674 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/networking_bgpvpn/bgpvpn.py0000664000175000017500000003643100000000000027452 0ustar00zuulzuul00000000000000# Copyright (c) 2016 Juniper Networks Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # import logging from osc_lib.cli import format_columns from osc_lib.cli.parseractions import KeyValueAction from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils as osc_utils from osc_lib.utils import columns as column_util from neutronclient._i18n import _ from neutronclient.osc import utils as nc_osc_utils LOG = logging.getLogger(__name__) _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('project_id', 'Project', column_util.LIST_LONG_ONLY), ('name', 'Name', column_util.LIST_BOTH), ('type', 'Type', column_util.LIST_BOTH), ('route_targets', 'Route Targets', column_util.LIST_LONG_ONLY), ('import_targets', 'Import Targets', column_util.LIST_LONG_ONLY), ('export_targets', 'Export Targets', column_util.LIST_LONG_ONLY), ('route_distinguishers', 'Route Distinguishers', column_util.LIST_LONG_ONLY), ('networks', 'Associated Networks', column_util.LIST_LONG_ONLY), ('routers', 'Associated Routers', column_util.LIST_LONG_ONLY), ('ports', 'Associated Ports', column_util.LIST_LONG_ONLY), ('vni', 'VNI', column_util.LIST_LONG_ONLY), ('local_pref', 'Local Pref', column_util.LIST_LONG_ONLY), ) _formatters = { 'route_targets': format_columns.ListColumn, 'import_targets': format_columns.ListColumn, 'export_targets': format_columns.ListColumn, 'route_distinguishers': format_columns.ListColumn, 'networks': format_columns.ListColumn, 'routers': format_columns.ListColumn, 'ports': format_columns.ListColumn, } def _get_common_parser(parser, update=None): """Adds to parser arguments common to create, set and unset commands. :params ArgumentParser parser: argparse object contains all command's arguments :params string update: Determines if it is a create command (value: None), it is a set command (value: 'set') or if it is an unset command (value: 'unset') """ ADD_RT = _("Add Route Target to import/export list") REMOVE_RT = _("Remove Route Target from import/export list") ADD_IMPORT_RT = _("Add Route Target to import list") REMOVE_IMPORT_RT = _("Remove Route Target from import list") ADD_EXPORT_RT = _("Add Route Target to export list") REMOVE_EXPORT_RT = _("Remove Route Target from export list") ADD_RD = _("Add Route Distinguisher to the list of Route Distinguishers " "from which a Route Distinguishers will be picked from to " "advertise a VPN route") REMOVE_RD = _("Remove Route Distinguisher from the list of Route " "Distinguishers from which a Route Distinguishers will be " "picked from to advertise a VPN route") REPEAT_RT = _("repeat option for multiple Route Targets") REPEAT_RD = _("repeat option for multiple Route Distinguishers") def is_appended(): return update is None or update == 'set' if update is None or update == 'set': parser.add_argument( '--name', metavar="", help=_("Name of the BGP VPN"), ) parser.add_argument( '--route-target', dest='route_targets', action='append', metavar="", help="%s (%s)" % ((ADD_RT if is_appended() else REMOVE_RT), REPEAT_RT), ) if update: parser.add_argument( '--no-route-target' if update == 'set' else '--all-route-target', dest='purge_route_target', action='store_true', help=_('Empty route target list'), ) parser.add_argument( '--import-target', dest='import_targets', action='append', metavar="", help="%s (%s)" % ((ADD_IMPORT_RT if is_appended() else REMOVE_IMPORT_RT), REPEAT_RT), ) if update: parser.add_argument( '--no-import-target' if update == 'set' else '--all-import-target', dest='purge_import_target', action='store_true', help=_('Empty import route target list'), ) parser.add_argument( '--export-target', dest='export_targets', action='append', metavar="", help="%s (%s)" % ((ADD_EXPORT_RT if is_appended() else REMOVE_EXPORT_RT), REPEAT_RT), ) if update: parser.add_argument( '--no-export-target' if update == 'set' else '--all-export-target', dest='purge_export_target', action='store_true', help=_('Empty export route target list'), ) parser.add_argument( '--route-distinguisher', dest='route_distinguishers', action='append', metavar="", help="%s (%s)" % ((ADD_RD if is_appended() else REMOVE_RD), REPEAT_RD), ) if update: parser.add_argument( '--no-route-distinguisher' if update == 'set' else '--all-route-distinguisher', dest='purge_route_distinguisher', action='store_true', help=_('Empty route distinguisher list'), ) parser.add_argument( '--vni', type=int, help=_('VXLAN Network Identifier to be used for this BGPVPN ' 'when a VXLAN encapsulation is used')) parser.add_argument( '--local-pref', type=int, dest='local_pref', help=_('Default BGP LOCAL_PREF to use in route advertisements' 'towards this BGPVPN.')) def _args2body(client_manager, id, action, args): if (not (args.purge_route_target and args.purge_import_target and args.purge_export_target and args.purge_route_distinguisher) and (args.route_targets or args.import_targets or args.export_targets or args.route_distinguishers)): bgpvpn = client_manager.network.get_bgpvpn(id) attrs = {} if 'name' in args and args.name is not None: attrs['name'] = str(args.name) if 'vni' in args and args.vni is not None: attrs['vni'] = args.vni if 'local_pref' in args and args.local_pref is not None: attrs['local_pref'] = args.local_pref if args.purge_route_target: attrs['route_targets'] = [] elif args.route_targets: if action == 'set': attrs['route_targets'] = list(set(bgpvpn['route_targets']) | set(args.route_targets)) elif action == 'unset': attrs['route_targets'] = list(set(bgpvpn['route_targets']) - set(args.route_targets)) if args.purge_import_target: attrs['import_targets'] = [] elif args.import_targets: if action == 'set': attrs['import_targets'] = list(set(bgpvpn['import_targets']) | set(args.import_targets)) elif action == 'unset': attrs['import_targets'] = list(set(bgpvpn['import_targets']) - set(args.import_targets)) if args.purge_export_target: attrs['export_targets'] = [] elif args.export_targets: if action == 'set': attrs['export_targets'] = list(set(bgpvpn['export_targets']) | set(args.export_targets)) elif action == 'unset': attrs['export_targets'] = list(set(bgpvpn['export_targets']) - set(args.export_targets)) if args.purge_route_distinguisher: attrs['route_distinguishers'] = [] elif args.route_distinguishers: if action == 'set': attrs['route_distinguishers'] = list( set(bgpvpn['route_distinguishers']) | set(args.route_distinguishers)) elif action == 'unset': attrs['route_distinguishers'] = list( set(bgpvpn['route_distinguishers']) - set(args.route_distinguishers)) return attrs class CreateBgpvpn(command.ShowOne): _description = _("Create BGP VPN resource") def get_parser(self, prog_name): parser = super(CreateBgpvpn, self).get_parser(prog_name) nc_osc_utils.add_project_owner_option_to_parser(parser) _get_common_parser(parser) parser.add_argument( '--type', default='l3', choices=['l2', 'l3'], help=_("BGP VPN type selection between IP VPN (l3) and Ethernet " "VPN (l2) (default: l3)"), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = {} if parsed_args.name is not None: attrs['name'] = str(parsed_args.name) if parsed_args.type is not None: attrs['type'] = parsed_args.type if parsed_args.route_targets is not None: attrs['route_targets'] = parsed_args.route_targets if parsed_args.import_targets is not None: attrs['import_targets'] = parsed_args.import_targets if parsed_args.export_targets is not None: attrs['export_targets'] = parsed_args.export_targets if parsed_args.route_distinguishers is not None: attrs['route_distinguishers'] = parsed_args.route_distinguishers if parsed_args.vni is not None: attrs['vni'] = parsed_args.vni if parsed_args.local_pref is not None: attrs['local_pref'] = parsed_args.local_pref if 'project' in parsed_args and parsed_args.project is not None: project_id = nc_osc_utils.find_project( self.app.client_manager.identity, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id obj = client.create_bgpvpn(**attrs) display_columns, columns = nc_osc_utils._get_columns(obj) data = osc_utils.get_dict_properties(obj, columns, formatters=_formatters) return display_columns, data class SetBgpvpn(command.Command): _description = _("Set BGP VPN properties") def get_parser(self, prog_name): parser = super(SetBgpvpn, self).get_parser(prog_name) parser.add_argument( 'bgpvpn', metavar="", help=_("BGP VPN to update (name or ID)"), ) _get_common_parser(parser, update='set') return parser def take_action(self, parsed_args): client = self.app.client_manager.network id = client.find_bgpvpn(parsed_args.bgpvpn)['id'] body = _args2body(self.app.client_manager, id, 'set', parsed_args) client.update_bgpvpn(id, **body) class UnsetBgpvpn(command.Command): _description = _("Unset BGP VPN properties") def get_parser(self, prog_name): parser = super(UnsetBgpvpn, self).get_parser(prog_name) parser.add_argument( 'bgpvpn', metavar="", help=_("BGP VPN to update (name or ID)"), ) _get_common_parser(parser, update='unset') return parser def take_action(self, parsed_args): client = self.app.client_manager.network id = client.find_bgpvpn(parsed_args.bgpvpn)['id'] body = _args2body(self.app.client_manager, id, 'unset', parsed_args) client.update_bgpvpn(id, **body) class DeleteBgpvpn(command.Command): _description = _("Delete BGP VPN resource(s)") def get_parser(self, prog_name): parser = super(DeleteBgpvpn, self).get_parser(prog_name) parser.add_argument( 'bgpvpns', metavar="", nargs="+", help=_("BGP VPN(s) to delete (name or ID)"), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network fails = 0 for id_or_name in parsed_args.bgpvpns: try: id = client.find_bgpvpn(id_or_name)['id'] client.delete_bgpvpn(id) LOG.warning("BGP VPN %(id)s deleted", {'id': id}) except Exception as e: fails += 1 LOG.error("Failed to delete BGP VPN with name or ID " "'%(id_or_name)s': %(e)s", {'id_or_name': id_or_name, 'e': e}) if fails > 0: msg = (_("Failed to delete %(fails)s of %(total)s BGP VPN.") % {'fails': fails, 'total': len(parsed_args.bgpvpns)}) raise exceptions.CommandError(msg) class ListBgpvpn(command.Lister): _description = _("List BGP VPN resources") def get_parser(self, prog_name): parser = super(ListBgpvpn, self).get_parser(prog_name) nc_osc_utils.add_project_owner_option_to_parser(parser) parser.add_argument( '--long', action='store_true', help=_("List additional fields in output"), ) parser.add_argument( '--property', metavar="", default=dict(), help=_("Filter property to apply on returned BGP VPNs (repeat to " "filter on multiple properties)"), action=KeyValueAction, ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network params = {} if parsed_args.project is not None: project_id = nc_osc_utils.find_project( self.app.client_manager.identity, parsed_args.project, parsed_args.project_domain, ).id params['tenant_id'] = project_id if parsed_args.property: params.update(parsed_args.property) objs = client.bgpvpns(**params) headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (osc_utils.get_dict_properties( s, columns, formatters=_formatters) for s in objs)) class ShowBgpvpn(command.ShowOne): _description = _("Show information of a given BGP VPN") def get_parser(self, prog_name): parser = super(ShowBgpvpn, self).get_parser(prog_name) parser.add_argument( 'bgpvpn', metavar="", help=_("BGP VPN to display (name or ID)"), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network id = client.find_bgpvpn(parsed_args.bgpvpn)['id'] obj = client.get_bgpvpn(id) display_columns, columns = nc_osc_utils._get_columns(obj) data = osc_utils.get_dict_properties(obj, columns, formatters=_formatters) return display_columns, data ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/networking_bgpvpn/constants.py0000664000175000017500000000202600000000000030163 0ustar00zuulzuul00000000000000# Copyright (c) 2016 Juniper Networks Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # BGPVPN = 'bgpvpn' BGPVPNS = '%ss' % BGPVPN NETWORK_RESOURCE_NAME = 'network' NETWORK_ASSOC = '%s_association' % NETWORK_RESOURCE_NAME NETWORK_ASSOCS = '%ss' % NETWORK_ASSOC ROUTER_RESOURCE_NAME = 'router' ROUTER_ASSOC = '%s_association' % ROUTER_RESOURCE_NAME ROUTER_ASSOCS = '%ss' % ROUTER_ASSOC PORT_RESOURCE_NAME = 'port' PORT_ASSOC = '%s_association' % PORT_RESOURCE_NAME PORT_ASSOCS = '%ss' % PORT_ASSOC ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/networking_bgpvpn/network_association.py0000664000175000017500000000426600000000000032244 0ustar00zuulzuul00000000000000# Copyright (c) 2016 Juniper Networks Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from osc_lib.utils import columns as column_util from neutronclient._i18n import _ from neutronclient.osc.v2.networking_bgpvpn import constants from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ CreateBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ DeleteBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ ListBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ ShowBgpvpnResAssoc class BgpvpnNetAssoc(object): _assoc_res_name = constants.NETWORK_RESOURCE_NAME _resource = constants.NETWORK_ASSOC _resource_plural = constants.NETWORK_ASSOCS _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), column_util.LIST_BOTH), ) _formatters = {} class CreateBgpvpnNetAssoc(BgpvpnNetAssoc, CreateBgpvpnResAssoc): _description = _("Create a BGP VPN network association") pass class DeleteBgpvpnNetAssoc(BgpvpnNetAssoc, DeleteBgpvpnResAssoc): _description = _("Delete a BGP VPN network association(s) for a given BGP " "VPN") pass class ListBgpvpnNetAssoc(BgpvpnNetAssoc, ListBgpvpnResAssoc): _description = _("List BGP VPN network associations for a given BGP VPN") pass class ShowBgpvpnNetAssoc(BgpvpnNetAssoc, ShowBgpvpnResAssoc): _description = _("Show information of a given BGP VPN network association") pass ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/networking_bgpvpn/port_association.py0000664000175000017500000002751100000000000031535 0ustar00zuulzuul00000000000000# Copyright (c) 2017 Juniper networks Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # import logging from osc_lib.cli import format_columns from osc_lib.cli import parseractions from osc_lib.utils import columns as column_util from neutronclient._i18n import _ from neutronclient.osc.v2.networking_bgpvpn import constants from neutronclient.osc.v2.networking_bgpvpn import resource_association LOG = logging.getLogger(__name__) class BgpvpnPortAssoc(object): _assoc_res_name = constants.PORT_RESOURCE_NAME _resource = constants.PORT_ASSOC _resource_plural = constants.PORT_ASSOCS _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), column_util.LIST_BOTH), ('prefix_routes', 'Prefix Routes (BGP LOCAL_PREF)', column_util.LIST_LONG_ONLY), ('bgpvpn_routes', 'BGP VPN Routes (BGP LOCAL_PREF)', column_util.LIST_LONG_ONLY), ('advertise_fixed_ips', "Advertise Port's Fixed IPs", column_util.LIST_LONG_ONLY), ) _formatters = { 'prefix_routes': format_columns.ListColumn, 'bgpvpn_routes': format_columns.ListColumn, } def _transform_resource(self, data): """Transforms BGP VPN port association routes property That permits to easily format the command output with ListColumn formater and separate the two route types. {'routes': [ { 'type': 'prefix', 'local_pref': 100, 'prefix': '8.8.8.0/27', }, { 'type': 'prefix', 'local_pref': 42, 'prefix': '80.50.30.0/28', }, { 'type': 'bgpvpn', 'local_pref': 50, 'bgpvpn': '157d72a9-9968-48e7-8087-6c9a9bc7a181', }, { 'type': 'bgpvpn', 'bgpvpn': 'd5c7aaab-c7e8-48b3-85ca-a115c00d3603', }, ], } to { 'prefix_routes': [ '8.8.8.0/27 (100)', '80.50.30.0/28 (42)', ], 'bgpvpn_routes': [ '157d72a9-9968-48e7-8087-6c9a9bc7a181 (50)', 'd5c7aaab-c7e8-48b3-85ca-a115c00d3603', ], } """ for route in data.get('routes', []): local_pref = '' if route.get('local_pref'): local_pref = ' (%d)' % route.get('local_pref') if route['type'] == 'prefix': data.setdefault('prefix_routes', []).append( '%s%s' % (route['prefix'], local_pref) ) elif route['type'] == 'bgpvpn': data.setdefault('bgpvpn_routes', []).append( '%s%s' % (route['bgpvpn_id'], local_pref) ) else: LOG.warning("Unknown route type %s (%s).", route['type'], route) data.pop('routes', None) return data def _get_common_parser(self, parser): """Adds to parser arguments common to create, set and unset commands. :params ArgumentParser parser: argparse object contains all command's arguments """ ADVERTISE_ROUTE = _("Fixed IPs of the port will be advertised to the " "BGP VPN%s") % ( _(' (default)') if self._action == 'create' else "") NOT_ADVERTISE_ROUTE = _("Fixed IPs of the port will not be advertised " "to the BGP VPN") LOCAL_PREF_VALUE = _(". Optionally, can control the value of the BGP " "LOCAL_PREF of the routes that will be " "advertised") ADD_PREFIX_ROUTE = _("Add prefix route in CIDR notation%s") %\ LOCAL_PREF_VALUE REMOVE_PREFIX_ROUTE = _("Remove prefix route in CIDR notation") REPEAT_PREFIX_ROUTE = _("repeat option for multiple prefix routes") ADD_BGVPVPN_ROUTE = _("Add BGP VPN route for route leaking%s") %\ LOCAL_PREF_VALUE REMOVE_BGPVPN_ROUTE = _("Remove BGP VPN route") REPEAT_BGPVPN_ROUTE = _("repeat option for multiple BGP VPN routes") group_advertise_fixed_ips = parser.add_mutually_exclusive_group() group_advertise_fixed_ips.add_argument( '--advertise-fixed-ips', action='store_true', help=NOT_ADVERTISE_ROUTE if self._action == 'unset' else ADVERTISE_ROUTE, ) group_advertise_fixed_ips.add_argument( '--no-advertise-fixed-ips', action='store_true', help=ADVERTISE_ROUTE if self._action == 'unset' else NOT_ADVERTISE_ROUTE, ) if self._action in ['create', 'set']: parser.add_argument( '--prefix-route', metavar="prefix=[,local_pref=]", dest='prefix_routes', action=parseractions.MultiKeyValueAction, required_keys=['prefix'], optional_keys=['local_pref'], help="%s (%s)" % (ADD_PREFIX_ROUTE, REPEAT_PREFIX_ROUTE), ) parser.add_argument( '--bgpvpn-route', metavar="bgpvpn=[,local_pref=]", dest='bgpvpn_routes', action=parseractions.MultiKeyValueAction, required_keys=['bgpvpn'], optional_keys=['local_pref'], help="%s (%s)" % (ADD_BGVPVPN_ROUTE, REPEAT_BGPVPN_ROUTE), ) else: parser.add_argument( '--prefix-route', metavar="", dest='prefix_routes', action='append', help="%s (%s)" % (REMOVE_PREFIX_ROUTE, REPEAT_PREFIX_ROUTE), ) parser.add_argument( '--bgpvpn-route', metavar="", dest='bgpvpn_routes', action='append', help="%s (%s)" % (REMOVE_BGPVPN_ROUTE, REPEAT_BGPVPN_ROUTE), ) if self._action != 'create': parser.add_argument( '--no-prefix-route' if self._action == 'set' else '--all-prefix-routes', dest='purge_prefix_route', action='store_true', help=_('Empty prefix route list'), ) parser.add_argument( '--no-bgpvpn-route' if self._action == 'set' else '--all-bgpvpn-routes', dest='purge_bgpvpn_route', action='store_true', help=_('Empty BGP VPN route list'), ) def _args2body(self, bgpvpn_id, args): client = self.app.client_manager.network attrs = {} if self._action != 'create': assoc = client.find_bgpvpn_port_association( args.resource_association_id, bgpvpn_id=bgpvpn_id) else: assoc = {'routes': []} if args.advertise_fixed_ips: attrs['advertise_fixed_ips'] = self._action != 'unset' elif args.no_advertise_fixed_ips: attrs['advertise_fixed_ips'] = self._action == 'unset' prefix_routes = None if 'purge_prefix_route' in args and args.purge_prefix_route: prefix_routes = [] else: prefix_routes = {r['prefix']: r.get('local_pref') for r in assoc['routes'] if r['type'] == 'prefix'} if args.prefix_routes: if self._action in ['create', 'set']: prefix_routes.update({r['prefix']: r.get('local_pref') for r in args.prefix_routes}) elif self._action == 'unset': for prefix in args.prefix_routes: prefix_routes.pop(prefix, None) bgpvpn_routes = None if 'purge_bgpvpn_route' in args and args.purge_bgpvpn_route: bgpvpn_routes = [] else: bgpvpn_routes = {r['bgpvpn_id']: r.get('local_pref') for r in assoc['routes'] if r['type'] == 'bgpvpn'} if args.bgpvpn_routes: if self._action == 'unset': routes = [ {'bgpvpn': bgpvpn} for bgpvpn in args.bgpvpn_routes ] else: routes = args.bgpvpn_routes args_bgpvpn_routes = { client.find_bgpvpn(r['bgpvpn']).id: r.get('local_pref') for r in routes } if self._action in ['create', 'set']: bgpvpn_routes.update(args_bgpvpn_routes) elif self._action == 'unset': for bgpvpn_id in args_bgpvpn_routes: bgpvpn_routes.pop(bgpvpn_id, None) if prefix_routes is not None and not prefix_routes: attrs.setdefault('routes', []) elif prefix_routes is not None: for prefix, local_pref in prefix_routes.items(): route = { 'type': 'prefix', 'prefix': prefix, } if local_pref: route['local_pref'] = int(local_pref) attrs.setdefault('routes', []).append(route) if bgpvpn_routes is not None and not bgpvpn_routes: attrs.setdefault('routes', []) elif bgpvpn_routes is not None: for bgpvpn_id, local_pref in bgpvpn_routes.items(): route = { 'type': 'bgpvpn', 'bgpvpn_id': bgpvpn_id, } if local_pref: route['local_pref'] = int(local_pref) attrs.setdefault('routes', []).append(route) return attrs class CreateBgpvpnPortAssoc(BgpvpnPortAssoc, resource_association.CreateBgpvpnResAssoc): _description = _("Create a BGP VPN port association") class SetBgpvpnPortAssoc(BgpvpnPortAssoc, resource_association.SetBgpvpnResAssoc): _description = _("Set BGP VPN port association properties") class UnsetBgpvpnPortAssoc(BgpvpnPortAssoc, resource_association.UnsetBgpvpnResAssoc): _description = _("Unset BGP VPN port association properties") class DeleteBgpvpnPortAssoc(BgpvpnPortAssoc, resource_association.DeleteBgpvpnResAssoc): _description = _("Delete a BGP VPN port association(s) for a given BGP " "VPN") class ListBgpvpnPortAssoc(BgpvpnPortAssoc, resource_association.ListBgpvpnResAssoc): _description = _("List BGP VPN port associations for a given BGP VPN") class ShowBgpvpnPortAssoc(BgpvpnPortAssoc, resource_association.ShowBgpvpnResAssoc): _description = _("Show information of a given BGP VPN port association") ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/networking_bgpvpn/resource_association.py0000664000175000017500000002620200000000000032374 0ustar00zuulzuul00000000000000# Copyright (c) 2016 Juniper Networks Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # import logging 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 osc_lib.utils import columns as column_util from neutronclient._i18n import _ from neutronclient.osc import utils as nc_osc_utils from neutronclient.osc.v2.networking_bgpvpn import constants LOG = logging.getLogger(__name__) class CreateBgpvpnResAssoc(command.ShowOne): """Create a BGP VPN resource association""" _action = 'create' def get_parser(self, prog_name): parser = super(CreateBgpvpnResAssoc, self).get_parser(prog_name) nc_osc_utils.add_project_owner_option_to_parser(parser) parser.add_argument( 'bgpvpn', metavar="", help=(_("BGP VPN to apply the %s association (name or ID)") % self._assoc_res_name), ) parser.add_argument( 'resource', metavar="<%s>" % self._assoc_res_name, help=(_("%s to associate the BGP VPN (name or ID)") % self._assoc_res_name.capitalize()), ) get_common_parser = getattr(self, '_get_common_parser', None) if callable(get_common_parser): get_common_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) find_res_method = getattr( client, 'find_%s' % self._assoc_res_name) assoc_res = find_res_method(parsed_args.resource) body = {'%s_id' % self._assoc_res_name: assoc_res['id']} if 'project' in parsed_args and parsed_args.project is not None: project_id = nc_osc_utils.find_project( self.app.client_manager.identity, parsed_args.project, parsed_args.project_domain, ).id body['tenant_id'] = project_id arg2body = getattr(self, '_args2body', None) if callable(arg2body): body.update( arg2body(bgpvpn['id'], parsed_args)) if self._assoc_res_name == constants.NETWORK_ASSOC: obj = client.create_bgpvpn_network_association( bgpvpn['id'], **body) elif self._assoc_res_name == constants.PORT_ASSOCS: obj = client.create_bgpvpn_port_association(bgpvpn['id'], **body) else: obj = client.create_bgpvpn_router_association( bgpvpn['id'], **body) transform = getattr(self, '_transform_resource', None) if callable(transform): transform(obj) display_columns, columns = nc_osc_utils._get_columns(obj) data = osc_utils.get_dict_properties(obj, columns, formatters=self._formatters) return display_columns, data class SetBgpvpnResAssoc(command.Command): """Set BGP VPN resource association properties""" _action = 'set' def get_parser(self, prog_name): parser = super(SetBgpvpnResAssoc, self).get_parser(prog_name) parser.add_argument( 'resource_association_id', metavar="<%s association ID>" % self._assoc_res_name, help=(_("%s association ID to update") % self._assoc_res_name.capitalize()), ) parser.add_argument( 'bgpvpn', metavar="", help=(_("BGP VPN the %s association belongs to (name or ID)") % self._assoc_res_name), ) get_common_parser = getattr(self, '_get_common_parser', None) if callable(get_common_parser): get_common_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) arg2body = getattr(self, '_args2body', None) if callable(arg2body): body = arg2body(bgpvpn['id'], parsed_args) if self._assoc_res_name == constants.NETWORK_ASSOC: client.update_bgpvpn_network_association( bgpvpn['id'], parsed_args.resource_association_id, **body) elif self._assoc_res_name == constants.PORT_ASSOCS: client.update_bgpvpn_port_association( bgpvpn['id'], parsed_args.resource_association_id, **body) else: client.update_bgpvpn_router_association( bgpvpn['id'], parsed_args.resource_association_id, **body) class UnsetBgpvpnResAssoc(SetBgpvpnResAssoc): """Unset BGP VPN resource association properties""" _action = 'unset' class DeleteBgpvpnResAssoc(command.Command): """Remove a BGP VPN resource association(s) for a given BGP VPN""" def get_parser(self, prog_name): parser = super(DeleteBgpvpnResAssoc, self).get_parser(prog_name) parser.add_argument( 'resource_association_ids', metavar="<%s association ID>" % self._assoc_res_name, nargs="+", help=(_("%s association ID(s) to remove") % self._assoc_res_name.capitalize()), ) parser.add_argument( 'bgpvpn', metavar="", help=(_("BGP VPN the %s association belongs to (name or ID)") % self._assoc_res_name), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) fails = 0 for id in parsed_args.resource_association_ids: try: if self._assoc_res_name == constants.NETWORK_ASSOC: client.delete_bgpvpn_network_association(bgpvpn['id'], id) elif self._assoc_res_name == constants.PORT_ASSOCS: client.delete_bgpvpn_port_association(bgpvpn['id'], id) else: client.delete_bgpvpn_router_association(bgpvpn['id'], id) LOG.warning( "%(assoc_res_name)s association %(id)s deleted", {'assoc_res_name': self._assoc_res_name.capitalize(), 'id': id}) except Exception as e: fails += 1 LOG.error("Failed to delete %(assoc_res_name)s " "association with ID '%(id)s': %(e)s", {'assoc_res_name': self._assoc_res_name, 'id': id, 'e': e}) if fails > 0: msg = (_("Failed to delete %(fails)s of %(total)s " "%(assoc_res_name)s BGP VPN association(s).") % {'fails': fails, 'total': len(parsed_args.resource_association_ids), 'assoc_res_name': self._assoc_res_name}) raise exceptions.CommandError(msg) class ListBgpvpnResAssoc(command.Lister): """List BGP VPN resource associations for a given BGP VPN""" def get_parser(self, prog_name): parser = super(ListBgpvpnResAssoc, self).get_parser(prog_name) parser.add_argument( 'bgpvpn', metavar="", help=_("BGP VPN listed associations belong to (name or ID)"), ) parser.add_argument( '--long', action='store_true', help=_("List additional fields in output"), ) parser.add_argument( '--property', metavar="", help=_("Filter property to apply on returned BGP VPNs (repeat to " "filter on multiple properties)"), action=parseractions.KeyValueAction, ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) params = {} if parsed_args.property: params.update(parsed_args.property) if self._assoc_res_name == constants.NETWORK_ASSOC: objs = client.bgpvpn_network_associations( bgpvpn['id'], retrieve_all=True, **params) elif self._assoc_res_name == constants.PORT_ASSOCS: objs = client.bgpvpn_port_associations( bgpvpn['id'], retrieve_all=True, **params) else: objs = client.bgpvpn_router_associations( bgpvpn['id'], retrieve_all=True, **params) transform = getattr(self, '_transform_resource', None) transformed_objs = [] if callable(transform): for obj in objs: transformed_objs.append(transform(obj)) else: transformed_objs = list(objs) headers, columns = column_util.get_column_definitions( self._attr_map, long_listing=parsed_args.long) return (headers, (osc_utils.get_dict_properties( s, columns, formatters=self._formatters) for s in transformed_objs)) class ShowBgpvpnResAssoc(command.ShowOne): """Show information of a given BGP VPN resource association""" def get_parser(self, prog_name): parser = super(ShowBgpvpnResAssoc, self).get_parser(prog_name) parser.add_argument( 'resource_association_id', metavar="<%s association ID>" % self._assoc_res_name, help=(_("%s association ID to look up") % self._assoc_res_name.capitalize()), ) parser.add_argument( 'bgpvpn', metavar="", help=_("BGP VPN the association belongs to (name or ID)"), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) if self._assoc_res_name == constants.NETWORK_ASSOC: obj = client.get_bgpvpn_network_association( bgpvpn['id'], parsed_args.resource_association_id) elif self._assoc_res_name == constants.PORT_ASSOCS: obj = client.get_bgpvpn_port_association( bgpvpn['id'], parsed_args.resource_association_id) else: obj = client.get_bgpvpn_router_association( bgpvpn['id'], parsed_args.resource_association_id) transform = getattr(self, '_transform_resource', None) if callable(transform): transform(obj) display_columns, columns = nc_osc_utils._get_columns(obj) data = osc_utils.get_dict_properties(obj, columns, formatters=self._formatters) return display_columns, data ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/networking_bgpvpn/router_association.py0000664000175000017500000001034100000000000032062 0ustar00zuulzuul00000000000000# Copyright (c) 2016 Juniper networks Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # from osc_lib.utils import columns as column_util from neutronclient._i18n import _ from neutronclient.osc.v2.networking_bgpvpn import constants from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ CreateBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ DeleteBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ ListBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ SetBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ ShowBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ UnsetBgpvpnResAssoc class BgpvpnRouterAssoc(object): _assoc_res_name = constants.ROUTER_RESOURCE_NAME _resource = constants.ROUTER_ASSOC _resource_plural = constants.ROUTER_ASSOCS _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), column_util.LIST_BOTH), ('advertise_extra_routes', 'Advertise extra routes', column_util.LIST_LONG_ONLY), ) _formatters = {} def _get_common_parser(self, parser): """Adds to parser arguments common to create, set and unset commands. :params ArgumentParser parser: argparse object contains all command's arguments """ ADVERTISE_ROUTES = _("Routes will be advertised to the " "BGP VPN%s") % ( _(' (default)') if self._action == 'create' else "") NOT_ADVERTISE_ROUTES = _("Routes from the router will not be " "advertised to the BGP VPN") group_advertise_extra_routes = parser.add_mutually_exclusive_group() group_advertise_extra_routes.add_argument( '--advertise_extra_routes', action='store_true', help=NOT_ADVERTISE_ROUTES if self._action == 'unset' else ADVERTISE_ROUTES, ) group_advertise_extra_routes.add_argument( '--no-advertise_extra_routes', action='store_true', help=ADVERTISE_ROUTES if self._action == 'unset' else NOT_ADVERTISE_ROUTES, ) def _args2body(self, _, args): attrs = {'advertise_extra_routes': False} if args.advertise_extra_routes: attrs['advertise_extra_routes'] = self._action != 'unset' elif args.no_advertise_extra_routes: attrs['advertise_extra_routes'] = self._action == 'unset' return attrs class CreateBgpvpnRouterAssoc(BgpvpnRouterAssoc, CreateBgpvpnResAssoc): _description = _("Create a BGP VPN router association") pass class SetBgpvpnRouterAssoc(BgpvpnRouterAssoc, SetBgpvpnResAssoc): _description = _("Set BGP VPN router association properties") class UnsetBgpvpnRouterAssoc(BgpvpnRouterAssoc, UnsetBgpvpnResAssoc): _description = _("Unset BGP VPN router association properties") class DeleteBgpvpnRouterAssoc(BgpvpnRouterAssoc, DeleteBgpvpnResAssoc): _description = _("Delete a BGP VPN router association(s) for a given BGP " "VPN") pass class ListBgpvpnRouterAssoc(BgpvpnRouterAssoc, ListBgpvpnResAssoc): _description = _("List BGP VPN router associations for a given BGP VPN") pass class ShowBgpvpnRouterAssoc(BgpvpnRouterAssoc, ShowBgpvpnResAssoc): _description = _("Show information of a given BGP VPN router association") pass ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1709201317.221662 python-neutronclient-11.2.0/neutronclient/osc/v2/sfc/0000775000175000017500000000000000000000000022605 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/sfc/__init__.py0000664000175000017500000000000000000000000024704 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/sfc/sfc_flow_classifier.py0000775000175000017500000003311100000000000027167 0ustar00zuulzuul00000000000000# Copyright (c) 2017 Huawei Technologies India Pvt.Limited. # 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 logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from neutronclient._i18n import _ from neutronclient.common import exceptions as nc_exc LOG = logging.getLogger(__name__) resource = 'flow_classifier' _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('summary', 'Summary', column_util.LIST_SHORT_ONLY), ('protocol', 'Protocol', column_util.LIST_LONG_ONLY), ('ethertype', 'Ethertype', column_util.LIST_LONG_ONLY), ('source_ip_prefix', 'Source IP', column_util.LIST_LONG_ONLY), ('destination_ip_prefix', 'Destination IP', column_util.LIST_LONG_ONLY), ('logical_source_port', 'Logical Source Port', column_util.LIST_LONG_ONLY), ('logical_destination_port', 'Logical Destination Port', column_util.LIST_LONG_ONLY), ('source_port_range_min', 'Source Port Range Min', column_util.LIST_LONG_ONLY), ('source_port_range_max', 'Source Port Range Max', column_util.LIST_LONG_ONLY), ('destination_port_range_min', 'Destination Port Range Min', column_util.LIST_LONG_ONLY), ('destination_port_range_max', 'Destination Port Range Max', column_util.LIST_LONG_ONLY), ('l7_parameters', 'L7 Parameters', column_util.LIST_LONG_ONLY), ('description', 'Description', column_util.LIST_LONG_ONLY), ('project_id', 'Project', column_util.LIST_LONG_ONLY), ) _attr_map_dict = { 'id': 'ID', 'name': 'Name', 'description': 'Description', 'summary': 'Summary', 'protocol': 'Protocol', 'ethertype': 'Ethertype', 'source_ip_prefix': 'Source IP', 'destination_ip_prefix': 'Destination IP', 'logical_source_port': 'Logical Source Port', 'logical_destination_port': 'Logical Destination Port', 'source_port_range_min': 'Source Port Range Min', 'source_port_range_max': 'Source Port Range Max', 'destination_port_range_min': 'Destination Port Range Min', 'destination_port_range_max': 'Destination Port Range Max', 'l7_parameters': 'L7 Parameters', 'tenant_id': 'Project', 'project_id': 'Project', } class CreateSfcFlowClassifier(command.ShowOne): _description = _("Create a flow classifier") def get_parser(self, prog_name): parser = super(CreateSfcFlowClassifier, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('Name of the flow classifier')) parser.add_argument( '--description', metavar='', help=_('Description for the flow classifier')) parser.add_argument( '--protocol', metavar='', help=_('IP protocol name. Protocol name should be as per ' 'IANA standard.')) parser.add_argument( '--ethertype', metavar='{IPv4,IPv6}', default='IPv4', choices=['IPv4', 'IPv6'], help=_('L2 ethertype, default is IPv4')) parser.add_argument( '--source-port', metavar=':', help=_('Source protocol port (allowed range [1,65535]. Must be ' 'specified as a:b, where a=min-port and b=max-port) ' 'in the allowed range.')) parser.add_argument( '--destination-port', metavar=':', help=_('Destination protocol port (allowed range [1,65535]. Must ' 'be specified as a:b, where a=min-port and b=max-port) ' 'in the allowed range.')) parser.add_argument( '--source-ip-prefix', metavar='', help=_('Source IP address in CIDR notation')) parser.add_argument( '--destination-ip-prefix', metavar='', help=_('Destination IP address in CIDR notation')) parser.add_argument( '--logical-source-port', metavar='', help=_('Neutron source port (name or ID)')) parser.add_argument( '--logical-destination-port', metavar='', help=_('Neutron destination port (name or ID)')) parser.add_argument( '--l7-parameters', help=_('Dictionary of L7 parameters. Currently, no value is ' 'supported for this option.')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) obj = client.create_sfc_flow_classifier(**attrs) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id', 'summary']) data = utils.get_dict_properties(obj, columns) return display_columns, data class DeleteSfcFlowClassifier(command.Command): _description = _("Delete a given flow classifier") def get_parser(self, prog_name): parser = super(DeleteSfcFlowClassifier, self).get_parser(prog_name) parser.add_argument( 'flow_classifier', metavar='', nargs='+', help=_("Flow classifier(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for fcl in parsed_args.flow_classifier: try: fc_id = client.find_sfc_flow_classifier( fcl, ignore_missing=False)['id'] client.delete_sfc_flow_classifier(fc_id) except Exception as e: result += 1 LOG.error(_("Failed to delete flow classifier with name " "or ID '%(fc)s': %(e)s"), {'fc': fcl, 'e': e}) if result > 0: total = len(parsed_args.flow_classifier) msg = (_("%(result)s of %(total)s flow classifier(s) " "failed to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListSfcFlowClassifier(command.Lister): _description = _("List flow classifiers") def get_parser(self, prog_name): parser = super(ListSfcFlowClassifier, self).get_parser(prog_name) parser.add_argument( '--long', action='store_true', help=_("List additional fields in output") ) return parser def extend_list(self, data, parsed_args): ext_data = [] for d in data: val = [] protocol = d['protocol'].upper() if d['protocol'] else 'any' val.append('protocol: ' + protocol) val.append(self._get_protocol_port_details(d, 'source')) val.append(self._get_protocol_port_details(d, 'destination')) if 'logical_source_port' in d: val.append('neutron_source_port: ' + str(d['logical_source_port'])) if 'logical_destination_port' in d: val.append('neutron_destination_port: ' + str(d['logical_destination_port'])) if 'l7_parameters' in d: l7_param = 'l7_parameters: {%s}' % ','.join(d['l7_parameters']) val.append(l7_param) d['summary'] = ',\n'.join(val) ext_data.append(d) return ext_data def _get_protocol_port_details(self, data, val): type_ip_prefix = val + '_ip_prefix' ip_prefix = data.get(type_ip_prefix) if not ip_prefix: ip_prefix = 'any' min_port = data.get(val + '_port_range_min') if min_port is None: min_port = 'any' max_port = data.get(val + '_port_range_max') if max_port is None: max_port = 'any' return '%s[port]: %s[%s:%s]' % ( val, ip_prefix, min_port, max_port) def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.sfc_flow_classifiers() obj_extend = self.extend_list(obj, parsed_args) headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties( s, columns) for s in obj_extend)) class SetSfcFlowClassifier(command.Command): _description = _("Set flow classifier properties") def get_parser(self, prog_name): parser = super(SetSfcFlowClassifier, self).get_parser(prog_name) parser.add_argument( '--name', metavar='', help=_('Name of the flow classifier')) parser.add_argument( '--description', metavar='', help=_('Description for the flow classifier')) parser.add_argument( 'flow_classifier', metavar='', help=_("Flow classifier to modify (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network fc_id = client.find_sfc_flow_classifier(parsed_args.flow_classifier, ignore_missing=False)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) try: client.update_sfc_flow_classifier(fc_id, **attrs) except Exception as e: msg = (_("Failed to update flow classifier '%(fc)s': %(e)s") % {'fc': parsed_args.flow_classifier, 'e': e}) raise exceptions.CommandError(msg) class ShowSfcFlowClassifier(command.ShowOne): _description = _("Display flow classifier details") def get_parser(self, prog_name): parser = super(ShowSfcFlowClassifier, self).get_parser(prog_name) parser.add_argument( 'flow_classifier', metavar='', help=_("Flow classifier to display (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network fc_id = client.find_sfc_flow_classifier(parsed_args.flow_classifier, ignore_missing=False)['id'] obj = client.get_sfc_flow_classifier(fc_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id', 'summary']) data = utils.get_dict_properties(obj, columns) return display_columns, data def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} if parsed_args.name is not None: attrs['name'] = parsed_args.name if parsed_args.description is not None: attrs['description'] = parsed_args.description if is_create: _get_attrs(client_manager, attrs, parsed_args) return attrs def _get_attrs(client_manager, attrs, parsed_args): if parsed_args.protocol is not None: attrs['protocol'] = parsed_args.protocol if parsed_args.ethertype: attrs['ethertype'] = parsed_args.ethertype if parsed_args.source_ip_prefix is not None: attrs['source_ip_prefix'] = parsed_args.source_ip_prefix if parsed_args.destination_ip_prefix is not None: attrs['destination_ip_prefix'] = parsed_args.destination_ip_prefix if parsed_args.logical_source_port is not None: attrs['logical_source_port'] = client_manager.network.find_port( parsed_args.logical_source_port, ignore_missing=False )['id'] if parsed_args.logical_destination_port is not None: attrs['logical_destination_port'] = client_manager.network.find_port( parsed_args.logical_destination_port, ignore_missing=False )['id'] if parsed_args.source_port is not None: _fill_protocol_port_info(attrs, 'source', parsed_args.source_port) if parsed_args.destination_port is not None: _fill_protocol_port_info(attrs, 'destination', parsed_args.destination_port) if parsed_args.l7_parameters is not None: attrs['l7_parameters'] = parsed_args.l7_parameters def _fill_protocol_port_info(attrs, port_type, port_val): min_port, sep, max_port = port_val.partition(":") if not min_port: msg = ("Invalid port value '%s', expected format is " "min-port:max-port or min-port.") raise argparse.ArgumentTypeError(msg % port_val) if not max_port: max_port = min_port try: attrs[port_type + '_port_range_min'] = int(min_port) attrs[port_type + '_port_range_max'] = int(max_port) except ValueError: message = (_("Protocol port value %s must be an integer " "or integer:integer.") % port_val) raise nc_exc.CommandError(message=message) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/sfc/sfc_port_chain.py0000775000175000017500000003547600000000000026162 0ustar00zuulzuul00000000000000# Copyright (c) 2017 Huawei Technologies India Pvt.Limited. # 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 logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from neutronclient._i18n import _ LOG = logging.getLogger(__name__) resource = 'port_chain' _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('port_pair_groups', 'Port Pair Groups', column_util.LIST_BOTH), ('flow_classifiers', 'Flow Classifiers', column_util.LIST_BOTH), ('chain_parameters', 'Chain Parameters', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), ('project_id', 'Project', column_util.LIST_LONG_ONLY), ) _attr_map_dict = { 'id': 'ID', 'name': 'Name', 'port_pair_groups': 'Port Pair Groups', 'flow_classifiers': 'Flow Classifiers', 'chain_parameters': 'Chain Parameters', 'description': 'Description', 'tenant_id': 'Project', 'project_id': 'Project', } class CreateSfcPortChain(command.ShowOne): _description = _("Create a port chain") def get_parser(self, prog_name): parser = super(CreateSfcPortChain, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('Name of the port chain')) parser.add_argument( '--description', metavar='', help=_('Description for the port chain')) parser.add_argument( '--flow-classifier', default=[], metavar='', dest='flow_classifiers', action='append', help=_('Add flow classifier (name or ID). ' 'This option can be repeated.')) parser.add_argument( '--chain-parameters', metavar='correlation=,symmetric=', action=parseractions.MultiKeyValueAction, optional_keys=['correlation', 'symmetric'], help=_('Dictionary of chain parameters. Supports ' 'correlation=(mpls|nsh) (default is mpls) ' 'and symmetric=(true|false).')) parser.add_argument( '--port-pair-group', metavar='', dest='port_pair_groups', required=True, action='append', help=_('Add port pair group (name or ID). ' 'This option can be repeated.')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) obj = client.create_sfc_port_chain(**attrs) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data class DeleteSfcPortChain(command.Command): _description = _("Delete a given port chain") def get_parser(self, prog_name): parser = super(DeleteSfcPortChain, self).get_parser(prog_name) parser.add_argument( 'port_chain', metavar="", nargs='+', help=_("Port chain(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for pc in parsed_args.port_chain: try: pc_id = client.find_sfc_port_chain( pc, ignore_missing=False)['id'] client.delete_sfc_port_chain(pc_id) except Exception as e: result += 1 LOG.error(_("Failed to delete port chain with name " "or ID '%(pc)s': %(e)s"), {'pc': pc, 'e': e}) if result > 0: total = len(parsed_args.port_chain) msg = (_("%(result)s of %(total)s port chain(s) " "failed to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListSfcPortChain(command.Lister): _description = _("List port chains") def get_parser(self, prog_name): parser = super(ListSfcPortChain, 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.network data = client.sfc_port_chains() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties(s, columns) for s in data)) class SetSfcPortChain(command.Command): _description = _("Set port chain properties") def get_parser(self, prog_name): parser = super(SetSfcPortChain, self).get_parser(prog_name) parser.add_argument( '--name', metavar='', help=_('Name of the port chain')) parser.add_argument( '--description', metavar='', help=_('Description for the port chain')) parser.add_argument( '--flow-classifier', metavar='', dest='flow_classifiers', action='append', help=_('Add flow classifier (name or ID). ' 'This option can be repeated.')) parser.add_argument( '--no-flow-classifier', action='store_true', help=_('Remove associated flow classifiers from the port chain')) parser.add_argument( '--port-pair-group', metavar='', dest='port_pair_groups', action='append', help=_('Add port pair group (name or ID). ' 'Current port pair groups order is kept, the added port ' 'pair group will be placed at the end of the port chain. ' 'This option can be repeated.')) parser.add_argument( '--no-port-pair-group', action='store_true', help=_('Remove associated port pair groups from the port chain. ' 'At least one --port-pair-group must be specified ' 'together.')) parser.add_argument( 'port_chain', metavar='', help=_("Port chain to modify (name or ID)")) return parser def take_action(self, parsed_args): client = self.app.client_manager.network pc_id = client.find_sfc_port_chain(parsed_args.port_chain, ignore_missing=False)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.no_flow_classifier: attrs['flow_classifiers'] = [] if parsed_args.flow_classifiers: if parsed_args.no_flow_classifier: fc_list = [] else: fc_list = client.find_sfc_port_chain( parsed_args.port_chain, ignore_missing=False )['flow_classifiers'] for fc in parsed_args.flow_classifiers: fc_id = client.find_sfc_flow_classifier( fc, ignore_missing=False)['id'] if fc_id not in fc_list: fc_list.append(fc_id) attrs['flow_classifiers'] = fc_list if (parsed_args.no_port_pair_group and not parsed_args.port_pair_groups): message = _('At least one --port-pair-group must be specified.') raise exceptions.CommandError(message) if parsed_args.no_port_pair_group and parsed_args.port_pair_groups: ppg_list = [] for ppg in parsed_args.port_pair_groups: ppg_id = client.find_sfc_port_pair_group( ppg, ignore_missing=False)['id'] if ppg_id not in ppg_list: ppg_list.append(ppg_id) attrs['port_pair_groups'] = ppg_list if (parsed_args.port_pair_groups and not parsed_args.no_port_pair_group): ppg_list = client.find_sfc_port_chain( parsed_args.port_chain, ignore_missing=False )['port_pair_groups'] for ppg in parsed_args.port_pair_groups: ppg_id = client.find_sfc_port_pair_group( ppg, ignore_missing=False)['id'] if ppg_id not in ppg_list: ppg_list.append(ppg_id) attrs['port_pair_groups'] = ppg_list try: client.update_sfc_port_chain(pc_id, **attrs) except Exception as e: msg = (_("Failed to update port chain '%(pc)s': %(e)s") % {'pc': parsed_args.port_chain, 'e': e}) raise exceptions.CommandError(msg) class ShowSfcPortChain(command.ShowOne): _description = _("Display port chain details") def get_parser(self, prog_name): parser = super(ShowSfcPortChain, self).get_parser(prog_name) parser.add_argument( 'port_chain', metavar="", help=_("Port chain to display (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network pc_id = client.find_sfc_port_chain(parsed_args.port_chain, ignore_missing=False)['id'] obj = client.get_sfc_port_chain(pc_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data class UnsetSfcPortChain(command.Command): _description = _("Unset port chain properties") def get_parser(self, prog_name): parser = super(UnsetSfcPortChain, self).get_parser(prog_name) parser.add_argument( 'port_chain', metavar='', help=_("Port chain to unset (name or ID)")) port_chain = parser.add_mutually_exclusive_group() port_chain.add_argument( '--flow-classifier', action='append', metavar='', dest='flow_classifiers', help=_('Remove flow classifier(s) from the port chain ' '(name or ID). This option can be repeated.')) port_chain.add_argument( '--all-flow-classifier', action='store_true', help=_('Remove all flow classifiers from the port chain')) parser.add_argument( '--port-pair-group', metavar='', dest='port_pair_groups', action='append', help=_('Remove port pair group(s) from the port chain ' '(name or ID). This option can be repeated.')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network pc_id = client.find_sfc_port_chain(parsed_args.port_chain, ignore_missing=False)['id'] attrs = {} if parsed_args.flow_classifiers: fc_list = client.find_sfc_port_chain( parsed_args.port_chain, ignore_missing=False )['flow_classifiers'] for fc in parsed_args.flow_classifiers: fc_id = client.find_sfc_flow_classifier( fc, ignore_missing=False)['id'] if fc_id in fc_list: fc_list.remove(fc_id) attrs['flow_classifiers'] = fc_list if parsed_args.all_flow_classifier: attrs['flow_classifiers'] = [] if parsed_args.port_pair_groups: ppg_list = client.find_sfc_port_chain( parsed_args.port_chain, ignore_missing=False)['port_pair_groups'] for ppg in parsed_args.port_pair_groups: ppg_id = client.find_sfc_port_pair_group( ppg, ignore_missing=False)['id'] if ppg_id in ppg_list: ppg_list.remove(ppg_id) if ppg_list == []: message = _('At least one port pair group must be' ' specified.') raise exceptions.CommandError(message) attrs['port_pair_groups'] = ppg_list try: client.update_sfc_port_chain(pc_id, **attrs) except Exception as e: msg = (_("Failed to unset port chain '%(pc)s': %(e)s") % {'pc': parsed_args.port_chain, 'e': e}) raise exceptions.CommandError(msg) def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} client = client_manager.network if parsed_args.name is not None: attrs['name'] = parsed_args.name if parsed_args.description is not None: attrs['description'] = parsed_args.description if parsed_args.port_pair_groups: attrs['port_pair_groups'] = [client.find_sfc_port_pair_group( ppg, ignore_missing=False)['id'] for ppg in parsed_args.port_pair_groups] if parsed_args.flow_classifiers: attrs['flow_classifiers'] = [client.find_sfc_flow_classifier( fc, ignore_missing=False)['id'] for fc in parsed_args.flow_classifiers] if is_create is True: _get_attrs(attrs, parsed_args) return attrs def _get_attrs(attrs, parsed_args): if parsed_args.chain_parameters is not None: chain_params = {} for chain_param in parsed_args.chain_parameters: if 'correlation' in chain_param: chain_params['correlation'] = chain_param['correlation'] if 'symmetric' in chain_param: chain_params['symmetric'] = chain_param['symmetric'] attrs['chain_parameters'] = chain_params ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/sfc/sfc_port_pair.py0000775000175000017500000002171700000000000026024 0ustar00zuulzuul00000000000000# Copyright (c) 2017 Huawei Technologies India Pvt.Limited. # 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 logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from neutronclient._i18n import _ LOG = logging.getLogger(__name__) resource = 'port_pair' _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('ingress', 'Ingress Logical Port', column_util.LIST_BOTH), ('egress', 'Egress Logical Port', column_util.LIST_BOTH), ('service_function_parameters', 'Service Function Parameters', column_util.LIST_LONG_ONLY), ('description', 'Description', column_util.LIST_LONG_ONLY), ('project_id', 'Project', column_util.LIST_LONG_ONLY), ) _attr_map_dict = { 'id': 'ID', 'name': 'Name', 'description': 'Description', 'ingress': 'Ingress Logical Port', 'egress': 'Egress Logical Port', 'service_function_parameters': 'Service Function Parameters', 'tenant_id': 'Project', 'project_id': 'Project', } class CreateSfcPortPair(command.ShowOne): _description = _("Create a port pair") def get_parser(self, prog_name): parser = super(CreateSfcPortPair, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('Name of the port pair')) parser.add_argument( '--description', metavar='', help=_('Description for the port pair')) parser.add_argument( '--service-function-parameters', metavar='correlation=,weight=', action=parseractions.MultiKeyValueAction, optional_keys=['correlation', 'weight'], help=_('Dictionary of service function parameters. ' 'Currently, correlation=(None|mpls|nsh) and weight ' 'are supported. Weight is an integer that influences ' 'the selection of a port pair within a port pair group ' 'for a flow. The higher the weight, the more flows will ' 'hash to the port pair. The default weight is 1.')) parser.add_argument( '--ingress', metavar='', required=True, help=_('Ingress neutron port (name or ID)')) parser.add_argument( '--egress', metavar='', required=True, help=_('Egress neutron port (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) obj = client.create_sfc_port_pair(**attrs) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data class DeleteSfcPortPair(command.Command): _description = _("Delete a given port pair") def get_parser(self, prog_name): parser = super(DeleteSfcPortPair, self).get_parser(prog_name) parser.add_argument( 'port_pair', metavar="", nargs='+', help=_("Port pair(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for pp in parsed_args.port_pair: try: port_pair_id = client.find_sfc_port_pair( pp, ignore_missing=False)['id'] client.delete_sfc_port_pair(port_pair_id) except Exception as e: result += 1 LOG.error(_("Failed to delete port pair with name " "or ID '%(port_pair)s': %(e)s"), {'port_pair': pp, 'e': e}) if result > 0: total = len(parsed_args.port_pair) msg = (_("%(result)s of %(total)s port pair(s) " "failed to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListSfcPortPair(command.Lister): _description = _("List port pairs") def get_parser(self, prog_name): parser = super(ListSfcPortPair, 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.network data = client.sfc_port_pairs() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties( s, columns, ) for s in data)) class SetSfcPortPair(command.Command): _description = _("Set port pair properties") def get_parser(self, prog_name): parser = super(SetSfcPortPair, self).get_parser(prog_name) parser.add_argument( '--name', metavar='', help=_('Name of the port pair')) parser.add_argument( '--description', metavar='', help=_('Description for the port pair')) parser.add_argument( 'port_pair', metavar='', help=_("Port pair to modify (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network port_pair_id = client.find_sfc_port_pair( parsed_args.port_pair, ignore_missing=False )['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) try: client.update_sfc_port_pair(port_pair_id, **attrs) except Exception as e: msg = (_("Failed to update port pair '%(port_pair)s': %(e)s") % {'port_pair': parsed_args.port_pair, 'e': e}) raise exceptions.CommandError(msg) class ShowSfcPortPair(command.ShowOne): _description = _("Display port pair details") def get_parser(self, prog_name): parser = super(ShowSfcPortPair, self).get_parser(prog_name) parser.add_argument( 'port_pair', metavar='', help=_("Port pair to display (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network port_pair_id = client.find_sfc_port_pair( parsed_args.port_pair, ignore_missing=False )['id'] obj = client.get_sfc_port_pair(port_pair_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} if parsed_args.name is not None: attrs['name'] = parsed_args.name if parsed_args.description is not None: attrs['description'] = parsed_args.description if is_create: _get_attrs(client_manager, attrs, parsed_args) return attrs def _get_attrs(client_manager, attrs, parsed_args): client = client_manager.network if parsed_args.ingress is not None: attrs['ingress'] = client.find_port( parsed_args.ingress, ignore_missing=False )['id'] if parsed_args.egress is not None: attrs['egress'] = client.find_port( parsed_args.egress, ignore_missing=False )['id'] if parsed_args.service_function_parameters is not None: attrs['service_function_parameters'] = _get_service_function_params( parsed_args.service_function_parameters) def _get_service_function_params(sf_params): attrs = {} for sf_param in sf_params: if 'correlation' in sf_param: if sf_param['correlation'] == 'None': attrs['correlation'] = None else: attrs['correlation'] = sf_param['correlation'] if 'weight' in sf_param: attrs['weight'] = sf_param['weight'] return attrs ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/sfc/sfc_port_pair_group.py0000775000175000017500000003024100000000000027230 0ustar00zuulzuul00000000000000# Copyright (c) 2017 Huawei Technologies India Pvt.Limited. # 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 logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from neutronclient._i18n import _ LOG = logging.getLogger(__name__) resource = 'port_pair_group' _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('port_pairs', 'Port Pair', column_util.LIST_BOTH), ('port_pair_group_parameters', 'Port Pair Group Parameters', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), ('project_id', 'Project', column_util.LIST_LONG_ONLY), ('is_tap_enabled', 'Tap Enabled', column_util.LIST_BOTH) ) _attr_map_dict = { 'id': 'ID', 'name': 'Name', 'description': 'Description', 'port_pairs': 'Port Pair', 'port_pair_group_parameters': 'Port Pair Group Parameters', 'is_tap_enabled': 'Tap Enabled', 'tenant_id': 'Project', 'project_id': 'Project', } class CreateSfcPortPairGroup(command.ShowOne): _description = _("Create a port pair group") def get_parser(self, prog_name): parser = super(CreateSfcPortPairGroup, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('Name of the port pair group')) parser.add_argument( '--description', metavar='', help=_('Description for the port pair group')) parser.add_argument( '--port-pair', metavar='', dest='port_pairs', default=[], action='append', help=_('Port pair (name or ID). ' 'This option can be repeated.')) tap_enable = parser.add_mutually_exclusive_group() tap_enable.add_argument( '--enable-tap', action='store_true', help=_('Port pairs of this port pair group are deployed as ' 'passive tap service function') ) tap_enable.add_argument( '--disable-tap', action='store_true', help=_('Port pairs of this port pair group are deployed as l3 ' 'service function (default)') ) parser.add_argument( '--port-pair-group-parameters', metavar='lb-fields=', action=parseractions.KeyValueAction, help=_('Dictionary of port pair group parameters. ' 'Currently only one parameter lb-fields is supported. ' ' is a & separated list of load-balancing ' 'fields.')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) obj = client.create_sfc_port_pair_group(**attrs) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data class DeleteSfcPortPairGroup(command.Command): _description = _("Delete a given port pair group") def get_parser(self, prog_name): parser = super(DeleteSfcPortPairGroup, self).get_parser(prog_name) parser.add_argument( 'port_pair_group', metavar='', nargs='+', help=_("Port pair group(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for ppg in parsed_args.port_pair_group: try: ppg_id = client.find_sfc_port_pair_group( ppg, ignore_missing=False)['id'] client.delete_sfc_port_pair_group(ppg_id) except Exception as e: result += 1 LOG.error(_("Failed to delete port pair group with name " "or ID '%(ppg)s': %(e)s"), {'ppg': ppg, 'e': e}) if result > 0: total = len(parsed_args.port_pair_group) msg = (_("%(result)s of %(total)s port pair group(s) " "failed to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListSfcPortPairGroup(command.Lister): _description = _("List port pair group") def get_parser(self, prog_name): parser = super(ListSfcPortPairGroup, 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.network data = client.sfc_port_pair_groups() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties( s, columns, ) for s in data)) class SetSfcPortPairGroup(command.Command): _description = _("Set port pair group properties") def get_parser(self, prog_name): parser = super(SetSfcPortPairGroup, self).get_parser(prog_name) parser.add_argument( 'port_pair_group', metavar='', help=_("Port pair group to modify (name or ID)")) parser.add_argument( '--name', metavar='', help=_('Name of the port pair group')) parser.add_argument( '--description', metavar='', help=_('Description for the port pair group')) parser.add_argument( '--port-pair', metavar='', dest='port_pairs', default=[], action='append', help=_('Port pair (name or ID). ' 'This option can be repeated.')) parser.add_argument( '--no-port-pair', action='store_true', help=_('Remove all port pair from port pair group')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network ppg_id = client.find_sfc_port_pair_group( parsed_args.port_pair_group)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.no_port_pair: attrs['port_pairs'] = [] if parsed_args.port_pairs: added = [client.find_sfc_port_pair(pp, ignore_missing=False)['id'] for pp in parsed_args.port_pairs] if parsed_args.no_port_pair: existing = [] else: existing = client.find_sfc_port_pair_group( parsed_args.port_pair_group, ignore_missing=False)['port_pairs'] attrs['port_pairs'] = sorted(list(set(existing) | set(added))) try: client.update_sfc_port_pair_group(ppg_id, **attrs) except Exception as e: msg = (_("Failed to update port pair group '%(ppg)s': %(e)s") % {'ppg': parsed_args.port_pair_group, 'e': e}) raise exceptions.CommandError(msg) class ShowSfcPortPairGroup(command.ShowOne): _description = _("Display port pair group details") def get_parser(self, prog_name): parser = super(ShowSfcPortPairGroup, self).get_parser(prog_name) parser.add_argument( 'port_pair_group', metavar='', help=_("Port pair group to display (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network ppg_id = client.find_sfc_port_pair_group( parsed_args.port_pair_group, ignore_missing=False)['id'] obj = client.get_sfc_port_pair_group(ppg_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data class UnsetSfcPortPairGroup(command.Command): _description = _("Unset port pairs from port pair group") def get_parser(self, prog_name): parser = super(UnsetSfcPortPairGroup, self).get_parser(prog_name) parser.add_argument( 'port_pair_group', metavar='', help=_("Port pair group to unset (name or ID)")) port_pair_group = parser.add_mutually_exclusive_group() port_pair_group.add_argument( '--port-pair', action='append', metavar='', dest='port_pairs', help=_('Remove port pair(s) from the port pair group ' '(name or ID). This option can be repeated.')) port_pair_group.add_argument( '--all-port-pair', action='store_true', help=_('Remove all port pairs from the port pair group')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network ppg_id = client.find_sfc_port_pair_group( parsed_args.port_pair_group, ignore_missing=False)['id'] attrs = {} if parsed_args.port_pairs: existing = client.find_sfc_port_pair_group( parsed_args.port_pair_group, ignore_missing=False)['port_pairs'] removed = [client.find_sfc_port_pair(pp, ignore_missing=False)['id'] for pp in parsed_args.port_pairs] attrs['port_pairs'] = list(set(existing) - set(removed)) if parsed_args.all_port_pair: attrs['port_pairs'] = [] try: client.update_sfc_port_pair_group(ppg_id, **attrs) except Exception as e: msg = (_("Failed to unset port pair group '%(ppg)s': %(e)s") % {'ppg': parsed_args.port_pair_group, 'e': e}) raise exceptions.CommandError(msg) def _get_ppg_param(attrs, ppg): attrs['port_pair_group_parameters'] = {} for key, value in ppg.items(): if key == 'lb-fields': attrs['port_pair_group_parameters']['lb_fields'] = ([ field for field in value.split('&') if field]) else: attrs['port_pair_group_parameters'][key] = value return attrs['port_pair_group_parameters'] def _get_common_attrs(client_manager, parsed_args, is_create=True): client = client_manager.network attrs = {} if parsed_args.name is not None: attrs['name'] = parsed_args.name if parsed_args.description is not None: attrs['description'] = parsed_args.description if parsed_args.port_pairs: attrs['port_pairs'] = [client.find_sfc_port_pair( pp, ignore_missing=False)['id'] for pp in parsed_args.port_pairs] if is_create: _get_attrs(attrs, parsed_args) return attrs def _get_attrs(attrs, parsed_args): if parsed_args.port_pair_group_parameters is not None: attrs['port_pair_group_parameters'] = ( _get_ppg_param(attrs, parsed_args.port_pair_group_parameters)) if parsed_args.enable_tap: attrs['tap_enabled'] = True if parsed_args.disable_tap: attrs['tap_enabled'] = False ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/sfc/sfc_service_graph.py0000664000175000017500000002371300000000000026641 0ustar00zuulzuul00000000000000# Copyright 2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from neutronclient._i18n import _ LOG = logging.getLogger(__name__) resource = 'service_graph' _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('port_chains', 'Branching Points', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), ('project_id', 'Project', column_util.LIST_LONG_ONLY), ) _attr_map_dict = { 'id': 'ID', 'name': 'Name', 'description': 'Description', 'port_chains': 'Branching Points', 'tenant_id': 'Project', 'project_id': 'Project', } class CreateSfcServiceGraph(command.ShowOne): """Create a service graph.""" def get_parser(self, prog_name): parser = super(CreateSfcServiceGraph, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('Name of the service graph.')) parser.add_argument( '--description', help=_('Description for the service graph.')) parser.add_argument( '--branching-point', metavar='SRC_CHAIN:DST_CHAIN_1,DST_CHAIN_2,DST_CHAIN_N', dest='branching_points', action='append', default=[], required=True, help=_('Service graph branching point: the key is the source ' 'Port Chain while the value is a list of destination ' 'Port Chains. This option can be repeated.')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) try: obj = client.create_sfc_service_graph(**attrs) display_columns, columns = \ utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data except Exception as e: msg = (_("Failed to create service graph using '%(pcs)s': %(e)s") % {'pcs': parsed_args.branching_points, 'e': e}) raise exceptions.CommandError(msg) class SetSfcServiceGraph(command.Command): _description = _("Set service graph properties") def get_parser(self, prog_name): parser = super(SetSfcServiceGraph, self).get_parser(prog_name) parser.add_argument( '--name', metavar='', help=_('Name of the service graph')) parser.add_argument( '--description', metavar='', help=_('Description for the service graph')) parser.add_argument( 'service_graph', metavar='', help=_("Service graph to modify (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network service_graph_id = client.find_sfc_service_graph( parsed_args.service_graph, ignore_missing=False)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) try: client.update_sfc_service_graph(service_graph_id, **attrs) except Exception as e: msg = (_("Failed to update service graph " "'%(service_graph)s': %(e)s") % {'service_graph': parsed_args.service_graph, 'e': e}) raise exceptions.CommandError(msg) class DeleteSfcServiceGraph(command.Command): """Delete a given service graph.""" def get_parser(self, prog_name): parser = super(DeleteSfcServiceGraph, self).get_parser(prog_name) parser.add_argument( 'service_graph', metavar="", nargs='+', help=_("ID or name of the service graph(s) to delete.") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for sg in parsed_args.service_graph: try: sg_id = client.find_sfc_service_graph( sg, ignore_missing=False)['id'] client.delete_sfc_service_graph(sg_id) except Exception as e: result += 1 LOG.error(_("Failed to delete service graph with name " "or ID '%(sg)s': %(e)s"), {'sg': sg, 'e': e}) if result > 0: total = len(parsed_args.service_graph) msg = (_("%(result)s of %(total)s service graph(s) " "failed to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListSfcServiceGraph(command.Lister): _description = _("List service graphs") def get_parser(self, prog_name): parser = super(ListSfcServiceGraph, 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.network data = client.sfc_service_graphs() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties(s, columns) for s in data)) class ShowSfcServiceGraph(command.ShowOne): """Show information of a given service graph.""" def get_parser(self, prog_name): parser = super(ShowSfcServiceGraph, self).get_parser(prog_name) parser.add_argument( 'service_graph', metavar="", help=_("ID or name of the service graph to display.") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network sg_id = client.find_sfc_service_graph(parsed_args.service_graph, ignore_missing=False)['id'] obj = client.get_sfc_service_graph(sg_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data def _get_common_attrs(client_manager, parsed_args, is_create=True): 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 is_create: _get_attrs_for_create(client_manager, attrs, parsed_args) return attrs def _validate_destination_chains(comma_split, attrs, client, sc_): for e in comma_split: if e != "": dc_ = client.find_sfc_port_chain(e, ignore_missing=False)['id'] attrs['port_chains'][sc_].append(dc_) if _check_cycle(attrs['port_chains'], sc_, dc_): raise exceptions.CommandError( "Error: Service graph contains a cycle") else: raise exceptions.CommandError( "Error: you must specify at least one " "destination chain for each source chain") return attrs def _check_cycle(graph, new_src, new_dest): for src in graph: if src == new_dest: if _visit(graph, src, new_dest, new_src): return True return False def _visit(graph, src, new_dest, new_src): if src in graph: found_cycle = False for dest in graph[src]: if new_src == dest or found_cycle: return True else: found_cycle = _visit(graph, dest, new_dest, new_src) return False def _get_attrs_for_create(client_manager, attrs, parsed_args): client = client_manager.network if parsed_args.branching_points: attrs['port_chains'] = {} src_chain = None for c in parsed_args.branching_points: if ':' not in c: raise exceptions.CommandError( "Error: You must specify at least one " "destination chain for each source chain.") colon_split = c.split(':') src_chain = colon_split.pop(0) sc_ = client.find_sfc_port_chain(src_chain, ignore_missing=False)['id'] for i in colon_split: comma_split = i.split(',') unique = set(comma_split) if len(unique) != len(comma_split): raise exceptions.CommandError( "Error: Duplicate " "destination chains from " "source chain {}".format(src_chain)) if sc_ in attrs['port_chains']: raise exceptions.CommandError( "Error: Source chain {} is in " "use already ".format(src_chain)) attrs['port_chains'][sc_] = [] _validate_destination_chains( comma_split, attrs, client, sc_) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1709201317.221662 python-neutronclient-11.2.0/neutronclient/osc/v2/subnet_onboard/0000775000175000017500000000000000000000000025036 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/subnet_onboard/__init__.py0000664000175000017500000000000000000000000027135 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/subnet_onboard/subnet_onboard.py0000664000175000017500000000405300000000000030416 0ustar00zuulzuul00000000000000# Copyright (c) 2019 SUSE Linux Products GmbH # 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. # """Subnet onboard action implementation""" import logging from osc_lib.command import command from osc_lib import exceptions from neutronclient._i18n import _ LOG = logging.getLogger(__name__) class NetworkOnboardSubnets(command.Command): """Onboard network subnets into a subnet pool""" def get_parser(self, prog_name): parser = super(NetworkOnboardSubnets, self).get_parser(prog_name) parser.add_argument( 'network', metavar="", help=_("Onboard all subnets associated with this network") ) parser.add_argument( 'subnetpool', metavar="", help=_("Target subnet pool for onboarding subnets") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.neutronclient subnetpool_id = _get_id(client, parsed_args.subnetpool, 'subnetpool') network_id = _get_id(client, parsed_args.network, 'network') body = {'network_id': network_id} try: client.onboard_network_subnets(subnetpool_id, body) except Exception as e: msg = (_("Failed to onboard subnets for network '%(n)s': %(e)s") % {'n': parsed_args.network, 'e': e}) raise exceptions.CommandError(msg) def _get_id(client, id_or_name, resource): return client.find_resource(resource, str(id_or_name))['id'] ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/utils.py0000664000175000017500000000157000000000000023547 0ustar00zuulzuul00000000000000# Copyright 2016 NEC Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """This module is intended to contain methods specific to Networking v2 API and its extensions. """ from cliff import columns as cliff_columns class AdminStateColumn(cliff_columns.FormattableColumn): def human_readable(self): return 'UP' if self._value else 'DOWN' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2256625 python-neutronclient-11.2.0/neutronclient/osc/v2/vpnaas/0000775000175000017500000000000000000000000023322 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/vpnaas/__init__.py0000664000175000017500000000000000000000000025421 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/vpnaas/endpoint_group.py0000664000175000017500000001770500000000000026742 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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 exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from oslo_log import log as logging from neutronclient._i18n import _ from neutronclient.osc import utils as osc_utils LOG = logging.getLogger(__name__) _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('type', 'Type', column_util.LIST_BOTH), ('endpoints', 'Endpoints', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), ('project_id', 'Project', column_util.LIST_LONG_ONLY), ) _attr_map_dict = { 'id': 'ID', 'name': 'Name', 'type': 'Type', 'endpoints': 'Endpoints', 'description': 'Description', 'tenant_id': 'Project', 'project_id': 'Project', } def _get_common_parser(parser): parser.add_argument( '--description', metavar='', help=_('Description for the endpoint group')) return parser def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} if is_create: if parsed_args.project is not None: attrs['tenant_id'] = osc_utils.find_project( client_manager.identity, parsed_args.project, parsed_args.project_domain, ).id if parsed_args.description: attrs['description'] = parsed_args.description return attrs class CreateEndpointGroup(command.ShowOne): _description = _("Create an endpoint group") def get_parser(self, prog_name): parser = super(CreateEndpointGroup, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( 'name', metavar='', help=_('Name for the endpoint group')) parser.add_argument( '--type', required=True, help=_('Type of endpoints in group (e.g. subnet, cidr)')) parser.add_argument( '--value', action='append', dest='endpoints', required=True, help=_('Endpoint(s) for the group. Must all be of the same type. ' '(--value) option can be repeated')) osc_utils.add_project_owner_option_to_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) if parsed_args.name: attrs['name'] = str(parsed_args.name) attrs['type'] = parsed_args.type if parsed_args.type == 'subnet': _subnet_ids = [client.find_subnet( endpoint, ignore_missing=False)['id'] for endpoint in parsed_args.endpoints] attrs['endpoints'] = _subnet_ids else: attrs['endpoints'] = parsed_args.endpoints obj = client.create_vpn_endpoint_group(**attrs) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data class DeleteEndpointGroup(command.Command): _description = _("Delete endpoint group(s)") def get_parser(self, prog_name): parser = super(DeleteEndpointGroup, self).get_parser(prog_name) parser.add_argument( 'endpoint_group', metavar='', nargs='+', help=_('Endpoint group(s) to delete (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for endpoint in parsed_args.endpoint_group: try: endpoint_id = client.find_vpn_endpoint_group( endpoint, ignore_missing=False)['id'] client.delete_vpn_endpoint_group(endpoint_id) except Exception as e: result += 1 LOG.error(_("Failed to delete endpoint group with " "name or ID '%(endpoint_group)s': %(e)s"), {'endpoint_group': endpoint, 'e': e}) if result > 0: total = len(parsed_args.endpoint_group) msg = (_("%(result)s of %(total)s endpoint group failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListEndpointGroup(command.Lister): _description = _("List endpoint groups that belong to a given project") def get_parser(self, prog_name): parser = super(ListEndpointGroup, 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.network obj = client.vpn_endpoint_groups() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties(s, columns) for s in obj)) class SetEndpointGroup(command.Command): _description = _("Set endpoint group properties") def get_parser(self, prog_name): parser = super(SetEndpointGroup, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( '--name', metavar='', help=_('Set a name for the endpoint group')) parser.add_argument( 'endpoint_group', metavar='', help=_('Endpoint group to set (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.name: attrs['name'] = str(parsed_args.name) endpoint_id = client.find_vpn_endpoint_group( parsed_args.endpoint_group, ignore_missing=False)['id'] try: client.update_vpn_endpoint_group(endpoint_id, **attrs) except Exception as e: msg = (_("Failed to set endpoint group " "%(endpoint_group)s: %(e)s") % {'endpoint_group': parsed_args.endpoint_group, 'e': e}) raise exceptions.CommandError(msg) class ShowEndpointGroup(command.ShowOne): _description = _("Display endpoint group details") def get_parser(self, prog_name): parser = super(ShowEndpointGroup, self).get_parser(prog_name) parser.add_argument( 'endpoint_group', metavar='', help=_('Endpoint group to display (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network endpoint_id = client.find_vpn_endpoint_group( parsed_args.endpoint_group, ignore_missing=False)['id'] obj = client.get_vpn_endpoint_group(endpoint_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return (display_columns, data) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/vpnaas/ikepolicy.py0000664000175000017500000002264700000000000025677 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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 exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from oslo_log import log as logging from neutronclient._i18n import _ from neutronclient.common import utils as nc_utils from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.vpnaas import utils as vpn_utils LOG = logging.getLogger(__name__) _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('auth_algorithm', 'Authentication Algorithm', column_util.LIST_BOTH), ('encryption_algorithm', 'Encryption Algorithm', column_util.LIST_BOTH), ('ike_version', 'IKE Version', column_util.LIST_BOTH), ('pfs', 'Perfect Forward Secrecy (PFS)', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), ('phase1_negotiation_mode', 'Phase1 Negotiation Mode', column_util.LIST_LONG_ONLY), ('project_id', 'Project', column_util.LIST_LONG_ONLY), ('lifetime', 'Lifetime', column_util.LIST_LONG_ONLY), ) _attr_map_dict = { 'id': 'ID', 'name': 'Name', 'auth_algorithm': 'Authentication Algorithm', 'encryption_algorithm': 'Encryption Algorithm', 'ike_version': 'IKE Version', 'pfs': 'Perfect Forward Secrecy (PFS)', 'phase1_negotiation_mode': 'Phase1 Negotiation Mode', 'lifetime': 'Lifetime', 'description': 'Description', 'tenant_id': 'Project', 'project_id': 'Project', } def _convert_to_lowercase(string): return string.lower() def _get_common_parser(parser): parser.add_argument( '--description', metavar='', help=_('Description of the IKE policy')) parser.add_argument( '--auth-algorithm', choices=['sha1', 'sha256', 'sha384', 'sha512'], type=_convert_to_lowercase, help=_('Authentication algorithm')) parser.add_argument( '--encryption-algorithm', choices=['aes-128', '3des', 'aes-192', 'aes-256'], type=_convert_to_lowercase, help=_('Encryption algorithm')) parser.add_argument( '--phase1-negotiation-mode', choices=['main', 'aggressive'], type=_convert_to_lowercase, help=_('IKE Phase1 negotiation mode')) parser.add_argument( '--ike-version', choices=['v1', 'v2'], type=_convert_to_lowercase, help=_('IKE version for the policy')) parser.add_argument( '--pfs', choices=['group5', 'group2', 'group14'], type=_convert_to_lowercase, help=_('Perfect Forward Secrecy')) parser.add_argument( '--lifetime', metavar="units=UNITS,value=VALUE", type=nc_utils.str2dict_type(optional_keys=['units', 'value']), help=vpn_utils.lifetime_help("IKE")) return parser def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} if is_create: if 'project' in parsed_args and parsed_args.project is not None: attrs['project_id'] = osc_utils.find_project( client_manager.identity, parsed_args.project, parsed_args.project_domain, ).id if parsed_args.description: attrs['description'] = parsed_args.description if parsed_args.auth_algorithm: attrs['auth_algorithm'] = parsed_args.auth_algorithm if parsed_args.encryption_algorithm: attrs['encryption_algorithm'] = parsed_args.encryption_algorithm if parsed_args.phase1_negotiation_mode: attrs['phase1_negotiation_mode'] = parsed_args.phase1_negotiation_mode if parsed_args.ike_version: attrs['ike_version'] = parsed_args.ike_version if parsed_args.pfs: attrs['pfs'] = parsed_args.pfs if parsed_args.lifetime: vpn_utils.validate_lifetime_dict(parsed_args.lifetime) attrs['lifetime'] = parsed_args.lifetime return attrs class CreateIKEPolicy(command.ShowOne): _description = _("Create an IKE policy") def get_parser(self, prog_name): parser = super(CreateIKEPolicy, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( 'name', metavar='', help=_('Name of the IKE policy')) osc_utils.add_project_owner_option_to_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) if parsed_args.name: attrs['name'] = str(parsed_args.name) obj = client.create_vpn_ike_policy(**attrs) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id', 'units', 'value']) data = utils.get_dict_properties(obj, columns) return display_columns, data class DeleteIKEPolicy(command.Command): _description = _("Delete IKE policy (policies)") def get_parser(self, prog_name): parser = super(DeleteIKEPolicy, self).get_parser(prog_name) parser.add_argument( 'ikepolicy', metavar='', nargs='+', help=_('IKE policy to delete (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for ike in parsed_args.ikepolicy: try: ike_id = client.find_vpn_ike_policy(ike, ignore_missing=False)['id'] client.delete_vpn_ike_policy(ike_id) except Exception as e: result += 1 LOG.error(_("Failed to delete IKE policy with " "name or ID '%(ikepolicy)s': %(e)s"), {'ikepolicy': ike, 'e': e}) if result > 0: total = len(parsed_args.ikepolicy) msg = (_("%(result)s of %(total)s IKE policy failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListIKEPolicy(command.Lister): _description = _("List IKE policies that belong to a given project") def get_parser(self, prog_name): parser = super(ListIKEPolicy, 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.network obj = client.vpn_ike_policies() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties(s, columns) for s in obj)) class SetIKEPolicy(command.Command): _description = _("Set IKE policy properties") def get_parser(self, prog_name): parser = super(SetIKEPolicy, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( '--name', metavar='', help=_('Name of the IKE policy')) parser.add_argument( 'ikepolicy', metavar='', help=_('IKE policy to set (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.name: attrs['name'] = parsed_args.name ike_id = client.find_vpn_ike_policy(parsed_args.ikepolicy, ignore_missing=False)['id'] try: client.update_vpn_ike_policy(ike_id, **attrs) except Exception as e: msg = (_("Failed to set IKE policy '%(ike)s': %(e)s") % {'ike': parsed_args.ikepolicy, 'e': e}) raise exceptions.CommandError(msg) class ShowIKEPolicy(command.ShowOne): _description = _("Display IKE policy details") def get_parser(self, prog_name): parser = super(ShowIKEPolicy, self).get_parser(prog_name) parser.add_argument( 'ikepolicy', metavar='', help=_('IKE policy to display (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network ike_id = client.find_vpn_ike_policy(parsed_args.ikepolicy, ignore_missing=False)['id'] obj = client.get_vpn_ike_policy(ike_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id', 'units', 'value']) data = utils.get_dict_properties(obj, columns) return (display_columns, data) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/vpnaas/ipsec_site_connection.py0000664000175000017500000003570600000000000030255 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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.cli import format_columns from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from oslo_log import log as logging from neutronclient._i18n import _ from neutronclient.common import utils as nc_utils from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.vpnaas import utils as vpn_utils LOG = logging.getLogger(__name__) _formatters = { 'peer_cidrs': format_columns.ListColumn } _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('peer_address', 'Peer Address', column_util.LIST_BOTH), ('auth_mode', 'Authentication Algorithm', column_util.LIST_BOTH), ('status', 'Status', column_util.LIST_BOTH), ('project_id', 'Project', column_util.LIST_LONG_ONLY), ('peer_cidrs', 'Peer CIDRs', column_util.LIST_LONG_ONLY), ('vpnservice_id', 'VPN Service', column_util.LIST_LONG_ONLY), ('ipsecpolicy_id', 'IPSec Policy', column_util.LIST_LONG_ONLY), ('ikepolicy_id', 'IKE Policy', column_util.LIST_LONG_ONLY), ('mtu', 'MTU', column_util.LIST_LONG_ONLY), ('initiator', 'Initiator', column_util.LIST_LONG_ONLY), ('is_admin_state_up', 'State', column_util.LIST_LONG_ONLY), ('description', 'Description', column_util.LIST_LONG_ONLY), ('psk', 'Pre-shared Key', column_util.LIST_LONG_ONLY), ('route_mode', 'Route Mode', column_util.LIST_LONG_ONLY), ('local_id', 'Local ID', column_util.LIST_LONG_ONLY), ('peer_id', 'Peer ID', column_util.LIST_LONG_ONLY), ('local_ep_group_id', 'Local Endpoint Group ID', column_util.LIST_LONG_ONLY), ('peer_ep_group_id', 'Peer Endpoint Group ID', column_util.LIST_LONG_ONLY), ('dpd', 'DPD', column_util.LIST_LONG_ONLY), ) _attr_map_dict = { 'id': 'ID', 'name': 'Name', 'peer_address': 'Peer Address', 'auth_mode': 'Authentication Algorithm', 'status': 'Status', 'peer_cidrs': 'Peer CIDRs', 'vpnservice_id': 'VPN Service', 'ipsecpolicy_id': 'IPSec Policy', 'ikepolicy_id': 'IKE Policy', 'mtu': 'MTU', 'initiator': 'Initiator', 'is_admin_state_up': 'State', 'psk': 'Pre-shared Key', 'route_mode': 'Route Mode', 'local_id': 'Local ID', 'peer_id': 'Peer ID', 'local_ep_group_id': 'Local Endpoint Group ID', 'peer_ep_group_id': 'Peer Endpoint Group ID', 'description': 'Description', 'project_id': 'Project', 'dpd': 'DPD', } def _convert_to_lowercase(string): return string.lower() def _get_common_parser(parser, is_create=True): parser.add_argument( '--description', metavar='', help=_('Description for the connection')) parser.add_argument( '--dpd', metavar="action=ACTION,interval=INTERVAL,timeout=TIMEOUT", type=nc_utils.str2dict_type( optional_keys=['action', 'interval', 'timeout']), help=vpn_utils.dpd_help("IPsec connection")) parser.add_argument( '--mtu', help=_('MTU size for the connection')) parser.add_argument( '--initiator', choices=['bi-directional', 'response-only'], type=_convert_to_lowercase, help=_('Initiator state')) peer_group = parser.add_mutually_exclusive_group() peer_group.add_argument( '--peer-cidr', dest='peer_cidrs', help=_('Remote subnet(s) in CIDR format. ' 'Cannot be specified when using endpoint groups. Only ' 'applicable, if subnet provided for VPN service.') ) peer_group.add_argument( '--local-endpoint-group', help=_('Local endpoint group (name or ID) with subnet(s) ' 'for IPsec connection') ) parser.add_argument( '--peer-endpoint-group', help=_('Peer endpoint group (name or ID) with CIDR(s) for ' 'IPSec connection')) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', help=_("Enable IPSec site connection") ) admin_group.add_argument( '--disable', action='store_true', help=_("Disable IPSec site connection") ) parser.add_argument( '--local-id', help=_('An ID to be used instead of the external IP ' 'address for a virtual router')) return parser def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} if is_create: if 'project' in parsed_args and parsed_args.project is not None: attrs['project_id'] = osc_utils.find_project( client_manager.identity, parsed_args.project, parsed_args.project_domain, ).id if parsed_args.description: attrs['description'] = str(parsed_args.description) if parsed_args.mtu: attrs['mtu'] = parsed_args.mtu if parsed_args.enable: attrs['admin_state_up'] = True if parsed_args.disable: attrs['admin_state_up'] = False if parsed_args.initiator: attrs['initiator'] = parsed_args.initiator if parsed_args.dpd: vpn_utils.validate_dpd_dict(parsed_args.dpd) attrs['dpd'] = parsed_args.dpd if parsed_args.local_endpoint_group: _local_epg = client_manager.network.find_vpn_endpoint_group( parsed_args.local_endpoint_group)['id'] attrs['local_ep_group_id'] = _local_epg if parsed_args.peer_endpoint_group: _peer_epg = client_manager.network.find_vpn_endpoint_group( parsed_args.peer_endpoint_group)['id'] attrs['peer_ep_group_id'] = _peer_epg if parsed_args.peer_cidrs: attrs['peer_cidrs'] = parsed_args.peer_cidrs if parsed_args.local_id: attrs['local_id'] = parsed_args.local_id return attrs class CreateIPsecSiteConnection(command.ShowOne): _description = _("Create an IPsec site connection") def get_parser(self, prog_name): parser = super(CreateIPsecSiteConnection, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( '--peer-id', required=True, help=_('Peer router identity for authentication. Can be ' 'IPv4/IPv6 address, e-mail address, key id, or FQDN')) parser.add_argument( '--peer-address', required=True, help=_('Peer gateway public IPv4/IPv6 address or FQDN')) parser.add_argument( '--psk', required=True, help=_('Pre-shared key string.')) parser.add_argument( '--vpnservice', metavar='VPNSERVICE', required=True, help=_('VPN service instance associated with this ' 'connection (name or ID)')) parser.add_argument( '--ikepolicy', metavar='IKEPOLICY', required=True, help=_('IKE policy associated with this connection (name or ID)')) parser.add_argument( '--ipsecpolicy', metavar='IPSECPOLICY', required=True, help=_('IPsec policy associated with this connection ' '(name or ID)')) parser.add_argument( 'name', metavar='', help=_('Set friendly name for the connection')) osc_utils.add_project_owner_option_to_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) if parsed_args.vpnservice: _vpnservice_id = client.find_vpn_service( parsed_args.vpnservice, ignore_missing=False)['id'] attrs['vpnservice_id'] = _vpnservice_id if parsed_args.ikepolicy: _ikepolicy_id = client.find_vpn_ike_policy( parsed_args.ikepolicy, ignore_missing=False)['id'] attrs['ikepolicy_id'] = _ikepolicy_id if parsed_args.ipsecpolicy: _ipsecpolicy_id = client.find_vpn_ipsec_policy( parsed_args.ipsecpolicy, ignore_missing=False)['id'] attrs['ipsecpolicy_id'] = _ipsecpolicy_id if parsed_args.peer_id: attrs['peer_id'] = parsed_args.peer_id if parsed_args.peer_address: attrs['peer_address'] = parsed_args.peer_address if parsed_args.psk: attrs['psk'] = parsed_args.psk if parsed_args.name: attrs['name'] = parsed_args.name if (bool(parsed_args.local_endpoint_group) != bool(parsed_args.peer_endpoint_group)): message = _("You must specify both local and peer endpoint " "groups") raise exceptions.CommandError(message) if not parsed_args.peer_cidrs and not parsed_args.local_endpoint_group: message = _("You must specify endpoint groups or peer CIDR(s)") raise exceptions.CommandError(message) obj = client.create_vpn_ipsec_site_connection(**attrs) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id', 'action', 'timeout', 'interval']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return display_columns, data class DeleteIPsecSiteConnection(command.Command): _description = _("Delete IPsec site connection(s)") def get_parser(self, prog_name): parser = super(DeleteIPsecSiteConnection, self).get_parser(prog_name) parser.add_argument( 'ipsec_site_connection', metavar='', nargs='+', help=_('IPsec site connection to delete (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for ipsec_conn in parsed_args.ipsec_site_connection: try: ipsec_con_id = client.find_vpn_ipsec_site_connection( ipsec_conn, ignore_missing=False)['id'] client.delete_vpn_ipsec_site_connection(ipsec_con_id) except Exception as e: result += 1 LOG.error(_("Failed to delete IPsec site connection with " "name or ID '%(ipsec_site_conn)s': %(e)s"), {'ipsec_site_conn': ipsec_conn, 'e': e}) if result > 0: total = len(parsed_args.ipsec_site_connection) msg = (_("%(result)s of %(total)s IPsec site connection failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListIPsecSiteConnection(command.Lister): _description = _("List IPsec site connections " "that belong to a given project") def get_parser(self, prog_name): parser = super(ListIPsecSiteConnection, 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.network obj = client.vpn_ipsec_site_connections() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties( s, columns, formatters=_formatters) for s in obj)) class SetIPsecSiteConnection(command.Command): _description = _("Set IPsec site connection properties") def get_parser(self, prog_name): parser = super(SetIPsecSiteConnection, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( '--peer-id', help=_('Peer router identity for authentication. Can be ' 'IPv4/IPv6 address, e-mail address, key id, or FQDN')) parser.add_argument( '--peer-address', help=_('Peer gateway public IPv4/IPv6 address or FQDN')) parser.add_argument( '--name', metavar='', help=_('Set friendly name for the connection')) parser.add_argument( 'ipsec_site_connection', metavar='', help=_('IPsec site connection to set (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.peer_id: attrs['peer_id'] = parsed_args.peer_id if parsed_args.peer_address: attrs['peer_address'] = parsed_args.peer_address if parsed_args.name: attrs['name'] = parsed_args.name ipsec_conn_id = client.find_vpn_ipsec_site_connection( parsed_args.ipsec_site_connection, ignore_missing=False)['id'] try: client.update_vpn_ipsec_site_connection(ipsec_conn_id, **attrs) except Exception as e: msg = (_("Failed to set IPsec site " "connection '%(ipsec_conn)s': %(e)s") % {'ipsec_conn': parsed_args.ipsec_site_connection, 'e': e}) raise exceptions.CommandError(msg) class ShowIPsecSiteConnection(command.ShowOne): _description = _("Show information of a given IPsec site connection") def get_parser(self, prog_name): parser = super(ShowIPsecSiteConnection, self).get_parser(prog_name) parser.add_argument( 'ipsec_site_connection', metavar='', help=_('IPsec site connection to display (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network ipsec_site_id = client.find_vpn_ipsec_site_connection( parsed_args.ipsec_site_connection, ignore_missing=False)['id'] obj = client.get_vpn_ipsec_site_connection(ipsec_site_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id', 'action', 'timeout', 'interval']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return (display_columns, data) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/vpnaas/ipsecpolicy.py0000664000175000017500000002320400000000000026220 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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 exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from oslo_log import log as logging from neutronclient._i18n import _ from neutronclient.common import utils as nc_utils from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.vpnaas import utils as vpn_utils LOG = logging.getLogger(__name__) _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('auth_algorithm', 'Authentication Algorithm', column_util.LIST_BOTH), ('encapsulation_mode', 'Encapsulation Mode', column_util.LIST_BOTH), ('transform_protocol', 'Transform Protocol', column_util.LIST_BOTH), ('encryption_algorithm', 'Encryption Algorithm', column_util.LIST_BOTH), ('pfs', 'Perfect Forward Secrecy (PFS)', column_util.LIST_LONG_ONLY), ('description', 'Description', column_util.LIST_LONG_ONLY), ('project_id', 'Project', column_util.LIST_LONG_ONLY), ('lifetime', 'Lifetime', column_util.LIST_LONG_ONLY), ) _attr_map_dict = { 'id': 'ID', 'name': 'Name', 'auth_algorithm': 'Authentication Algorithm', 'encapsulation_mode': 'Encapsulation Mode', 'transform_protocol': 'Transform Protocol', 'encryption_algorithm': 'Encryption Algorithm', 'pfs': 'Perfect Forward Secrecy (PFS)', 'lifetime': 'Lifetime', 'description': 'Description', 'project_id': 'Project', } def _convert_to_lowercase(string): return string.lower() def _get_common_parser(parser): parser.add_argument( '--description', metavar='', help=_('Description of the IPsec policy')) parser.add_argument( '--auth-algorithm', choices=['sha1', 'sha256', 'sha384', 'sha512'], type=_convert_to_lowercase, help=_('Authentication algorithm for IPsec policy')) parser.add_argument( '--encapsulation-mode', choices=['tunnel', 'transport'], type=_convert_to_lowercase, help=_('Encapsulation mode for IPsec policy')) parser.add_argument( '--encryption-algorithm', choices=['3des', 'aes-128', 'aes-192', 'aes-256'], type=_convert_to_lowercase, help=_('Encryption algorithm for IPsec policy')) parser.add_argument( '--lifetime', metavar="units=UNITS,value=VALUE", type=nc_utils.str2dict_type(optional_keys=['units', 'value']), help=vpn_utils.lifetime_help("IPsec")) parser.add_argument( '--pfs', choices=['group2', 'group5', 'group14'], type=_convert_to_lowercase, help=_('Perfect Forward Secrecy for IPsec policy')) parser.add_argument( '--transform-protocol', type=_convert_to_lowercase, choices=['esp', 'ah', 'ah-esp'], help=_('Transform protocol for IPsec policy')) def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} if is_create: if 'project' in parsed_args and parsed_args.project is not None: attrs['project_id'] = osc_utils.find_project( client_manager.identity, parsed_args.project, parsed_args.project_domain, ).id if parsed_args.description: attrs['description'] = str(parsed_args.description) if parsed_args.auth_algorithm: attrs['auth_algorithm'] = parsed_args.auth_algorithm if parsed_args.encapsulation_mode: attrs['encapsulation_mode'] = parsed_args.encapsulation_mode if parsed_args.transform_protocol: attrs['transform_protocol'] = parsed_args.transform_protocol if parsed_args.encryption_algorithm: attrs['encryption_algorithm'] = parsed_args.encryption_algorithm if parsed_args.pfs: attrs['pfs'] = parsed_args.pfs if parsed_args.lifetime: vpn_utils.validate_lifetime_dict(parsed_args.lifetime) attrs['lifetime'] = parsed_args.lifetime return attrs class CreateIPsecPolicy(command.ShowOne): _description = _("Create an IPsec policy") def get_parser(self, prog_name): parser = super(CreateIPsecPolicy, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( 'name', metavar='', help=_('Name of the IPsec policy')) osc_utils.add_project_owner_option_to_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) if parsed_args.name: attrs['name'] = str(parsed_args.name) obj = client.create_vpn_ipsec_policy(**attrs) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id', 'phase1_negotiation_mode', 'units', 'value']) data = utils.get_dict_properties(obj, columns) return display_columns, data class DeleteIPsecPolicy(command.Command): _description = _("Delete IPsec policy(policies)") def get_parser(self, prog_name): parser = super(DeleteIPsecPolicy, self).get_parser(prog_name) parser.add_argument( 'ipsecpolicy', metavar='', nargs='+', help=_('ipsec policy to delete (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for ipsec in parsed_args.ipsecpolicy: try: ipsec_id = client.find_vpn_ipsec_policy( ipsec, ignore_missing=False)['id'] client.delete_vpn_ipsec_policy(ipsec_id) except Exception as e: result += 1 LOG.error(_("Failed to delete IPsec policy with " "name or ID '%(ipsecpolicy)s': %(e)s"), {'ipsecpolicy': ipsec, 'e': e}) if result > 0: total = len(parsed_args.ipsecpolicy) msg = (_("%(result)s of %(total)s IPsec policy failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListIPsecPolicy(command.Lister): _description = _("List IPsec policies that belong to a given project") def get_parser(self, prog_name): parser = super(ListIPsecPolicy, 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.network obj = client.vpn_ipsec_policies() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties(s, columns) for s in obj)) class SetIPsecPolicy(command.Command): _description = _("Set IPsec policy properties") def get_parser(self, prog_name): parser = super(SetIPsecPolicy, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( '--name', metavar='', help=_('Name of the IPsec policy')) parser.add_argument( 'ipsecpolicy', metavar='', help=_('IPsec policy to set (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.name: attrs['name'] = str(parsed_args.name) ipsec_id = client.find_vpn_ipsec_policy( parsed_args.ipsecpolicy, ignore_missing=False)['id'] try: client.update_vpn_ipsec_policy(ipsec_id, **attrs) except Exception as e: msg = (_("Failed to set IPsec policy '%(ipsec)s': %(e)s") % {'ipsec': parsed_args.ipsecpolicy, 'e': e}) raise exceptions.CommandError(msg) class ShowIPsecPolicy(command.ShowOne): _description = _("Display IPsec policy details") def get_parser(self, prog_name): parser = super(ShowIPsecPolicy, self).get_parser(prog_name) parser.add_argument( 'ipsecpolicy', metavar='', help=_('IPsec policy to display (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network ipsec_id = client.find_vpn_ipsec_policy( parsed_args.ipsecpolicy, ignore_missing=False)['id'] obj = client.get_vpn_ipsec_policy(ipsec_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id', 'phase1_negotiation_mode', 'units', 'value']) data = utils.get_dict_properties(obj, columns) return (display_columns, data) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/vpnaas/utils.py0000664000175000017500000001033000000000000025031 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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. # """VPN Utilities and helper functions.""" from neutronclient._i18n import _ from neutronclient.common import exceptions DPD_SUPPORTED_ACTIONS = ['hold', 'clear', 'restart', 'restart-by-peer', 'disabled'] DPD_SUPPORTED_KEYS = ['action', 'interval', 'timeout'] lifetime_keys = ['units', 'value'] lifetime_units = ['seconds'] def validate_dpd_dict(dpd_dict): for key, value in dpd_dict.items(): if key not in DPD_SUPPORTED_KEYS: message = _( "DPD Dictionary KeyError: " "Reason-Invalid DPD key : " "'%(key)s' not in %(supported_key)s") % { 'key': key, 'supported_key': DPD_SUPPORTED_KEYS} raise exceptions.CommandError(message) if key == 'action' and value not in DPD_SUPPORTED_ACTIONS: message = _( "DPD Dictionary ValueError: " "Reason-Invalid DPD action : " "'%(key_value)s' not in %(supported_action)s") % { 'key_value': value, 'supported_action': DPD_SUPPORTED_ACTIONS} raise exceptions.CommandError(message) if key in ('interval', 'timeout'): try: if int(value) <= 0: raise ValueError() except ValueError: message = _( "DPD Dictionary ValueError: " "Reason-Invalid positive integer value: " "'%(key)s' = %(value)s") % { 'key': key, 'value': value} raise exceptions.CommandError(message) else: dpd_dict[key] = int(value) return def validate_lifetime_dict(lifetime_dict): for key, value in lifetime_dict.items(): if key not in lifetime_keys: message = _( "Lifetime Dictionary KeyError: " "Reason-Invalid unit key : " "'%(key)s' not in %(supported_key)s") % { 'key': key, 'supported_key': lifetime_keys} raise exceptions.CommandError(message) if key == 'units' and value not in lifetime_units: message = _( "Lifetime Dictionary ValueError: " "Reason-Invalid units : " "'%(key_value)s' not in %(supported_units)s") % { 'key_value': key, 'supported_units': lifetime_units} raise exceptions.CommandError(message) if key == 'value': try: if int(value) < 60: raise ValueError() except ValueError: message = _( "Lifetime Dictionary ValueError: " "Reason-Invalid value should be at least 60:" "'%(key_value)s' = %(value)s") % { 'key_value': key, 'value': value} raise exceptions.CommandError(message) else: lifetime_dict['value'] = int(value) return def lifetime_help(policy): lifetime = _("%s lifetime attributes. " "'units'-seconds, default:seconds. " "'value'-non negative integer, default:3600.") % policy return lifetime def dpd_help(policy): dpd = _(" %s Dead Peer Detection attributes." " 'action'-hold,clear,disabled,restart,restart-by-peer." " 'interval' and 'timeout' are non negative integers. " " 'interval' should be less than 'timeout' value. " " 'action', default:hold 'interval', default:30, " " 'timeout', default:120.") % policy.capitalize() return dpd ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/osc/v2/vpnaas/vpnservice.py0000664000175000017500000002143400000000000026064 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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 exceptions from osc_lib import utils from osc_lib.utils import columns as column_util from oslo_log import log as logging from neutronclient._i18n import _ from neutronclient.osc import utils as osc_utils LOG = logging.getLogger(__name__) _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('router_id', 'Router', column_util.LIST_BOTH), ('subnet_id', 'Subnet', column_util.LIST_BOTH), ('flavor_id', 'Flavor', column_util.LIST_BOTH), ('is_admin_state_up', 'State', column_util.LIST_BOTH), ('status', 'Status', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), ('project_id', 'Project', column_util.LIST_LONG_ONLY), ) _attr_map_dict = { 'id': 'ID', 'name': 'Name', 'router_id': 'Router', 'subnet_id': 'Subnet', 'flavor_id': 'Flavor', 'is_admin_state_up': 'State', 'status': 'Status', 'description': 'Description', 'project_id': 'Project', } def _get_common_parser(parser): parser.add_argument( '--description', metavar='', help=_('Description for the VPN service')) parser.add_argument( '--subnet', metavar='', help=_('Local private subnet (name or ID)')) parser.add_argument( '--flavor', metavar='', help=_('Flavor for the VPN service (name or ID)')) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', help=_("Enable VPN service") ) admin_group.add_argument( '--disable', action='store_true', help=_("Disable VPN service") ) return parser def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} if is_create: if 'project' in parsed_args and parsed_args.project is not None: attrs['project_id'] = osc_utils.find_project( client_manager.identity, parsed_args.project, parsed_args.project_domain, ).id if parsed_args.description: attrs['description'] = str(parsed_args.description) if parsed_args.subnet: _subnet_id = client_manager.network.find_subnet( parsed_args.subnet).id attrs['subnet_id'] = _subnet_id if parsed_args.flavor: _flavor_id = client_manager.network.find_flavor( parsed_args.flavor, ignore_missing=False ).id attrs['flavor_id'] = _flavor_id if parsed_args.enable: attrs['admin_state_up'] = True if parsed_args.disable: attrs['admin_state_up'] = False return attrs class CreateVPNService(command.ShowOne): _description = _("Create an VPN service") def get_parser(self, prog_name): parser = super(CreateVPNService, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( 'name', metavar='', help=_('Name for the VPN service')) parser.add_argument( '--router', metavar='ROUTER', required=True, help=_('Router for the VPN service (name or ID)')) osc_utils.add_project_owner_option_to_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) if parsed_args.name: attrs['name'] = str(parsed_args.name) if parsed_args.router: _router_id = client.find_router(parsed_args.router, ignore_missing=False).id attrs['router_id'] = _router_id obj = client.create_vpn_service(**attrs) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id', 'external_v4_ip', 'external_v6_ip']) data = utils.get_dict_properties(obj, columns) return display_columns, data class DeleteVPNService(command.Command): _description = _("Delete VPN service(s)") def get_parser(self, prog_name): parser = super(DeleteVPNService, self).get_parser(prog_name) parser.add_argument( 'vpnservice', metavar='', nargs='+', help=_('VPN service to delete (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for vpn in parsed_args.vpnservice: try: vpn_id = client.find_vpn_service(vpn, ignore_missing=False)['id'] client.delete_vpn_service(vpn_id) except Exception as e: result += 1 LOG.error(_("Failed to delete VPN service with " "name or ID '%(vpnservice)s': %(e)s"), {'vpnservice': vpn, 'e': e}) if result > 0: total = len(parsed_args.vpnservice) msg = (_("%(result)s of %(total)s vpn service failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListVPNService(command.Lister): _description = _("List VPN services that belong to a given project") def get_parser(self, prog_name): parser = super(ListVPNService, 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.network obj = client.vpn_services() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties(s, columns) for s in obj)) class SetVPNSercice(command.Command): _description = _("Set VPN service properties") def get_parser(self, prog_name): parser = super(SetVPNSercice, self).get_parser(prog_name) _get_common_parser(parser) parser.add_argument( '--name', metavar='', help=_('Name for the VPN service')) parser.add_argument( 'vpnservice', metavar='', help=_('VPN service to modify (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.name: attrs['name'] = str(parsed_args.name) vpn_id = client.find_vpn_service(parsed_args.vpnservice, ignore_missing=False)['id'] try: client.update_vpn_service(vpn_id, **attrs) except Exception as e: msg = (_("Failed to set vpn service '%(vpn)s': %(e)s") % {'vpn': parsed_args.vpnservice, 'e': e}) raise exceptions.CommandError(msg) class ShowVPNService(command.ShowOne): _description = _("Display VPN service details") def get_parser(self, prog_name): parser = super(ShowVPNService, self).get_parser(prog_name) parser.add_argument( 'vpnservice', metavar='', help=_('VPN service to display (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network vpn_id = client.find_vpn_service(parsed_args.vpnservice, ignore_missing=False)['id'] obj = client.get_vpn_service(vpn_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id', 'external_v4_ip', 'external_v6_ip']) data = utils.get_dict_properties(obj, columns) return (display_columns, data) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2256625 python-neutronclient-11.2.0/neutronclient/tests/0000775000175000017500000000000000000000000022061 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/__init__.py0000664000175000017500000000000000000000000024160 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2256625 python-neutronclient-11.2.0/neutronclient/tests/unit/0000775000175000017500000000000000000000000023040 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/__init__.py0000664000175000017500000000000000000000000025137 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2256625 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/0000775000175000017500000000000000000000000023624 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/__init__.py0000664000175000017500000000000000000000000025723 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2256625 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/0000775000175000017500000000000000000000000024153 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/__init__.py0000664000175000017500000000000000000000000026252 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2256625 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/dynamic_routing/0000775000175000017500000000000000000000000027346 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/dynamic_routing/__init__.py0000664000175000017500000000000000000000000031445 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py0000664000175000017500000001123500000000000031013 0ustar00zuulzuul00000000000000# 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 unittest import mock import uuid from openstack.network.v2 import agent as _agent from openstack.network.v2 import bgp_peer as _bgp_peer from openstack.network.v2 import bgp_speaker as _bgp_speaker from neutronclient.tests.unit.osc.v2 import fakes class TestNeutronDynamicRoutingOSCV2(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestNeutronDynamicRoutingOSCV2, self).setUp() self.neutronclient.find_resource = mock.Mock( side_effect=lambda resource, name_or_id, project_id=None, cmd_resource=None, parent_id=None, fields=None: {'id': name_or_id}) self.networkclient.find_bgp_speaker = mock.Mock( side_effect=lambda name_or_id, project_id=None, cmd_resource=None, parent_id=None, fields=None, ignore_missing=False: _bgp_speaker.BgpSpeaker(id=name_or_id)) self.networkclient.find_bgp_peer = mock.Mock( side_effect=lambda name_or_id, project_id=None, cmd_resource=None, parent_id=None, fields=None, ignore_missing=False: _bgp_peer.BgpPeer(id=name_or_id)) class FakeBgpSpeaker(object): """Fake one or more bgp speakers.""" @staticmethod def create_one_bgp_speaker(attrs=None): attrs = attrs or {} # Set default attributes. bgp_speaker_attrs = { 'peers': [], 'local_as': 200, 'advertise_tenant_networks': True, 'networks': [], 'ip_version': 4, 'advertise_floating_ip_host_routes': True, 'id': uuid.uuid4().hex, 'name': 'bgp-speaker-' + uuid.uuid4().hex, 'tenant_id': uuid.uuid4().hex, } # Overwrite default attributes. bgp_speaker_attrs.update(attrs) ret_bgp_speaker = _bgp_speaker.BgpSpeaker(**bgp_speaker_attrs) return ret_bgp_speaker @staticmethod def create_bgp_speakers(attrs=None, count=1): """Create multiple fake bgp speakers. """ bgp_speakers = [] for i in range(count): bgp_speaker = FakeBgpSpeaker.create_one_bgp_speaker(attrs) bgp_speakers.append(bgp_speaker) return bgp_speakers class FakeBgpPeer(object): """Fake one or more bgp peers.""" @staticmethod def create_one_bgp_peer(attrs=None): attrs = attrs or {} # Set default attributes. bgp_peer_attrs = { 'auth_type': None, 'peer_ip': '1.1.1.1', 'remote_as': 100, 'id': uuid.uuid4().hex, 'name': 'bgp-peer-' + uuid.uuid4().hex, 'tenant_id': uuid.uuid4().hex, } # Overwrite default attributes. bgp_peer_attrs.update(attrs) ret_bgp_peer = _bgp_peer.BgpPeer(**bgp_peer_attrs) return ret_bgp_peer @staticmethod def create_bgp_peers(attrs=None, count=1): """Create one or multiple fake bgp peers.""" bgp_peers = [] for i in range(count): bgp_peer = FakeBgpPeer.create_one_bgp_peer(attrs) bgp_peers.append(bgp_peer) return bgp_peers class FakeDRAgent(object): """Fake one or more dynamic routing agents.""" @staticmethod def create_one_dragent(attrs=None): attrs = attrs or {} # Set default attributes. dragent_attrs = { 'binary': 'neutron-bgp-dragent', 'admin_state_up': True, 'availability_zone': None, 'alive': True, 'topic': 'bgp_dragent', 'host': 'network-' + uuid.uuid4().hex, 'name': 'bgp-dragent-' + uuid.uuid4().hex, 'agent_type': 'BGP dynamic routing agent', 'id': uuid.uuid4().hex, } # Overwrite default attributes. dragent_attrs.update(attrs) return _agent.Agent(**dragent_attrs) @staticmethod def create_dragents(attrs=None, count=1): """Create one or multiple fake dynamic routing agents.""" agents = [] for i in range(count): agent = FakeDRAgent.create_one_dragent(attrs) agents.append(agent) return agents ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py0000664000175000017500000000633700000000000033244 0ustar00zuulzuul00000000000000# 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 unittest import mock from neutronclient.osc.v2.dynamic_routing import bgp_dragent from neutronclient.tests.unit.osc.v2.dynamic_routing import fakes class TestAddBgpSpeakerToDRAgent(fakes.TestNeutronDynamicRoutingOSCV2): _bgp_speaker = fakes.FakeBgpSpeaker.create_one_bgp_speaker() _bgp_dragent = fakes.FakeDRAgent.create_one_dragent() _bgp_speaker_id = _bgp_speaker['id'] _bgp_dragent_id = _bgp_dragent['id'] def setUp(self): super(TestAddBgpSpeakerToDRAgent, self).setUp() # Get the command object to test self.cmd = bgp_dragent.AddBgpSpeakerToDRAgent(self.app, self.namespace) def test_add_bgp_speaker_to_dragent(self): arglist = [ self._bgp_dragent_id, self._bgp_speaker_id, ] verifylist = [ ('dragent_id', self._bgp_dragent_id), ('bgp_speaker', self._bgp_speaker_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(self.networkclient, "add_bgp_speaker_to_dragent", return_value=None): result = self.cmd.take_action(parsed_args) self.networkclient.add_bgp_speaker_to_dragent.\ assert_called_once_with( self._bgp_dragent_id, self._bgp_speaker_id) self.assertIsNone(result) class TestRemoveBgpSpeakerFromDRAgent(fakes.TestNeutronDynamicRoutingOSCV2): _bgp_speaker = fakes.FakeBgpSpeaker.create_one_bgp_speaker() _bgp_dragent = fakes.FakeDRAgent.create_one_dragent() _bgp_speaker_id = _bgp_speaker['id'] _bgp_dragent_id = _bgp_dragent['id'] def setUp(self): super(TestRemoveBgpSpeakerFromDRAgent, self).setUp() # Get the command object to test self.cmd = bgp_dragent.RemoveBgpSpeakerFromDRAgent( self.app, self.namespace) def test_remove_bgp_speaker_from_dragent(self): arglist = [ self._bgp_dragent_id, self._bgp_speaker_id, ] verifylist = [ ('dragent_id', self._bgp_dragent_id), ('bgp_speaker', self._bgp_speaker_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(self.networkclient, "remove_bgp_speaker_from_dragent", return_value=None): result = self.cmd.take_action(parsed_args) self.networkclient.remove_bgp_speaker_from_dragent.\ assert_called_once_with(self._bgp_dragent_id, self._bgp_speaker_id) self.assertIsNone(result) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_peer.py0000664000175000017500000001133500000000000032545 0ustar00zuulzuul00000000000000# 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 unittest import mock from neutronclient.osc.v2.dynamic_routing import bgp_peer from neutronclient.tests.unit.osc.v2.dynamic_routing import fakes class TestListBgpPeer(fakes.TestNeutronDynamicRoutingOSCV2): _bgp_peers = fakes.FakeBgpPeer.create_bgp_peers(count=1) columns = ('ID', 'Name', 'Peer IP', 'Remote AS') data = [] for _bgp_peer in _bgp_peers: data.append(( _bgp_peer['id'], _bgp_peer['name'], _bgp_peer['peer_ip'], _bgp_peer['remote_as'])) def setUp(self): super(TestListBgpPeer, self).setUp() self.networkclient.bgp_peers = mock.Mock( return_value=self._bgp_peers ) # Get the command object to test self.cmd = bgp_peer.ListBgpPeer(self.app, self.namespace) def test_bgp_peer_list(self): parsed_args = self.check_parser(self.cmd, [], []) columns, data = self.cmd.take_action(parsed_args) self.networkclient.bgp_peers.assert_called_once_with( retrieve_all=True) self.assertEqual(self.columns, columns) self.assertEqual(self.data, list(data)) class TestDeleteBgpPeer(fakes.TestNeutronDynamicRoutingOSCV2): _bgp_peer = fakes.FakeBgpPeer.create_one_bgp_peer() def setUp(self): super(TestDeleteBgpPeer, self).setUp() self.networkclient.delete_bgp_peer = mock.Mock(return_value=None) self.cmd = bgp_peer.DeleteBgpPeer(self.app, self.namespace) def test_delete_bgp_peer(self): arglist = [ self._bgp_peer['name'], ] verifylist = [ ('bgp_peer', self._bgp_peer['name']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.networkclient.delete_bgp_peer.assert_called_once_with( self._bgp_peer['name']) self.assertIsNone(result) class TestShowBgpPeer(fakes.TestNeutronDynamicRoutingOSCV2): _one_bgp_peer = fakes.FakeBgpPeer.create_one_bgp_peer() data = ( _one_bgp_peer['auth_type'], _one_bgp_peer['id'], _one_bgp_peer['name'], _one_bgp_peer['peer_ip'], _one_bgp_peer['tenant_id'], _one_bgp_peer['remote_as'], ) _bgp_peer = _one_bgp_peer _bgp_peer_name = _one_bgp_peer['name'] columns = ( 'auth_type', 'id', 'name', 'peer_ip', 'project_id', 'remote_as', ) def setUp(self): super(TestShowBgpPeer, self).setUp() self.networkclient.get_bgp_peer = mock.Mock( return_value=self._bgp_peer ) # Get the command object to test self.cmd = bgp_peer.ShowBgpPeer(self.app, self.namespace) def test_bgp_peer_show(self): arglist = [ self._bgp_peer_name, ] verifylist = [ ('bgp_peer', self._bgp_peer_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) data = self.cmd.take_action(parsed_args) self.networkclient.get_bgp_peer.assert_called_once_with( self._bgp_peer_name) self.assertEqual(self.columns, data[0]) self.assertEqual(self.data, data[1]) class TestSetBgpPeer(fakes.TestNeutronDynamicRoutingOSCV2): _one_bgp_peer = fakes.FakeBgpPeer.create_one_bgp_peer() _bgp_peer_name = _one_bgp_peer['name'] def setUp(self): super(TestSetBgpPeer, self).setUp() self.networkclient.update_bgp_peer = mock.Mock(return_value=None) bgp_peer.get_bgp_peer_id = mock.Mock(return_value=self._bgp_peer_name) self.cmd = bgp_peer.SetBgpPeer(self.app, self.namespace) def test_set_bgp_peer(self): arglist = [ self._bgp_peer_name, '--name', 'noob', ] verifylist = [ ('bgp_peer', self._bgp_peer_name), ('name', 'noob'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) attrs = {'name': 'noob', 'password': None} self.networkclient.update_bgp_peer.assert_called_once_with( self._bgp_peer_name, **attrs) self.assertIsNone(result) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_speaker.py0000664000175000017500000001213600000000000033244 0ustar00zuulzuul00000000000000# 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 unittest import mock from neutronclient.osc.v2.dynamic_routing import bgp_speaker from neutronclient.tests.unit.osc.v2.dynamic_routing import fakes class TestListBgpSpeaker(fakes.TestNeutronDynamicRoutingOSCV2): _bgp_speakers = fakes.FakeBgpSpeaker.create_bgp_speakers() columns = ('ID', 'Name', 'Local AS', 'IP Version') data = [] for _bgp_speaker in _bgp_speakers: data.append(( _bgp_speaker['id'], _bgp_speaker['name'], _bgp_speaker['local_as'], _bgp_speaker['ip_version'])) def setUp(self): super(TestListBgpSpeaker, self).setUp() self.networkclient.bgp_speakers = mock.Mock( return_value=self._bgp_speakers ) # Get the command object to test self.cmd = bgp_speaker.ListBgpSpeaker(self.app, self.namespace) def test_bgp_speaker_list(self): parsed_args = self.check_parser(self.cmd, [], []) columns, data = self.cmd.take_action(parsed_args) self.networkclient.bgp_speakers.assert_called_once_with( retrieve_all=True) self.assertEqual(self.columns, columns) self.assertEqual(self.data, list(data)) class TestDeleteBgpSpeaker(fakes.TestNeutronDynamicRoutingOSCV2): _bgp_speaker = fakes.FakeBgpSpeaker.create_one_bgp_speaker() def setUp(self): super(TestDeleteBgpSpeaker, self).setUp() self.networkclient.delete_bgp_speaker = mock.Mock(return_value=None) self.cmd = bgp_speaker.DeleteBgpSpeaker(self.app, self.namespace) def test_delete_bgp_speaker(self): arglist = [ self._bgp_speaker['name'], ] verifylist = [ ('bgp_speaker', self._bgp_speaker['name']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.networkclient.delete_bgp_speaker.assert_called_once_with( self._bgp_speaker['name']) self.assertIsNone(result) class TestShowBgpSpeaker(fakes.TestNeutronDynamicRoutingOSCV2): _one_bgp_speaker = fakes.FakeBgpSpeaker.create_one_bgp_speaker() data = ( _one_bgp_speaker['advertise_floating_ip_host_routes'], _one_bgp_speaker['advertise_tenant_networks'], _one_bgp_speaker['id'], _one_bgp_speaker['ip_version'], _one_bgp_speaker['local_as'], _one_bgp_speaker['name'], _one_bgp_speaker['networks'], _one_bgp_speaker['peers'], _one_bgp_speaker['tenant_id'] ) _bgp_speaker = _one_bgp_speaker _bgp_speaker_name = _one_bgp_speaker['name'] columns = ( 'advertise_floating_ip_host_routes', 'advertise_tenant_networks', 'id', 'ip_version', 'local_as', 'name', 'networks', 'peers', 'project_id' ) def setUp(self): super(TestShowBgpSpeaker, self).setUp() self.networkclient.get_bgp_speaker = mock.Mock( return_value=self._bgp_speaker ) # Get the command object to test self.cmd = bgp_speaker.ShowBgpSpeaker(self.app, self.namespace) def test_bgp_speaker_show(self): arglist = [ self._bgp_speaker_name, ] verifylist = [ ('bgp_speaker', self._bgp_speaker_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) data = self.cmd.take_action(parsed_args) self.networkclient.get_bgp_speaker.assert_called_once_with( self._bgp_speaker_name) self.assertEqual(self.columns, data[0]) self.assertEqual(self.data, data[1]) class TestSetBgpSpeaker(fakes.TestNeutronDynamicRoutingOSCV2): _one_bgp_speaker = fakes.FakeBgpSpeaker.create_one_bgp_speaker() _bgp_speaker_name = _one_bgp_speaker['name'] def setUp(self): super(TestSetBgpSpeaker, self).setUp() self.networkclient.update_bgp_speaker = mock.Mock( return_value=None) self.cmd = bgp_speaker.SetBgpSpeaker(self.app, self.namespace) def test_set_bgp_speaker(self): arglist = [ self._bgp_speaker_name, '--name', 'noob', ] verifylist = [ ('bgp_speaker', self._bgp_speaker_name), ('name', 'noob'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) attrs = {'name': 'noob'} self.networkclient.update_bgp_speaker.assert_called_once_with( self._bgp_speaker_name, **attrs) self.assertIsNone(result) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/fakes.py0000664000175000017500000000375700000000000025632 0ustar00zuulzuul00000000000000# 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 from unittest import mock from cliff import columns as cliff_columns from osc_lib.tests import utils class TestNeutronClientOSCV2(utils.TestCommand): def setUp(self): super(TestNeutronClientOSCV2, self).setUp() self.namespace = argparse.Namespace() self.app.client_manager.session = mock.Mock() self.app.client_manager.neutronclient = mock.Mock() self.neutronclient = self.app.client_manager.neutronclient self.app.client_manager.network = mock.Mock() self.networkclient = self.app.client_manager.network self.addCleanup(mock.patch.stopall) # TODO(amotoki): Move this to osc_lib def assertListItemEqual(self, expected, actual): self.assertEqual(len(expected), len(actual)) for item_expected, item_actual in zip(expected, actual): self.assertItemEqual(item_expected, item_actual) # TODO(amotoki): Move this to osc_lib def assertItemEqual(self, expected, actual): self.assertEqual(len(expected), len(actual)) for col_expected, col_actual in zip(expected, actual): if isinstance(col_expected, cliff_columns.FormattableColumn): self.assertIsInstance(col_actual, col_expected.__class__) self.assertEqual(col_expected.human_readable(), col_actual.human_readable()) else: self.assertEqual(col_expected, col_actual) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2256625 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/fwaas/0000775000175000017500000000000000000000000025254 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/fwaas/__init__.py0000664000175000017500000000000000000000000027353 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/fwaas/common.py0000664000175000017500000002432100000000000027120 0ustar00zuulzuul00000000000000# Copyright 2016-2017 FUJITSU LIMITED # 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 testtools from osc_lib import exceptions from osc_lib.tests import utils from neutronclient.tests.unit.osc.v2 import fakes as test_fakes class TestListFWaaS(test_fakes.TestNeutronClientOSCV2): def test_list_with_no_option(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.list_headers), headers) self.assertEqual([self.list_data], list(data)) def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) class TestShowFWaaS(test_fakes.TestNeutronClientOSCV2): def test_show_filtered_by_id_or_name(self): target = self.resource['id'] headers, data = None, None def _mock_fwaas(*args, **kwargs): return {'id': args[0]} self.networkclient.find_firewall_policy.side_effect = _mock_fwaas self.networkclient.find_firewall_group.side_effect = _mock_fwaas self.networkclient.find_firewall_rule.side_effect = _mock_fwaas arglist = [target] verifylist = [(self.res, target)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target) self.assertEqual(self.ordered_headers, headers) class TestCreateFWaaS(test_fakes.TestNeutronClientOSCV2): pass class TestSetFWaaS(test_fakes.TestNeutronClientOSCV2): def test_set_name(self): target = self.resource['id'] update = 'change' arglist = [target, '--name', update] verifylist = [ (self.res, target), ('name', update), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'name': update}) self.assertIsNone(result) def test_set_description(self): target = self.resource['id'] update = 'change-desc' arglist = [target, '--description', update] verifylist = [ (self.res, target), ('description', update), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'description': update}) self.assertIsNone(result) def test_set_shared(self): target = self.resource['id'] arglist = [target, '--share'] verifylist = [ (self.res, target), ('share', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'shared': True}) self.assertIsNone(result) def test_set_duplicate_shared(self): target = self.resource['id'] arglist = [target, '--share', '--share'] verifylist = [ (self.res, target), ('share', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'shared': True}) self.assertIsNone(result) def test_set_no_share(self): target = self.resource['id'] arglist = [target, '--no-share'] verifylist = [ (self.res, target), ('share', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'shared': False}) self.assertIsNone(result) def test_set_duplicate_no_share(self): target = self.resource['id'] arglist = [target, '--no-share', '--no-share'] verifylist = [ (self.res, target), ('no_share', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'shared': False}) self.assertIsNone(result) def test_set_no_share_and_shared(self): target = self.resource['id'] arglist = [target, '--no-share', '--share'] verifylist = [ (self.res, target), ('no_share', True), ('share', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_set_shared_and_no_share(self): target = self.resource['id'] arglist = [target, '--share', '--no_share'] verifylist = [ (self.res, target), ('share', True), ('no_share', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_set_project(self): target = self.resource['id'] project_id = 'b14ce3b699594d13819a859480286489' arglist = [target, '--project', project_id] verifylist = [ (self.res, target), ('tenant_id', project_id), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_set_project_domain(self): target = self.resource['id'] project_domain = 'mydomain.com' arglist = [target, '--project-domain', project_domain] verifylist = [ (self.res, target), ('project_domain', project_domain), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) class TestDeleteFWaaS(test_fakes.TestNeutronClientOSCV2): def test_delete_with_one_resource(self): target = self.resource['id'] def _mock_fwaas(*args, **kwargs): return {'id': args[0]} self.networkclient.find_firewall_group.side_effect = _mock_fwaas self.networkclient.find_firewall_policy.side_effect = _mock_fwaas self.networkclient.find_firewall_rule.side_effect = _mock_fwaas arglist = [target] verifylist = [(self.res, [target])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target) self.assertIsNone(result) def test_delete_with_multiple_resources(self): def _mock_fwaas(*args, **kwargs): return {'id': args[0]} self.networkclient.find_firewall_group.side_effect = _mock_fwaas self.networkclient.find_firewall_policy.side_effect = _mock_fwaas self.networkclient.find_firewall_rule.side_effect = _mock_fwaas target1 = 'target1' target2 = 'target2' arglist = [target1, target2] verifylist = [(self.res, [target1, target2])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.assertEqual(2, self.mocked.call_count) for idx, reference in enumerate([target1, target2]): actual = ''.join(self.mocked.call_args_list[idx][0][0]) self.assertEqual(reference, actual) def test_delete_multiple_with_exception(self): target1 = 'target' arglist = [target1] verifylist = [(self.res, [target1])] self.networkclient.find_firewall_group.side_effect = [ target1, exceptions.CommandError ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) resource_name = self.res.replace('_', ' ') msg = "1 of 2 %s(s) failed to delete." % resource_name with testtools.ExpectedException(exceptions.CommandError) as e: self.cmd.take_action(parsed_args) self.assertEqual(msg, str(e)) class TestUnsetFWaaS(test_fakes.TestNeutronClientOSCV2): def test_unset_shared(self): target = self.resource['id'] arglist = [ target, '--share', ] verifylist = [ (self.res, target), ('share', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'shared': False}) self.assertIsNone(result) def test_set_shared_and_no_shared(self): target = self.resource['id'] arglist = [target, '--share', '--no-share'] verifylist = [ (self.res, target), ('share', True), ('no_share', True), ] # check_parser: error: unrecognized arguments: --no-share self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_set_duplicate_shared(self): target = self.resource['id'] arglist = [target, '--share', '--share'] verifylist = [ (self.res, target), ('share', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'shared': False}) self.assertIsNone(result) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/fwaas/fakes.py0000664000175000017500000001304500000000000026722 0ustar00zuulzuul00000000000000# Copyright 2016 FUJITSU LIMITED # 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 collections from unittest import mock from openstack.network.v2 import firewall_group as fw_group from openstack.network.v2 import firewall_policy as fw_policy from openstack.network.v2 import firewall_rule as fw_rule from oslo_utils import uuidutils class FakeFWaaS(object): def create(self, attrs={}): """Create a fake fwaas resources :param Dictionary attrs: A dictionary with all attributes :return: A OrderedDict faking the fwaas resource """ self.ordered.update(attrs) if 'FirewallGroup' == self.__class__.__name__: return fw_group.FirewallGroup(**self.ordered) if 'FirewallPolicy' == self.__class__.__name__: return fw_policy.FirewallPolicy(**self.ordered) if 'FirewallRule' == self.__class__.__name__: fw_r = fw_rule.FirewallRule(**self.ordered) protocol = fw_r['protocol'].upper() if fw_r['protocol'] else 'ANY' src_ip = str(fw_r['source_ip_address']).lower() src_port = '(' + str(fw_r['source_port']).lower() + ')' dst_ip = str(fw_r['destination_ip_address']).lower() dst_port = '(' + str(fw_r['destination_port']).lower() + ')' src = 'source(port): ' + src_ip + src_port dst = 'dest(port): ' + dst_ip + dst_port action = fw_r['action'] if fw_r.get('action') else 'no-action' fw_r['summary'] = ',\n '.join([protocol, src, dst, action]) return fw_r def bulk_create(self, attrs=None, count=2): """Create multiple fake fwaas resources :param Dictionary attrs: A dictionary with all attributes :param int count: The number of fwaas resources to fake :return: A list of dictionaries faking the fwaas resources """ return [self.create(attrs=attrs) for i in range(0, count)] def get(self, attrs=None, count=2): """Create multiple fake fwaas resources :param Dictionary attrs: A dictionary with all attributes :param int count: The number of fwaas resources to fake :return: A list of dictionaries faking the fwaas resource """ if attrs is None: self.attrs = self.bulk_create(count=count) return mock.Mock(side_effect=attrs) class FirewallGroup(FakeFWaaS): """Fake one or more firewall group""" def __init__(self): super(FirewallGroup, self).__init__() self.ordered = collections.OrderedDict(( ('id', 'firewall-group-id-' + uuidutils.generate_uuid(dashed=False)), ('name', 'my-group-' + uuidutils.generate_uuid(dashed=False)), ('ingress_firewall_policy_id', None), ('egress_firewall_policy_id', None), ('description', 'my-desc-' + uuidutils.generate_uuid(dashed=False)), ('status', 'INACTIVE'), ('ports', []), ('admin_state_up', True), ('shared', False), ('tenant_id', 'tenant-id-' + uuidutils.generate_uuid(dashed=False)), )) class FirewallPolicy(FakeFWaaS): """Fake one or more firewall policy""" def __init__(self): super(FirewallPolicy, self).__init__() self.ordered = collections.OrderedDict(( ('id', 'firewall-policy-' + uuidutils.generate_uuid(dashed=False)), ('name', 'my-policy-' + uuidutils.generate_uuid(dashed=False)), ('firewall_rules', []), ('description', 'my-desc-' + uuidutils.generate_uuid(dashed=False)), ('audited', True), ('shared', False), ('tenant_id', 'tenant-id-' + uuidutils.generate_uuid(dashed=False)), )) class FirewallRule(FakeFWaaS): """Fake one or more firewall rule""" def __init__(self): super(FirewallRule, self).__init__() self.ordered = collections.OrderedDict(( ('id', 'firewall-rule-id-' + uuidutils.generate_uuid(dashed=False)), ('name', 'my-rule-' + uuidutils.generate_uuid(dashed=False)), ('enabled', False), ('description', 'my-desc-' + uuidutils.generate_uuid(dashed=False)), ('ip_version', 4), ('action', 'deny'), ('protocol', None), ('source_ip_address', '192.168.1.0/24'), ('source_port', '1:11111'), ('destination_ip_address', '192.168.2.2'), ('destination_port', '2:22222'), ('shared', False), ('tenant_id', 'tenant-id-' + uuidutils.generate_uuid(dashed=False)), ('source_firewall_group_id', 'firewall-group-id-' + uuidutils.generate_uuid(dashed=False)), ('destination_firewall_group_id', 'firewall-group-id-' + uuidutils.generate_uuid(dashed=False)), )) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py0000664000175000017500000006236000000000000031556 0ustar00zuulzuul00000000000000# Copyright 2016 FUJITSU LIMITED # 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 copy import re from unittest import mock from osc_lib import exceptions from osc_lib.tests import utils from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.fwaas import firewallgroup 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.fwaas import common from neutronclient.tests.unit.osc.v2.fwaas import fakes _fwg = fakes.FirewallGroup().create() CONVERT_MAP = { 'ingress_firewall_policy': 'ingress_firewall_policy_id', 'egress_firewall_policy': 'egress_firewall_policy_id', 'no_ingress_firewall_policy': 'ingress_firewall_policy_id', 'no_egress_firewall_policy': 'egress_firewall_policy_id', 'share': 'shared', 'no_share': 'shared', 'project': 'tenant_id', 'enable': 'admin_state_up', 'disable': 'admin_state_up', 'port': 'ports', } def _generate_response(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _fwg up = {'admin_state_up': v2_utils.AdminStateColumn(source['admin_state_up'])} if data: up.append(data) source.update(up) return source def _generate_req_and_res(verifylist): request = dict(verifylist) response = _fwg for key, val in verifylist: del request[key] if re.match('^no_', key) and val is True: new_value = None elif key == 'enable' and val: new_value = True elif key == 'disable' and val: new_value = False elif val is True or val is False: new_value = val elif key in ('name', 'description'): new_value = val else: new_value = val converted = CONVERT_MAP.get(key, key) request[converted] = new_value response[converted] = new_value return request, response class TestFirewallGroup(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req, is_list=False): if is_list: req_body = {self.res_plural: list(exp_req)} else: req_body = exp_req self.mocked.assert_called_once_with(**req_body) self.assertEqual(self.ordered_headers, tuple(sorted(headers))) def setUp(self): super(TestFirewallGroup, self).setUp() def _find_resource(*args, **kwargs): return {'id': args[0], 'ports': _fwg['ports']} self.networkclient.find_firewall_group = mock.Mock( side_effect=_find_resource) osc_utils.find_project = mock.Mock() osc_utils.find_project.id = _fwg['tenant_id'] self.res = 'firewall_group' self.res_plural = 'firewall_groups' self.resource = _fwg self.list_headers = ( 'ID', 'Name', 'Ingress Policy ID', 'Egress Policy ID', ) self.list_data = ( _fwg['id'], _fwg['name'], _fwg['ingress_firewall_policy_id'], _fwg['egress_firewall_policy_id'], ) self.headers = tuple(self.list_headers + ( 'Description', 'Status', 'Ports', 'State', 'Shared', 'Project', )) self.data = _generate_response() self.ordered_headers = copy.deepcopy(tuple(sorted(self.headers))) self.expected_data = ( _fwg['description'], _fwg['egress_firewall_policy_id'], _fwg['id'], _fwg['ingress_firewall_policy_id'], _fwg['name'], _fwg['ports'], _fwg['tenant_id'], _fwg['shared'], v2_utils.AdminStateColumn(_fwg['admin_state_up']), _fwg['status'], ) self.ordered_columns = ( 'description', 'egress_firewall_policy_id', 'id', 'ingress_firewall_policy_id', 'name', 'ports', 'tenant_id', 'shared', 'admin_state_up', 'status', ) class TestCreateFirewallGroup(TestFirewallGroup, common.TestCreateFWaaS): def setUp(self): # Mock objects super(TestCreateFirewallGroup, self).setUp() self.networkclient.create_firewall_group = mock.Mock( return_value=_fwg) self.mocked = self.networkclient.create_firewall_group self.cmd = firewallgroup.CreateFirewallGroup(self.app, self.namespace) def _update_expect_response(self, request, response): """Set expected request and response :param request A dictionary of request body(dict of verifylist) :param response A OrderedDict of request body """ # Update response body self.networkclient.create_firewall_group.return_value = response osc_utils.find_project.return_value.id = response['tenant_id'] # Update response(finally returns 'data') self.data = _generate_response(ordered_dict=response) self.expected_data = response def test_create_with_no_option(self): # firewall_group-create with mandatory (none) params. arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.assertEqual(self.ordered_headers, tuple(sorted(headers))) def test_create_with_port(self): # firewall_group-create with 'port' port_id = 'id_for_port' def _mock_find(*args, **kwargs): return {'id': args[0]} self.networkclient.find_port.side_effect = _mock_find arglist = ['--port', port_id] verifylist = [('port', [port_id])] request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.check_results(headers, data, request) def test_create_with_ingress_policy(self): ingress_policy = 'my-ingress-policy' def _mock_port_fwg(*args, **kwargs): return {'id': args[0]} self.networkclient.find_firewall_policy.side_effect = _mock_port_fwg arglist = ['--ingress-firewall-policy', ingress_policy] verifylist = [('ingress_firewall_policy', ingress_policy)] request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.networkclient.find_firewall_policy.assert_called_once_with( ingress_policy) self.check_results(headers, data, request) def test_create_with_egress_policy(self): egress_policy = 'my-egress-policy' def _mock_find(*args, **kwargs): return {'id': args[0]} self.networkclient.find_firewall_group.side_effect = _mock_find self.networkclient.find_firewall_policy.side_effect = _mock_find arglist = ['--egress-firewall-policy', egress_policy] verifylist = [('egress_firewall_policy', egress_policy)] request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.networkclient.find_firewall_policy.assert_called_once_with( egress_policy) self.check_results(headers, data, request) def test_create_with_all_params(self): name = 'my-name' description = 'my-desc' ingress_policy = 'my-ingress-policy' egress_policy = 'my-egress-policy' def _mock_find(*args, **kwargs): return {'id': args[0]} self.networkclient.find_firewall_policy.side_effect = _mock_find port = 'port' self.networkclient.find_port.side_effect = _mock_find tenant_id = 'my-tenant' arglist = [ '--name', name, '--description', description, '--ingress-firewall-policy', ingress_policy, '--egress-firewall-policy', egress_policy, '--port', port, '--project', tenant_id, '--share', '--disable', ] verifylist = [ ('name', name), ('description', description), ('ingress_firewall_policy', ingress_policy), ('egress_firewall_policy', egress_policy), ('port', [port]), ('share', True), ('project', tenant_id), ('disable', True), ] request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.check_results(headers, data, request) def test_create_with_shared_and_no_share(self): arglist = [ '--share', '--no-share', ] verifylist = [ ('share', True), ('no_share', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_ports_and_no(self): port = 'my-port' arglist = [ '--port', port, '--no-port', ] verifylist = [ ('port', [port]), ('no_port', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_ingress_policy_and_no(self): policy = 'my-policy' arglist = [ '--ingress-firewall-policy', policy, '--no-ingress-firewall-policy', ] verifylist = [ ('ingress_firewall_policy', policy), ('no_ingress_firewall_policy', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_egress_policy_and_no(self): policy = 'my-policy' arglist = [ '--egress-firewall-policy', policy, '--no-egress-firewall-policy', ] verifylist = [ ('egress_firewall_policy', policy), ('no_egress_firewall_policy', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) class TestListFirewallGroup(TestFirewallGroup, common.TestListFWaaS): def setUp(self): super(TestListFirewallGroup, self).setUp() # Mock objects self.networkclient.firewall_groups = mock.Mock( return_value=[_fwg]) self.mocked = self.networkclient.firewall_groups self.cmd = firewallgroup.ListFirewallGroup(self.app, self.namespace) class TestShowFirewallGroup(TestFirewallGroup, common.TestShowFWaaS): def setUp(self): super(TestShowFirewallGroup, self).setUp() # Mock objects self.networkclient.get_firewall_group = mock.Mock( return_value=_fwg) self.mocked = self.networkclient.get_firewall_group self.cmd = firewallgroup.ShowFirewallGroup(self.app, self.namespace) class TestSetFirewallGroup(TestFirewallGroup, common.TestSetFWaaS): def setUp(self): super(TestSetFirewallGroup, self).setUp() # Mock objects _fwg['ports'] = ['old_port'] self.networkclient.update_firewall_group = mock.Mock( return_value={self.res: _fwg}) self.mocked = self.networkclient.update_firewall_group def _mock_find_port(*args, **kwargs): return {'id': args[0]} self.networkclient.find_port.side_effect = _mock_find_port self.cmd = firewallgroup.SetFirewallGroup(self.app, self.namespace) def _update_expect_response(self, request, response): """Set expected request and response :param request A dictionary of request body(dict of verifylist) :param response A OrderedDict of request body """ osc_utils.find_project.return_value.id = response['tenant_id'] # Update response(finally returns 'data') self.data = _generate_response(ordered_dict=response) self.ordered_data = tuple( response[column] for column in self.ordered_columns ) def test_set_ingress_policy_and_egress_policy(self): target = self.resource['id'] ingress_policy = 'ingress_policy' egress_policy = 'egress_policy' def _mock_fwg_policy(*args, **kwargs): # 1. Find specified firewall_group if self.networkclient.find_firewall_group.call_count == 1: self.networkclient.find_firewall_group.assert_called_with( target) # 2. Find specified 'ingress_firewall_policy' if self.networkclient.find_firewall_policy.call_count == 1: self.networkclient.find_firewall_policy.assert_called_with( ingress_policy) # 3. Find specified 'ingress_firewall_policy' if self.networkclient.find_firewall_policy.call_count == 2: self.networkclient.find_firewall_policy.assert_called_with( egress_policy) return {'id': args[0]} self.networkclient.find_firewall_group.side_effect = _mock_fwg_policy self.networkclient.find_firewall_policy.side_effect = _mock_fwg_policy arglist = [ target, '--ingress-firewall-policy', ingress_policy, '--egress-firewall-policy', egress_policy, ] verifylist = [ (self.res, target), ('ingress_firewall_policy', ingress_policy), ('egress_firewall_policy', egress_policy), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'ingress_firewall_policy_id': ingress_policy, 'egress_firewall_policy_id': egress_policy}) self.assertIsNone(result) def test_set_port(self): target = self.resource['id'] port1 = 'additional_port1' port2 = 'additional_port2' def _mock_port_fwg(*args, **kwargs): # 1. Find specified firewall_group if self.networkclient.find_firewall_group.call_count in [1, 2]: self.networkclient.find_firewall_group.assert_called_with( target) return {'id': args[0], 'ports': _fwg['ports']} # 2. Find specified 'port' #1 if self.networkclient.find_port.call_count == 1: self.networkclient.find_port.assert_called_with(args) return {'id': args[0]} # 3. Find specified 'port' #2 if self.networkclient.find_port.call_count == 2: self.networkclient.find_port.assert_called_with(args) return {'id': args[0]} self.networkclient.find_fireall_group.side_effect = _mock_port_fwg self.networkclient.find_port.side_effect = _mock_port_fwg arglist = [ target, '--port', port1, '--port', port2, ] verifylist = [ (self.res, target), ('port', [port1, port2]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'ports': sorted(_fwg['ports'] + [port1, port2])} self.mocked.assert_called_once_with(target, **expect) self.assertEqual(2, self.networkclient.find_firewall_group.call_count) self.assertIsNone(result) def test_set_no_port(self): # firewall_group-update myid --policy newpolicy. target = self.resource['id'] arglist = [target, '--no-port'] verifylist = [ (self.res, target), ('no_port', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'ports': []}) self.assertIsNone(result) def test_set_admin_state(self): target = self.resource['id'] arglist = [target, '--enable'] verifylist = [ (self.res, target), ('enable', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'admin_state_up': True}) self.assertIsNone(result) def test_set_egress_policy(self): target = self.resource['id'] policy = 'egress_policy' def _mock_find_policy(*args, **kwargs): return {'id': args[0]} self.networkclient.find_firewall_policy.side_effect = _mock_find_policy arglist = [target, '--egress-firewall-policy', policy] verifylist = [ (self.res, target), ('egress_firewall_policy', policy), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'egress_firewall_policy_id': policy}) self.assertIsNone(result) def test_set_no_ingress_policies(self): target = self.resource['id'] arglist = [target, '--no-ingress-firewall-policy'] verifylist = [ (self.res, target), ('no_ingress_firewall_policy', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'ingress_firewall_policy_id': None}) self.assertIsNone(result) def test_set_no_egress_policies(self): target = self.resource['id'] arglist = [target, '--no-egress-firewall-policy'] verifylist = [ (self.res, target), ('no_egress_firewall_policy', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'egress_firewall_policy_id': None}) self.assertIsNone(result) def test_set_port_and_no_port(self): target = self.resource['id'] port = 'my-port' arglist = [ target, '--port', port, '--no-port', ] verifylist = [ (self.res, target), ('port', [port]), ('no_port', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'ports': [port]}) self.assertIsNone(result) def test_set_ingress_policy_and_no_ingress_policy(self): target = self.resource['id'] arglist = [ target, '--ingress-firewall-policy', 'my-ingress', '--no-ingress-firewall-policy', ] verifylist = [ (self.res, target), ('ingress_firewall_policy', 'my-ingress'), ('no_ingress_firewall_policy', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_set_egress_policy_and_no_egress_policy(self): target = self.resource['id'] arglist = [ target, '--egress-firewall-policy', 'my-egress', '--no-egress-firewall-policy', ] verifylist = [ (self.res, target), ('egress_firewall_policy', 'my-egress'), ('no_egress_firewall_policy', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_set_and_raises(self): self.networkclient.update_firewall_group = mock.Mock( side_effect=Exception) target = self.resource['id'] arglist = [target, '--name', 'my-name'] verifylist = [(self.res, target), ('name', 'my-name')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) class TestDeleteFirewallGroup(TestFirewallGroup, common.TestDeleteFWaaS): def setUp(self): super(TestDeleteFirewallGroup, self).setUp() # Mock objects self.networkclient.delete_firewall_group = mock.Mock() self.mocked = self.networkclient.delete_firewall_group self.cmd = firewallgroup.DeleteFirewallGroup(self.app, self.namespace) class TestUnsetFirewallGroup(TestFirewallGroup, common.TestUnsetFWaaS): def setUp(self): super(TestUnsetFirewallGroup, self).setUp() _fwg['ports'] = ['old_port'] # Mock objects self.networkclient.update_firewall_group = mock.Mock() self.mocked = self.networkclient.update_firewall_group self.cmd = firewallgroup.UnsetFirewallGroup(self.app, self.namespace) def test_unset_ingress_policy(self): target = self.resource['id'] arglist = [ target, '--ingress-firewall-policy', ] verifylist = [ (self.res, target), ('ingress_firewall_policy', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'ingress_firewall_policy_id': None}) self.assertIsNone(result) def test_unset_egress_policy(self): target = self.resource['id'] arglist = [ target, '--egress-firewall-policy', ] verifylist = [ (self.res, target), ('egress_firewall_policy', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'egress_firewall_policy_id': None}) self.assertIsNone(result) def test_unset_enable(self): target = self.resource['id'] arglist = [ target, '--enable', ] verifylist = [ (self.res, target), ('enable', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'admin_state_up': False}) self.assertIsNone(result) def test_unset_port(self): target = self.resource['id'] port = 'old_port' def _mock_port_fwg(*args, **kwargs): # 1. Find specified firewall_group if self.networkclient.find_firewall_group.call_count in [1, 2]: self.networkclient.find_firewall_group.assert_called_with( target) return {'id': args[0], 'ports': _fwg['ports']} # 2. Find specified firewall_group and refer 'ports' attribute if self.networkclient.find_port.call_count == 2: self.networkclient.find_port.assert_called_with(target) return {'ports': _fwg['ports']} # 3. Find specified 'port' if self.networkclient.find_port.call_count == 3: self.networkclient.find_port.assert_called_with(port) return {'id': args[0]} self.networkclient.find_firewall_group.side_effect = _mock_port_fwg self.networkclient.find_port.side_effect = _mock_port_fwg arglist = [ target, '--port', port, ] verifylist = [ (self.res, target), ('port', [port]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'ports': []}) self.assertIsNone(result) def test_unset_all_port(self): target = self.resource['id'] arglist = [ target, '--all-port', ] verifylist = [ (self.res, target), ('all_port', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'ports': []}) self.assertIsNone(result) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py0000664000175000017500000005313100000000000031715 0ustar00zuulzuul00000000000000# Copyright 2016 FUJITSU LIMITED # 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 re from unittest import mock from osc_lib import exceptions from osc_lib.tests import utils from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.fwaas import firewallpolicy from neutronclient.tests.unit.osc.v2 import fakes as test_fakes from neutronclient.tests.unit.osc.v2.fwaas import common from neutronclient.tests.unit.osc.v2.fwaas import fakes _fwp = fakes.FirewallPolicy().create() CONVERT_MAP = { 'share': 'shared', 'no_share': 'shared', 'project': 'tenant_id', 'port': 'ports', 'name': 'name', 'id': 'id', 'firewall_rule': 'firewall_rules', 'description': 'description' } def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _fwp if data: source.update(data) return tuple(source[key] for key in source) def _generate_req_and_res(verifylist): request = dict(verifylist) response = _fwp for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] if re.match('^no_', key) and val is True: new_value = None elif key == 'enable' and val: new_value = True elif key == 'disable' and val: new_value = False elif val is True or val is False: new_value = val elif key in ('name', 'description'): new_value = val else: new_value = val request[converted] = new_value response[converted] = new_value return request, response class TestFirewallPolicy(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req, is_list=False): if is_list: req_body = {self.res_plural: [exp_req]} else: req_body = exp_req self.mocked.assert_called_once_with(**req_body) self.assertEqual(self.ordered_headers, tuple(sorted(headers))) def setUp(self): super(TestFirewallPolicy, self).setUp() osc_utils.find_project = mock.Mock() osc_utils.find_project.id = _fwp['tenant_id'] self.res = 'firewall_policy' self.res_plural = 'firewall_policies' self.resource = _fwp self.list_headers = ( 'ID', 'Name', 'Firewall Rules', ) self.list_data = ( _fwp['id'], _fwp['name'], _fwp['firewall_rules'], ) self.headers = tuple(self.list_headers + ( 'Description', 'Audited', 'Shared', 'Project') ) self.data = _generate_data() self.ordered_headers = ( 'Audited', 'Description', 'Firewall Rules', 'ID', 'Name', 'Project', 'Shared', ) self.ordered_data = ( _fwp['audited'], _fwp['description'], _fwp['firewall_rules'], _fwp['id'], _fwp['name'], _fwp['tenant_id'], _fwp['shared'], ) self.ordered_columns = ( 'audited', 'description', 'firewall_rules', 'id', 'name', 'tenant_id', 'shared', ) class TestCreateFirewallPolicy(TestFirewallPolicy, common.TestCreateFWaaS): def setUp(self): super(TestCreateFirewallPolicy, self).setUp() self.networkclient.create_firewall_policy = mock.Mock( return_value={self.res: _fwp}) self.mocked = self.networkclient.create_firewall_policy self.cmd = firewallpolicy.CreateFirewallPolicy(self.app, self.namespace) def _update_expect_response(self, request, response): """Set expected request and response :param request A dictionary of request body(dict of verifylist) :param response A OrderedDict of request body """ # Update response body self.networkclient.create_firewall_policy.return_value = response osc_utils.find_project.return_value.id = response['tenant_id'] # Update response(finally returns 'data') self.data = _generate_data(data=response) self.ordered_data = tuple( response[column] for column in self.ordered_columns ) def test_create_with_no_options(self): arglist = [] verifylist = [] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_mandatory_param(self): name = 'my-fwg' arglist = [ name, ] verifylist = [ ('name', name), ] request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.check_results(headers, data, request) def test_create_with_rules(self): name = 'my-fwg' rule1 = 'rule1' rule2 = 'rule2' def _mock_policy(*args, **kwargs): return {'id': args[0]} self.networkclient.find_firewall_rule.side_effect = _mock_policy arglist = [ name, '--firewall-rule', rule1, '--firewall-rule', rule2, ] verifylist = [ ('name', name), ('firewall_rule', [rule1, rule2]), ] request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.assertEqual(2, self.networkclient.find_firewall_rule.call_count) self.check_results(headers, data, request) def test_create_with_all_params(self): name = 'my-fwp' desc = 'my-desc' rule1 = 'rule1' rule2 = 'rule2' project = 'my-tenant' def _mock_find(*args, **kwargs): if self.res in args[0]: rules = _fwp['firewall_rules'] return {'id': args[0], 'firewall_rules': rules} return {'id': args[0]} self.networkclient.find_firewall_policy.side_effect = _mock_find self.networkclient.find_firewall_rule.side_effect = _mock_find arglist = [ name, '--description', desc, '--firewall-rule', rule1, '--firewall-rule', rule2, '--project', project, '--share', '--audited', ] verifylist = [ ('name', name), ('description', desc), ('firewall_rule', [rule1, rule2]), ('project', project), ('share', True), ('audited', True), ] request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.check_results(headers, data, request) def test_create_with_firewall_rule_and_no(self): name = 'my-fwp' rule1 = 'rule1' rule2 = 'rule2' arglist = [ name, '--firewall-rule', rule1, '--firewall-rule', rule2, '--no-firewall-rule', ] verifylist = [ ('name', name), ('firewall_rule', [rule1, rule2]), ('no_firewall_rule', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_shared_and_no_share(self): name = 'my-fwp' arglist = [ name, '--share', '--no-share', ] verifylist = [ ('name', name), ('share', True), ('no_share', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_audited_and_no(self): name = 'my-fwp' arglist = [ name, '--audited', '--no-audited', ] verifylist = [ ('name', name), ('audited', True), ('no_audited', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) class TestListFirewallPolicy(TestFirewallPolicy, common.TestListFWaaS): def setUp(self): super(TestListFirewallPolicy, self).setUp() self.networkclient.firewall_policies = mock.Mock( return_value=[_fwp]) self.mocked = self.networkclient.firewall_policies self.cmd = firewallpolicy.ListFirewallPolicy(self.app, self.namespace) class TestShowFirewallPolicy(TestFirewallPolicy, common.TestShowFWaaS): def setUp(self): super(TestShowFirewallPolicy, self).setUp() self.networkclient.get_firewall_policy = mock.Mock( return_value=_fwp) self.mocked = self.networkclient.get_firewall_policy self.cmd = firewallpolicy.ShowFirewallPolicy(self.app, self.namespace) class TestSetFirewallPolicy(TestFirewallPolicy, common.TestSetFWaaS): def setUp(self): super(TestSetFirewallPolicy, self).setUp() self.networkclient.update_firewall_policy = mock.Mock( return_value=_fwp) self.mocked = self.networkclient.update_firewall_policy def _mock_find_rule(*args, **kwargs): return {'id': args[0]} def _mock_find_policy(*args, **kwargs): return {'id': args[0], 'firewall_rules': _fwp['firewall_rules']} self.networkclient.find_firewall_policy.side_effect = _mock_find_policy self.networkclient.find_firewall_rule.side_effect = _mock_find_rule self.cmd = firewallpolicy.SetFirewallPolicy(self.app, self.namespace) def test_set_rules(self): target = self.resource['id'] rule1 = 'new_rule1' rule2 = 'new_rule2' arglist = [ target, '--firewall-rule', rule1, '--firewall-rule', rule2, ] verifylist = [ (self.res, target), ('firewall_rule', [rule1, rule2]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = _fwp['firewall_rules'] + [rule1, rule2] body = {'firewall_rules': expect} self.mocked.assert_called_once_with(target, **body) self.assertEqual(2, self.networkclient.find_firewall_rule.call_count) self.assertEqual(2, self.networkclient.find_firewall_policy.call_count) self.assertIsNone(result) def test_set_no_rules(self): target = self.resource['id'] arglist = [target, '--no-firewall-rule'] verifylist = [ (self.res, target), ('no_firewall_rule', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) body = {'firewall_rules': []} self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) def test_set_rules_and_no_rules(self): target = self.resource['id'] rule1 = 'rule1' arglist = [ target, '--firewall-rule', rule1, '--no-firewall-rule', ] verifylist = [ (self.res, target), ('firewall_rule', [rule1]), ('no_firewall_rule', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) body = {'firewall_rules': [rule1]} self.mocked.assert_called_once_with(target, **body) self.assertEqual(1, self.networkclient.find_firewall_rule.call_count) self.assertEqual(1, self.networkclient.find_firewall_policy.call_count) self.assertIsNone(result) def test_set_audited(self): target = self.resource['id'] arglist = [target, '--audited'] verifylist = [ (self.res, target), ('audited', True), ] body = {'audited': True} parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) def test_set_no_audited(self): target = self.resource['id'] arglist = [target, '--no-audited'] verifylist = [ (self.res, target), ('no_audited', True), ] body = {'audited': False} parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) def test_set_audited_and_no_audited(self): target = self.resource['id'] arglist = [ target, '--audited', '--no-audited', ] verifylist = [ (self.res, target), ('audited', True), ('no_audited', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_set_and_raises(self): self.networkclient.update_firewall_policy = mock.Mock( side_effect=Exception) target = self.resource['id'] arglist = [target, '--name', 'my-name'] verifylist = [(self.res, target), ('name', 'my-name')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) class TestDeleteFirewallPolicy(TestFirewallPolicy, common.TestDeleteFWaaS): def setUp(self): super(TestDeleteFirewallPolicy, self).setUp() self.networkclient.delete_firewall_policy = mock.Mock( return_value={self.res: _fwp}) self.mocked = self.networkclient.delete_firewall_policy self.cmd = firewallpolicy.DeleteFirewallPolicy( self.app, self.namespace) class TestFirewallPolicyInsertRule(TestFirewallPolicy): def setUp(self): super(TestFirewallPolicyInsertRule, self).setUp() self.networkclient.insert_rule_firewall_policy = mock.Mock( return_value={self.res: _fwp}) self.mocked = self.networkclient.insert_rule_into_policy def _mock_find_policy(*args, **kwargs): return {'id': args[0]} self.networkclient.find_firewall_policy.side_effect = _mock_find_policy self.networkclient.find_firewall_rule.side_effect = _mock_find_policy self.cmd = firewallpolicy.FirewallPolicyInsertRule(self.app, self.namespace) def test_insert_firewall_rule(self): target = self.resource['id'] rule = 'new-rule' before = 'before' after = 'after' arglist = [ target, rule, '--insert-before', before, '--insert-after', after, ] verifylist = [ (self.res, target), ('firewall_rule', rule), ('insert_before', before), ('insert_after', after), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, { 'firewall_rule_id': rule, 'insert_before': before, 'insert_after': after }) self.assertIsNone(result) self.assertEqual(1, self.networkclient.find_firewall_policy.call_count) self.assertEqual(3, self.networkclient.find_firewall_rule.call_count) def test_insert_with_no_firewall_rule(self): target = self.resource['id'] arglist = [ target, ] verifylist = [ (self.res, target), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) class TestFirewallPolicyRemoveRule(TestFirewallPolicy): def setUp(self): super(TestFirewallPolicyRemoveRule, self).setUp() self.networkclient.remove_rule_firewall_policy = mock.Mock( return_value={self.res: _fwp}) self.mocked = self.networkclient.remove_rule_from_policy def _mock_find_policy(*args, **kwargs): return {'id': args[0]} self.networkclient.find_firewall_policy.side_effect = _mock_find_policy self.networkclient.find_firewall_rule.side_effect = _mock_find_policy self.cmd = firewallpolicy.FirewallPolicyRemoveRule(self.app, self.namespace) def test_remove_firewall_rule(self): target = self.resource['id'] rule = 'remove-rule' arglist = [ target, rule, ] verifylist = [ (self.res, target), ('firewall_rule', rule), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, {'firewall_rule_id': rule}) self.assertIsNone(result) self.assertEqual(1, self.networkclient.find_firewall_policy.call_count) self.assertEqual(1, self.networkclient.find_firewall_rule.call_count) def test_remove_with_no_firewall_rule(self): target = self.resource['id'] arglist = [ target, ] verifylist = [ (self.res, target), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) class TestUnsetFirewallPolicy(TestFirewallPolicy, common.TestUnsetFWaaS): def setUp(self): super(TestUnsetFirewallPolicy, self).setUp() self.networkclient.update_firewall_policy = mock.Mock( return_value={self.res: _fwp}) self.mocked = self.networkclient.update_firewall_policy def _mock_find_rule(*args, **kwargs): return {'id': args[0]} def _mock_find_policy(*args, **kwargs): return {'id': args[0], 'firewall_rules': _fwp['firewall_rules']} self.networkclient.find_firewall_policy.side_effect = _mock_find_policy self.networkclient.find_firewall_rule.side_effect = _mock_find_rule self.cmd = firewallpolicy.UnsetFirewallPolicy(self.app, self.namespace) def test_unset_audited(self): target = self.resource['id'] arglist = [ target, '--audited', ] verifylist = [ (self.res, target), ('audited', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) body = {'audited': False} self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) def test_unset_firewall_rule_not_matched(self): _fwp['firewall_rules'] = ['old_rule'] target = self.resource['id'] rule = 'new_rule' arglist = [ target, '--firewall-rule', rule, ] verifylist = [ (self.res, target), ('firewall_rule', [rule]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) body = {'firewall_rules': _fwp['firewall_rules']} self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) def test_unset_firewall_rule_matched(self): _fwp['firewall_rules'] = ['rule1', 'rule2'] target = self.resource['id'] rule = 'rule1' arglist = [ target, '--firewall-rule', rule, ] verifylist = [ (self.res, target), ('firewall_rule', [rule]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) body = {'firewall_rules': ['rule2']} self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) self.assertEqual(2, self.networkclient.find_firewall_policy.call_count) self.assertEqual(1, self.networkclient.find_firewall_rule.call_count) def test_unset_all_firewall_rule(self): target = self.resource['id'] arglist = [ target, '--all-firewall-rule', ] verifylist = [ (self.res, target), ('all_firewall_rule', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) body = {'firewall_rules': []} self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py0000664000175000017500000007403300000000000031371 0ustar00zuulzuul00000000000000# Copyright 2016 FUJITSU LIMITED # 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 re from unittest import mock from osc_lib import exceptions from osc_lib.tests import utils import testtools from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.fwaas import firewallrule from neutronclient.tests.unit.osc.v2 import fakes as test_fakes from neutronclient.tests.unit.osc.v2.fwaas import common from neutronclient.tests.unit.osc.v2.fwaas import fakes _fwr = fakes.FirewallRule().create() CONVERT_MAP = { 'project': 'tenant_id', 'enable_rule': 'enabled', 'disable_rule': 'enabled', 'share': 'shared', 'no_share': 'shared', 'source_firewall_group': 'source_firewall_group_id', 'destination_firewall_group': 'destination_firewall_group_id', 'no_source_firewall_group': 'source_firewall_group_id', 'no_destination_firewall_group': 'destination_firewall_group_id', } def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _fwr if data: source.update(data) ret = tuple(_replace_display_columns(key, source[key]) for key in source) return ret def _replace_display_columns(key, val): if key == 'protocol': return firewallrule.ProtocolColumn(val) return val def _generate_req_and_res(verifylist): request = dict(verifylist) response = _fwr for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] if re.match('^no_', key) and val is True: new_value = None elif (key == 'enable' or key == 'enable_rule') and val: new_value = True elif (key == 'disable' or key == 'disable_rule') and val: new_value = False elif (key == 'protocol' and val and val.lower() == 'any'): new_value = None elif val is True or val is False: new_value = val elif key in ('name', 'description'): new_value = val else: new_value = val request[converted] = new_value response[converted] = new_value return request, response class TestFirewallRule(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req=None, is_list=False): if is_list: req_body = {self.res_plural: [exp_req]} else: req_body = exp_req if not exp_req: self.mocked.assert_called_once_with() else: self.mocked.assert_called_once_with(**req_body) self.assertEqual(self.ordered_headers, headers) def setUp(self): super(TestFirewallRule, self).setUp() osc_utils.find_project = mock.Mock() osc_utils.find_project.id = _fwr['tenant_id'] self.res = 'firewall_rule' self.res_plural = 'firewall_rules' self.resource = _fwr self.headers = ( 'ID', 'Name', 'Enabled', 'Description', 'Firewall Policy', 'IP Version', 'Action', 'Protocol', 'Source IP Address', 'Source Port', 'Destination IP Address', 'Destination Port', 'Shared', 'Project', 'Source Firewall Group ID', 'Destination Firewall Group ID', ) self.data = _generate_data() self.ordered_headers = ( 'Action', 'Description', 'Destination Firewall Group ID', 'Destination IP Address', 'Destination Port', 'Enabled', 'Firewall Policy', 'ID', 'IP Version', 'Name', 'Project', 'Protocol', 'Shared', 'Source Firewall Group ID', 'Source IP Address', 'Source Port', 'Summary', ) self.ordered_data = ( _fwr['action'], _fwr['description'], _fwr['destination_firewall_group_id'], _fwr['destination_ip_address'], _fwr['destination_port'], _fwr['firewall_policy_id'], _fwr['enabled'], _fwr['id'], _fwr['ip_version'], _fwr['name'], _fwr['tenant_id'], _replace_display_columns('protocol', _fwr['protocol']), _fwr['shared'], _fwr['source_firewall_group_id'], _fwr['source_ip_address'], _fwr['source_port'], ) self.ordered_columns = ( 'action', 'description', 'destination_firewall_group_id', 'destination_ip_address', 'destination_port', 'enabled', 'id', 'ip_version', 'name', 'tenant_id', 'protocol', 'shared', 'source_firewall_group_id', 'source_ip_address', 'source_port', ) class TestCreateFirewallRule(TestFirewallRule, common.TestCreateFWaaS): def setUp(self): super(TestCreateFirewallRule, self).setUp() self.networkclient.create_firewall_rule = mock.Mock( return_value=_fwr) self.mocked = self.networkclient.create_firewall_rule def _mock_find_group(*args, **kwargs): return {'id': args[0]} self.networkclient.find_firewall_group.side_effect = _mock_find_group self.cmd = firewallrule.CreateFirewallRule(self.app, self.namespace) def _update_expect_response(self, request, response): """Set expected request and response :param request A dictionary of request body(dict of verifylist) :param response A OrderedDict of request body """ # Update response body self.networkclient.create_firewall_rule.return_value = response osc_utils.find_project.return_value.id = response['tenant_id'] # Update response(finally returns 'data') self.data = _generate_data(ordered_dict=response) self.ordered_data = tuple( _replace_display_columns(column, response[column]) for column in self.ordered_columns ) def _set_all_params(self, args={}): name = args.get('name') or 'my-name' description = args.get('description') or 'my-desc' source_ip = args.get('source_ip_address') or '192.168.1.0/24' destination_ip = args.get('destination_ip_address') or '192.168.2.0/24' source_port = args.get('source_port') or '0:65535' protocol = args.get('protocol') or 'udp' action = args.get('action') or 'deny' ip_version = args.get('ip_version') or '4' destination_port = args.get('destination_port') or '0:65535' destination_firewall_group = args.get( 'destination_firewall_group') or 'my-dst-fwg' source_firewall_group = args.get( 'source_firewall_group') or 'my-src-fwg' tenant_id = args.get('tenant_id') or 'my-tenant' arglist = [ '--description', description, '--name', name, '--protocol', protocol, '--ip-version', ip_version, '--source-ip-address', source_ip, '--destination-ip-address', destination_ip, '--source-port', source_port, '--destination-port', destination_port, '--action', action, '--project', tenant_id, '--disable-rule', '--share', '--source-firewall-group', source_firewall_group, '--destination-firewall-group', destination_firewall_group ] verifylist = [ ('name', name), ('description', description), ('share', True), ('protocol', protocol), ('ip_version', ip_version), ('source_ip_address', source_ip), ('destination_ip_address', destination_ip), ('source_port', source_port), ('destination_port', destination_port), ('action', action), ('disable_rule', True), ('project', tenant_id), ('source_firewall_group', source_firewall_group), ('destination_firewall_group', destination_firewall_group) ] return arglist, verifylist def _test_create_with_all_params(self, args={}): arglist, verifylist = self._set_all_params(args) request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.check_results(headers, data, request) def test_create_with_no_options(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.check_results(headers, data, None) def test_create_with_all_params(self): self._test_create_with_all_params() def test_create_with_all_params_protocol_any(self): self._test_create_with_all_params({'protocol': 'any'}) def test_create_with_all_params_ip_version_6(self): self._test_create_with_all_params({'ip_version': '6'}) def test_create_with_all_params_invalid_ip_version(self): arglist, verifylist = self._set_all_params({'ip_version': '128'}) self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_all_params_action_upper_capitalized(self): for action in ('Allow', 'DENY', 'Reject'): arglist, verifylist = self._set_all_params({'action': action}) self.assertRaises( testtools.matchers._impl.MismatchError, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_all_params_protocol_upper_capitalized(self): for protocol in ('TCP', 'Tcp', 'ANY', 'AnY', 'iCMp'): arglist, verifylist = self._set_all_params({'protocol': protocol}) self.assertRaises( testtools.matchers._impl.MismatchError, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_src_fwg_and_no(self): fwg = 'my-fwg' arglist = [ '--source-firewall-group', fwg, '--no-source-firewall-group', ] verifylist = [ ('source_firewall_group', fwg), ('no_source_firewall_group', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_dst_fwg_and_no(self): fwg = 'my-fwg' arglist = [ '--destination-firewall-group', fwg, '--no-destination-firewall-group', ] verifylist = [ ('destination_firewall_group', fwg), ('no_destination_firewall_group', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) class TestListFirewallRule(TestFirewallRule): def _setup_summary(self, expect=None): protocol = (_fwr['protocol'] or 'any').upper() src = 'source(port): 192.168.1.0/24(1:11111)' dst = 'dest(port): 192.168.2.2(2:22222)' action = 'deny' if expect: if expect.get('protocol'): protocol = expect['protocol'] if expect.get('source_ip_address'): src_ip = expect['source_ip_address'] if expect.get('source_port'): src_port = expect['source_port'] if expect.get('destination_ip_address'): dst_ip = expect['destination_ip_address'] if expect.get('destination_port'): dst_port = expect['destination_port'] if expect.get('action'): action = expect['action'] src = 'source(port): ' + src_ip + '(' + src_port + ')' dst = 'dest(port): ' + dst_ip + '(' + dst_port + ')' return ',\n '.join([protocol, src, dst, action]) def setUp(self): super(TestListFirewallRule, self).setUp() self.cmd = firewallrule.ListFirewallRule(self.app, self.namespace) self.short_header = ( 'ID', 'Name', 'Enabled', 'Summary', 'Firewall Policy', ) summary = self._setup_summary(_fwr) self.short_data = ( _fwr['id'], _fwr['name'], _fwr['enabled'], summary, _fwr['firewall_policy_id'] ) self.networkclient.firewall_rules = mock.Mock( return_value=[_fwr]) self.mocked = self.networkclient.firewall_rules def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) def test_list_with_no_option(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.short_header), headers) self.assertListItemEqual([self.short_data], list(data)) class TestShowFirewallRule(TestFirewallRule, common.TestShowFWaaS): def setUp(self): super(TestShowFirewallRule, self).setUp() self.networkclient.get_firewall_rule = mock.Mock( return_value=_fwr) self.mocked = self.networkclient.get_firewall_rule self.cmd = firewallrule.ShowFirewallRule(self.app, self.namespace) class TestSetFirewallRule(TestFirewallRule, common.TestSetFWaaS): def setUp(self): super(TestSetFirewallRule, self).setUp() self.networkclient.update_firewall_rule = mock.Mock( return_value=_fwr) self.mocked = self.networkclient.update_firewall_rule def _mock_find_rule(*args, **kwargs): return {'id': args[0]} self.networkclient.find_firewall_rule.side_effect = _mock_find_rule self.cmd = firewallrule.SetFirewallRule(self.app, self.namespace) def test_set_protocol_with_any(self): target = self.resource['id'] protocol = 'any' arglist = [target, '--protocol', protocol] verifylist = [ (self.res, target), ('protocol', protocol), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'protocol': None}) self.assertIsNone(result) def test_set_protocol_with_udp(self): target = self.resource['id'] protocol = 'udp' arglist = [target, '--protocol', protocol] verifylist = [ (self.res, target), ('protocol', protocol), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'protocol': protocol}) self.assertIsNone(result) def test_set_source_ip_address(self): target = self.resource['id'] src_ip = '192.192.192.192' arglist = [target, '--source-ip-address', src_ip] verifylist = [ (self.res, target), ('source_ip_address', src_ip), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'source_ip_address': src_ip}) self.assertIsNone(result) def test_set_source_port(self): target = self.resource['id'] src_port = '32678' arglist = [target, '--source-port', src_port] verifylist = [ (self.res, target), ('source_port', src_port), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'source_port': src_port}) self.assertIsNone(result) def test_set_destination_ip_address(self): target = self.resource['id'] dst_ip = '0.1.0.1' arglist = [target, '--destination-ip-address', dst_ip] verifylist = [ (self.res, target), ('destination_ip_address', dst_ip), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'destination_ip_address': dst_ip}) self.assertIsNone(result) def test_set_destination_port(self): target = self.resource['id'] dst_port = '65432' arglist = [target, '--destination-port', dst_port] verifylist = [ (self.res, target), ('destination_port', dst_port), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'destination_port': dst_port}) self.assertIsNone(result) def test_set_enable_rule(self): target = self.resource['id'] arglist = [target, '--enable-rule'] verifylist = [ (self.res, target), ('enable_rule', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'enabled': True}) self.assertIsNone(result) def test_set_disable_rule(self): target = self.resource['id'] arglist = [target, '--disable-rule'] verifylist = [ (self.res, target), ('disable_rule', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'enabled': False}) self.assertIsNone(result) def test_set_action(self): target = self.resource['id'] action = 'reject' arglist = [target, '--action', action] verifylist = [ (self.res, target), ('action', action), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'action': action}) self.assertIsNone(result) def test_set_enable_rule_and_disable_rule(self): target = self.resource['id'] arglist = [target, '--enable-rule', '--disable-rule'] verifylist = [ (self.res, target), ('enable_rule', True), ('disable_rule', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_set_no_source_ip_address(self): target = self.resource['id'] arglist = [ target, '--no-source-ip-address', ] verifylist = [ (self.res, target), ('no_source_ip_address', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'source_ip_address': None}) self.assertIsNone(result) def test_set_no_source_port(self): target = self.resource['id'] arglist = [ target, '--no-source-port', ] verifylist = [ (self.res, target), ('no_source_port', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'source_port': None}) self.assertIsNone(result) def test_set_no_destination_ip_address(self): target = self.resource['id'] arglist = [ target, '--no-destination-ip-address', ] verifylist = [ (self.res, target), ('no_destination_ip_address', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'destination_ip_address': None}) self.assertIsNone(result) def test_set_no_destination_port(self): target = self.resource['id'] arglist = [ target, '--no-destination-port', ] verifylist = [ (self.res, target), ('no_destination_port', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'destination_port': None}) self.assertIsNone(result) def test_set_source_ip_address_and_no(self): target = self.resource['id'] arglist = [ target, '--source-ip-address', '192.168.1.0/24', '--no-source-ip-address', ] verifylist = [ (self.res, target), ('source_ip_address', '192.168.1.0/24'), ('no_source_ip_address', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_set_destination_ip_address_and_no(self): target = self.resource['id'] arglist = [ target, '--destination-ip-address', '192.168.2.0/24', '--no-destination-ip-address', ] verifylist = [ (self.res, target), ('destination_ip_address', '192.168.2.0/24'), ('no_destination_ip_address', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_set_source_port_and_no(self): target = self.resource['id'] arglist = [ target, '--source-port', '1:12345', '--no-source-port', ] verifylist = [ (self.res, target), ('source_port', '1:12345'), ('no_source_port', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_set_destination_port_and_no(self): target = self.resource['id'] arglist = [ target, '--destination-port', '1:54321', '--no-destination-port', ] verifylist = [ (self.res, target), ('destination_port', '1:54321'), ('no_destination_port', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_set_and_raises(self): self.networkclient.update_firewall_rule = mock.Mock( side_effect=Exception) target = self.resource['id'] arglist = [target, '--name', 'my-name'] verifylist = [(self.res, target), ('name', 'my-name')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_set_no_destination_fwg(self): target = self.resource['id'] arglist = [ target, '--no-destination-firewall-group', ] verifylist = [ (self.res, target), ('no_destination_firewall_group', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'destination_firewall_group_id': None}) self.assertIsNone(result) def test_set_no_source_fwg(self): target = self.resource['id'] arglist = [ target, '--no-source-firewall-group', ] verifylist = [ (self.res, target), ('no_source_firewall_group', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'source_firewall_group_id': None}) self.assertIsNone(result) def test_create_with_src_fwg_and_no(self): target = self.resource['id'] fwg = 'my-fwg' arglist = [ target, '--source-firewall-group', fwg, '--no-source-firewall-group', ] verifylist = [ (self.res, target), ('source_firewall_group', fwg), ('no_source_firewall_group', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_dst_fwg_and_no(self): target = self.resource['id'] fwg = 'my-fwg' arglist = [ target, '--destination-firewall-group', fwg, '--no-destination-firewall-group', ] verifylist = [ (self.res, target), ('destination_firewall_group', fwg), ('no_destination_firewall_group', True), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) class TestUnsetFirewallRule(TestFirewallRule, common.TestUnsetFWaaS): def setUp(self): super(TestUnsetFirewallRule, self).setUp() self.networkclient.update_firewall_rule = mock.Mock( return_value={self.res: _fwr}) self.mocked = self.networkclient.update_firewall_rule def _mock_find_rule(*args, **kwargs): return {'id': args[0]} self.networkclient.find_firewall_rule.side_effect = _mock_find_rule self.cmd = firewallrule.UnsetFirewallRule(self.app, self.namespace) def test_unset_protocol_and_raise(self): self.networkclient.update_firewall_rule.side_effect = Exception target = self.resource['id'] arglist = [ target, '--protocol', ] verifylist = [ (self.res, target), ('protocol', False) ] self.assertRaises(utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_unset_source_port(self): target = self.resource['id'] arglist = [ target, '--source-port', ] verifylist = [ (self.res, target), ('source_port', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'source_port': None}) self.assertIsNone(result) def test_unset_destination_port(self): target = self.resource['id'] arglist = [ target, '--destination-port', ] verifylist = [ (self.res, target), ('destination_port', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'destination_port': None}) self.assertIsNone(result) def test_unset_source_ip_address(self): target = self.resource['id'] arglist = [ target, '--source-ip-address', ] verifylist = [ (self.res, target), ('source_ip_address', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'source_ip_address': None}) self.assertIsNone(result) def test_unset_destination_ip_address(self): target = self.resource['id'] arglist = [ target, '--destination-ip-address', ] verifylist = [ (self.res, target), ('destination_ip_address', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'destination_ip_address': None}) self.assertIsNone(result) def test_unset_enable_rule(self): target = self.resource['id'] arglist = [ target, '--enable-rule', ] verifylist = [ (self.res, target), ('enable_rule', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'enabled': False}) self.assertIsNone(result) class TestDeleteFirewallRule(TestFirewallRule, common.TestDeleteFWaaS): def setUp(self): super(TestDeleteFirewallRule, self).setUp() self.networkclient.delete_firewall_rule = mock.Mock(return_value=_fwr) self.mocked = self.networkclient.delete_firewall_rule self.cmd = firewallrule.DeleteFirewallRule(self.app, self.namespace) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2256625 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/lbaas/0000775000175000017500000000000000000000000025235 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/lbaas/__init__.py0000664000175000017500000000000000000000000027334 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2256625 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/logging/0000775000175000017500000000000000000000000025601 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/logging/__init__.py0000664000175000017500000000000000000000000027700 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/logging/fakes.py0000664000175000017500000000467200000000000027255 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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 collections import copy from unittest import mock import uuid class FakeLogging(object): def create(self, attrs={}): """Create a fake network logs :param Dictionary attrs: A dictionary with all attributes :return: A OrderedDict faking the network log """ self.ordered.update(attrs) return copy.deepcopy(self.ordered) def bulk_create(self, attrs=None, count=2): """Create multiple fake network logs :param Dictionary attrs: A dictionary with all attributes :param int count: The number of network logs to fake :return: A list of dictionaries faking the network logs """ return [self.create(attrs=attrs) for i in range(0, count)] def get(self, attrs=None, count=2): """Create multiple fake network logs :param Dictionary attrs: A dictionary with all attributes :param int count: The number of network logs to fake :return: A list of dictionaries faking the network log """ if attrs is None: self.attrs = self.bulk_create(count=count) return mock.Mock(side_effect=attrs) class NetworkLog(FakeLogging): """Fake one or more network log""" def __init__(self): super(NetworkLog, self).__init__() self.ordered = collections.OrderedDict(( ('id', 'log-id-' + uuid.uuid4().hex), ('description', 'my-desc-' + uuid.uuid4().hex), ('enabled', False), ('name', 'my-log-' + uuid.uuid4().hex), ('target_id', None), ('project_id', 'project-id-' + uuid.uuid4().hex), ('resource_id', None), ('resource_type', 'security_group'), ('event', 'all'), )) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/logging/test_network_log.py0000664000175000017500000006407500000000000031560 0ustar00zuulzuul00000000000000# Copyright 2017-2018 FUJITSU LIMITED # 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 copy from unittest import mock from osc_lib import exceptions from osc_lib.tests import utils import testtools from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.logging import network_log from neutronclient.tests.unit.osc.v2 import fakes as test_fakes from neutronclient.tests.unit.osc.v2.logging import fakes _log = fakes.NetworkLog().create() RES_TYPE_SG = 'security_group' RES_TYPE_FWG = 'firewall_group' CONVERT_MAP = { 'project': 'project_id', 'enable': 'enabled', 'disable': 'enabled', 'target': 'target_id', 'resource': 'resource_id', 'event': 'event', } def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _log if data: source.update(data) return tuple(source[key] for key in source) def _generate_req_and_res(verifylist): request = dict(verifylist) response = copy.deepcopy(_log) for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] if key == 'enable' and val: new_value = True elif key == 'disable' and val: new_value = False else: new_value = val request[converted] = new_value response[converted] = new_value return request, response class TestNetworkLog(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req, is_list=False): if is_list: req_body = {'logs': [exp_req]} else: req_body = {'log': exp_req} self.mocked.assert_called_once_with(req_body) self.assertEqual(self.ordered_headers, headers) self.assertEqual(self.ordered_data, data) def setUp(self): super(TestNetworkLog, self).setUp() self.neutronclient.find_resource = mock.Mock() self.neutronclient.find_resource.side_effect = \ lambda x, y, **k: {'id': y} osc_utils.find_project = mock.Mock() osc_utils.find_project.id = _log['project_id'] self.res = _log self.headers = ( 'ID', 'Description', 'Enabled', 'Name', 'Target', 'Project', 'Resource', 'Type', 'Event', ) self.data = _generate_data() self.ordered_headers = ( 'Description', 'Enabled', 'Event', 'ID', 'Name', 'Project', 'Resource', 'Target', 'Type', ) self.ordered_data = ( _log['description'], _log['enabled'], _log['event'], _log['id'], _log['name'], _log['project_id'], _log['resource_id'], _log['target_id'], _log['resource_type'], ) self.ordered_columns = ( 'description', 'enabled', 'event', 'id', 'name', 'project_id', 'resource_id', 'target_id', 'resource_type', ) class TestCreateNetworkLog(TestNetworkLog): def setUp(self): super(TestCreateNetworkLog, self).setUp() self.neutronclient.create_network_log = mock.Mock( return_value={'log': _log}) self.mocked = self.neutronclient.create_network_log self.cmd = network_log.CreateNetworkLog(self.app, self.namespace) loggables = { "loggable_resources": [{"type": RES_TYPE_SG}, {"type": RES_TYPE_FWG}] } self.neutronclient.list_network_loggable_resources = mock.Mock( return_value=loggables) def _update_expect_response(self, request, response): """Set expected request and response :param request A dictionary of request body(dict of verifylist) :param response A OrderedDict of request body """ # Update response body self.neutronclient.create_network_log.return_value = \ {'log': dict(response)} osc_utils.find_project.return_value.id = response['project_id'] # Update response(finally returns 'data') self.data = _generate_data(ordered_dict=response) self.ordered_data = tuple( response[column] for column in self.ordered_columns ) def _set_all_params(self, args={}): name = args.get('name', 'my-log') desc = args.get('description', 'my-description-for-log') event = args.get('event', 'ACCEPT') resource = args.get('resource', 'id-target-log') target = args.get('target', 'id-target-log') resource_type = args.get('resource_type', 'security_group') project = args.get('project_id', 'id-my-project') arglist = [ name, '--description', desc, '--enable', '--target', target, '--resource', resource, '--event', event, '--project', project, '--resource-type', resource_type, ] verifylist = [ ('description', desc), ('enable', True), ('event', event), ('name', name), ('target', target), ('project', project), ('resource', target), ('resource_type', resource_type), ] return arglist, verifylist def _test_create_with_all_params(self, args={}): arglist, verifylist = self._set_all_params(args) request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.check_results(headers, data, request) def test_create_with_no_options_and_raise(self): arglist = [] verifylist = [] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_mandatory_params(self): name = self.res['name'] arglist = [ name, '--resource-type', RES_TYPE_SG, ] verifylist = [ ('name', name), ('resource_type', RES_TYPE_SG), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) expect = { 'name': self.res['name'], 'resource_type': self.res['resource_type'], } self.mocked.assert_called_once_with({'log': expect}) self.assertEqual(self.ordered_headers, headers) self.assertEqual(self.ordered_data, data) def test_create_with_disable(self): name = self.res['name'] arglist = [ name, '--resource-type', RES_TYPE_SG, '--disable', ] verifylist = [ ('name', name), ('resource_type', RES_TYPE_SG), ('disable', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) expect = { 'name': self.res['name'], 'resource_type': self.res['resource_type'], 'enabled': False, } self.mocked.assert_called_once_with({'log': expect}) self.assertEqual(self.ordered_headers, headers) self.assertEqual(self.ordered_data, data) def test_create_with_all_params(self): self._test_create_with_all_params() def test_create_with_all_params_event_drop(self): self._test_create_with_all_params({'event': 'DROP'}) def test_create_with_all_params_event_all(self): self._test_create_with_all_params({'event': 'ALL'}) def test_create_with_all_params_except_event(self): arglist, verifylist = self._set_all_params({'event': ''}) self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_all_params_event_upper_capitalized(self): for event in ('all', 'All', 'dROP', 'accePt', 'accept', 'drop'): arglist, verifylist = self._set_all_params({'event': event}) self.assertRaises( testtools.matchers._impl.MismatchError, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_all_params_resource_type_upper_capitalized(self): for res_type in ('SECURITY_GROUP', 'Security_group', 'security_Group'): arglist, verifylist = self._set_all_params( {'resource_type': res_type}) self.assertRaises( testtools.matchers._impl.MismatchError, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_valid_fwg_resource(self): name = self.res['name'] resource_id = 'valid_fwg_id' resource_type = RES_TYPE_FWG # Test with valid FWG ID with mock.patch.object(self.neutronclient, 'find_resource', return_value={'id': resource_id}): arglist = [name, '--resource-type', resource_type, '--resource', resource_id ] verifylist = [ ('name', name), ('resource_type', resource_type), ('resource', resource_id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) expect = { 'name': self.res['name'], 'resource_type': RES_TYPE_FWG, 'resource_id': 'valid_fwg_id', } self.neutronclient.find_resource.assert_called_with( resource_type, resource_id, cmd_resource='fwaas_firewall_group') self.mocked.assert_called_once_with({'log': expect}) self.assertEqual(self.ordered_headers, headers) self.assertEqual(self.ordered_data, data) def test_create_with_invalid_fwg_resource(self): name = self.res['name'] resource_id = 'invalid_fwg_id' resource_type = RES_TYPE_FWG # Test with invalid FWG ID with mock.patch.object(self.neutronclient, 'find_resource', side_effect=exceptions.NotFound(code=0)): arglist = [name, '--resource-type', resource_type, '--resource', resource_id ] verifylist = [ ('name', name), ('resource_type', resource_type), ('resource', resource_id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.NotFound, self.cmd.take_action, parsed_args) self.neutronclient.find_resource.assert_called_with( resource_type, resource_id, cmd_resource='fwaas_firewall_group') self.mocked.assert_not_called() def test_create_with_invalid_resource_type(self): name = self.res['name'] resource_type = 'invalid_resource_type' resource_id = 'valid_fwg_id' with mock.patch.object(self.neutronclient, 'find_resource', side_effect=exceptions.NotFound(code=0)): arglist = [name, '--resource-type', resource_type, '--resource', resource_id ] verifylist = [ ('name', name), ('resource_type', resource_type), ('resource', resource_id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.NotFound, self.cmd.take_action, parsed_args) self.neutronclient.find_resource.assert_called_with( resource_type, resource_id, cmd_resource=None) self.mocked.assert_not_called() class TestListNetworkLog(TestNetworkLog): def _setup_summary(self, expect=None): event = 'Event: ' + self.res['event'].upper() target = 'Logged: (None specified)' if expect: if expect.get('event'): event = expect['event'] if expect.get('resource'): target = expect['resource'] summary = ',\n'.join([event, target]) self.short_data = ( expect['id'] if expect else self.res['id'], expect['enabled'] if expect else self.res['enabled'], expect['name'] if expect else self.res['name'], expect['resource_type'] if expect else self.res['resource_type'], summary ) def setUp(self): super(TestListNetworkLog, self).setUp() self.cmd = network_log.ListNetworkLog(self.app, self.namespace) self.short_header = ( 'ID', 'Enabled', 'Name', 'Type', 'Summary', ) self._setup_summary() self.neutronclient.list_network_logs = mock.Mock( return_value={'logs': [self.res]}) self.mocked = self.neutronclient.list_network_logs def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) self.assertEqual([self.data], list(data)) def test_list_with_no_option(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.short_header), headers) self.assertEqual([self.short_data], list(data)) def test_list_with_target_and_resource(self): arglist = [] verifylist = [] target_id = 'aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaaaaaaa' resource_id = 'bbbbbbbb-bbbb-bbbb-bbbbbbbbbbbbbbbbb' log = fakes.NetworkLog().create({ 'target_id': target_id, 'resource_id': resource_id}) self.mocked.return_value = {'logs': [log]} logged = 'Logged: (security_group) %(res_id)s on (port) %(t_id)s' % { 'res_id': resource_id, 't_id': target_id} expect_log = copy.deepcopy(log) expect_log.update({ 'resource': logged, 'event': 'Event: ALL'}) self._setup_summary(expect=expect_log) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.short_header), headers) self.assertEqual([self.short_data], list(data)) def test_list_with_resource(self): arglist = [] verifylist = [] resource_id = 'bbbbbbbb-bbbb-bbbb-bbbbbbbbbbbbbbbbb' log = fakes.NetworkLog().create({'resource_id': resource_id}) self.mocked.return_value = {'logs': [log]} logged = 'Logged: (security_group) %s' % resource_id expect_log = copy.deepcopy(log) expect_log.update({ 'resource': logged, 'event': 'Event: ALL'}) self._setup_summary(expect=expect_log) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.short_header), headers) self.assertEqual([self.short_data], list(data)) def test_list_with_target(self): arglist = [] verifylist = [] target_id = 'aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaaaaaaa' log = fakes.NetworkLog().create({'target_id': target_id}) self.mocked.return_value = {'logs': [log]} logged = 'Logged: (port) %s' % target_id expect_log = copy.deepcopy(log) expect_log.update({ 'resource': logged, 'event': 'Event: ALL'}) self._setup_summary(expect=expect_log) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.short_header), headers) self.assertEqual([self.short_data], list(data)) class TestShowNetworkLog(TestNetworkLog): def setUp(self): super(TestShowNetworkLog, self).setUp() self.neutronclient.show_network_log = mock.Mock( return_value={'log': self.res}) self.mocked = self.neutronclient.show_network_log self.cmd = network_log.ShowNetworkLog(self.app, self.namespace) def test_show_filtered_by_id_or_name(self): target = self.res['id'] arglist = [target] verifylist = [('network_log', target)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target) self.assertEqual(self.ordered_headers, headers) self.assertEqual(self.ordered_data, data) class TestSetNetworkLog(TestNetworkLog): def setUp(self): super(TestSetNetworkLog, self).setUp() self.neutronclient.update_network_log = mock.Mock( return_value={'log': self.res}) self.mocked = self.neutronclient.update_network_log self.cmd = network_log.SetNetworkLog(self.app, self.namespace) def test_set_name(self): target = self.res['id'] update = 'change' arglist = [target, '--name', update] verifylist = [ ('network_log', target), ('name', update), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, {'log': {'name': update}}) self.assertIsNone(result) def test_set_description(self): target = self.res['id'] update = 'change-desc' arglist = [target, '--description', update] verifylist = [ ('network_log', target), ('description', update), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, {'log': {'description': update}}) self.assertIsNone(result) def test_set_enable(self): target = self.res['id'] arglist = [target, '--enable'] verifylist = [ ('network_log', target), ('enable', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, {'log': {'enabled': True}}) self.assertIsNone(result) def test_set_disable(self): target = self.res['id'] arglist = [target, '--disable'] verifylist = [ ('network_log', target), ('disable', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, {'log': {'enabled': False}}) self.assertIsNone(result) # Illegal tests def test_illegal_set_resource_type(self): target = self.res['id'] resource_type = 'security_group' arglist = [target, '--resource-type', resource_type] verifylist = [ ('network_log', target), ('resource_type', resource_type), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_illegal_set_event(self): target = self.res['id'] for event in ['all', 'accept', 'drop']: arglist = [target, '--event', event] verifylist = [ ('network_log', target), ('event', event), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_illegal_set_resource_id(self): target = self.res['id'] resource_id = 'resource-id-for-logged-target' arglist = [target, '--resource', resource_id] verifylist = [ ('network_log', target), ('resource', resource_id), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_illegal_set_project(self): target = self.res['id'] arglist = [ target, '--project', ] verifylist = [ ('network_log', target), ('project', 'other-project'), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_illegal_set_project_domain(self): target = self.res['id'] arglist = [ target, '--project-domain', ] verifylist = [ ('network_log', target), ('project_domain', 'other-project-domain'), ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_illegal_set_and_raises(self): self.neutronclient.update_network_log = mock.Mock( side_effect=Exception) target = self.res['id'] arglist = [target, '--name', 'my-name'] verifylist = [('network_log', target), ('name', 'my-name')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) class TestDeleteNetworkLog(TestNetworkLog): def setUp(self): super(TestDeleteNetworkLog, self).setUp() self.neutronclient.delete_network_log = mock.Mock( return_value={'log': self.res}) self.mocked = self.neutronclient.delete_network_log self.cmd = network_log.DeleteNetworkLog(self.app, self.namespace) def test_delete_with_one_resource(self): target = self.res['id'] arglist = [target] verifylist = [('network_log', [target])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target) self.assertIsNone(result) def test_delete_with_multiple_resources(self): target1 = 'target1' target2 = 'target2' arglist = [target1, target2] verifylist = [('network_log', [target1, target2])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.assertEqual(2, self.mocked.call_count) for idx, reference in enumerate([target1, target2]): actual = ''.join(self.mocked.call_args_list[idx][0]) self.assertEqual(reference, actual) def test_delete_with_no_exist_id(self): self.neutronclient.find_resource.side_effect = Exception target = 'not_exist' arglist = [target] verifylist = [('network_log', [target])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) class TestLoggableResource(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req, is_list=False): if is_list: req_body = {'logs': [exp_req]} else: req_body = {'log': exp_req} self.mocked.assert_called_once_with(req_body) self.assertEqual(self.ordered_headers, headers) self.assertEqual(self.ordered_data, data) def setUp(self): super(TestLoggableResource, self).setUp() self.headers = ('Supported types',) self.data = ('security_group', ) class TestListLoggableResource(TestLoggableResource): def setUp(self): super(TestListLoggableResource, self).setUp() self.cmd = network_log.ListLoggableResource(self.app, self.namespace) loggables = { "loggable_resources": [{"type": "security_group"}] } self.neutronclient.list_network_loggable_resources = mock.Mock( return_value=loggables) self.mocked = self.neutronclient.list_network_loggable_resources def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) self.assertEqual([self.data], list(data)) def test_list_with_no_option(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) self.assertEqual([self.data], list(data)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2296627 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/networking_bgpvpn/0000775000175000017500000000000000000000000027716 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/networking_bgpvpn/__init__.py0000664000175000017500000000000000000000000032015 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py0000664000175000017500000001747300000000000031375 0ustar00zuulzuul00000000000000# Copyright (c) 2016 Juniper Networks Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # import copy from unittest import mock from openstack.network.v2 import bgpvpn as _bgpvpn from openstack import resource as sdk_resource from osc_lib.utils import columns as column_util from neutronclient.osc import utils as nc_osc_utils from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ CreateBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ DeleteBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ ListBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ SetBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ ShowBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ UnsetBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.router_association import\ CreateBgpvpnRouterAssoc from neutronclient.osc.v2.networking_bgpvpn.router_association import\ SetBgpvpnRouterAssoc from neutronclient.osc.v2.networking_bgpvpn.router_association import\ ShowBgpvpnRouterAssoc from neutronclient.tests.unit.osc.v2 import fakes as test_fakes _FAKE_PROJECT_ID = 'fake_project_id' class TestNeutronClientBgpvpn(test_fakes.TestNeutronClientOSCV2): def setUp(self): super(TestNeutronClientBgpvpn, self).setUp() self.neutronclient.find_resource = mock.Mock( side_effect=lambda resource, name_or_id, project_id=None, cmd_resource=None, parent_id=None, fields=None: {'id': name_or_id, 'tenant_id': _FAKE_PROJECT_ID}) self.neutronclient.find_resource_by_id = mock.Mock( side_effect=lambda resource, resource_id, cmd_resource=None, parent_id=None, fields=None: {'id': resource_id, 'tenant_id': _FAKE_PROJECT_ID}) nc_osc_utils.find_project = mock.Mock( side_effect=lambda _, name_or_id, __: mock.Mock(id=name_or_id)) def create_one_bgpvpn(attrs=None): """Create a fake BGP VPN.""" attrs = attrs or {} # Set default attributes. bgpvpn_attrs = { 'id': 'fake_bgpvpn_id', 'tenant_id': _FAKE_PROJECT_ID, 'name': '', 'type': 'l3', 'route_targets': [], 'import_targets': [], 'export_targets': [], 'route_distinguishers': [], 'networks': [], 'routers': [], 'ports': [], 'vni': 100, 'local_pref': 777, } # Overwrite default attributes. bgpvpn_attrs.update(attrs) return _bgpvpn.BgpVpn(**bgpvpn_attrs) def create_bgpvpns(attrs=None, count=1): """Create multiple fake BGP VPN.""" bgpvpns = [] for i in range(0, count): if attrs is None: attrs = {'id': 'fake_id%d' % i} elif getattr(attrs, 'id', None) is None: attrs['id'] = 'fake_id%d' % i bgpvpns.append(create_one_bgpvpn(attrs)) return bgpvpns class BgpvpnFakeAssoc(object): _assoc_res_name = 'fake_resource' _resource = '%s_association' % _assoc_res_name _resource_plural = '%ss' % _resource _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('project_id', 'Project ID', column_util.LIST_BOTH), ) _formatters = {} class CreateBgpvpnFakeResAssoc(BgpvpnFakeAssoc, CreateBgpvpnResAssoc): pass class SetBgpvpnFakeResAssoc(BgpvpnFakeAssoc, SetBgpvpnResAssoc): pass class UnsetBgpvpnFakeResAssoc(BgpvpnFakeAssoc, UnsetBgpvpnResAssoc): pass class DeleteBgpvpnFakeResAssoc(BgpvpnFakeAssoc, DeleteBgpvpnResAssoc): pass class ListBgpvpnFakeResAssoc(BgpvpnFakeAssoc, ListBgpvpnResAssoc): pass class ShowBgpvpnFakeResAssoc(BgpvpnFakeAssoc, ShowBgpvpnResAssoc): pass class BgpvpnFakeRouterAssoc(object): _assoc_res_name = 'fake_resource' _resource = '%s_association' % _assoc_res_name _resource_plural = '%ss' % _resource _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), column_util.LIST_BOTH), ('advertise_extra_routes', 'Advertise extra routes', column_util.LIST_LONG_ONLY), ('name', 'Name', column_util.LIST_BOTH), ('project_id', 'Project ID', column_util.LIST_BOTH), ) _formatters = {} class CreateBgpvpnFakeRouterAssoc(BgpvpnFakeRouterAssoc, CreateBgpvpnRouterAssoc): pass class SetBgpvpnFakeRouterAssoc(BgpvpnFakeRouterAssoc, SetBgpvpnRouterAssoc): pass class ShowBgpvpnFakeRouterAssoc(BgpvpnFakeRouterAssoc, ShowBgpvpnRouterAssoc): pass class FakeResource(sdk_resource.Resource): resource_key = 'fakeresource' resources_key = 'fakeresources' base_path = '/bgpvpn/fakeresources' _allow_unknown_attrs_in_body = True # capabilities allow_create = True allow_fetch = True allow_commit = True allow_delete = True allow_list = True id = sdk_resource.Body('id') tenant_id = sdk_resource.Body('tenant_id', deprecated=True) project_id = sdk_resource.Body('project_id', alias='tenant_id') class FakeResoureAssociation(sdk_resource.Resource): resource_key = 'fakeresourceassociation' resources_key = 'fakeresourceassociations' base_path = '/bgpvpn/fakeresourceassociations' _allow_unknown_attrs_in_body = True # capabilities allow_create = True allow_fetch = True allow_commit = True allow_delete = True allow_list = True id = sdk_resource.Body('id') tenant_id = sdk_resource.Body('tenant_id', deprecated=True) project_id = sdk_resource.Body('project_id', alias='tenant_id') def create_one_resource(attrs=None): """Create a fake resource.""" attrs = attrs or {} # Set default attributes. res_attrs = { 'id': 'fake_resource_id', 'tenant_id': _FAKE_PROJECT_ID, } # Overwrite default attributes. res_attrs.update(attrs) return FakeResource(**res_attrs) def create_resources(attrs=None, count=1): """Create multiple fake resources.""" resources = [] for i in range(0, count): if attrs is None: attrs = {'id': 'fake_id%d' % i} elif getattr(attrs, 'id', None) is None: attrs['id'] = 'fake_id%d' % i resources.append(create_one_resource(attrs)) return resources def create_one_resource_association(resource, attrs=None): """Create a fake resource association.""" attrs = attrs or {} res_assoc_attrs = { 'id': 'fake_association_id', 'tenant_id': resource['tenant_id'], 'fake_resource_id': resource['id'], } # Overwrite default attributes. res_assoc_attrs.update(attrs) return FakeResoureAssociation(**res_assoc_attrs) def create_resource_associations(resources): """Create multiple fake resource associations.""" res_assocs = [] for idx, resource in enumerate(resources): res_assoc_attrs = { 'id': 'fake_association_id%d' % idx, 'tenant_id': resource['tenant_id'], 'fake_resource_id': resource['id'], } res_assocs.append(copy.deepcopy(res_assoc_attrs)) return res_assocs ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py0000664000175000017500000004652200000000000032634 0ustar00zuulzuul00000000000000# Copyright (c) 2016 Juniper Networks Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # import copy import operator from unittest import mock from osc_lib import exceptions from osc_lib import utils as osc_utils from osc_lib.utils import columns as column_util from neutronclient.osc.v2.networking_bgpvpn import bgpvpn from neutronclient.tests.unit.osc.v2.networking_bgpvpn import fakes columns_short = tuple(col for col, _, listing_mode in bgpvpn._attr_map if listing_mode in (column_util.LIST_BOTH, column_util.LIST_SHORT_ONLY)) columns_long = tuple(col for col, _, listing_mode in bgpvpn._attr_map if listing_mode in (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)) headers_short = tuple(head for _, head, listing_mode in bgpvpn._attr_map if listing_mode in (column_util.LIST_BOTH, column_util.LIST_SHORT_ONLY)) headers_long = tuple(head for _, head, listing_mode in bgpvpn._attr_map if listing_mode in (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)) sorted_attr_map = sorted(bgpvpn._attr_map, key=operator.itemgetter(1)) sorted_columns = tuple(col for col, _, _ in sorted_attr_map) sorted_headers = tuple(head for _, head, _ in sorted_attr_map) def _get_data(attrs, columns=sorted_columns): return osc_utils.get_dict_properties(attrs, columns, formatters=bgpvpn._formatters) class TestCreateBgpvpn(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestCreateBgpvpn, self).setUp() self.cmd = bgpvpn.CreateBgpvpn(self.app, self.namespace) def test_create_bgpvpn_with_no_args(self): fake_bgpvpn = fakes.create_one_bgpvpn() self.networkclient.create_bgpvpn = mock.Mock( return_value=fake_bgpvpn) arglist = [] verifylist = [ ('project', None), ('name', None), ('type', 'l3'), ('vni', None), ('local_pref', None), ('route_targets', None), ('import_targets', None), ('export_targets', None), ('route_distinguishers', None), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) cols, data = self.cmd.take_action(parsed_args) self.networkclient.create_bgpvpn.assert_called_once_with( **{'type': 'l3'}) self.assertEqual(sorted(sorted_columns), sorted(cols)) def test_create_bgpvpn_with_all_args(self): attrs = { 'tenant_id': 'new_fake_project_id', 'name': 'fake_name', 'type': 'l2', 'vni': 100, 'local_pref': 777, 'route_targets': ['fake_rt1', 'fake_rt2', 'fake_rt3'], 'import_targets': ['fake_irt1', 'fake_irt2', 'fake_irt3'], 'export_targets': ['fake_ert1', 'fake_ert2', 'fake_ert3'], 'route_distinguishers': ['fake_rd1', 'fake_rd2', 'fake_rd3'], } fake_bgpvpn = fakes.create_one_bgpvpn(attrs) self.networkclient.create_bgpvpn = mock.Mock( return_value=fake_bgpvpn) arglist = [ '--project', fake_bgpvpn['tenant_id'], '--name', fake_bgpvpn['name'], '--type', fake_bgpvpn['type'], '--vni', str(fake_bgpvpn['vni']), '--local-pref', str(fake_bgpvpn['local_pref']), ] for rt in fake_bgpvpn['route_targets']: arglist.extend(['--route-target', rt]) for rt in fake_bgpvpn['import_targets']: arglist.extend(['--import-target', rt]) for rt in fake_bgpvpn['export_targets']: arglist.extend(['--export-target', rt]) for rd in fake_bgpvpn['route_distinguishers']: arglist.extend(['--route-distinguisher', rd]) verifylist = [ ('project', fake_bgpvpn['tenant_id']), ('name', fake_bgpvpn['name']), ('type', fake_bgpvpn['type']), ('vni', fake_bgpvpn['vni']), ('local_pref', fake_bgpvpn['local_pref']), ('route_targets', fake_bgpvpn['route_targets']), ('import_targets', fake_bgpvpn['import_targets']), ('export_targets', fake_bgpvpn['export_targets']), ('route_distinguishers', fake_bgpvpn['route_distinguishers']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) cols, data = self.cmd.take_action(parsed_args) fake_bgpvpn_call = copy.deepcopy(attrs) self.networkclient.create_bgpvpn.assert_called_once_with( **fake_bgpvpn_call) self.assertEqual(sorted(sorted_columns), sorted(cols)) class TestSetBgpvpn(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestSetBgpvpn, self).setUp() self.networkclient.find_bgpvpn = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = bgpvpn.SetBgpvpn(self.app, self.namespace) def test_set_bgpvpn(self): attrs = { 'route_targets': ['set_rt1', 'set_rt2', 'set_rt3'], 'import_targets': ['set_irt1', 'set_irt2', 'set_irt3'], 'export_targets': ['set_ert1', 'set_ert2', 'set_ert3'], 'route_distinguishers': ['set_rd1', 'set_rd2', 'set_rd3'], } fake_bgpvpn = fakes.create_one_bgpvpn(attrs) self.networkclient.get_bgpvpn = mock.Mock( return_value=fake_bgpvpn) self.networkclient.update_bgpvpn = mock.Mock() arglist = [ fake_bgpvpn['id'], '--name', 'set_name', '--route-target', 'set_rt1', '--import-target', 'set_irt1', '--export-target', 'set_ert1', '--route-distinguisher', 'set_rd1', ] verifylist = [ ('bgpvpn', fake_bgpvpn['id']), ('name', 'set_name'), ('route_targets', ['set_rt1']), ('purge_route_target', False), ('import_targets', ['set_irt1']), ('purge_import_target', False), ('export_targets', ['set_ert1']), ('purge_export_target', False), ('route_distinguishers', ['set_rd1']), ('purge_route_distinguisher', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) attrs = { 'name': 'set_name', 'route_targets': list(set(fake_bgpvpn['route_targets']) | set(['set_rt1'])), 'import_targets': list(set(fake_bgpvpn['import_targets']) | set(['set_irt1'])), 'export_targets': list(set(fake_bgpvpn['export_targets']) | set(['set_ert1'])), 'route_distinguishers': list( set(fake_bgpvpn['route_distinguishers']) | set(['set_rd1'])), } self.networkclient.update_bgpvpn.assert_called_once_with( fake_bgpvpn['id'], **attrs) self.assertIsNone(result) def test_set_bgpvpn_with_purge_list(self): fake_bgpvpn = fakes.create_one_bgpvpn() self.networkclient.get_bgpvpn = mock.Mock( return_value=fake_bgpvpn) self.neutronclient.update_bgpvpn = mock.Mock() arglist = [ fake_bgpvpn['id'], '--route-target', 'set_rt1', '--no-route-target', '--import-target', 'set_irt1', '--no-import-target', '--export-target', 'set_ert1', '--no-export-target', '--route-distinguisher', 'set_rd1', '--no-route-distinguisher', ] verifylist = [ ('bgpvpn', fake_bgpvpn['id']), ('route_targets', ['set_rt1']), ('purge_route_target', True), ('import_targets', ['set_irt1']), ('purge_import_target', True), ('export_targets', ['set_ert1']), ('purge_export_target', True), ('route_distinguishers', ['set_rd1']), ('purge_route_distinguisher', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) attrs = { 'route_targets': [], 'import_targets': [], 'export_targets': [], 'route_distinguishers': [], } self.networkclient.update_bgpvpn.assert_called_once_with( fake_bgpvpn['id'], **attrs) self.assertIsNone(result) class TestUnsetBgpvpn(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestUnsetBgpvpn, self).setUp() self.networkclient.find_bgpvpn = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = bgpvpn.UnsetBgpvpn(self.app, self.namespace) def test_unset_bgpvpn(self): attrs = { 'route_targets': ['unset_rt1', 'unset_rt2', 'unset_rt3'], 'import_targets': ['unset_irt1', 'unset_irt2', 'unset_irt3'], 'export_targets': ['unset_ert1', 'unset_ert2', 'unset_ert3'], 'route_distinguishers': ['unset_rd1', 'unset_rd2', 'unset_rd3'], } fake_bgpvpn = fakes.create_one_bgpvpn(attrs) self.networkclient.get_bgpvpn = mock.Mock( return_value=fake_bgpvpn) self.networkclient.update_bgpvpn = mock.Mock() arglist = [ fake_bgpvpn['id'], '--route-target', 'unset_rt1', '--import-target', 'unset_irt1', '--export-target', 'unset_ert1', '--route-distinguisher', 'unset_rd1', ] verifylist = [ ('bgpvpn', fake_bgpvpn['id']), ('route_targets', ['unset_rt1']), ('purge_route_target', False), ('import_targets', ['unset_irt1']), ('purge_import_target', False), ('export_targets', ['unset_ert1']), ('purge_export_target', False), ('route_distinguishers', ['unset_rd1']), ('purge_route_distinguisher', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) attrs = { 'route_targets': list(set(fake_bgpvpn['route_targets']) - set(['unset_rt1'])), 'import_targets': list(set(fake_bgpvpn['import_targets']) - set(['unset_irt1'])), 'export_targets': list(set(fake_bgpvpn['export_targets']) - set(['unset_ert1'])), 'route_distinguishers': list( set(fake_bgpvpn['route_distinguishers']) - set(['unset_rd1'])), } self.networkclient.update_bgpvpn.assert_called_once_with( fake_bgpvpn['id'], **attrs) self.assertIsNone(result) def test_unset_bgpvpn_with_purge_list(self): fake_bgpvpn = fakes.create_one_bgpvpn() self.networkclient.show_bgpvpn = mock.Mock( return_value=fake_bgpvpn) self.neutronclient.update_bgpvpn = mock.Mock() arglist = [ fake_bgpvpn['id'], '--route-target', 'unset_rt1', '--all-route-target', '--import-target', 'unset_irt1', '--all-import-target', '--export-target', 'unset_ert1', '--all-export-target', '--route-distinguisher', 'unset_rd1', '--all-route-distinguisher', ] verifylist = [ ('bgpvpn', fake_bgpvpn['id']), ('route_targets', ['unset_rt1']), ('purge_route_target', True), ('import_targets', ['unset_irt1']), ('purge_import_target', True), ('export_targets', ['unset_ert1']), ('purge_export_target', True), ('route_distinguishers', ['unset_rd1']), ('purge_route_distinguisher', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) attrs = { 'route_targets': [], 'import_targets': [], 'export_targets': [], 'route_distinguishers': [], } self.networkclient.update_bgpvpn.assert_called_once_with( fake_bgpvpn['id'], **attrs) self.assertIsNone(result) class TestDeleteBgpvpn(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestDeleteBgpvpn, self).setUp() self.networkclient.find_bgpvpn = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = bgpvpn.DeleteBgpvpn(self.app, self.namespace) def test_delete_one_bgpvpn(self): fake_bgpvpn = fakes.create_one_bgpvpn() self.networkclient.delete_bgpvpn = mock.Mock() arglist = [ fake_bgpvpn['id'], ] verifylist = [ ('bgpvpns', [fake_bgpvpn['id']]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.networkclient.delete_bgpvpn.assert_called_once_with( fake_bgpvpn['id']) self.assertIsNone(result) def test_delete_multi_bpgvpn(self): fake_bgpvpns = fakes.create_bgpvpns(count=3) fake_bgpvpn_ids = [fake_bgpvpn['id'] for fake_bgpvpn in fake_bgpvpns] self.networkclient.delete_bgpvpn = mock.Mock() arglist = fake_bgpvpn_ids verifylist = [ ('bgpvpns', fake_bgpvpn_ids), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.networkclient.delete_bgpvpn.assert_has_calls( [mock.call(id) for id in fake_bgpvpn_ids]) self.assertIsNone(result) def test_delete_multi_bpgvpn_with_unknown(self): count = 3 fake_bgpvpns = fakes.create_bgpvpns(count=count) fake_bgpvpn_ids = [fake_bgpvpn['id'] for fake_bgpvpn in fake_bgpvpns] def raise_unknonw_resource(resource_path, name_or_id): if str(count - 2) in name_or_id: raise Exception() self.networkclient.delete_bgpvpn = mock.Mock( side_effect=raise_unknonw_resource) arglist = fake_bgpvpn_ids verifylist = [ ('bgpvpns', fake_bgpvpn_ids), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.networkclient.delete_bgpvpn.assert_has_calls( [mock.call(id) for id in fake_bgpvpn_ids]) class TestListBgpvpn(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestListBgpvpn, self).setUp() self.cmd = bgpvpn.ListBgpvpn(self.app, self.namespace) def test_list_all_bgpvpn(self): count = 3 fake_bgpvpns = fakes.create_bgpvpns(count=count) self.networkclient.bgpvpns = mock.Mock(return_value=fake_bgpvpns) arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.networkclient.bgpvpns.assert_called_once() self.assertEqual(headers, list(headers_short)) self.assertListItemEqual( list(data), [_get_data(fake_bgpvpn, columns_short) for fake_bgpvpn in fake_bgpvpns]) def test_list_all_bgpvpn_long_mode(self): count = 3 fake_bgpvpns = fakes.create_bgpvpns(count=count) self.networkclient.bgpvpns = mock.Mock(return_value=fake_bgpvpns) arglist = [ '--long', ] verifylist = [ ('long', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.networkclient.bgpvpns.assert_called_once() self.assertEqual(headers, list(headers_long)) self.assertListItemEqual( list(data), [_get_data(fake_bgpvpn, columns_long) for fake_bgpvpn in fake_bgpvpns]) def test_list_project_bgpvpn(self): count = 3 project_id = 'list_fake_project_id' attrs = {'tenant_id': project_id} fake_bgpvpns = fakes.create_bgpvpns(count=count, attrs=attrs) self.networkclient.bgpvpns = mock.Mock(return_value=fake_bgpvpns) arglist = [ '--project', project_id, ] verifylist = [ ('project', project_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.networkclient.bgpvpns.assert_called_once_with( tenant_id=project_id) self.assertEqual(headers, list(headers_short)) self.assertListItemEqual( list(data), [_get_data(fake_bgpvpn, columns_short) for fake_bgpvpn in fake_bgpvpns]) def test_list_bgpvpn_with_filters(self): count = 3 name = 'fake_id0' layer_type = 'l2' attrs = {'type': layer_type} fake_bgpvpns = fakes.create_bgpvpns(count=count, attrs=attrs) returned_bgpvpn = fake_bgpvpns[0] self.networkclient.bgpvpns = mock.Mock(return_value=[returned_bgpvpn]) arglist = [ '--property', 'name=%s' % name, '--property', 'type=%s' % layer_type, ] verifylist = [ ('property', {'name': name, 'type': layer_type}), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.networkclient.bgpvpns.assert_called_once_with( name=name, type=layer_type) self.assertEqual(headers, list(headers_short)) self.assertListItemEqual(list(data), [_get_data(returned_bgpvpn, columns_short)]) class TestShowBgpvpn(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestShowBgpvpn, self).setUp() self.cmd = bgpvpn.ShowBgpvpn(self.app, self.namespace) self.networkclient.find_bgpvpn = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) def test_show_bgpvpn(self): fake_bgpvpn = fakes.create_one_bgpvpn() self.networkclient.get_bgpvpn = mock.Mock( return_value=fake_bgpvpn) arglist = [ fake_bgpvpn['id'], ] verifylist = [ ('bgpvpn', fake_bgpvpn['id']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.networkclient.get_bgpvpn.assert_called_once_with( fake_bgpvpn['id']) self.assertEqual(sorted(sorted_columns), sorted(headers)) ././@PaxHeader0000000000000000000000000000021200000000000011450 xustar0000000000000000116 path=python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py 22 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_associat0000664000175000017500000002750700000000000034430 0ustar00zuulzuul00000000000000# Copyright (c) 2016 Juniper Networks Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # import operator from unittest import mock from osc_lib import exceptions from osc_lib import utils as osc_utils from osc_lib.utils import columns as column_util from neutronclient.tests.unit.osc.v2.networking_bgpvpn import fakes columns_short = tuple(col for col, _, listing_mode in fakes.BgpvpnFakeAssoc._attr_map if listing_mode in (column_util.LIST_BOTH, column_util.LIST_SHORT_ONLY)) columns_long = tuple(col for col, _, listing_mode in fakes.BgpvpnFakeAssoc._attr_map if listing_mode in (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)) headers_short = tuple(head for _, head, listing_mode in fakes.BgpvpnFakeAssoc._attr_map if listing_mode in (column_util.LIST_BOTH, column_util.LIST_SHORT_ONLY)) headers_long = tuple(head for _, head, listing_mode in fakes.BgpvpnFakeAssoc._attr_map if listing_mode in (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)) sorted_attr_map = sorted(fakes.BgpvpnFakeAssoc._attr_map, key=operator.itemgetter(1)) sorted_columns = tuple(col for col, _, _ in sorted_attr_map) sorted_headers = tuple(head for _, head, _ in sorted_attr_map) def _get_data(attrs, columns=sorted_columns): return osc_utils.get_dict_properties( attrs, columns, formatters=fakes.BgpvpnFakeAssoc._formatters) class TestCreateResAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestCreateResAssoc, self).setUp() self.networkclient.find_bgpvpn = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) self.networkclient.find_fake_resource = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = fakes.CreateBgpvpnFakeResAssoc(self.app, self.namespace) def test_create_resource_association(self): fake_bgpvpn = fakes.create_one_bgpvpn() fake_res = fakes.create_one_resource() fake_res_assoc = fakes.create_one_resource_association( fake_res) self.networkclient.create_bgpvpn_router_association = mock.Mock( return_value=fake_res_assoc) self.networkclient.find_bgpvpn_fake_resource_association = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) arglist = [ fake_bgpvpn['id'], fake_res['id'], '--project', fake_bgpvpn['tenant_id'], ] verifylist = [ ('bgpvpn', fake_bgpvpn['id']), ('resource', fake_res['id']), ('project', fake_bgpvpn['tenant_id']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) cols, data = self.cmd.take_action(parsed_args) fake_res_assoc_call = { 'fake_resource_id': 'fake_resource_id', 'tenant_id': 'fake_project_id' } self.networkclient.create_bgpvpn_router_association.\ assert_called_once_with( fake_bgpvpn['id'], **fake_res_assoc_call) self.assertEqual(sorted_columns, cols) self.assertEqual(_get_data(fake_res_assoc), data) class TestSetResAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestSetResAssoc, self).setUp() self.cmd = fakes.SetBgpvpnFakeResAssoc(self.app, self.namespace) def test_set_resource_association(self): fake_bgpvpn = fakes.create_one_bgpvpn() fake_res = fakes.create_one_resource() fake_res_assoc = fakes.create_one_resource_association( fake_res) self.networkclient.update_bgpvpn_router_association = mock.Mock( return_value={fakes.BgpvpnFakeAssoc._resource: fake_res_assoc}) arglist = [ fake_res_assoc['id'], fake_bgpvpn['id'], ] verifylist = [ ('resource_association_id', fake_res_assoc['id']), ('bgpvpn', fake_bgpvpn['id']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.networkclient.update_bgpvpn_router_association.\ assert_not_called() self.assertIsNone(result) class TestDeleteResAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestDeleteResAssoc, self).setUp() self.networkclient.find_bgpvpn = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = fakes.DeleteBgpvpnFakeResAssoc(self.app, self.namespace) def test_delete_one_association(self): fake_bgpvpn = fakes.create_one_bgpvpn() fake_res = fakes.create_one_resource() fake_res_assoc = fakes.create_one_resource_association( fake_res) self.networkclient.delete_bgpvpn_router_association = \ mock.Mock() arglist = [ fake_res_assoc['id'], fake_bgpvpn['id'], ] verifylist = [ ('resource_association_ids', [fake_res_assoc['id']]), ('bgpvpn', fake_bgpvpn['id']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.networkclient.delete_bgpvpn_router_association.\ assert_called_once_with(fake_bgpvpn['id'], fake_res_assoc['id']) self.assertIsNone(result) def test_delete_multi_bpgvpn(self): count = 3 fake_bgpvpn = fakes.create_one_bgpvpn() fake_res = fakes.create_resources(count=count) fake_res_assocs = fakes.create_resource_associations( fake_res) fake_res_assoc_ids = [ fake_res_assoc['id'] for fake_res_assoc in fake_res_assocs ] self.networkclient.delete_bgpvpn_router_association = \ mock.Mock() arglist = \ fake_res_assoc_ids + [ fake_bgpvpn['id'] ] verifylist = [ ('resource_association_ids', fake_res_assoc_ids), ('bgpvpn', fake_bgpvpn['id']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.networkclient.delete_bgpvpn_router_association.\ assert_has_calls([ mock.call( fake_bgpvpn['id'], id) for id in fake_res_assoc_ids]) self.assertIsNone(result) def test_delete_multi_bpgvpn_with_unknown(self): count = 3 fake_bgpvpn = fakes.create_one_bgpvpn() fake_res = fakes.create_resources(count=count) fake_res_assocs = fakes.create_resource_associations( fake_res) fake_res_assoc_ids = [ fake_res_assoc['id'] for fake_res_assoc in fake_res_assocs ] def raise_unknonw_resource(resource_path, name_or_id): if str(count - 2) in name_or_id: raise Exception() self.networkclient.delete_bgpvpn_router_association = mock.Mock( side_effect=raise_unknonw_resource) arglist = \ fake_res_assoc_ids + [ fake_bgpvpn['id'] ] verifylist = [ ('resource_association_ids', fake_res_assoc_ids), ('bgpvpn', fake_bgpvpn['id']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.networkclient.delete_bgpvpn_router_association.\ assert_has_calls([ mock.call(fake_bgpvpn['id'], id) for id in fake_res_assoc_ids] ) class TestListResAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestListResAssoc, self).setUp() self.networkclient.find_bgpvpn = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = fakes.ListBgpvpnFakeResAssoc(self.app, self.namespace) def test_list_bgpvpn_associations(self): count = 3 fake_bgpvpn = fakes.create_one_bgpvpn() fake_res = fakes.create_resources(count=count) fake_res_assocs = fakes.create_resource_associations( fake_res) self.networkclient.bgpvpn_router_associations = mock.Mock( return_value=fake_res_assocs) arglist = [ fake_bgpvpn['id'], ] verifylist = [ ('bgpvpn', fake_bgpvpn['id']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.networkclient.bgpvpn_router_associations.\ assert_called_once_with(fake_bgpvpn['id'], retrieve_all=True) self.assertEqual(headers, list(headers_short)) self.assertEqual( list(data), [_get_data(fake_res_assoc, columns_short) for fake_res_assoc in fake_res_assocs]) def test_list_bgpvpn_associations_long_mode(self): count = 3 fake_bgpvpn = fakes.create_one_bgpvpn() fake_res = fakes.create_resources(count=count) fake_res_assocs = fakes.create_resource_associations( fake_res) self.networkclient.bgpvpn_router_associations = mock.Mock( return_value=fake_res_assocs) arglist = [ '--long', fake_bgpvpn['id'], ] verifylist = [ ('long', True), ('bgpvpn', fake_bgpvpn['id']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.networkclient.bgpvpn_router_associations.\ assert_called_once_with(fake_bgpvpn['id'], retrieve_all=True) self.assertEqual(headers, list(headers_long)) self.assertEqual( list(data), [_get_data(fake_res_assoc, columns_long) for fake_res_assoc in fake_res_assocs]) class TestShowResAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestShowResAssoc, self).setUp() self.networkclient.find_bgpvpn = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = fakes.ShowBgpvpnFakeResAssoc(self.app, self.namespace) def test_show_resource_association(self): fake_bgpvpn = fakes.create_one_bgpvpn() fake_res = fakes.create_one_resource() fake_res_assoc = fakes.create_one_resource_association( fake_res) self.networkclient.get_bgpvpn_router_association = mock.Mock( return_value=fake_res_assoc) arglist = [ fake_res_assoc['id'], fake_bgpvpn['id'], ] verifylist = [ ('resource_association_id', fake_res_assoc['id']), ('bgpvpn', fake_bgpvpn['id']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.networkclient.get_bgpvpn_router_association.\ assert_called_once_with(fake_bgpvpn['id'], fake_res_assoc['id']) self.assertEqual(sorted_columns, columns) self.assertEqual(data, _get_data(fake_res_assoc)) ././@PaxHeader0000000000000000000000000000021000000000000011446 xustar0000000000000000114 path=python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py 22 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_associatio0000664000175000017500000002577500000000000034456 0ustar00zuulzuul00000000000000# Copyright (c) 2018 Orange SA. # 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 operator from unittest import mock from osc_lib.tests.utils import ParserException from osc_lib import utils as osc_utils from osc_lib.utils import columns as column_util from neutronclient.tests.unit.osc.v2.networking_bgpvpn import fakes columns_short = tuple(col for col, _, listing_mode in fakes.BgpvpnFakeRouterAssoc._attr_map if listing_mode in (column_util.LIST_BOTH, column_util.LIST_SHORT_ONLY)) columns_long = tuple(col for col, _, listing_mode in fakes.BgpvpnFakeRouterAssoc._attr_map if listing_mode in (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)) headers_short = tuple(head for _, head, listing_mode in fakes.BgpvpnFakeRouterAssoc._attr_map if listing_mode in (column_util.LIST_BOTH, column_util.LIST_SHORT_ONLY)) headers_long = tuple(head for _, head, listing_mode in fakes.BgpvpnFakeRouterAssoc._attr_map if listing_mode in (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)) sorted_attr_map = sorted(fakes.BgpvpnFakeRouterAssoc._attr_map, key=operator.itemgetter(1)) sorted_columns = tuple(col for col, _, _ in sorted_attr_map) sorted_headers = tuple(head for _, head, _ in sorted_attr_map) def _get_data(attrs, columns=sorted_columns): return osc_utils.get_dict_properties( attrs, columns, formatters=fakes.BgpvpnFakeAssoc._formatters) class TestCreateRouterAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestCreateRouterAssoc, self).setUp() self.cmd = fakes.CreateBgpvpnFakeRouterAssoc(self.app, self.namespace) self.fake_bgpvpn = fakes.create_one_bgpvpn() self.fake_router = fakes.create_one_resource() self.networkclient.find_bgpvpn = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) self.networkclient.find_fake_resource = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) def _build_args(self, param=None): arglist_base = [ self.fake_bgpvpn['id'], self.fake_router['id'], '--project', self.fake_bgpvpn['tenant_id'] ] if param is not None: if isinstance(param, list): arglist_base.extend(param) else: arglist_base.append(param) return arglist_base def _build_verify_list(self, param=None): verifylist = [ ('bgpvpn', self.fake_bgpvpn['id']), ('resource', self.fake_router['id']), ('project', self.fake_bgpvpn['tenant_id']) ] if param is not None: verifylist.append(param) return verifylist def _exec_create_router_association( self, fake_res_assoc, arglist, verifylist): parsed_args = self.check_parser(self.cmd, arglist, verifylist) cols, data = self.cmd.take_action(parsed_args) fake_res_assoc_call = { 'fake_resource_id': 'fake_resource_id', 'tenant_id': 'fake_project_id' } for key, value in verifylist: if value not in fake_res_assoc_call.values(): fake_res_assoc_call[key] = value fake_res_assoc_call.pop('bgpvpn') self.networkclient.create_bgpvpn_router_association.\ assert_called_once_with( self.fake_bgpvpn['id'], **fake_res_assoc_call) return cols, data def test_create_router_association(self): fake_res_assoc = fakes.create_one_resource_association( self.fake_router) self.networkclient.create_bgpvpn_router_association = mock.Mock( return_value={ fakes.BgpvpnFakeRouterAssoc._resource: fake_res_assoc, 'advertise_extra_routes': True}) arglist = self._build_args() # advertise_extra_routes will be False since none # of the mutually exclusive args present verifylist = self._build_verify_list(('advertise_extra_routes', False)) self._exec_create_router_association( fake_res_assoc, arglist, verifylist) def test_create_router_association_advertise(self): fake_res_assoc = fakes.create_one_resource_association( self.fake_router, {'advertise_extra_routes': True}) self.networkclient.create_bgpvpn_router_association = mock.Mock( return_value=fake_res_assoc) arglist = self._build_args('--advertise_extra_routes') verifylist = self._build_verify_list(('advertise_extra_routes', True)) cols, data = self._exec_create_router_association( fake_res_assoc, arglist, verifylist) self.assertEqual(sorted_columns, cols) self.assertEqual(_get_data(fake_res_assoc), data) def test_create_router_association_no_advertise(self): fake_res_assoc = fakes.create_one_resource_association( self.fake_router, {'advertise_extra_routes': False}) self.networkclient.create_bgpvpn_router_association = mock.Mock( return_value=fake_res_assoc) arglist = self._build_args('--no-advertise_extra_routes') verifylist = self._build_verify_list(('advertise_extra_routes', False)) cols, data = self._exec_create_router_association( fake_res_assoc, arglist, verifylist) self.assertEqual(sorted_columns, cols) self.assertEqual(_get_data(fake_res_assoc), data) def test_create_router_association_advertise_fault(self): arglist = self._build_args( ['--advertise_extra_routes', '--no-advertise_extra_routes']) try: self._exec_create_router_association(None, arglist, None) except ParserException as e: self.assertEqual(format(e), 'Argument parse failed') def test_router_association_unknown_arg(self): arglist = self._build_args('--unknown arg') try: self._exec_create_router_association(None, arglist, None) except ParserException as e: self.assertEqual(format(e), 'Argument parse failed') class TestSetRouterAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestSetRouterAssoc, self).setUp() self.cmd = fakes.SetBgpvpnFakeRouterAssoc(self.app, self.namespace) self.fake_bgpvpn = fakes.create_one_bgpvpn() self.fake_router = fakes.create_one_resource() self.networkclient.find_bgpvpn = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) def _build_args(self, fake_res_assoc, param=None): arglist_base = [ fake_res_assoc['id'], self.fake_bgpvpn['id'] ] if param is not None: if isinstance(param, list): arglist_base.extend(param) else: arglist_base.append(param) return arglist_base def _build_verify_list(self, fake_res_assoc, param=None): verifylist = [ ('resource_association_id', fake_res_assoc['id']), ('bgpvpn', self.fake_bgpvpn['id']) ] if param is not None: verifylist.append(param) return verifylist def test_set_router_association_no_advertise(self): fake_res_assoc = fakes.create_one_resource_association( self.fake_router, {'advertise_extra_routes': True}) self.networkclient.update_bgpvpn_router_association = \ mock.Mock() arglist = self._build_args( fake_res_assoc, '--no-advertise_extra_routes') verifylist = [ ('resource_association_id', fake_res_assoc['id']), ('bgpvpn', self.fake_bgpvpn['id']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.networkclient.update_bgpvpn_router_association.\ assert_called_once_with( self.fake_bgpvpn['id'], fake_res_assoc['id'], **{'advertise_extra_routes': False} ) self.assertIsNone(result) def test_set_router_association_advertise(self): fake_res_assoc = fakes.create_one_resource_association( self.fake_router, {'advertise_extra_routes': False}) self.networkclient.update_bgpvpn_router_association = \ mock.Mock() arglist = self._build_args( fake_res_assoc, '--advertise_extra_routes') verifylist = [ ('resource_association_id', fake_res_assoc['id']), ('bgpvpn', self.fake_bgpvpn['id']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.networkclient.update_bgpvpn_router_association.\ assert_called_once_with( self.fake_bgpvpn['id'], fake_res_assoc['id'], **{'advertise_extra_routes': True} ) self.assertIsNone(result) class TestShowRouterAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestShowRouterAssoc, self).setUp() self.cmd = fakes.ShowBgpvpnFakeRouterAssoc(self.app, self.namespace) self.networkclient.find_bgpvpn = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) def test_show_router_association(self): fake_bgpvpn = fakes.create_one_bgpvpn() fake_res = fakes.create_one_resource() fake_res_assoc = fakes.create_one_resource_association( fake_res, {'advertise_extra_routes': True}) self.networkclient.get_bgpvpn_router_association = mock.Mock( return_value=fake_res_assoc) arglist = [ fake_res_assoc['id'], fake_bgpvpn['id'], ] verifylist = [ ('resource_association_id', fake_res_assoc['id']), ('bgpvpn', fake_bgpvpn['id']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) cols, data = self.cmd.take_action(parsed_args) self.networkclient.get_bgpvpn_router_association.\ assert_called_once_with(fake_bgpvpn['id'], fake_res_assoc['id']) self.assertEqual(sorted_columns, cols) self.assertEqual(data, _get_data(fake_res_assoc)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2296627 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/sfc/0000775000175000017500000000000000000000000024726 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/sfc/__init__.py0000664000175000017500000000000000000000000027025 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/sfc/fakes.py0000775000175000017500000002360400000000000026401 0ustar00zuulzuul00000000000000# Copyright (c) 2017 Huawei Technologies India Pvt.Limited. # 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 from unittest import mock from osc_lib.tests import utils from oslo_utils import uuidutils from openstack.network.v2 import sfc_flow_classifier as flow_classifier from openstack.network.v2 import sfc_port_chain as port_chain from openstack.network.v2 import sfc_port_pair as port_pair from openstack.network.v2 import sfc_port_pair_group as port_pair_group from openstack.network.v2 import sfc_service_graph as service_graph class TestNeutronClientOSCV2(utils.TestCommand): def setUp(self): super(TestNeutronClientOSCV2, self).setUp() self.namespace = argparse.Namespace() self.app.client_manager.session = mock.Mock() self.app.client_manager.network = mock.Mock() self.network = self.app.client_manager.network self.network.find_sfc_flow_classifier = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id} ) self.network.find_sfc_port_chain = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id} ) self.network.find_sfc_port_pair = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id} ) self.network.find_sfc_port_pair_group = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id} ) self.network.find_sfc_service_graph = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id} ) self.network.find_port = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id} ) class FakeSfcPortPair(object): """Fake port pair attributes.""" @staticmethod def create_port_pair(attrs=None): """Create a fake port pair. :param Dictionary attrs: A dictionary with all attributes :return: A Dictionary with id, name, description, ingress, egress, service-function-parameter, project_id """ attrs = attrs or {} # Set default attributes. port_pair_attrs = { 'description': 'description', 'egress': uuidutils.generate_uuid(), 'id': uuidutils.generate_uuid(), 'ingress': uuidutils.generate_uuid(), 'name': 'port-pair-name', 'service_function_parameters': [('correlation', None), ('weight', 1)], 'project_id': uuidutils.generate_uuid(), } # Overwrite default attributes. port_pair_attrs.update(attrs) return port_pair.SfcPortPair(**port_pair_attrs) @staticmethod def create_port_pairs(attrs=None, count=1): """Create multiple port_pairs. :param Dictionary attrs: A dictionary with all attributes :param int count: The number of port_pairs to fake :return: A list of dictionaries faking the port_pairs """ port_pairs = [] for _ in range(count): port_pairs.append(FakeSfcPortPair.create_port_pair(attrs)) return port_pairs class FakeSfcPortPairGroup(object): """Fake port pair group attributes.""" @staticmethod def create_port_pair_group(attrs=None): """Create a fake port pair group. :param Dictionary attrs: A dictionary with all attributes :return: A Dictionary with id, name, description, port_pairs, group_id port_pair_group_parameters, project_id """ attrs = attrs or {} # Set default attributes. port_pair_group_attrs = { 'id': uuidutils.generate_uuid(), 'name': 'port-pair-group-name', 'description': 'description', 'port_pairs': uuidutils.generate_uuid(), 'port_pair_group_parameters': {"lb_fields": []}, 'project_id': uuidutils.generate_uuid(), 'tap_enabled': False } port_pair_group_attrs.update(attrs) return port_pair_group.SfcPortPairGroup(**port_pair_group_attrs) @staticmethod def create_port_pair_groups(attrs=None, count=1): """Create multiple port pair groups. :param Dictionary attrs: A dictionary with all attributes :param int count: The number of port_pair_groups to fake :return: A list of dictionaries faking the port pair groups """ port_pair_groups = [] for _ in range(count): port_pair_groups.append( FakeSfcPortPairGroup.create_port_pair_group(attrs)) return port_pair_groups class FakeSfcFlowClassifier(object): """Fake flow classifier attributes.""" @staticmethod def create_flow_classifier(attrs=None): """Create a fake flow classifier. :param Dictionary attrs: A dictionary with all attributes :return: A Dictionary with faking port chain attributes """ attrs = attrs or {} # Set default attributes. flow_classifier_attrs = { 'id': uuidutils.generate_uuid(), 'destination_ip_prefix': '2.2.2.2/32', 'destination_port_range_max': '90', 'destination_port_range_min': '80', 'ethertype': 'IPv4', 'logical_destination_port': uuidutils.generate_uuid(), 'logical_source_port': uuidutils.generate_uuid(), 'name': 'flow-classifier-name', 'description': 'fc_description', 'protocol': 'tcp', 'source_ip_prefix': '1.1.1.1/32', 'source_port_range_max': '20', 'source_port_range_min': '10', 'project_id': uuidutils.generate_uuid(), 'l7_parameters': {} } flow_classifier_attrs.update(attrs) return flow_classifier.SfcFlowClassifier(**flow_classifier_attrs) @staticmethod def create_flow_classifiers(attrs=None, count=1): """Create multiple flow classifiers. :param Dictionary attrs: A dictionary with all attributes :param int count: The number of flow classifiers to fake :return: A list of dictionaries faking the flow classifiers """ flow_classifiers = [] for _ in range(count): flow_classifiers.append( FakeSfcFlowClassifier.create_flow_classifier(attrs)) return flow_classifiers class FakeSfcPortChain(object): """Fake port chain attributes.""" @staticmethod def create_port_chain(attrs=None): """Create a fake port chain. :param Dictionary attrs: A dictionary with all attributes :return: A Dictionary with faking port chain attributes """ attrs = attrs or {} # Set default attributes. port_chain_attrs = { 'id': uuidutils.generate_uuid(), 'name': 'port-chain-name', 'description': 'description', 'port_pair_groups': uuidutils.generate_uuid(), 'flow_classifiers': uuidutils.generate_uuid(), 'chain_parameters': {"correlation": "mpls", "symmetric": False}, 'project_id': uuidutils.generate_uuid(), } port_chain_attrs.update(attrs) return port_chain.SfcPortChain(**port_chain_attrs) @staticmethod def create_port_chains(attrs=None, count=1): """Create multiple port chains. :param Dictionary attrs: A dictionary with all attributes :param int count: The number of port chains to fake :return: A list of dictionaries faking the port chains. """ port_chains = [] for _ in range(count): port_chains.append(FakeSfcPortChain.create_port_chain(attrs)) return port_chains class FakeSfcServiceGraph(object): """Fake service graph attributes.""" @staticmethod def create_sfc_service_graph(attrs=None): """Create a fake service graph. :param Dictionary attrs: A dictionary with all attributes :return: A Dictionary with faking service graph attributes """ attrs = attrs or {} # Set default attributes. service_graph_attrs = { 'id': uuidutils.generate_uuid(), 'name': 'port-pair-group-name', 'description': 'description', 'port_chains': {uuidutils.generate_uuid(): [ uuidutils.generate_uuid()]}, 'project_id': uuidutils.generate_uuid(), } service_graph_attrs.update(attrs) return service_graph.SfcServiceGraph(**service_graph_attrs) @staticmethod def create_sfc_service_graphs(attrs=None, count=1): """Create multiple service graphs. :param Dictionary attrs: A dictionary with all attributes :param int count: The number of service graphs to fake :return: A list of dictionaries faking the service graphs. """ service_graphs = [] for _ in range(count): service_graphs.append( FakeSfcServiceGraph.create_sfc_service_graph(attrs)) return service_graphs ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py0000775000175000017500000003422500000000000031523 0ustar00zuulzuul00000000000000# Copyright (c) 2017 Huawei Technologies India Pvt.Limited. # 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 unittest import mock from osc_lib import exceptions import testtools from neutronclient.osc.v2.sfc import sfc_flow_classifier from neutronclient.tests.unit.osc.v2.sfc import fakes class TestCreateSfcFlowClassifier(fakes.TestNeutronClientOSCV2): _fc = fakes.FakeSfcFlowClassifier.create_flow_classifier() columns = ('Description', 'Destination IP', 'Destination Port Range Max', 'Destination Port Range Min', 'Ethertype', 'ID', 'L7 Parameters', 'Logical Destination Port', 'Logical Source Port', 'Name', 'Project', 'Protocol', 'Source IP', 'Source Port Range Max', 'Source Port Range Min', 'Summary',) def get_data(self): return ( self._fc['description'], self._fc['destination_ip_prefix'], self._fc['destination_port_range_max'], self._fc['destination_port_range_min'], self._fc['ethertype'], self._fc['id'], self._fc['l7_parameters'], self._fc['logical_destination_port'], self._fc['logical_source_port'], self._fc['name'], self._fc['project_id'], self._fc['protocol'], self._fc['source_ip_prefix'], self._fc['source_port_range_max'], self._fc['source_port_range_min'] ) def setUp(self): super(TestCreateSfcFlowClassifier, self).setUp() self.network.create_sfc_flow_classifier = mock.Mock( return_value=self._fc) self.data = self.get_data() # Get the command object to test self.cmd = sfc_flow_classifier.CreateSfcFlowClassifier(self.app, self.namespace) def test_create_flow_classifier_default_options(self): arglist = [ "--logical-source-port", self._fc['logical_source_port'], "--ethertype", self._fc['ethertype'], self._fc['name'], ] verifylist = [ ('logical_source_port', self._fc['logical_source_port']), ('ethertype', self._fc['ethertype']), ('name', self._fc['name']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) self.network.create_sfc_flow_classifier.assert_called_once_with( **{'name': self._fc['name'], 'logical_source_port': self._fc['logical_source_port'], 'ethertype': self._fc['ethertype'] } ) self.assertEqual(self.columns, columns) def test_create_flow_classifier(self): arglist = [ "--description", self._fc['description'], "--ethertype", self._fc['ethertype'], "--protocol", self._fc['protocol'], "--source-ip-prefix", self._fc['source_ip_prefix'], "--destination-ip-prefix", self._fc['destination_ip_prefix'], "--logical-source-port", self._fc['logical_source_port'], "--logical-destination-port", self._fc['logical_destination_port'], self._fc['name'], "--l7-parameters", 'url=path', ] param = 'url=path' verifylist = [ ('description', self._fc['description']), ('name', self._fc['name']), ('ethertype', self._fc['ethertype']), ('protocol', self._fc['protocol']), ('source_ip_prefix', self._fc['source_ip_prefix']), ('destination_ip_prefix', self._fc['destination_ip_prefix']), ('logical_source_port', self._fc['logical_source_port']), ('logical_destination_port', self._fc['logical_destination_port']), ('l7_parameters', param) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) self.network.create_sfc_flow_classifier.assert_called_once_with( **{ 'name': self._fc['name'], 'description': self._fc['description'], 'ethertype': self._fc['ethertype'], 'protocol': self._fc['protocol'], 'source_ip_prefix': self._fc['source_ip_prefix'], 'destination_ip_prefix': self._fc['destination_ip_prefix'], 'logical_source_port': self._fc['logical_source_port'], 'logical_destination_port': self._fc['logical_destination_port'], 'l7_parameters': param } ) self.assertEqual(self.columns, columns) class TestDeleteSfcFlowClassifier(fakes.TestNeutronClientOSCV2): _flow_classifier = \ fakes.FakeSfcFlowClassifier.create_flow_classifiers(count=1) def setUp(self): super(TestDeleteSfcFlowClassifier, self).setUp() self.network.delete_sfc_flow_classifier = mock.Mock( return_value=None) self.cmd = sfc_flow_classifier.DeleteSfcFlowClassifier(self.app, self.namespace) def test_delete_flow_classifier(self): client = self.app.client_manager.network mock_flow_classifier_delete = client.delete_sfc_flow_classifier arglist = [ self._flow_classifier[0]['id'], ] verifylist = [ ('flow_classifier', [self._flow_classifier[0]['id']]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) mock_flow_classifier_delete.assert_called_once_with( self._flow_classifier[0]['id']) self.assertIsNone(result) def test_delete_multiple_flow_classifiers_with_exception(self): client = self.app.client_manager.network target1 = self._flow_classifier[0]['id'] arglist = [target1] verifylist = [('flow_classifier', [target1])] client.find_sfc_flow_classifier.side_effect = [ target1, exceptions.CommandError ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) msg = "1 of 2 flow classifier(s) failed to delete." with testtools.ExpectedException(exceptions.CommandError) as e: self.cmd.take_action(parsed_args) self.assertEqual(msg, str(e)) class TestSetSfcFlowClassifier(fakes.TestNeutronClientOSCV2): _flow_classifier = fakes.FakeSfcFlowClassifier.create_flow_classifier() _flow_classifier_name = _flow_classifier['name'] _flow_classifier_id = _flow_classifier['id'] def setUp(self): super(TestSetSfcFlowClassifier, self).setUp() self.network.update_sfc_flow_classifier = mock.Mock( return_value=None) self.cmd = sfc_flow_classifier.SetSfcFlowClassifier(self.app, self.namespace) def test_set_flow_classifier(self): client = self.app.client_manager.network mock_flow_classifier_update = client.update_sfc_flow_classifier arglist = [ self._flow_classifier_name, '--name', 'name_updated', '--description', 'desc_updated' ] verifylist = [ ('flow_classifier', self._flow_classifier_name), ('name', 'name_updated'), ('description', 'desc_updated'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) attrs = { 'name': 'name_updated', 'description': 'desc_updated'} mock_flow_classifier_update.assert_called_once_with( self._flow_classifier_name, **attrs) self.assertIsNone(result) class TestShowSfcFlowClassifier(fakes.TestNeutronClientOSCV2): _fc = fakes.FakeSfcFlowClassifier.create_flow_classifier() data = ( _fc['description'], _fc['destination_ip_prefix'], _fc['destination_port_range_max'], _fc['destination_port_range_min'], _fc['ethertype'], _fc['id'], _fc['l7_parameters'], _fc['logical_destination_port'], _fc['logical_source_port'], _fc['name'], _fc['project_id'], _fc['protocol'], _fc['source_ip_prefix'], _fc['source_port_range_max'], _fc['source_port_range_min'] ) _flow_classifier = _fc _flow_classifier_id = _fc['id'] columns = ('Description', 'Destination IP', 'Destination Port Range Max', 'Destination Port Range Min', 'Ethertype', 'ID', 'L7 Parameters', 'Logical Destination Port', 'Logical Source Port', 'Name', 'Project', 'Protocol', 'Source IP', 'Source Port Range Max', 'Source Port Range Min', 'Summary',) def setUp(self): super(TestShowSfcFlowClassifier, self).setUp() self.network.get_sfc_flow_classifier = mock.Mock( return_value=self._flow_classifier ) # Get the command object to test self.cmd = sfc_flow_classifier.ShowSfcFlowClassifier(self.app, self.namespace) def test_show_flow_classifier(self): client = self.app.client_manager.network mock_flow_classifier_show = client.get_sfc_flow_classifier arglist = [ self._flow_classifier_id, ] verifylist = [ ('flow_classifier', self._flow_classifier_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) mock_flow_classifier_show.assert_called_once_with( self._flow_classifier_id) self.assertEqual(self.columns, columns) class TestListSfcFlowClassifier(fakes.TestNeutronClientOSCV2): _fc = fakes.FakeSfcFlowClassifier.create_flow_classifiers(count=1) columns = ('ID', 'Name', 'Summary') columns_long = ('ID', 'Name', 'Protocol', 'Ethertype', 'Source IP', 'Destination IP', 'Logical Source Port', 'Logical Destination Port', 'Source Port Range Min', 'Source Port Range Max', 'Destination Port Range Min', 'Destination Port Range Max', 'L7 Parameters', 'Description', 'Project') _flow_classifier = _fc[0] data = [ _flow_classifier['id'], _flow_classifier['name'], _flow_classifier['protocol'], _flow_classifier['source_ip_prefix'], _flow_classifier['destination_ip_prefix'], _flow_classifier['logical_source_port'], _flow_classifier['logical_destination_port'] ] data_long = [ _flow_classifier['id'], _flow_classifier['name'], _flow_classifier['protocol'], _flow_classifier['ethertype'], _flow_classifier['source_ip_prefix'], _flow_classifier['destination_ip_prefix'], _flow_classifier['logical_source_port'], _flow_classifier['logical_destination_port'], _flow_classifier['source_port_range_min'], _flow_classifier['source_port_range_max'], _flow_classifier['destination_port_range_min'], _flow_classifier['destination_port_range_max'], _flow_classifier['l7_parameters'], _flow_classifier['description'] ] _flow_classifier1 = {'flow_classifiers': _flow_classifier} _flow_classifier_id = _flow_classifier['id'] def setUp(self): super(TestListSfcFlowClassifier, self).setUp() self.network.sfc_flow_classifiers = mock.Mock( return_value=self._fc ) # Get the command object to test self.cmd = sfc_flow_classifier.ListSfcFlowClassifier(self.app, self.namespace) def test_list_flow_classifiers(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args) fcs = self.network.sfc_flow_classifiers() fc = fcs[0] data = [ fc['id'], fc['name'], fc['protocol'], fc['source_ip_prefix'], fc['destination_ip_prefix'], fc['logical_source_port'], fc['logical_destination_port'] ] self.assertEqual(list(self.columns), columns[0]) self.assertEqual(self.data, data) def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] fcs = self.network.sfc_flow_classifiers() fc = fcs[0] data = [ fc['id'], fc['name'], fc['protocol'], fc['ethertype'], fc['source_ip_prefix'], fc['destination_ip_prefix'], fc['logical_source_port'], fc['logical_destination_port'], fc['source_port_range_min'], fc['source_port_range_max'], fc['destination_port_range_min'], fc['destination_port_range_max'], fc['l7_parameters'], fc['description'] ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns_long = self.cmd.take_action(parsed_args)[0] self.assertEqual(list(self.columns_long), columns_long) self.assertEqual(self.data_long, data) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py0000775000175000017500000004312100000000000030471 0ustar00zuulzuul00000000000000# Copyright (c) 2017 Huawei Technologies India Pvt.Limited. # 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 unittest import mock from osc_lib import exceptions import testtools from neutronclient.osc.v2.sfc import sfc_port_chain from neutronclient.tests.unit.osc.v2.sfc import fakes def _get_id(client, id_or_name, resource): return id_or_name class TestCreateSfcPortChain(fakes.TestNeutronClientOSCV2): # The new port_chain created _port_chain = fakes.FakeSfcPortChain.create_port_chain() columns = ('Chain Parameters', 'Description', 'Flow Classifiers', 'ID', 'Name', 'Port Pair Groups', 'Project') def get_data(self): return ( self._port_chain['chain_parameters'], self._port_chain['description'], self._port_chain['flow_classifiers'], self._port_chain['id'], self._port_chain['name'], self._port_chain['port_pair_groups'], self._port_chain['project_id'], ) def setUp(self): super(TestCreateSfcPortChain, self).setUp() self.network.create_sfc_port_chain = mock.Mock( return_value=self._port_chain) self.data = self.get_data() # Get the command object to test self.cmd = sfc_port_chain.CreateSfcPortChain(self.app, self.namespace) def test_create_port_chain_default_options(self): arglist = [ self._port_chain['name'], "--port-pair-group", self._port_chain['port_pair_groups'] ] verifylist = [ ('name', self._port_chain['name']), ('port_pair_groups', [self._port_chain['port_pair_groups']]), ('flow_classifiers', []), ('chain_parameters', None), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) self.network.create_sfc_port_chain.assert_called_once_with( **{ 'name': self._port_chain['name'], 'port_pair_groups': [self._port_chain['port_pair_groups']] } ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) def test_create_port_chain_all_options(self): arglist = [ "--description", self._port_chain['description'], "--port-pair-group", self._port_chain['port_pair_groups'], self._port_chain['name'], "--flow-classifier", self._port_chain['flow_classifiers'], "--chain-parameters", 'correlation=mpls,symmetric=true', ] cp = {'correlation': 'mpls', 'symmetric': 'true'} verifylist = [ ('port_pair_groups', [self._port_chain['port_pair_groups']]), ('name', self._port_chain['name']), ('description', self._port_chain['description']), ('flow_classifiers', [self._port_chain['flow_classifiers']]), ('chain_parameters', [cp]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) self.network.create_sfc_port_chain.assert_called_once_with( **{ 'name': self._port_chain['name'], 'port_pair_groups': [self._port_chain['port_pair_groups']], 'description': self._port_chain['description'], 'flow_classifiers': [self._port_chain['flow_classifiers']], 'chain_parameters': cp } ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) class TestDeleteSfcPortChain(fakes.TestNeutronClientOSCV2): _port_chain = fakes.FakeSfcPortChain.create_port_chains(count=1) def setUp(self): super(TestDeleteSfcPortChain, self).setUp() self.network.delete_sfc_port_chain = mock.Mock(return_value=None) self.cmd = sfc_port_chain.DeleteSfcPortChain(self.app, self.namespace) def test_delete_port_chain(self): client = self.app.client_manager.network mock_port_chain_delete = client.delete_sfc_port_chain arglist = [ self._port_chain[0]['id'], ] verifylist = [ ('port_chain', [self._port_chain[0]['id']]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) mock_port_chain_delete.assert_called_once_with( self._port_chain[0]['id']) self.assertIsNone(result) def test_delete_multiple_port_chains_with_exception(self): client = self.app.client_manager.network target1 = self._port_chain[0]['id'] arglist = [target1] verifylist = [('port_chain', [target1])] client.find_sfc_port_chain.side_effect = [ target1, exceptions.CommandError ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) msg = "1 of 2 port chain(s) failed to delete." with testtools.ExpectedException(exceptions.CommandError) as e: self.cmd.take_action(parsed_args) self.assertEqual(msg, str(e)) class TestListSfcPortChain(fakes.TestNeutronClientOSCV2): _port_chains = fakes.FakeSfcPortChain.create_port_chains(count=1) columns = ('ID', 'Name', 'Port Pair Groups', 'Flow Classifiers', 'Chain Parameters') columns_long = ('ID', 'Name', 'Port Pair Groups', 'Flow Classifiers', 'Chain Parameters', 'Description', 'Project') _port_chain = _port_chains[0] data = [ _port_chain['id'], _port_chain['name'], _port_chain['port_pair_groups'], _port_chain['flow_classifiers'], _port_chain['chain_parameters'], ] data_long = [ _port_chain['id'], _port_chain['name'], _port_chain['project_id'], _port_chain['port_pair_groups'], _port_chain['flow_classifiers'], _port_chain['chain_parameters'], _port_chain['description'] ] _port_chain1 = {'port_chains': _port_chain} _port_chain_id = _port_chain['id'] def setUp(self): super(TestListSfcPortChain, self).setUp() self.network.sfc_port_chains = mock.Mock( return_value=self._port_chains ) # Get the command object to test self.cmd = sfc_port_chain.ListSfcPortChain(self.app, self.namespace) def test_list_port_chains(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args)[0] pcs = self.network.sfc_port_chains() pc = pcs[0] data = [ pc['id'], pc['name'], pc['port_pair_groups'], pc['flow_classifiers'], pc['chain_parameters'], ] self.assertEqual(list(self.columns), columns) self.assertEqual(self.data, data) def test_list_port_chain_with_long_opion(self): arglist = ['--long'] verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args)[0] pcs = self.network.sfc_port_chains() pc = pcs[0] data = [ pc['id'], pc['name'], pc['project_id'], pc['port_pair_groups'], pc['flow_classifiers'], pc['chain_parameters'], pc['description'] ] self.assertEqual(list(self.columns_long), columns) self.assertEqual(self.data_long, data) class TestSetSfcPortChain(fakes.TestNeutronClientOSCV2): _port_chain = fakes.FakeSfcPortChain.create_port_chain() resource = _port_chain res = 'port_chain' _port_chain_name = _port_chain['name'] _port_chain_id = _port_chain['id'] pc_ppg = _port_chain['port_pair_groups'] pc_fc = _port_chain['flow_classifiers'] def setUp(self): super(TestSetSfcPortChain, self).setUp() self.mocked = self.network.update_sfc_port_chain self.cmd = sfc_port_chain.SetSfcPortChain(self.app, self.namespace) def test_set_port_chain(self): client = self.app.client_manager.network mock_port_chain_update = client.update_sfc_port_chain arglist = [ self._port_chain_name, '--name', 'name_updated', '--description', 'desc_updated', ] verifylist = [ ('port_chain', self._port_chain_name), ('name', 'name_updated'), ('description', 'desc_updated'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) attrs = {'name': 'name_updated', 'description': 'desc_updated'} mock_port_chain_update.assert_called_once_with(self._port_chain_name, **attrs) self.assertIsNone(result) def test_set_flow_classifiers(self): target = self.resource['id'] fc1 = 'flow_classifier1' fc2 = 'flow_classifier2' self.network.find_sfc_port_chain = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id, 'flow_classifiers': [self.pc_fc]} ) self.network.find_sfc_flow_classifier.side_effect = \ lambda name_or_id, ignore_missing=False: {'id': name_or_id} arglist = [ target, '--flow-classifier', fc1, '--flow-classifier', fc2, ] verifylist = [ (self.res, target), ('flow_classifiers', [fc1, fc2]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'flow_classifiers': [self.pc_fc, fc1, fc2]} self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_set_no_flow_classifier(self): client = self.app.client_manager.network mock_port_chain_update = client.update_sfc_port_chain arglist = [ self._port_chain_name, '--no-flow-classifier', ] verifylist = [ ('port_chain', self._port_chain_name), ('no_flow_classifier', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) attrs = {'flow_classifiers': []} mock_port_chain_update.assert_called_once_with(self._port_chain_name, **attrs) self.assertIsNone(result) def test_set_port_pair_groups(self): target = self.resource['id'] existing_ppg = self.pc_ppg ppg1 = 'port_pair_group1' ppg2 = 'port_pair_group2' self.network.find_sfc_port_chain = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id, 'port_pair_groups': [self.pc_ppg]} ) arglist = [ target, '--port-pair-group', ppg1, '--port-pair-group', ppg2, ] verifylist = [ (self.res, target), ('port_pair_groups', [ppg1, ppg2]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'port_pair_groups': [existing_ppg, ppg1, ppg2]} self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_set_no_port_pair_group(self): target = self.resource['id'] ppg1 = 'port_pair_group1' arglist = [ target, '--no-port-pair-group', '--port-pair-group', ppg1, ] verifylist = [ (self.res, target), ('no_port_pair_group', True), ('port_pair_groups', [ppg1]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'port_pair_groups': [ppg1]} self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_set_only_no_port_pair_group(self): target = self.resource['id'] arglist = [ target, '--no-port-pair-group', ] verifylist = [ (self.res, target), ('no_port_pair_group', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) class TestShowSfcPortChain(fakes.TestNeutronClientOSCV2): _pc = fakes.FakeSfcPortChain.create_port_chain() data = ( _pc['chain_parameters'], _pc['description'], _pc['flow_classifiers'], _pc['id'], _pc['name'], _pc['port_pair_groups'], _pc['project_id'] ) _port_chain = _pc _port_chain_id = _pc['id'] columns = ('Chain Parameters', 'Description', 'Flow Classifiers', 'ID', 'Name', 'Port Pair Groups', 'Project') def setUp(self): super(TestShowSfcPortChain, self).setUp() self.network.get_sfc_port_chain = mock.Mock( return_value=self._port_chain ) # Get the command object to test self.cmd = sfc_port_chain.ShowSfcPortChain(self.app, self.namespace) def test_show_port_chain(self): client = self.app.client_manager.network mock_port_chain_show = client.get_sfc_port_chain arglist = [ self._port_chain_id, ] verifylist = [ ('port_chain', self._port_chain_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) mock_port_chain_show.assert_called_once_with(self._port_chain_id) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) class TestUnsetSfcPortChain(fakes.TestNeutronClientOSCV2): _port_chain = fakes.FakeSfcPortChain.create_port_chain() resource = _port_chain res = 'port_chain' _port_chain_name = _port_chain['name'] _port_chain_id = _port_chain['id'] pc_ppg = _port_chain['port_pair_groups'] pc_fc = _port_chain['flow_classifiers'] def setUp(self): super(TestUnsetSfcPortChain, self).setUp() self.network.update_sfc_port_chain = mock.Mock( return_value=None) self.mocked = self.network.update_sfc_port_chain self.cmd = sfc_port_chain.UnsetSfcPortChain(self.app, self.namespace) def test_unset_port_pair_group(self): target = self.resource['id'] ppg1 = 'port_pair_group1' self.network.find_sfc_port_chain = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id, 'port_pair_groups': [self.pc_ppg]} ) self.network.find_sfc_port_pair_group.side_effect = \ lambda name_or_id, ignore_missing=False: {'id': name_or_id} arglist = [ target, '--port-pair-group', ppg1, ] verifylist = [ (self.res, target), ('port_pair_groups', [ppg1]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'port_pair_groups': [self.pc_ppg]} self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_unset_flow_classifier(self): target = self.resource['id'] fc1 = 'flow_classifier1' self.network.find_sfc_port_chain = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id, 'flow_classifiers': [self.pc_fc]} ) self.network.find_sfc_flow_classifier.side_effect = \ lambda name_or_id, ignore_missing=False: {'id': name_or_id} arglist = [ target, '--flow-classifier', fc1, ] verifylist = [ (self.res, target), ('flow_classifiers', [fc1]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'flow_classifiers': [self.pc_fc]} self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_unset_all_flow_classifier(self): client = self.app.client_manager.network target = self.resource['id'] mock_port_chain_update = client.update_sfc_port_chain arglist = [ target, '--all-flow-classifier', ] verifylist = [ (self.res, target), ('all_flow_classifier', True) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'flow_classifiers': []} mock_port_chain_update.assert_called_once_with(target, **expect) self.assertIsNone(result) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/sfc/test_port_pair.py0000775000175000017500000002544100000000000030347 0ustar00zuulzuul00000000000000# Copyright (c) 2017 Huawei Technologies India Pvt.Limited. # 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 unittest import mock from osc_lib import exceptions import testtools from neutronclient.osc.v2.sfc import sfc_port_pair from neutronclient.tests.unit.osc.v2.sfc import fakes class TestCreateSfcPortPair(fakes.TestNeutronClientOSCV2): # The new port_pair created _port_pair = fakes.FakeSfcPortPair.create_port_pair() columns = ('Description', 'Egress Logical Port', 'ID', 'Ingress Logical Port', 'Name', 'Project', 'Service Function Parameters') def get_data(self): return ( self._port_pair['description'], self._port_pair['egress'], self._port_pair['id'], self._port_pair['ingress'], self._port_pair['name'], self._port_pair['project_id'], self._port_pair['service_function_parameters'] ) def setUp(self): super(TestCreateSfcPortPair, self).setUp() self.network.create_sfc_port_pair = mock.Mock( return_value=self._port_pair) self.data = self.get_data() # Get the command object to test self.cmd = sfc_port_pair.CreateSfcPortPair(self.app, self.namespace) def test_create_port_pair_default_options(self): arglist = [ "--ingress", self._port_pair['ingress'], "--egress", self._port_pair['egress'], self._port_pair['name'], ] verifylist = [ ('ingress', self._port_pair['ingress']), ('egress', self._port_pair['egress']), ('name', self._port_pair['name']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) self.network.create_sfc_port_pair.assert_called_once_with( **{'name': self._port_pair['name'], 'ingress': self._port_pair['ingress'], 'egress': self._port_pair['egress']} ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) def _test_create_port_pair_all_options(self, correlation): arglist = [ "--description", self._port_pair['description'], "--egress", self._port_pair['egress'], "--ingress", self._port_pair['ingress'], self._port_pair['name'], "--service-function-parameters", 'correlation=%s,weight=1' % correlation, ] verifylist = [ ('ingress', self._port_pair['ingress']), ('egress', self._port_pair['egress']), ('name', self._port_pair['name']), ('description', self._port_pair['description']), ('service_function_parameters', [{'correlation': correlation, 'weight': '1'}]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) if correlation == "None": correlation_param = None else: correlation_param = correlation self.network.create_sfc_port_pair.assert_called_once_with( **{'name': self._port_pair['name'], 'ingress': self._port_pair['ingress'], 'egress': self._port_pair['egress'], 'description': self._port_pair['description'], 'service_function_parameters': {'correlation': correlation_param, 'weight': '1'}} ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) def test_create_port_pair_all_options(self): self._test_create_port_pair_all_options('None') def test_create_port_pair_all_options_mpls(self): self._test_create_port_pair_all_options('mpls') class TestDeleteSfcPortPair(fakes.TestNeutronClientOSCV2): _port_pair = fakes.FakeSfcPortPair.create_port_pairs(count=1) def setUp(self): super(TestDeleteSfcPortPair, self).setUp() self.network.delete_sfc_port_pair = mock.Mock(return_value=None) self.cmd = sfc_port_pair.DeleteSfcPortPair(self.app, self.namespace) def test_delete_port_pair(self): client = self.app.client_manager.network mock_port_pair_delete = client.delete_sfc_port_pair arglist = [ self._port_pair[0]['id'], ] verifylist = [ ('port_pair', [self._port_pair[0]['id']]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) mock_port_pair_delete.assert_called_once_with( self._port_pair[0]['id']) self.assertIsNone(result) def test_delete_multiple_port_pairs_with_exception(self): client = self.app.client_manager.network target1 = self._port_pair[0]['id'] arglist = [target1] verifylist = [('port_pair', [target1])] client.find_sfc_port_pair.side_effect = [ target1, exceptions.CommandError ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) msg = "1 of 2 port pair(s) failed to delete." with testtools.ExpectedException(exceptions.CommandError) as e: self.cmd.take_action(parsed_args) self.assertEqual(msg, str(e)) class TestListSfcPortPair(fakes.TestNeutronClientOSCV2): _port_pairs = fakes.FakeSfcPortPair.create_port_pairs() columns = ('ID', 'Name', 'Ingress Logical Port', 'Egress Logical Port') columns_long = ('ID', 'Name', 'Ingress Logical Port', 'Egress Logical Port', 'Service Function Parameters', 'Description', 'Project') _port_pair = _port_pairs[0] data = [ _port_pair['id'], _port_pair['name'], _port_pair['ingress'], _port_pair['egress'] ] data_long = [ _port_pair['id'], _port_pair['name'], _port_pair['ingress'], _port_pair['egress'], _port_pair['service_function_parameters'], _port_pair['description'] ] _port_pair1 = {'port_pairs': _port_pair} _port_pair_id = _port_pair['id'], def setUp(self): super(TestListSfcPortPair, self).setUp() self.network.sfc_port_pairs = mock.Mock( return_value=self._port_pairs) # Get the command object to test self.cmd = sfc_port_pair.ListSfcPortPair(self.app, self.namespace) def test_list_port_pairs(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args)[0] port_pairs = self.network.sfc_port_pairs() port_pair = port_pairs[0] data = [ port_pair['id'], port_pair['name'], port_pair['ingress'], port_pair['egress'] ] self.assertEqual(list(self.columns), columns) self.assertEqual(self.data, data) def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] port_pairs = self.network.sfc_port_pairs() port_pair = port_pairs[0] data = [ port_pair['id'], port_pair['name'], port_pair['ingress'], port_pair['egress'], port_pair['service_function_parameters'], port_pair['description'] ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns_long = self.cmd.take_action(parsed_args)[0] self.assertEqual(list(self.columns_long), columns_long) self.assertEqual(self.data_long, data) class TestSetSfcPortPair(fakes.TestNeutronClientOSCV2): _port_pair = fakes.FakeSfcPortPair.create_port_pair() _port_pair_name = _port_pair['name'] _port_pair_id = _port_pair['id'] def setUp(self): super(TestSetSfcPortPair, self).setUp() self.network.update_sfc_port_pair = mock.Mock(return_value=None) self.cmd = sfc_port_pair.SetSfcPortPair(self.app, self.namespace) def test_set_port_pair(self): client = self.app.client_manager.network mock_port_pair_update = client.update_sfc_port_pair arglist = [ self._port_pair_name, '--name', 'name_updated', '--description', 'desc_updated' ] verifylist = [ ('port_pair', self._port_pair_name), ('name', 'name_updated'), ('description', 'desc_updated'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) attrs = { 'name': 'name_updated', 'description': 'desc_updated' } mock_port_pair_update.assert_called_once_with(self._port_pair_name, **attrs) self.assertIsNone(result) class TestShowSfcPortPair(fakes.TestNeutronClientOSCV2): _pp = fakes.FakeSfcPortPair.create_port_pair() data = ( _pp['description'], _pp['egress'], _pp['id'], _pp['ingress'], _pp['name'], _pp['project_id'], _pp['service_function_parameters'], ) _port_pair = _pp _port_pair_id = _pp['id'] columns = ( 'Description', 'Egress Logical Port', 'ID', 'Ingress Logical Port', 'Name', 'Project', 'Service Function Parameters' ) def setUp(self): super(TestShowSfcPortPair, self).setUp() self.network.get_sfc_port_pair = mock.Mock( return_value=self._port_pair ) # Get the command object to test self.cmd = sfc_port_pair.ShowSfcPortPair(self.app, self.namespace) def test_show_port_pair(self): client = self.app.client_manager.network mock_port_pair_show = client.get_sfc_port_pair arglist = [ self._port_pair_id, ] verifylist = [ ('port_pair', self._port_pair_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) mock_port_pair_show.assert_called_once_with(self._port_pair_id) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/sfc/test_port_pair_group.py0000775000175000017500000003740400000000000031565 0ustar00zuulzuul00000000000000# Copyright (c) 2017 Huawei Technologies India Pvt.Limited. # 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 unittest import mock from osc_lib import exceptions import testtools from neutronclient.osc.v2.sfc import sfc_port_pair_group from neutronclient.tests.unit.osc.v2.sfc import fakes class TestCreateSfcPortPairGroup(fakes.TestNeutronClientOSCV2): _port_pair_group = fakes.FakeSfcPortPairGroup.create_port_pair_group() columns = ('Description', 'ID', 'Name', 'Port Pair', 'Port Pair Group Parameters', 'Project', 'Tap Enabled') def get_data(self, ppg): return ( ppg['description'], ppg['id'], ppg['name'], ppg['port_pairs'], ppg['port_pair_group_parameters'], ppg['project_id'], ppg['tap_enabled'] ) def setUp(self): super(TestCreateSfcPortPairGroup, self).setUp() self.network.create_sfc_port_pair_group = mock.Mock( return_value=self._port_pair_group) self.data = self.get_data(self._port_pair_group) # Get the command object to test self.cmd = sfc_port_pair_group.CreateSfcPortPairGroup(self.app, self.namespace) def test_create_port_pair_group_default_options(self): arglist = [ "--port-pair", self._port_pair_group['port_pairs'], self._port_pair_group['name'], ] verifylist = [ ('port_pairs', [self._port_pair_group['port_pairs']]), ('name', self._port_pair_group['name']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) self.network.create_sfc_port_pair_group.assert_called_once_with( **{'name': self._port_pair_group['name'], 'port_pairs': [self._port_pair_group['port_pairs']]}) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) def test_create_port_pair_group(self): arglist = [ "--description", self._port_pair_group['description'], "--port-pair", self._port_pair_group['port_pairs'], self._port_pair_group['name'], ] verifylist = [ ('port_pairs', [self._port_pair_group['port_pairs']]), ('name', self._port_pair_group['name']), ('description', self._port_pair_group['description']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) self.network.create_sfc_port_pair_group.assert_called_once_with( **{ 'name': self._port_pair_group['name'], 'port_pairs': [self._port_pair_group['port_pairs']], 'description': self._port_pair_group['description']}) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) def test_create_tap_enabled_port_pair_group(self): arglist = [ "--description", self._port_pair_group['description'], "--port-pair", self._port_pair_group['port_pairs'], self._port_pair_group['name'], "--enable-tap" ] verifylist = [ ('port_pairs', [self._port_pair_group['port_pairs']]), ('name', self._port_pair_group['name']), ('description', self._port_pair_group['description']), ('enable_tap', True) ] expected_data = self._update_expected_response_data( data={ 'tap_enabled': True } ) parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) self.network.create_sfc_port_pair_group.assert_called_once_with( **{ 'name': self._port_pair_group['name'], 'port_pairs': [self._port_pair_group['port_pairs']], 'description': self._port_pair_group['description'], 'tap_enabled': True}) self.assertEqual(self.columns, columns) self.assertEqual(expected_data, data) def _update_expected_response_data(self, data): # REVISIT(vks1) - This method can be common for other test functions. ppg = fakes.FakeSfcPortPairGroup.create_port_pair_group(data) self.network.create_sfc_port_pair_group.return_value = ppg return self.get_data(ppg) class TestDeleteSfcPortPairGroup(fakes.TestNeutronClientOSCV2): _port_pair_group = (fakes.FakeSfcPortPairGroup.create_port_pair_groups (count=1)) def setUp(self): super(TestDeleteSfcPortPairGroup, self).setUp() self.network.delete_sfc_port_pair_group = mock.Mock( return_value=None) self.cmd = sfc_port_pair_group.DeleteSfcPortPairGroup(self.app, self.namespace) def test_delete_port_pair_group(self): client = self.app.client_manager.network mock_port_pair_group_delete = client.delete_sfc_port_pair_group arglist = [ self._port_pair_group[0]['id'], ] verifylist = [ ('port_pair_group', [self._port_pair_group[0]['id']]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) mock_port_pair_group_delete.assert_called_once_with( self._port_pair_group[0]['id']) self.assertIsNone(result) def test_delete_multiple_port_pair_groups_with_exception(self): client = self.app.client_manager.network target1 = 'target' arglist = [target1] verifylist = [('port_pair_group', [target1])] client.find_sfc_port_pair_group.side_effect = [ target1, exceptions.CommandError ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) msg = "1 of 2 port pair group(s) failed to delete." with testtools.ExpectedException(exceptions.CommandError) as e: self.cmd.take_action(parsed_args) self.assertEqual(msg, str(e)) class TestListSfcPortPairGroup(fakes.TestNeutronClientOSCV2): _ppgs = fakes.FakeSfcPortPairGroup.create_port_pair_groups(count=1) columns = ('ID', 'Name', 'Port Pair', 'Port Pair Group Parameters', 'Tap Enabled') columns_long = ('ID', 'Name', 'Port Pair', 'Port Pair Group Parameters', 'Description', 'Project', 'Tap Enabled') _port_pair_group = _ppgs[0] data = [ _port_pair_group['id'], _port_pair_group['name'], _port_pair_group['port_pairs'], _port_pair_group['port_pair_group_parameters'], _port_pair_group['tap_enabled'] ] data_long = [ _port_pair_group['id'], _port_pair_group['name'], _port_pair_group['port_pairs'], _port_pair_group['port_pair_group_parameters'], _port_pair_group['description'], _port_pair_group['tap_enabled'] ] _port_pair_group1 = {'port_pair_groups': _port_pair_group} _port_pair_id = _port_pair_group['id'] def setUp(self): super(TestListSfcPortPairGroup, self).setUp() self.network.sfc_port_pair_groups = mock.Mock( return_value=self._ppgs ) # Get the command object to test self.cmd = sfc_port_pair_group.ListSfcPortPairGroup(self.app, self.namespace) def test_list_port_pair_groups(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args)[0] ppgs = self.network.sfc_port_pair_groups() ppg = ppgs[0] data = [ ppg['id'], ppg['name'], ppg['port_pairs'], ppg['port_pair_group_parameters'], ppg['tap_enabled'] ] self.assertEqual(list(self.columns), columns) self.assertEqual(self.data, data) def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] ppgs = self.network.sfc_port_pair_groups() ppg = ppgs[0] data = [ ppg['id'], ppg['name'], ppg['port_pairs'], ppg['port_pair_group_parameters'], ppg['description'], ppg['tap_enabled'] ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns_long = self.cmd.take_action(parsed_args)[0] self.assertEqual(list(self.columns_long), columns_long) self.assertEqual(self.data_long, data) class TestSetSfcPortPairGroup(fakes.TestNeutronClientOSCV2): _port_pair_group = fakes.FakeSfcPortPairGroup.create_port_pair_group() resource = _port_pair_group res = 'port_pair_group' _port_pair_group_name = _port_pair_group['name'] ppg_pp = _port_pair_group['port_pairs'] _port_pair_group_id = _port_pair_group['id'] def setUp(self): super(TestSetSfcPortPairGroup, self).setUp() self.network.update_sfc_port_pair_group = mock.Mock( return_value=None) self.mocked = self.network.update_sfc_port_pair_group self.cmd = sfc_port_pair_group.SetSfcPortPairGroup(self.app, self.namespace) def test_set_port_pair_group(self): target = self.resource['id'] port_pair1 = 'additional_port1' port_pair2 = 'additional_port2' self.network.find_sfc_port_pair = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id} ) self.network.find_sfc_port_pair_group = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id, 'port_pairs': self.ppg_pp} ) arglist = [ target, '--port-pair', port_pair1, '--port-pair', port_pair2, ] verifylist = [ (self.res, target), ('port_pairs', [port_pair1, port_pair2]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'port_pairs': sorted([*self.ppg_pp, port_pair1, port_pair2])} self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_set_no_port_pair(self): client = self.app.client_manager.network mock_port_pair_group_update = client.update_sfc_port_pair_group arglist = [ self._port_pair_group_name, '--name', 'name_updated', '--description', 'desc_updated', '--no-port-pair', ] verifylist = [ ('port_pair_group', self._port_pair_group_name), ('name', 'name_updated'), ('description', 'desc_updated'), ('no_port_pair', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) attrs = {'name': 'name_updated', 'description': 'desc_updated', 'port_pairs': []} mock_port_pair_group_update.assert_called_once_with( self._port_pair_group_name, **attrs) self.assertIsNone(result) class TestShowSfcPortPairGroup(fakes.TestNeutronClientOSCV2): _ppg = fakes.FakeSfcPortPairGroup.create_port_pair_group() data = ( _ppg['description'], _ppg['id'], _ppg['name'], _ppg['port_pairs'], _ppg['port_pair_group_parameters'], _ppg['project_id'], _ppg['tap_enabled']) _port_pair_group = _ppg _port_pair_group_id = _ppg['id'] columns = ( 'Description', 'ID', 'Name', 'Port Pair', 'Port Pair Group Parameters', 'Project', 'Tap Enabled' ) def setUp(self): super(TestShowSfcPortPairGroup, self).setUp() self.network.get_sfc_port_pair_group = mock.Mock( return_value=self._port_pair_group ) self.cmd = sfc_port_pair_group.ShowSfcPortPairGroup(self.app, self.namespace) def test_show_port_pair_group(self): client = self.app.client_manager.network mock_port_pair_group_show = client.get_sfc_port_pair_group arglist = [ self._port_pair_group_id, ] verifylist = [ ('port_pair_group', self._port_pair_group_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) mock_port_pair_group_show.assert_called_once_with( self._port_pair_group_id) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) class TestUnsetSfcPortPairGroup(fakes.TestNeutronClientOSCV2): _port_pair_group = fakes.FakeSfcPortPairGroup.create_port_pair_group() resource = _port_pair_group res = 'port_pair_group' _port_pair_group_name = _port_pair_group['name'] _port_pair_group_id = _port_pair_group['id'] ppg_pp = _port_pair_group['port_pairs'] def setUp(self): super(TestUnsetSfcPortPairGroup, self).setUp() self.network.update_sfc_port_pair_group = mock.Mock( return_value=None) self.mocked = self.network.update_sfc_port_pair_group self.cmd = sfc_port_pair_group.UnsetSfcPortPairGroup( self.app, self.namespace) def test_unset_port_pair(self): target = self.resource['id'] port_pair1 = 'additional_port1' port_pair2 = 'additional_port2' self.network.find_sfc_port_pair = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id} ) self.network.find_sfc_port_pair_group = mock.Mock( side_effect=lambda name_or_id, ignore_missing=False: {'id': name_or_id, 'port_pairs': self.ppg_pp} ) arglist = [ target, '--port-pair', port_pair1, '--port-pair', port_pair2, ] verifylist = [ (self.res, target), ('port_pairs', [port_pair1, port_pair2]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'port_pairs': sorted([*self.ppg_pp])} self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_unset_all_port_pair(self): client = self.app.client_manager.network mock_port_pair_group_update = client.update_sfc_port_pair_group arglist = [ self._port_pair_group_name, '--all-port-pair', ] verifylist = [ ('port_pair_group', self._port_pair_group_name), ('all_port_pair', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) attrs = {'port_pairs': []} mock_port_pair_group_update.assert_called_once_with( self._port_pair_group_name, **attrs) self.assertIsNone(result) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py0000664000175000017500000002740500000000000031170 0ustar00zuulzuul00000000000000# Copyright 2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from unittest import mock from osc_lib import exceptions from osc_lib.tests import utils as tests_utils import testtools from neutronclient.osc.v2.sfc import sfc_service_graph from neutronclient.tests.unit.osc.v2.sfc import fakes class TestListSfcServiceGraph(fakes.TestNeutronClientOSCV2): _service_graphs = fakes.FakeSfcServiceGraph.create_sfc_service_graphs( count=1) columns = ('ID', 'Name', 'Branching Points') columns_long = ('ID', 'Name', 'Branching Points', 'Description', 'Project') _service_graph = _service_graphs[0] data = [ _service_graph['id'], _service_graph['name'], _service_graph['port_chains'] ] data_long = [ _service_graph['id'], _service_graph['name'], _service_graph['port_chains'], _service_graph['description'], _service_graph['project_id'] ] _service_graph1 = {'service_graphs': _service_graph} _service_graph_id = _service_graph['id'] def setUp(self): super(TestListSfcServiceGraph, self).setUp() self.network.sfc_service_graphs = mock.Mock( return_value=self._service_graphs ) # Get the command object to test self.cmd = sfc_service_graph.ListSfcServiceGraph( self.app, self.namespace) def test_list_sfc_service_graphs(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args)[0] sgs = self.network.sfc_service_graphs() sg = sgs[0] data = [ sg['id'], sg['name'], sg['port_chains'] ] self.assertEqual(list(self.columns), columns) self.assertEqual(self.data, data) def test_list_sfc_service_graphs_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args)[0] sgs = self.network.sfc_service_graphs() sg = sgs[0] data = [ sg['id'], sg['name'], sg['port_chains'], sg['description'], sg['project_id'] ] self.assertEqual(list(self.columns_long), columns) self.assertEqual(self.data_long, data) class TestCreateSfcServiceGraph(fakes.TestNeutronClientOSCV2): _service_graph = fakes.FakeSfcServiceGraph.create_sfc_service_graph() columns = ('ID', 'Name', 'Branching Points') columns_long = ('Branching Points', 'Description', 'ID', 'Name', 'Project') def get_data(self): return ( self._service_graph['port_chains'], self._service_graph['description'], self._service_graph['id'], self._service_graph['name'], self._service_graph['project_id'], ) def setUp(self): super(TestCreateSfcServiceGraph, self).setUp() self.network.create_sfc_service_graph = mock.Mock( return_value=self._service_graph) self.data = self.get_data() self.cmd = sfc_service_graph.CreateSfcServiceGraph( self.app, self.namespace) def test_create_sfc_service_graph(self): arglist = [] verifylist = [] self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_sfc_service_graph_without_loop(self): bp1_str = 'pc1:pc2,pc3' bp2_str = 'pc2:pc4' self.cmd = sfc_service_graph.CreateSfcServiceGraph( self.app, self.namespace) arglist = [ "--description", self._service_graph['description'], "--branching-point", bp1_str, "--branching-point", bp2_str, self._service_graph['name']] pcs = {'pc1': ['pc2', 'pc3'], 'pc2': ['pc4']} verifylist = [ ("description", self._service_graph['description']), ("branching_points", [bp1_str, bp2_str]), ("name", self._service_graph['name']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) self.network.create_sfc_service_graph.assert_called_once_with(**{ 'description': self._service_graph['description'], 'name': self._service_graph['name'], 'port_chains': pcs }) self.assertEqual(self.columns_long, columns) self.assertEqual(self.data, data) def test_create_sfc_service_graph_with_loop(self): bp1_str = 'pc1:pc2,pc3;' bp2_str = 'pc2:pc1' self.cmd = sfc_service_graph.CreateSfcServiceGraph( self.app, self.namespace) arglist = [ "--description", self._service_graph['description'], "--branching-point", bp1_str, "--branching-point", bp2_str, self._service_graph['name']] verifylist = [ ("description", self._service_graph['description']), ("branching_points", [bp1_str, bp2_str]), ("name", self._service_graph['name']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_create_sfc_service_graph_invalid_port_chains(self): bp1_str = 'pc1:pc2,pc3:' self.cmd = sfc_service_graph.CreateSfcServiceGraph( self.app, self.namespace) arglist = [ "--description", self._service_graph['description'], "--branching-point", bp1_str, self._service_graph['name']] verifylist = [ ("description", self._service_graph['description']), ("branching_points", [bp1_str]), ("name", self._service_graph['name']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_create_sfc_service_graph_duplicate_src_chains(self): bp1_str = 'pc1:pc2,pc3;' bp2_str = 'pc1:pc4' self.cmd = sfc_service_graph.CreateSfcServiceGraph( self.app, self.namespace) arglist = [ "--description", self._service_graph['description'], "--branching-point", bp1_str, "--branching-point", bp2_str, self._service_graph['name']] verifylist = [ ("description", self._service_graph['description']), ("branching_points", [bp1_str, bp2_str]), ("name", self._service_graph['name']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) class TestDeleteSfcServiceGraph(fakes.TestNeutronClientOSCV2): _service_graph = fakes.FakeSfcServiceGraph.create_sfc_service_graphs( count=1) def setUp(self): super(TestDeleteSfcServiceGraph, self).setUp() self.network.delete_sfc_service_graph = mock.Mock( return_value=None) self.cmd = sfc_service_graph.DeleteSfcServiceGraph( self.app, self.namespace) def test_delete_sfc_service_graph(self): client = self.app.client_manager.network mock_service_graph_delete = client.delete_sfc_service_graph arglist = [ self._service_graph[0]['id'], ] verifylist = [ ('service_graph', [self._service_graph[0]['id']]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) mock_service_graph_delete.assert_called_once_with( self._service_graph[0]['id']) self.assertIsNone(result) def test_delete_multiple_service_graphs_with_exception(self): client = self.app.client_manager.network target = self._service_graph[0]['id'] arglist = [target] verifylist = [('service_graph', [target])] client.find_sfc_service_graph.side_effect = [ target, exceptions.CommandError ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) msg = "1 of 2 service graph(s) failed to delete." with testtools.ExpectedException(exceptions.CommandError) as e: self.cmd.take_action(parsed_args) self.assertEqual(msg, str(e)) class TestShowSfcServiceGraph(fakes.TestNeutronClientOSCV2): _sg = fakes.FakeSfcServiceGraph.create_sfc_service_graph() columns = ('ID', 'Name', 'Branching Points') columns_long = ('Branching Points', 'Description', 'ID', 'Name', 'Project') data = ( _sg['id'], _sg['name'], _sg['port_chains'] ) data_long = ( _sg['port_chains'], _sg['description'], _sg['id'], _sg['name'], _sg['project_id'] ) _service_graph = _sg _service_graph_id = _sg['id'] def setUp(self): super(TestShowSfcServiceGraph, self).setUp() self.network.get_sfc_service_graph = mock.Mock( return_value=self._service_graph ) # Get the command object to test self.cmd = sfc_service_graph.ShowSfcServiceGraph( self.app, self.namespace) def test_service_graph_show(self): client = self.app.client_manager.network mock_service_graph_show = client.get_sfc_service_graph arglist = [ self._service_graph_id, ] verifylist = [ ('service_graph', self._service_graph_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) mock_service_graph_show.assert_called_once_with(self._service_graph_id) self.assertEqual(self.columns_long, columns) self.assertEqual(self.data_long, data) class TestSetSfcServiceGraph(fakes.TestNeutronClientOSCV2): _service_graph = fakes.FakeSfcServiceGraph.create_sfc_service_graph() _service_graph_name = _service_graph['name'] _service_graph_id = _service_graph['id'] def setUp(self): super(TestSetSfcServiceGraph, self).setUp() self.network.update_sfc_service_graph = mock.Mock( return_value=None) self.cmd = sfc_service_graph.SetSfcServiceGraph( self.app, self.namespace) def test_set_service_graph(self): client = self.app.client_manager.network mock_service_graph_update = client.update_sfc_service_graph arglist = [ self._service_graph_name, '--name', 'name_updated', '--description', 'desc_updated' ] verifylist = [ ('service_graph', self._service_graph_name), ('name', 'name_updated'), ('description', 'desc_updated'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) attrs = { 'name': 'name_updated', 'description': 'desc_updated' } mock_service_graph_update.assert_called_once_with( self._service_graph_name, **attrs) self.assertIsNone(result) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2296627 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/subnet_onboard/0000775000175000017500000000000000000000000027157 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/subnet_onboard/__init__.py0000664000175000017500000000000000000000000031256 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000021200000000000011450 xustar0000000000000000116 path=python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/subnet_onboard/test_network_onboard_subnets.py 22 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/subnet_onboard/test_network_onboard_subn0000664000175000017500000000356300000000000034374 0ustar00zuulzuul00000000000000# Copyright (c) 2019 SUSE Linux Products GmbH # 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 unittest import mock from neutronclient.osc.v2.subnet_onboard import subnet_onboard from neutronclient.tests.unit.osc.v2 import fakes as test_fakes def _get_id(client, id_or_name, resource): return id_or_name class TestNetworkOnboardSubnets(test_fakes.TestNeutronClientOSCV2): def setUp(self): super(TestNetworkOnboardSubnets, self).setUp() mock.patch( 'neutronclient.osc.v2.subnet_onboard.subnet_onboard._get_id', new=_get_id).start() self.network_id = 'my_network_id' self.subnetpool_id = 'my_subnetpool_id' # Get the command object to test self.cmd = subnet_onboard.NetworkOnboardSubnets(self.app, self.namespace) def test_options(self): arglist = [ self.network_id, self.subnetpool_id ] verifylist = [ ('network', self.network_id), ('subnetpool', self.subnetpool_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.neutronclient.onboard_network_subnets.assert_called_once_with( self.subnetpool_id, {'network_id': self.network_id}) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2296627 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/vpnaas/0000775000175000017500000000000000000000000025443 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/vpnaas/__init__.py0000664000175000017500000000000000000000000027542 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/vpnaas/common.py0000664000175000017500000001511600000000000027311 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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 testtools from osc_lib import exceptions from neutronclient.tests.unit.osc.v2 import fakes as test_fakes class TestCreateVPNaaS(test_fakes.TestNeutronClientOSCV2): pass class TestDeleteVPNaaS(test_fakes.TestNeutronClientOSCV2): def test_delete_with_one_resource(self): target = self.resource['id'] def _mock_vpnaas(*args, **kwargs): return {'id': args[0]} self.networkclient.find_vpn_endpoint_group.side_effect = _mock_vpnaas self.networkclient.find_vpn_ipsec_site_connection.side_effect = \ _mock_vpnaas self.networkclient.find_vpn_ike_policy.side_effect = _mock_vpnaas self.networkclient.find_vpn_ipsec_policy.side_effect = _mock_vpnaas self.networkclient.find_vpn_service.side_effect = _mock_vpnaas arglist = [target] verifylist = [(self.res, [target])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target) self.assertIsNone(result) def test_delete_with_multiple_resources(self): def _mock_vpnaas(*args, **kwargs): return {'id': args[0]} self.networkclient.find_vpn_endpoint_group.side_effect = _mock_vpnaas self.networkclient.find_vpn_ipsec_site_connection.side_effect = \ _mock_vpnaas self.networkclient.find_vpn_ike_policy.side_effect = _mock_vpnaas self.networkclient.find_vpn_ipsec_policy.side_effect = _mock_vpnaas self.networkclient.find_vpn_service.side_effect = _mock_vpnaas target1 = 'target1' target2 = 'target2' arglist = [target1, target2] verifylist = [(self.res, [target1, target2])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.assertEqual(2, self.mocked.call_count) for idx, reference in enumerate([target1, target2]): actual = ''.join(self.mocked.call_args_list[idx][0]) self.assertEqual(reference, actual) def test_delete_multiple_with_exception(self): target1 = 'target' arglist = [target1] verifylist = [(self.res, [target1])] self.networkclient.find_vpn_ipsec_site_connection.side_effect = [ target1, exceptions.CommandError ] self.networkclient.find_vpn_endpoint_group.side_effect = [ target1, exceptions.CommandError ] self.networkclient.find_vpn_ike_policy.side_effect = [ target1, exceptions.CommandError ] self.networkclient.find_vpn_service.side_effect = [ target1, exceptions.CommandError ] self.networkclient.find_vpn_ipsec_policy.side_effect = [ target1, exceptions.CommandError ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) resource_name = self.res.replace('_', ' ') msg = "1 of 2 %s(s) failed to delete." % resource_name with testtools.ExpectedException(exceptions.CommandError) as e: self.cmd.take_action(parsed_args) self.assertEqual(msg, str(e)) class TestListVPNaaS(test_fakes.TestNeutronClientOSCV2): def test_list_with_no_option(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.list_headers), headers) self.assertEqual([self.list_data], list(data)) def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) self.assertEqual([self.data], list(data)) class TestSetVPNaaS(test_fakes.TestNeutronClientOSCV2): def test_set_name(self): target = self.resource['id'] update = 'change' arglist = [target, '--name', update] verifylist = [ (self.res, target), ('name', update), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'name': update}) self.assertIsNone(result) def test_set_description(self): target = self.resource['id'] update = 'change-desc' arglist = [target, '--description', update] verifylist = [ (self.res, target), ('description', update), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'description': update}) self.assertIsNone(result) class TestShowVPNaaS(test_fakes.TestNeutronClientOSCV2): def test_show_filtered_by_id_or_name(self): target = self.resource['id'] def _mock_vpnaas(*args, **kwargs): return {'id': args[0]} self.networkclient.find_vpn_endpoint_group.side_effect = _mock_vpnaas self.networkclient.find_vpn_ipsec_site_connection.side_effect = \ _mock_vpnaas self.networkclient.find_vpn_ike_policy.side_effect = _mock_vpnaas self.networkclient.find_vpn_ipsec_policy.side_effect = _mock_vpnaas self.networkclient.find_vpn_service.side_effect = _mock_vpnaas arglist = [target] verifylist = [(self.res, target)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target) self.assertEqual(self.ordered_headers, headers) self.assertItemEqual(self.ordered_data, data) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/vpnaas/fakes.py0000664000175000017500000001553000000000000027112 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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 collections from unittest import mock import uuid from openstack.network.v2 import vpn_endpoint_group as vpn_epg from openstack.network.v2 import vpn_ike_policy as vpn_ikep from openstack.network.v2 import vpn_ipsec_policy as vpn_ipsecp from openstack.network.v2 import vpn_ipsec_site_connection as vpn_sitec from openstack.network.v2 import vpn_service class FakeVPNaaS(object): def create(self, attrs={}): """Create a fake vpnaas resources :param Dictionary attrs: A dictionary with all attributes :return: A OrderedDict faking the vpnaas resource """ self.ordered.update(attrs) if 'IKEPolicy' == self.__class__.__name__: return vpn_ikep.VpnIkePolicy(**self.ordered) if 'IPSecPolicy' == self.__class__.__name__: return vpn_ipsecp.VpnIpsecPolicy(**self.ordered) if 'VPNService' == self.__class__.__name__: return vpn_service.VpnService(**self.ordered) if 'EndpointGroup' == self.__class__.__name__: return vpn_epg.VpnEndpointGroup(**self.ordered) def bulk_create(self, attrs=None, count=2): """Create multiple fake vpnaas resources :param Dictionary attrs: A dictionary with all attributes :param int count: The number of vpnaas resources to fake :return: A list of dictionaries faking the vpnaas resources """ return [self.create(attrs=attrs) for i in range(0, count)] def get(self, attrs=None, count=2): """Get multiple fake vpnaas resources :param Dictionary attrs: A dictionary with all attributes :param int count: The number of vpnaas resources to fake :return: A list of dictionaries faking the vpnaas resource """ if attrs is None: self.attrs = self.bulk_create(count=count) return mock.Mock(side_effect=attrs) class IKEPolicy(FakeVPNaaS): """Fake one or more IKE policies""" def __init__(self): super(IKEPolicy, self).__init__() self.ordered = collections.OrderedDict(( ('id', 'ikepolicy-id-' + uuid.uuid4().hex), ('name', 'my-ikepolicy-' + uuid.uuid4().hex), ('auth_algorithm', 'sha1'), ('encryption_algorithm', 'aes-128'), ('ike_version', 'v1'), ('pfs', 'group5'), ('description', 'my-desc-' + uuid.uuid4().hex), ('phase1_negotiation_mode', 'main'), ('project_id', 'project-id-' + uuid.uuid4().hex), ('lifetime', {'units': 'seconds', 'value': 3600}), )) class IPSecPolicy(FakeVPNaaS): """Fake one or more IPsec policies""" def __init__(self): super(IPSecPolicy, self).__init__() self.ordered = collections.OrderedDict(( ('id', 'ikepolicy-id-' + uuid.uuid4().hex), ('name', 'my-ikepolicy-' + uuid.uuid4().hex), ('auth_algorithm', 'sha1'), ('encapsulation_mode', 'tunnel'), ('transform_protocol', 'esp'), ('encryption_algorithm', 'aes-128'), ('pfs', 'group5'), ('description', 'my-desc-' + uuid.uuid4().hex), ('project_id', 'project-id-' + uuid.uuid4().hex), ('lifetime', {'units': 'seconds', 'value': 3600}), )) class VPNService(FakeVPNaaS): """Fake one or more VPN services""" def __init__(self): super(VPNService, self).__init__() self.ordered = collections.OrderedDict(( ('id', 'vpnservice-id-' + uuid.uuid4().hex), ('name', 'my-vpnservice-' + uuid.uuid4().hex), ('router_id', 'router-id-' + uuid.uuid4().hex), ('subnet_id', 'subnet-id-' + uuid.uuid4().hex), ('flavor_id', 'flavor-id-' + uuid.uuid4().hex), ('admin_state_up', True), ('status', 'ACTIVE'), ('description', 'my-desc-' + uuid.uuid4().hex), ('project_id', 'project-id-' + uuid.uuid4().hex), )) class EndpointGroup(FakeVPNaaS): """Fake one or more Endpoint Groups""" def __init__(self): super(EndpointGroup, self).__init__() self.ordered = collections.OrderedDict(( ('id', 'ep-group-id-' + uuid.uuid4().hex), ('name', 'my-ep-group-' + uuid.uuid4().hex), ('type', 'cidr'), ('endpoints', ['10.0.0.0/24', '20.0.0.0/24']), ('description', 'my-desc-' + uuid.uuid4().hex), ('project_id', 'project-id-' + uuid.uuid4().hex), )) class IPsecSiteConnection(object): """Fake one or more IPsec site connections""" @staticmethod def create_conn(attrs=None): """Create a fake IPsec conn. :param Dictionary attrs: A dictionary with all attributes :return: A Dictionary with id, name, peer_address, auth_mode, status, project_id, peer_cidrs, vpnservice_id, ipsecpolicy_id, ikepolicy_id, mtu, initiator, admin_state_up, description, psk, route_mode, local_id, peer_id, local_ep_group_id, peer_ep_group_id """ attrs = attrs or {} # Set default attributes. conn_attrs = { 'id': 'ipsec-site-conn-id-' + uuid.uuid4().hex, 'name': 'my-ipsec-site-conn-' + uuid.uuid4().hex, 'peer_address': '192.168.2.10', 'auth_mode': '', 'status': '', 'project_id': 'project-id-' + uuid.uuid4().hex, 'peer_cidrs': [], 'vpnservice_id': 'vpnservice-id-' + uuid.uuid4().hex, 'ipsecpolicy_id': 'ipsecpolicy-id-' + uuid.uuid4().hex, 'ikepolicy_id': 'ikepolicy-id-' + uuid.uuid4().hex, 'mtu': 1500, 'initiator': 'bi-directional', 'admin_state_up': True, 'description': 'my-vpn-connection', 'psk': 'abcd', 'route_mode': '', 'local_id': '', 'peer_id': '192.168.2.10', 'local_ep_group_id': 'local-ep-group-id-' + uuid.uuid4().hex, 'peer_ep_group_id': 'peer-ep-group-id-' + uuid.uuid4().hex, } # Overwrite default attributes. conn_attrs.update(attrs) return vpn_sitec.VpnIPSecSiteConnection(**conn_attrs) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/vpnaas/test_endpoint_group.py0000664000175000017500000002103300000000000032107 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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 unittest import mock from osc_lib.tests import utils as tests_utils from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.vpnaas import endpoint_group from neutronclient.tests.unit.osc.v2 import fakes as test_fakes from neutronclient.tests.unit.osc.v2.vpnaas import common from neutronclient.tests.unit.osc.v2.vpnaas import fakes _endpoint_group = fakes.EndpointGroup().create() CONVERT_MAP = { 'project': 'tenant_id', } def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _endpoint_group if data: source.update(data) return source def _generate_req_and_res(verifylist): request = dict(verifylist) response = _endpoint_group for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] new_value = val request[converted] = new_value response[converted] = new_value return request, response class TestEndpointGroup(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req, is_list=False): if is_list: req_body = {self.res_plural: list(exp_req)} else: req_body = exp_req self.mocked.assert_called_once_with(**req_body) self.assertEqual(self.ordered_headers, tuple(sorted(headers))) self.assertEqual(self.ordered_data, data) def setUp(self): super(TestEndpointGroup, self).setUp() def _mock_endpoint_group(*args, **kwargs): self.networkclient.find_vpn_endpoint_group.assert_called_once_with( self.resource['id'], ignore_missing=False) return {'id': args[0]} self.networkclient.find_vpn_endpoint_group.side_effect = mock.Mock( side_effect=_mock_endpoint_group) osc_utils.find_project = mock.Mock() osc_utils.find_project.id = _endpoint_group['project_id'] self.res = 'endpoint_group' self.res_plural = 'endpoint_groups' self.resource = _endpoint_group self.headers = ( 'ID', 'Name', 'Type', 'Endpoints', 'Description', 'Project', ) self.data = _generate_data() self.ordered_headers = ( 'Description', 'Endpoints', 'ID', 'Name', 'Project', 'Type', ) self.ordered_data = ( _endpoint_group['description'], _endpoint_group['endpoints'], _endpoint_group['id'], _endpoint_group['name'], _endpoint_group['project_id'], _endpoint_group['type'], ) self.ordered_columns = ( 'description', 'endpoints', 'id', 'name', 'project_id', 'type', ) class TestCreateEndpointGroup(TestEndpointGroup, common.TestCreateVPNaaS): def setUp(self): super(TestCreateEndpointGroup, self).setUp() self.networkclient.create_vpn_endpoint_group = mock.Mock( return_value=_endpoint_group) self.mocked = self.networkclient.create_vpn_endpoint_group self.cmd = endpoint_group.CreateEndpointGroup(self.app, self.namespace) def _update_expect_response(self, request, response): """Set expected request and response :param request A dictionary of request body(dict of verifylist) :param response A OrderedDict of request body """ # Update response body self.neutronclient.create_endpoint_group.return_value = \ {self.res: dict(response)} osc_utils.find_project.return_value.id = response['tenant_id'] # Update response(finally returns 'data') self.data = _generate_data(ordered_dict=response) self.ordered_data = tuple( response[column] for column in self.ordered_columns ) def _set_all_params_cidr(self, args={}): name = args.get('name') or 'my-name' description = args.get('description') or 'my-desc' endpoint_type = args.get('type') or 'cidr' endpoints = args.get('endpoints') or ['10.0.0.0/24', '20.0.0.0/24'] tenant_id = args.get('project_id') or 'my-tenant' arglist = [ '--description', description, '--type', endpoint_type, '--value', '10.0.0.0/24', '--value', '20.0.0.0/24', '--project', tenant_id, name, ] verifylist = [ ('description', description), ('type', endpoint_type), ('endpoints', endpoints), ('project', tenant_id), ('name', name), ] return arglist, verifylist def _test_create_with_all_params_cidr(self, args={}): arglist, verifylist = self._set_all_params_cidr(args) request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.check_results(headers, data, request) def test_create_with_no_options(self): arglist = [] verifylist = [] self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_all_params_cidr(self): self._test_create_with_all_params_cidr() class TestDeleteEndpointGroup(TestEndpointGroup, common.TestDeleteVPNaaS): def setUp(self): super(TestDeleteEndpointGroup, self).setUp() self.networkclient.delete_vpn_endpoint_group = mock.Mock() self.mocked = self.networkclient.delete_vpn_endpoint_group self.cmd = endpoint_group.DeleteEndpointGroup(self.app, self.namespace) class TestListEndpointGroup(TestEndpointGroup): def setUp(self): super(TestListEndpointGroup, self).setUp() self.cmd = endpoint_group.ListEndpointGroup(self.app, self.namespace) self.short_header = ( 'ID', 'Name', 'Type', 'Endpoints', ) self.short_data = ( _endpoint_group['id'], _endpoint_group['name'], _endpoint_group['type'], _endpoint_group['endpoints'], ) self.networkclient.vpn_endpoint_groups = mock.Mock( return_value=[_endpoint_group]) self.mocked = self.networkclient.vpn_endpoint_groups def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) def test_list_with_no_option(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.short_header), headers) self.assertEqual([self.short_data], list(data)) class TestSetEndpointGroup(TestEndpointGroup, common.TestSetVPNaaS): def setUp(self): super(TestSetEndpointGroup, self).setUp() self.networkclient.update_vpn_endpoint_group = mock.Mock( return_value=_endpoint_group) self.mocked = self.networkclient.update_vpn_endpoint_group self.cmd = endpoint_group.SetEndpointGroup(self.app, self.namespace) class TestShowEndpointGroup(TestEndpointGroup, common.TestShowVPNaaS): def setUp(self): super(TestShowEndpointGroup, self).setUp() self.networkclient.get_vpn_endpoint_group = mock.Mock( return_value=_endpoint_group) self.mocked = self.networkclient.get_vpn_endpoint_group self.cmd = endpoint_group.ShowEndpointGroup(self.app, self.namespace) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py0000664000175000017500000002565600000000000031062 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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 unittest import mock from osc_lib.tests import utils as tests_utils from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.vpnaas import ikepolicy from neutronclient.tests.unit.osc.v2 import fakes as test_fakes from neutronclient.tests.unit.osc.v2.vpnaas import common from neutronclient.tests.unit.osc.v2.vpnaas import fakes _ikepolicy = fakes.IKEPolicy().create() CONVERT_MAP = { 'project': 'project_id', } def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _ikepolicy if data: source.update(data) return source def _generate_req_and_res(verifylist): request = dict(verifylist) response = _ikepolicy for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] new_value = val request[converted] = new_value response[converted] = new_value return request, response class TestIKEPolicy(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req, is_list=False): if is_list: req_body = {self.res_plural: list(exp_req)} else: req_body = exp_req self.mocked.assert_called_once_with(**req_body) self.assertEqual(self.ordered_headers, tuple(sorted(headers))) self.assertEqual(self.ordered_data, data) def setUp(self): super(TestIKEPolicy, self).setUp() def _mock_ikepolicy(*args, **kwargs): self.networkclient.find_vpn_ike_policy.assert_called_once_with( self.resource['id'], ignore_missing=False) return {'id': args[0]} self.networkclient.find_vpn_ike_policy.side_effect = mock.Mock( side_effect=_mock_ikepolicy) osc_utils.find_project = mock.Mock() osc_utils.find_project.id = _ikepolicy['project_id'] self.res = 'ikepolicy' self.res_plural = 'ikepolicies' self.resource = _ikepolicy self.headers = ( 'ID', 'Name', 'Authentication Algorithm', 'Encryption Algorithm', 'IKE Version', 'Perfect Forward Secrecy (PFS)', 'Description', 'Phase1 Negotiation Mode', 'Project', 'Lifetime', ) self.data = _generate_data() self.ordered_headers = ( 'Authentication Algorithm', 'Description', 'Encryption Algorithm', 'ID', 'IKE Version', 'Lifetime', 'Name', 'Perfect Forward Secrecy (PFS)', 'Phase1 Negotiation Mode', 'Project', ) self.ordered_data = ( _ikepolicy['auth_algorithm'], _ikepolicy['description'], _ikepolicy['encryption_algorithm'], _ikepolicy['id'], _ikepolicy['ike_version'], _ikepolicy['lifetime'], _ikepolicy['name'], _ikepolicy['pfs'], _ikepolicy['phase1_negotiation_mode'], _ikepolicy['project_id'], ) self.ordered_columns = ( 'auth_algorithm', 'description', 'encryption_algorithm', 'id', 'ike_version', 'lifetime', 'name', 'pfs', 'phase1_negotiation_mode', 'project_id', ) class TestCreateIKEPolicy(TestIKEPolicy, common.TestCreateVPNaaS): def setUp(self): super(TestCreateIKEPolicy, self).setUp() self.networkclient.create_vpn_ike_policy = mock.Mock( return_value=_ikepolicy) self.mocked = self.networkclient.create_vpn_ike_policy self.cmd = ikepolicy.CreateIKEPolicy(self.app, self.namespace) def _update_expect_response(self, request, response): """Set expected request and response :param request A dictionary of request body(dict of verifylist) :param response A OrderedDict of request body """ # Update response body self.networkclient.create_vpn_ikepolicy.return_value = response osc_utils.find_project.return_value.id = response['project_id'] # Update response(finally returns 'data') self.data = _generate_data(ordered_dict=response) self.ordered_data = tuple( response[column] for column in self.ordered_columns ) def _set_all_params(self, args={}): name = args.get('name') or 'my-name' description = args.get('description') or 'my-desc' auth_algorithm = args.get('auth_algorithm') or 'sha1' encryption_algorithm = args.get('encryption_algorithm') or 'aes-128' phase1_negotiation_mode = args.get('phase1_negotiation_mode') or 'main' ike_version = args.get('ike_version') or 'v1' pfs = args.get('pfs') or 'group5' tenant_id = args.get('tenant_id') or 'my-tenant' arglist = [ '--description', description, '--auth-algorithm', auth_algorithm, '--encryption-algorithm', encryption_algorithm, '--phase1-negotiation-mode', phase1_negotiation_mode, '--ike-version', ike_version, '--pfs', pfs, '--project', tenant_id, name, ] verifylist = [ ('description', description), ('auth_algorithm', auth_algorithm), ('encryption_algorithm', encryption_algorithm), ('phase1_negotiation_mode', phase1_negotiation_mode), ('ike_version', ike_version), ('pfs', pfs), ('project', tenant_id), ('name', name), ] return arglist, verifylist def _test_create_with_all_params(self, args={}): arglist, verifylist = self._set_all_params(args) request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.check_results(headers, data, request) def test_create_with_no_options(self): arglist = [] verifylist = [] self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_all_params(self): self._test_create_with_all_params() def test_create_with_all_params_name(self): self._test_create_with_all_params({'name': 'new_ikepolicy'}) def test_create_with_all_params_aggressive_mode(self): self._test_create_with_all_params( {'phase1_negotiation_mode': 'aggressive'}) class TestDeleteIKEPolicy(TestIKEPolicy, common.TestDeleteVPNaaS): def setUp(self): super(TestDeleteIKEPolicy, self).setUp() self.networkclient.delete_vpn_ike_policy = mock.Mock() self.mocked = self.networkclient.delete_vpn_ike_policy self.cmd = ikepolicy.DeleteIKEPolicy(self.app, self.namespace) class TestListIKEPolicy(TestIKEPolicy): def setUp(self): super(TestListIKEPolicy, self).setUp() self.cmd = ikepolicy.ListIKEPolicy(self.app, self.namespace) self.short_header = ( 'ID', 'Name', 'Authentication Algorithm', 'Encryption Algorithm', 'IKE Version', 'Perfect Forward Secrecy (PFS)', ) self.short_data = ( _ikepolicy['id'], _ikepolicy['name'], _ikepolicy['auth_algorithm'], _ikepolicy['encryption_algorithm'], _ikepolicy['ike_version'], _ikepolicy['pfs'], ) self.networkclient.vpn_ike_policies = mock.Mock( return_value=[_ikepolicy]) self.mocked = self.networkclient.vpn_ike_policies def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) def test_list_with_no_option(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.short_header), headers) self.assertEqual([self.short_data], list(data)) class TestSetIKEPolicy(TestIKEPolicy, common.TestSetVPNaaS): def setUp(self): super(TestSetIKEPolicy, self).setUp() self.networkclient.update_vpn_ike_policy = mock.Mock( return_value=_ikepolicy) self.mocked = self.networkclient.update_vpn_ike_policy self.cmd = ikepolicy.SetIKEPolicy(self.app, self.namespace) def test_set_auth_algorithm_with_sha256(self): target = self.resource['id'] auth_algorithm = 'sha256' arglist = [target, '--auth-algorithm', auth_algorithm] verifylist = [ (self.res, target), ('auth_algorithm', auth_algorithm), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'auth_algorithm': 'sha256'}) self.assertIsNone(result) def test_set_phase1_negotiation_mode_with_aggressive(self): target = self.resource['id'] phase1_negotiation_mode = 'aggressive' arglist = [target, '--phase1-negotiation-mode', phase1_negotiation_mode] verifylist = [ (self.res, target), ('phase1_negotiation_mode', phase1_negotiation_mode), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'phase1_negotiation_mode': 'aggressive'}) self.assertIsNone(result) class TestShowIKEPolicy(TestIKEPolicy, common.TestShowVPNaaS): def setUp(self): super(TestShowIKEPolicy, self).setUp() self.networkclient.get_vpn_ike_policy = mock.Mock( return_value=_ikepolicy) self.mocked = self.networkclient.get_vpn_ike_policy self.cmd = ikepolicy.ShowIKEPolicy(self.app, self.namespace) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsec_site_connection.py0000664000175000017500000003207000000000000033424 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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 unittest import mock from osc_lib.cli import format_columns from osc_lib.tests import utils as tests_utils from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.vpnaas import ipsec_site_connection from neutronclient.tests.unit.osc.v2 import fakes as test_fakes from neutronclient.tests.unit.osc.v2.vpnaas import common from neutronclient.tests.unit.osc.v2.vpnaas import fakes _ipsec_site_conn = fakes.IPsecSiteConnection().create_conn() CONVERT_MAP = { 'project': 'project_id', 'ikepolicy': 'ikepolicy_id', 'ipsecpolicy': 'ipsecpolicy_id', 'vpnservice': 'vpnservice_id', 'peer_endpoint_group': 'peer_ep_group_id', 'local_endpoint_group': 'local_ep_group_id', } def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _ipsec_site_conn if data: source.update(data) return source def _generate_req_and_res(verifylist): request = dict(verifylist) response = _ipsec_site_conn for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] new_value = val request[converted] = new_value response[converted] = new_value return request, response class TestIPsecSiteConn(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req, is_list=False): if is_list: req_body = {self.res_plural: list(exp_req)} else: req_body = exp_req self.mocked.assert_called_once_with(**req_body) self.assertEqual(self.ordered_headers, tuple(sorted(headers))) self.assertItemEqual(self.ordered_data, data) def setUp(self): super(TestIPsecSiteConn, self).setUp() def _mock_ipsec_site_conn(*args, **kwargs): return {'id': args[0]} self.networkclient.find_vpn_ipsec_site_connection.side_effect = \ mock.Mock(side_effect=_mock_ipsec_site_conn) osc_utils.find_project = mock.Mock() osc_utils.find_project.id = _ipsec_site_conn['project_id'] self.res = 'ipsec_site_connection' self.res_plural = 'ipsec_site_connections' self.resource = _ipsec_site_conn self.headers = ( 'ID', 'Name', 'Peer Address', 'Authentication Algorithm', 'Status', 'Project', 'Peer CIDRs', 'VPN Service', 'IPSec Policy', 'IKE Policy', 'MTU', 'Initiator', 'State', 'Description', 'Pre-shared Key', 'Route Mode', 'Local ID', 'Peer ID', 'Local Endpoint Group ID', 'Peer Endpoint Group ID', 'DPD', ) self.data = _generate_data() self.ordered_headers = ( 'Authentication Algorithm', 'DPD', 'Description', 'ID', 'IKE Policy', 'IPSec Policy', 'Initiator', 'Local Endpoint Group ID', 'Local ID', 'MTU', 'Name', 'Peer Address', 'Peer CIDRs', 'Peer Endpoint Group ID', 'Peer ID', 'Pre-shared Key', 'Project', 'Route Mode', 'State', 'Status', 'VPN Service', ) self.ordered_data = ( _ipsec_site_conn['auth_mode'], _ipsec_site_conn['dpd'], _ipsec_site_conn['description'], _ipsec_site_conn['id'], _ipsec_site_conn['ikepolicy_id'], _ipsec_site_conn['ipsecpolicy_id'], _ipsec_site_conn['initiator'], _ipsec_site_conn['local_ep_group_id'], _ipsec_site_conn['local_id'], _ipsec_site_conn['mtu'], _ipsec_site_conn['name'], _ipsec_site_conn['peer_address'], format_columns.ListColumn(_ipsec_site_conn['peer_cidrs']), _ipsec_site_conn['peer_ep_group_id'], _ipsec_site_conn['peer_id'], _ipsec_site_conn['psk'], _ipsec_site_conn['project_id'], _ipsec_site_conn['route_mode'], _ipsec_site_conn['admin_state_up'], _ipsec_site_conn['status'], _ipsec_site_conn['vpnservice_id'], ) class TestCreateIPsecSiteConn(TestIPsecSiteConn, common.TestCreateVPNaaS): def setUp(self): super(TestCreateIPsecSiteConn, self).setUp() self.networkclient.create_vpn_ipsec_site_connection = mock.Mock( return_value=_ipsec_site_conn) self.mocked = self.networkclient.create_vpn_ipsec_site_connection self.cmd = ipsec_site_connection.CreateIPsecSiteConnection( self.app, self.namespace) def _update_expect_response(self, request, response): """Set expected request and response :param request A dictionary of request body(dict of verifylist) :param response A OrderedDict of request body """ # Update response body self.networkclient.create_vpn_ipsec_site_connection.return_value = \ response osc_utils.find_project.return_value.id = response['project_id'] # Update response(finally returns 'data') self.data = _generate_data(ordered_dict=response) self.ordered_data = ( response['auth_mode'], response['dpd'], response['description'], response['id'], response['ikepolicy_id'], response['ipsecpolicy_id'], response['initiator'], response['local_ep_group_id'], response['local_id'], response['mtu'], response['name'], response['peer_address'], format_columns.ListColumn(response['peer_cidrs']), response['peer_ep_group_id'], response['peer_id'], response['psk'], response['project_id'], response['route_mode'], response['admin_state_up'], response['status'], response['vpnservice_id'], ) def _set_all_params(self, args={}): tenant_id = args.get('tenant_id') or 'my-tenant' name = args.get('name') or 'connection1' peer_address = args.get('peer_address') or '192.168.2.10' peer_id = args.get('peer_id') or '192.168.2.10' psk = args.get('psk') or 'abcd' mtu = args.get('mtu') or '1500' initiator = args.get('initiator') or 'bi-directional' vpnservice_id = args.get('vpnservice') or 'vpnservice_id' ikepolicy_id = args.get('ikepolicy') or 'ikepolicy_id' ipsecpolicy_id = args.get('ipsecpolicy') or 'ipsecpolicy_id' local_ep_group = args.get('local_ep_group_id') or 'local-epg' peer_ep_group = args.get('peer_ep_group_id') or 'peer-epg' description = args.get('description') or 'my-vpn-connection' arglist = [ '--project', tenant_id, '--peer-address', peer_address, '--peer-id', peer_id, '--psk', psk, '--initiator', initiator, '--vpnservice', vpnservice_id, '--ikepolicy', ikepolicy_id, '--ipsecpolicy', ipsecpolicy_id, '--mtu', mtu, '--description', description, '--local-endpoint-group', local_ep_group, '--peer-endpoint-group', peer_ep_group, name, ] verifylist = [ ('project', tenant_id), ('peer_address', peer_address), ('peer_id', peer_id), ('psk', psk), ('initiator', initiator), ('vpnservice', vpnservice_id), ('ikepolicy', ikepolicy_id), ('ipsecpolicy', ipsecpolicy_id), ('mtu', mtu), ('description', description), ('local_endpoint_group', local_ep_group), ('peer_endpoint_group', peer_ep_group), ('name', name), ] return arglist, verifylist def _test_create_with_all_params(self, args={}): arglist, verifylist = self._set_all_params(args) request, response = _generate_req_and_res(verifylist) def _mock_endpoint_group(*args, **kwargs): return {'id': args[0]} self.networkclient.find_vpn_endpoint_group.side_effect = mock.Mock( side_effect=_mock_endpoint_group) self.networkclient.find_vpn_service.side_effect = mock.Mock( side_effect=_mock_endpoint_group) self.networkclient.find_vpn_ike_policy.side_effect = mock.Mock( side_effect=_mock_endpoint_group) self.networkclient.find_vpn_ipsec_policy.side_effect = mock.Mock( side_effect=_mock_endpoint_group) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.check_results(headers, data, request) def test_create_with_no_options(self): arglist = [] verifylist = [] self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_all_params(self): self._test_create_with_all_params() class TestDeleteIPsecSiteConn(TestIPsecSiteConn, common.TestDeleteVPNaaS): def setUp(self): super(TestDeleteIPsecSiteConn, self).setUp() self.networkclient.delete_vpn_ipsec_site_connection = mock.Mock() self.mocked = self.networkclient.delete_vpn_ipsec_site_connection self.cmd = ipsec_site_connection.DeleteIPsecSiteConnection( self.app, self.namespace) class TestListIPsecSiteConn(TestIPsecSiteConn): def setUp(self): super(TestListIPsecSiteConn, self).setUp() self.cmd = ipsec_site_connection.ListIPsecSiteConnection( self.app, self.namespace) self.short_header = ( 'ID', 'Name', 'Peer Address', 'Authentication Algorithm', 'Status', ) self.short_data = ( _ipsec_site_conn['id'], _ipsec_site_conn['name'], _ipsec_site_conn['peer_address'], _ipsec_site_conn['auth_mode'], _ipsec_site_conn['status'], ) self.networkclient.vpn_ipsec_site_connections = mock.Mock( return_value=[_ipsec_site_conn]) self.mocked = self.networkclient.vpn_ipsec_site_connections def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) def test_list_with_no_option(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.short_header), headers) self.assertEqual([self.short_data], list(data)) class TestSetIPsecSiteConn(TestIPsecSiteConn, common.TestSetVPNaaS): def setUp(self): super(TestSetIPsecSiteConn, self).setUp() self.networkclient.update_vpn_ipsec_site_connection = mock.Mock( return_value=_ipsec_site_conn) self.mocked = self.networkclient.update_vpn_ipsec_site_connection self.cmd = ipsec_site_connection.SetIPsecSiteConnection( self.app, self.namespace) def test_set_ipsec_site_conn_with_peer_id(self): target = self.resource['id'] peer_id = '192.168.3.10' arglist = [target, '--peer-id', peer_id] verifylist = [ (self.res, target), ('peer_id', peer_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with(target, **{'peer_id': peer_id}) self.assertIsNone(result) class TestShowIPsecSiteConn(TestIPsecSiteConn, common.TestShowVPNaaS): def setUp(self): super(TestShowIPsecSiteConn, self).setUp() self.networkclient.get_vpn_ipsec_site_connection = mock.Mock( return_value=_ipsec_site_conn) self.mocked = self.networkclient.get_vpn_ipsec_site_connection self.cmd = ipsec_site_connection.ShowIPsecSiteConnection( self.app, self.namespace) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsecpolicy.py0000664000175000017500000002450600000000000031406 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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 unittest import mock from osc_lib.tests import utils as tests_utils from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.vpnaas import ipsecpolicy from neutronclient.tests.unit.osc.v2 import fakes as test_fakes from neutronclient.tests.unit.osc.v2.vpnaas import common from neutronclient.tests.unit.osc.v2.vpnaas import fakes _ipsecpolicy = fakes.IPSecPolicy().create() CONVERT_MAP = { 'project': 'project_id', } def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _ipsecpolicy if data: source.update(data) return source def _generate_req_and_res(verifylist): request = dict(verifylist) response = _ipsecpolicy for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] new_value = val request[converted] = new_value response[converted] = new_value return request, response class TestIPSecPolicy(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req, is_list=False): if is_list: req_body = {self.res_plural: list(exp_req)} else: req_body = exp_req self.mocked.assert_called_once_with(**req_body) self.assertEqual(self.ordered_headers, headers) self.assertEqual(self.ordered_data, data) def setUp(self): super(TestIPSecPolicy, self).setUp() def _mock_ipsecpolicy(*args, **kwargs): self.networkclient.find_vpn_ipsec_policy.assert_called_once_with( self.resource['id'], ignore_missing=False) return {'id': args[0]} self.networkclient.find_vpn_ipsec_policy.side_effect = mock.Mock( side_effect=_mock_ipsecpolicy) osc_utils.find_project = mock.Mock() osc_utils.find_project.id = _ipsecpolicy['project_id'] self.res = 'ipsecpolicy' self.res_plural = 'ipsecpolicies' self.resource = _ipsecpolicy self.headers = ( 'ID', 'Name', 'Authentication Algorithm', 'Encapsulation Mode', 'Transform Protocol', 'Encryption Algorithm', 'Perfect Forward Secrecy (PFS)', 'Description', 'Project', 'Lifetime', ) self.data = _generate_data() self.ordered_headers = ( 'Authentication Algorithm', 'Description', 'Encapsulation Mode', 'Encryption Algorithm', 'ID', 'Lifetime', 'Name', 'Perfect Forward Secrecy (PFS)', 'Project', 'Transform Protocol', ) self.ordered_data = ( _ipsecpolicy['auth_algorithm'], _ipsecpolicy['description'], _ipsecpolicy['encapsulation_mode'], _ipsecpolicy['encryption_algorithm'], _ipsecpolicy['id'], _ipsecpolicy['lifetime'], _ipsecpolicy['name'], _ipsecpolicy['pfs'], _ipsecpolicy['project_id'], _ipsecpolicy['transform_protocol'], ) self.ordered_columns = ( 'auth_algorithm', 'description', 'encapsulation_mode', 'encryption_algorithm', 'id', 'lifetime', 'name', 'pfs', 'project_id', 'transform_protocol', ) class TestCreateIPSecPolicy(TestIPSecPolicy, common.TestCreateVPNaaS): def setUp(self): super(TestCreateIPSecPolicy, self).setUp() self.networkclient.create_vpn_ipsec_policy = mock.Mock( return_value=_ipsecpolicy) self.mocked = self.networkclient.create_vpn_ipsec_policy self.cmd = ipsecpolicy.CreateIPsecPolicy(self.app, self.namespace) def _update_expect_response(self, request, response): """Set expected request and response :param request A dictionary of request body(dict of verifylist) :param response A OrderedDict of request body """ # Update response body self.networkclient.create_vpn_ipsec_policy.return_value = \ response osc_utils.find_project.return_value.id = response['project_id'] # Update response(finally returns 'data') self.data = _generate_data(ordered_dict=response) self.ordered_data = tuple( response[column] for column in self.ordered_columns ) def _set_all_params(self, args={}): name = args.get('name') or 'my-name' auth_algorithm = args.get('auth_algorithm') or 'sha1' encapsulation_mode = args.get('encapsulation_mode') or 'tunnel' transform_protocol = args.get('transform_protocol') or 'esp' encryption_algorithm = args.get('encryption_algorithm') or 'aes-128' pfs = args.get('pfs') or 'group5' description = args.get('description') or 'my-desc' project_id = args.get('project_id') or 'my-project' arglist = [ name, '--auth-algorithm', auth_algorithm, '--encapsulation-mode', encapsulation_mode, '--transform-protocol', transform_protocol, '--encryption-algorithm', encryption_algorithm, '--pfs', pfs, '--description', description, '--project', project_id, ] verifylist = [ ('name', name), ('auth_algorithm', auth_algorithm), ('encapsulation_mode', encapsulation_mode), ('transform_protocol', transform_protocol), ('encryption_algorithm', encryption_algorithm), ('pfs', pfs), ('description', description), ('project', project_id), ] return arglist, verifylist def _test_create_with_all_params(self, args={}): arglist, verifylist = self._set_all_params(args) request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.check_results(headers, data, request) def test_create_with_no_options(self): arglist = [] verifylist = [] self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_create_with_all_params(self): self._test_create_with_all_params() def test_create_with_all_params_name(self): self._test_create_with_all_params({'name': 'new_ipsecpolicy'}) class TestDeleteIPSecPolicy(TestIPSecPolicy, common.TestDeleteVPNaaS): def setUp(self): super(TestDeleteIPSecPolicy, self).setUp() self.networkclient.delete_vpn_ipsec_policy = mock.Mock() self.mocked = self.networkclient.delete_vpn_ipsec_policy self.cmd = ipsecpolicy.DeleteIPsecPolicy(self.app, self.namespace) class TestListIPSecPolicy(TestIPSecPolicy): def setUp(self): super(TestListIPSecPolicy, self).setUp() self.cmd = ipsecpolicy.ListIPsecPolicy(self.app, self.namespace) self.short_header = ( 'ID', 'Name', 'Authentication Algorithm', 'Encapsulation Mode', 'Transform Protocol', 'Encryption Algorithm', ) self.short_data = ( _ipsecpolicy['id'], _ipsecpolicy['name'], _ipsecpolicy['auth_algorithm'], _ipsecpolicy['encapsulation_mode'], _ipsecpolicy['transform_protocol'], _ipsecpolicy['encryption_algorithm'], ) self.networkclient.vpn_ipsec_policies = mock.Mock( return_value=[_ipsecpolicy]) self.mocked = self.networkclient.vpn_ipsec_policies def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) def test_list_with_no_option(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.short_header), headers) self.assertEqual([self.short_data], list(data)) class TestSetIPSecPolicy(TestIPSecPolicy, common.TestSetVPNaaS): def setUp(self): super(TestSetIPSecPolicy, self).setUp() self.networkclient.update_vpn_ipsec_policy = mock.Mock( return_value=_ipsecpolicy) self.mocked = self.networkclient.update_vpn_ipsec_policy self.cmd = ipsecpolicy.SetIPsecPolicy(self.app, self.namespace) def test_set_auth_algorithm_with_sha256(self): target = self.resource['id'] auth_algorithm = 'sha256' arglist = [target, '--auth-algorithm', auth_algorithm] verifylist = [ (self.res, target), ('auth_algorithm', auth_algorithm), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'auth_algorithm': 'sha256'}) self.assertIsNone(result) class TestShowIPSecPolicy(TestIPSecPolicy, common.TestShowVPNaaS): def setUp(self): super(TestShowIPSecPolicy, self).setUp() self.networkclient.get_vpn_ipsec_policy = mock.Mock( return_value=_ipsecpolicy) self.mocked = self.networkclient.get_vpn_ipsec_policy self.cmd = ipsecpolicy.ShowIPsecPolicy(self.app, self.namespace) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py0000664000175000017500000002302400000000000031241 0ustar00zuulzuul00000000000000# Copyright 2017 FUJITSU LIMITED # 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 unittest import mock import uuid from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.vpnaas import vpnservice from neutronclient.tests.unit.osc.v2 import fakes as test_fakes from neutronclient.tests.unit.osc.v2.vpnaas import common from neutronclient.tests.unit.osc.v2.vpnaas import fakes _vpnservice = fakes.VPNService().create() CONVERT_MAP = { 'project': 'project_id', 'router': 'router_id', 'subnet': 'subnet_id' } def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _vpnservice if data: source.update(data) return source def _generate_req_and_res(verifylist): request = dict(verifylist) response = _vpnservice for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] new_value = val request[converted] = new_value response[converted] = new_value return request, response class TestVPNService(test_fakes.TestNeutronClientOSCV2): def _check_results(self, headers, data, exp_req, is_list=False): if is_list: req_body = {self.res_plural: list(exp_req)} else: req_body = exp_req self.mocked.assert_called_once_with(**req_body) self.assertEqual(self.ordered_headers, headers) self.assertEqual(self.ordered_data, data) def setUp(self): super(TestVPNService, self).setUp() def _mock_vpnservice(*args, **kwargs): self.networkclient.find_vpn_service.assert_called_once_with( self.resource['id'], ignore_missing=False) return {'id': args[0]} self.networkclient.find_router = mock.Mock() self.networkclient.find_subnet = mock.Mock() self.fake_router = mock.Mock() self.fake_subnet = mock.Mock() self.networkclient.find_router.return_value = self.fake_router self.networkclient.find_subnet.return_value = self.fake_subnet self.args = { 'name': 'my-name', 'description': 'my-desc', 'project_id': 'project-id-' + uuid.uuid4().hex, 'router_id': 'router-id-' + uuid.uuid4().hex, 'subnet_id': 'subnet-id-' + uuid.uuid4().hex, } self.fake_subnet.id = self.args['subnet_id'] self.fake_router.id = self.args['router_id'] self.networkclient.find_vpn_service.side_effect = mock.Mock( side_effect=_mock_vpnservice) osc_utils.find_project = mock.Mock() osc_utils.find_project.id = _vpnservice['project_id'] self.res = 'vpnservice' self.res_plural = 'vpnservices' self.resource = _vpnservice self.headers = ( 'ID', 'Name', 'Router', 'Subnet', 'Flavor', 'State', 'Status', 'Description', 'Project', ) self.data = _generate_data() self.ordered_headers = ( 'Description', 'Flavor', 'ID', 'Name', 'Project', 'Router', 'State', 'Status', 'Subnet', ) self.ordered_data = ( _vpnservice['description'], _vpnservice['flavor_id'], _vpnservice['id'], _vpnservice['name'], _vpnservice['project_id'], _vpnservice['router_id'], _vpnservice['admin_state_up'], _vpnservice['status'], _vpnservice['subnet_id'], ) self.ordered_columns = ( 'description', 'flavor_id', 'id', 'name', 'project_id', 'router_id', 'admin_state_up', 'status', 'subnet_id', ) class TestCreateVPNService(TestVPNService, common.TestCreateVPNaaS): def setUp(self): super(TestCreateVPNService, self).setUp() self.networkclient.create_vpn_service = mock.Mock( return_value=_vpnservice) self.mocked = self.networkclient.create_vpn_service self.cmd = vpnservice.CreateVPNService(self.app, self.namespace) def _update_expect_response(self, request, response): """Set expected request and response :param request A dictionary of request body(dict of verifylist) :param response A OrderedDict of request body """ # Update response body self.networkclient.create_vpn_service.return_value = response osc_utils.find_project.return_value.id = response['project_id'] # Update response(finally returns 'data') self.data = _generate_data(ordered_dict=response) self.ordered_data = tuple( response[column] for column in self.ordered_columns ) def _set_all_params(self): name = self.args.get('name') description = self.args.get('description') router_id = self.args.get('router_id') subnet_id = self.args.get('subnet_id') project_id = self.args.get('project_id') arglist = [ '--description', description, '--project', project_id, '--subnet', subnet_id, '--router', router_id, name, ] verifylist = [ ('description', description), ('project', project_id), ('subnet', subnet_id), ('router', router_id), ('name', name), ] return arglist, verifylist def _test_create_with_all_params(self): arglist, verifylist = self._set_all_params() request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self._check_results(headers, data, request) def test_create_with_all_params(self): self._test_create_with_all_params() class TestDeleteVPNService(TestVPNService, common.TestDeleteVPNaaS): def setUp(self): super(TestDeleteVPNService, self).setUp() self.networkclient.delete_vpn_service = mock.Mock() self.mocked = self.networkclient.delete_vpn_service self.cmd = vpnservice.DeleteVPNService(self.app, self.namespace) class TestListVPNService(TestVPNService): def setUp(self): super(TestListVPNService, self).setUp() self.cmd = vpnservice.ListVPNService(self.app, self.namespace) self.short_header = ( 'ID', 'Name', 'Router', 'Subnet', 'Flavor', 'State', 'Status', ) self.short_data = ( _vpnservice['id'], _vpnservice['name'], _vpnservice['router_id'], _vpnservice['subnet_id'], _vpnservice['flavor_id'], _vpnservice['admin_state_up'], _vpnservice['status'], ) self.networkclient.vpn_services = mock.Mock(return_value=[_vpnservice]) self.mocked = self.networkclient.vpn_services def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) def test_list_with_no_option(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with() self.assertEqual(list(self.short_header), headers) self.assertEqual([self.short_data], list(data)) class TestSetVPNService(TestVPNService, common.TestSetVPNaaS): def setUp(self): super(TestSetVPNService, self).setUp() self.networkclient.update_vpn_service = mock.Mock( return_value=_vpnservice) self.mocked = self.networkclient.update_vpn_service self.cmd = vpnservice.SetVPNSercice(self.app, self.namespace) def test_set_name(self): target = self.resource['id'] update = 'change' arglist = [target, '--name', update] verifylist = [ (self.res, target), ('name', update), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( target, **{'name': update}) self.assertIsNone(result) class TestShowVPNService(TestVPNService, common.TestShowVPNaaS): def setUp(self): super(TestShowVPNService, self).setUp() self.networkclient.get_vpn_service = mock.Mock( return_value=_vpnservice) self.mocked = self.networkclient.get_vpn_service self.cmd = vpnservice.ShowVPNService(self.app, self.namespace) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/test_casual_args.py0000664000175000017500000001326600000000000026745 0ustar00zuulzuul00000000000000# Copyright 2012 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 testtools from neutronclient.common import exceptions from neutronclient.neutron import v2_0 as neutronV20 class CLITestArgs(testtools.TestCase): def test_empty(self): _mydict = neutronV20.parse_args_to_dict([]) self.assertEqual({}, _mydict) def test_default_bool(self): _specs = ['--my_bool', '--arg1', 'value1'] _mydict = neutronV20.parse_args_to_dict(_specs) self.assertTrue(_mydict['my_bool']) def test_bool_true(self): _specs = ['--my-bool', 'type=bool', 'true', '--arg1', 'value1'] _mydict = neutronV20.parse_args_to_dict(_specs) self.assertTrue(_mydict['my_bool']) def test_bool_false(self): _specs = ['--my_bool', 'type=bool', 'false', '--arg1', 'value1'] _mydict = neutronV20.parse_args_to_dict(_specs) self.assertFalse(_mydict['my_bool']) def test_int_and_str(self): _specs = ['--my-int', 'type=int', '10', '--my-str', 'type=str', 'value1'] _mydict = neutronV20.parse_args_to_dict(_specs) self.assertEqual(10, _mydict['my_int']) self.assertEqual('value1', _mydict['my_str']) def test_nargs(self): _specs = ['--tag', 'x', 'y', '--arg1', 'value1'] _mydict = neutronV20.parse_args_to_dict(_specs) self.assertIn('x', _mydict['tag']) self.assertIn('y', _mydict['tag']) def test_badarg(self): _specs = ['--tag=t', 'x', 'y', '--arg1', 'value1'] self.assertRaises(exceptions.CommandError, neutronV20.parse_args_to_dict, _specs) def test_badarg_with_minus(self): _specs = ['--arg1', 'value1', '-D'] self.assertRaises(exceptions.CommandError, neutronV20.parse_args_to_dict, _specs) def test_goodarg_with_minus_number(self): _specs = ['--arg1', 'value1', '-1', '-1.0'] _mydict = neutronV20.parse_args_to_dict(_specs) self.assertEqual(['value1', '-1', '-1.0'], _mydict['arg1']) def test_badarg_duplicate(self): _specs = ['--tag=t', '--arg1', 'value1', '--arg1', 'value1'] self.assertRaises(exceptions.CommandError, neutronV20.parse_args_to_dict, _specs) def test_badarg_early_type_specification(self): _specs = ['type=dict', 'key=value'] self.assertRaises(exceptions.CommandError, neutronV20.parse_args_to_dict, _specs) def test_arg(self): _specs = ['--tag=t', '--arg1', 'value1'] self.assertEqual('value1', neutronV20.parse_args_to_dict(_specs)['arg1']) def test_arg_invalid_syntax(self): _specs = ['--tag=t', '---arg1', 'value1'] self.assertRaises(exceptions.CommandError, neutronV20.parse_args_to_dict, _specs) def test_dict_arg(self): _specs = ['--tag=t', '--arg1', 'type=dict', 'key1=value1,key2=value2'] arg1 = neutronV20.parse_args_to_dict(_specs)['arg1'] self.assertEqual('value1', arg1['key1']) self.assertEqual('value2', arg1['key2']) def test_dict_arg_with_attribute_named_type(self): _specs = ['--tag=t', '--arg1', 'type=dict', 'type=value1,key2=value2'] arg1 = neutronV20.parse_args_to_dict(_specs)['arg1'] self.assertEqual('value1', arg1['type']) self.assertEqual('value2', arg1['key2']) def test_list_of_dict_arg(self): _specs = ['--tag=t', '--arg1', 'type=dict', 'list=true', 'key1=value1,key2=value2'] arg1 = neutronV20.parse_args_to_dict(_specs)['arg1'] self.assertEqual('value1', arg1[0]['key1']) self.assertEqual('value2', arg1[0]['key2']) def test_parse_args_to_dict_bad_type(self): _specs = ['--badtypearg', 'type=badtype', 'val1'] ex = self.assertRaises(exceptions.CommandError, neutronV20.parse_args_to_dict, _specs) self.assertEqual('Invalid value_specs --badtypearg type=badtype val1: ' 'type badtype is not supported', str(ex)) def test_clear_action(self): _specs = ['--anyarg', 'action=clear'] args = neutronV20.parse_args_to_dict(_specs) self.assertIsNone(args['anyarg']) def test_bad_values_str_without_value(self): _specs = ['--strarg', 'type=str'] ex = self.assertRaises(exceptions.CommandError, neutronV20.parse_args_to_dict, _specs) self.assertEqual('Invalid values_specs --strarg type=str', str(ex)) def test_bad_values_list(self): _specs = ['--listarg', 'list=true', 'type=str'] self.assertRaises(exceptions.CommandError, neutronV20.parse_args_to_dict, _specs) _specs = ['--listarg', 'type=list'] self.assertRaises(exceptions.CommandError, neutronV20.parse_args_to_dict, _specs) _specs = ['--listarg', 'type=list', 'action=clear'] self.assertRaises(exceptions.CommandError, neutronV20.parse_args_to_dict, _specs) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/test_command_meta.py0000664000175000017500000000264000000000000027077 0ustar00zuulzuul00000000000000# Copyright 2013 Intel # Copyright 2013 Isaku Yamahata # # 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 logging import testtools from neutronclient.neutron import v2_0 as neutronV20 class TestCommandMeta(testtools.TestCase): def test_neutron_command_meta_defines_log(self): class FakeCommand(neutronV20.NeutronCommand): pass self.assertTrue(hasattr(FakeCommand, 'log')) self.assertIsInstance(FakeCommand.log, logging.getLoggerClass()) self.assertEqual(__name__ + ".FakeCommand", FakeCommand.log.name) def test_neutron_command_log_defined_explicitly(self): class FakeCommand(neutronV20.NeutronCommand): log = None self.assertTrue(hasattr(FakeCommand, 'log')) self.assertIsNone(FakeCommand.log) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/test_exceptions.py0000664000175000017500000000331700000000000026636 0ustar00zuulzuul00000000000000# All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import sys from unittest import mock from oslo_utils import encodeutils import testtools from neutronclient._i18n import _ from neutronclient.common import exceptions class TestExceptions(testtools.TestCase): def test_exception_print_with_unicode(self): class TestException(exceptions.NeutronException): message = _('Exception with %(reason)s') multibyte_unicode_string = u'\uff21\uff22\uff23' e = TestException(reason=multibyte_unicode_string) with mock.patch.object(sys, 'stdout') as mock_stdout: print(e) exc_str = 'Exception with %s' % multibyte_unicode_string mock_stdout.assert_has_calls([mock.call.write(exc_str)]) def test_exception_message_with_encoded_unicode(self): class TestException(exceptions.NeutronException): message = _('Exception with %(reason)s') multibyte_string = u'\uff21\uff22\uff23' multibyte_binary = encodeutils.safe_encode(multibyte_string) e = TestException(reason=multibyte_binary) self.assertEqual('Exception with %s' % multibyte_string, str(e)) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/test_http.py0000664000175000017500000001276000000000000025436 0ustar00zuulzuul00000000000000# Copyright (C) 2013 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 abc from oslo_utils import uuidutils import osprofiler.profiler import osprofiler.web from requests_mock.contrib import fixture as mock_fixture import testtools from neutronclient import client from neutronclient.common import exceptions AUTH_TOKEN = 'test_token' END_URL = 'test_url' METHOD = 'GET' URL = 'http://test.test:1234/v2.0/test' BODY = 'IAMFAKE' class TestHTTPClientMixin(object, metaclass=abc.ABCMeta): def setUp(self): super(TestHTTPClientMixin, self).setUp() self.requests = self.useFixture(mock_fixture.Fixture()) self.http = self.initialize() @abc.abstractmethod def initialize(self): """Return client class, instance.""" def _test_headers(self, expected_headers, **kwargs): # Test headers. self.requests.register_uri(METHOD, URL, request_headers=expected_headers) self.http.request(URL, METHOD, **kwargs) self.assertEqual(kwargs.get('body'), self.requests.last_request.body) def test_headers_without_body(self): self._test_headers({'Accept': 'application/json'}) def test_headers_with_body(self): headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} self._test_headers(headers, body=BODY) def test_headers_without_body_with_content_type(self): headers = {'Accept': 'application/json'} self._test_headers(headers, content_type='application/json') def test_headers_with_body_with_content_type(self): headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} self._test_headers(headers, body=BODY, content_type='application/json') def test_headers_defined_in_headers(self): headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} self._test_headers(headers, body=BODY, headers=headers) def test_osprofiler_headers_are_injected(self): osprofiler.profiler.init('SWORDFISH') self.addCleanup(osprofiler.profiler.clean) headers = {'Accept': 'application/json'} headers.update(osprofiler.web.get_trace_id_headers()) self._test_headers(headers) class TestHTTPClient(TestHTTPClientMixin, testtools.TestCase): def initialize(self): return client.HTTPClient(token=AUTH_TOKEN, endpoint_url=END_URL) def test_request_error(self): def cb(*args, **kwargs): raise Exception('error msg') self.requests.get(URL, body=cb) self.assertRaises( exceptions.ConnectionFailed, self.http._cs_request, URL, METHOD ) def test_request_success(self): text = 'test content' self.requests.register_uri(METHOD, URL, text=text) resp, resp_text = self.http._cs_request(URL, METHOD) self.assertEqual(200, resp.status_code) self.assertEqual(text, resp_text) def test_request_unauthorized(self): text = 'unauthorized message' self.requests.register_uri(METHOD, URL, status_code=401, text=text) e = self.assertRaises(exceptions.Unauthorized, self.http._cs_request, URL, METHOD) self.assertEqual(text, e.message) def test_request_forbidden_is_returned_to_caller(self): text = 'forbidden message' self.requests.register_uri(METHOD, URL, status_code=403, text=text) resp, resp_text = self.http._cs_request(URL, METHOD) self.assertEqual(403, resp.status_code) self.assertEqual(text, resp_text) def test_do_request_success(self): text = 'test content' self.requests.register_uri(METHOD, END_URL + URL, text=text) resp, resp_text = self.http.do_request(URL, METHOD) self.assertEqual(200, resp.status_code) self.assertEqual(text, resp_text) def test_do_request_with_headers_success(self): text = 'test content' self.requests.register_uri(METHOD, END_URL + URL, text=text, request_headers={'key': 'value'}) resp, resp_text = self.http.do_request(URL, METHOD, headers={'key': 'value'}) self.assertEqual(200, resp.status_code) self.assertEqual(text, resp_text) class TestHTTPClientWithReqId(TestHTTPClientMixin, testtools.TestCase): """Tests for when global_request_id is set.""" def initialize(self): self.req_id = "req-%s" % uuidutils.generate_uuid() return client.HTTPClient(token=AUTH_TOKEN, endpoint_url=END_URL, global_request_id=self.req_id) def test_request_success(self): headers = { 'Accept': 'application/json', 'X-OpenStack-Request-ID': self.req_id } self.requests.register_uri(METHOD, URL, request_headers=headers) self.http.request(URL, METHOD) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/test_utils.py0000664000175000017500000001434000000000000025613 0ustar00zuulzuul00000000000000# Copyright (C) 2013 Yahoo! Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import argparse from oslo_utils import netutils import testtools from neutronclient.common import exceptions from neutronclient.common import utils class TestUtils(testtools.TestCase): def test_string_to_bool_true(self): self.assertTrue(utils.str2bool('true')) def test_string_to_bool_false(self): self.assertFalse(utils.str2bool('false')) def test_string_to_bool_None(self): self.assertIsNone(utils.str2bool(None)) def test_string_to_dictionary(self): input_str = 'key1=value1,key2=value2' expected = {'key1': 'value1', 'key2': 'value2'} self.assertEqual(expected, utils.str2dict(input_str)) def test_none_string_to_dictionary(self): input_str = '' expected = {} self.assertEqual(expected, utils.str2dict(input_str)) input_str = None expected = {} self.assertEqual(expected, utils.str2dict(input_str)) def test_invalid_string_to_dictionary(self): input_str = 'invalid' self.assertRaises(argparse.ArgumentTypeError, utils.str2dict, input_str) def test_string_with_comma_value_to_dictionary(self): input_str = ('opt_name=classless-static-route,' 'opt_value=169.254.169.254/32,10.0.0.1') expected = {'opt_name': 'classless-static-route', 'opt_value': '169.254.169.254/32,10.0.0.1'} self.assertEqual(expected, utils.str2dict(input_str)) def test_str2dict_optional_keys(self): self.assertDictEqual({'key1': 'value1'}, utils.str2dict('key1=value1', optional_keys=['key1', 'key2'])) self.assertDictEqual({'key1': 'value1', 'key2': 'value2'}, utils.str2dict('key1=value1,key2=value2', optional_keys=['key1', 'key2'])) e = self.assertRaises(argparse.ArgumentTypeError, utils.str2dict, 'key1=value1,key2=value2,key3=value3', optional_keys=['key1', 'key2']) self.assertEqual("Invalid key(s) 'key3' specified. " "Valid key(s): 'key1, key2'.", str(e)) def test_str2dict_required_keys(self): self.assertDictEqual( {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}, utils.str2dict('key1=value1,key2=value2,key3=value3', required_keys=['key1', 'key2'], optional_keys=['key3'])) self.assertDictEqual( {'key1': 'value1', 'key2': 'value2'}, utils.str2dict('key1=value1,key2=value2', required_keys=['key1', 'key2'])) e = self.assertRaises(argparse.ArgumentTypeError, utils.str2dict, 'key1=value1', required_keys=['key1', 'key2']) self.assertEqual("Required key(s) 'key2' not specified.", str(e)) def test_get_dict_item_properties(self): item = {'name': 'test_name', 'id': 'test_id'} fields = ('name', 'id') actual = utils.get_item_properties(item=item, fields=fields) self.assertEqual(('test_name', 'test_id'), actual) def test_get_object_item_properties_mixed_case_fields(self): class Fake(object): def __init__(self): self.id = 'test_id' self.name = 'test_name' self.test_user = 'test' fields = ('name', 'id', 'test user') mixed_fields = ('test user', 'ID') item = Fake() actual = utils.get_item_properties(item, fields, mixed_fields) self.assertEqual(('test_name', 'test_id', 'test'), actual) def test_get_object_item_desired_fields_differ_from_item(self): class Fake(object): def __init__(self): self.id = 'test_id_1' self.name = 'test_name' self.test_user = 'test' fields = ('name', 'id', 'test user') item = Fake() actual = utils.get_item_properties(item, fields) self.assertNotEqual(('test_name', 'test_id', 'test'), actual) def test_get_object_item_desired_fields_is_empty(self): class Fake(object): def __init__(self): self.id = 'test_id_1' self.name = 'test_name' self.test_user = 'test' fields = [] item = Fake() actual = utils.get_item_properties(item, fields) self.assertEqual((), actual) def test_get_object_item_with_formatters(self): class Fake(object): def __init__(self): self.id = 'test_id' self.name = 'test_name' self.test_user = 'test' class FakeCallable(object): def __call__(self, *args, **kwargs): return 'pass' fields = ('name', 'id', 'test user', 'is_public') formatters = {'is_public': FakeCallable()} item = Fake() act = utils.get_item_properties(item, fields, formatters=formatters) self.assertEqual(('test_name', 'test_id', 'test', 'pass'), act) def test_is_cidr(self): self.assertTrue(netutils.is_valid_cidr('10.10.10.0/24')) self.assertFalse(netutils.is_valid_cidr('10.10.10..0/24')) self.assertFalse(netutils.is_valid_cidr('wrong_cidr_format')) class ImportClassTestCase(testtools.TestCase): def test_get_client_class_invalid_version(self): self.assertRaises( exceptions.UnsupportedVersion, utils.get_client_class, 'image', '2', {'image': '2'}) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/tests/unit/test_validators.py0000664000175000017500000001000500000000000026615 0ustar00zuulzuul00000000000000# Copyright 2014 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 testtools from neutronclient.common import exceptions from neutronclient.common import validators class FakeParsedArgs(object): pass class ValidatorTest(testtools.TestCase): def _test_validate_int(self, attr_val, attr_name='attr1', min_value=1, max_value=10): obj = FakeParsedArgs() setattr(obj, attr_name, attr_val) ret = validators.validate_int_range(obj, attr_name, min_value, max_value) # Come here only if there is no exception. self.assertIsNone(ret) def _test_validate_int_error(self, attr_val, expected_msg, attr_name='attr1', expected_exc=None, min_value=1, max_value=10): if expected_exc is None: expected_exc = exceptions.CommandError e = self.assertRaises(expected_exc, self._test_validate_int, attr_val, attr_name, min_value, max_value) self.assertEqual(expected_msg, str(e)) def test_validate_int_min_max(self): self._test_validate_int(1) self._test_validate_int(10) self._test_validate_int('1') self._test_validate_int('10') self._test_validate_int('0x0a') self._test_validate_int_error( 0, 'attr1 "0" should be an integer [1:10].') self._test_validate_int_error( 11, 'attr1 "11" should be an integer [1:10].') self._test_validate_int_error( '0x10', 'attr1 "0x10" should be an integer [1:10].') def test_validate_int_min_only(self): self._test_validate_int(1, max_value=None) self._test_validate_int(10, max_value=None) self._test_validate_int(11, max_value=None) self._test_validate_int_error( 0, 'attr1 "0" should be an integer greater than or equal to 1.', max_value=None) def test_validate_int_max_only(self): self._test_validate_int(0, min_value=None) self._test_validate_int(1, min_value=None) self._test_validate_int(10, min_value=None) self._test_validate_int_error( 11, 'attr1 "11" should be an integer smaller than or equal to 10.', min_value=None) def test_validate_int_no_limit(self): self._test_validate_int(0, min_value=None, max_value=None) self._test_validate_int(1, min_value=None, max_value=None) self._test_validate_int(10, min_value=None, max_value=None) self._test_validate_int(11, min_value=None, max_value=None) self._test_validate_int_error( 'abc', 'attr1 "abc" should be an integer.', min_value=None, max_value=None) def _test_validate_subnet(self, attr_val, attr_name='attr1'): obj = FakeParsedArgs() setattr(obj, attr_name, attr_val) ret = validators.validate_ip_subnet(obj, attr_name) # Come here only if there is no exception. self.assertIsNone(ret) def test_validate_ip_subnet(self): self._test_validate_subnet('192.168.2.0/24') self._test_validate_subnet('192.168.2.3/20') self._test_validate_subnet('192.168.2.1') e = self.assertRaises(exceptions.CommandError, self._test_validate_subnet, '192.168.2.256') self.assertEqual('attr1 "192.168.2.256" is not a valid CIDR.', str(e)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2296627 python-neutronclient-11.2.0/neutronclient/v2_0/0000775000175000017500000000000000000000000021465 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/v2_0/__init__.py0000664000175000017500000000000000000000000023564 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/v2_0/client.py0000664000175000017500000034361100000000000023325 0ustar00zuulzuul00000000000000# Copyright 2012 OpenStack Foundation. # Copyright 2015 Hewlett-Packard Development Company, L.P. # Copyright 2017 FUJITSU LIMITED # 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 inspect import itertools import logging import re import time import urllib.parse as urlparse import debtcollector.renames from keystoneauth1 import exceptions as ksa_exc import requests from neutronclient._i18n import _ from neutronclient import client from neutronclient.common import exceptions from neutronclient.common import extension as client_extension from neutronclient.common import serializer from neutronclient.common import utils _logger = logging.getLogger(__name__) HEX_ELEM = '[0-9A-Fa-f]' UUID_PATTERN = '-'.join([HEX_ELEM + '{8}', HEX_ELEM + '{4}', HEX_ELEM + '{4}', HEX_ELEM + '{4}', HEX_ELEM + '{12}']) def exception_handler_v20(status_code, error_content): """Exception handler for API v2.0 client. This routine generates the appropriate Neutron exception according to the contents of the response body. :param status_code: HTTP error status code :param error_content: deserialized body of error response """ error_dict = None request_ids = error_content.request_ids if isinstance(error_content, dict): error_dict = error_content.get('NeutronError') # Find real error type client_exc = None if error_dict: # If Neutron key is found, it will definitely contain # a 'message' and 'type' keys? try: error_type = error_dict['type'] error_message = error_dict['message'] if error_dict['detail']: error_message += "\n" + error_dict['detail'] # If corresponding exception is defined, use it. client_exc = getattr(exceptions, '%sClient' % error_type, None) except Exception: error_message = "%s" % error_dict else: error_message = None if isinstance(error_content, dict): error_message = error_content.get('message') if not error_message: # If we end up here the exception was not a neutron error error_message = "%s-%s" % (status_code, error_content) # If an exception corresponding to the error type is not found, # look up per status-code client exception. if not client_exc: client_exc = exceptions.HTTP_EXCEPTION_MAP.get(status_code) # If there is no exception per status-code, # Use NeutronClientException as fallback. if not client_exc: client_exc = exceptions.NeutronClientException raise client_exc(message=error_message, status_code=status_code, request_ids=request_ids) class _RequestIdMixin(object): """Wrapper class to expose x-openstack-request-id to the caller.""" def _request_ids_setup(self): self._request_ids = [] @property def request_ids(self): return self._request_ids def _append_request_ids(self, resp): """Add request_ids as an attribute to the object :param resp: Response object or list of Response objects """ if isinstance(resp, list): # Add list of request_ids if response is of type list. for resp_obj in resp: self._append_request_id(resp_obj) elif resp is not None: # Add request_ids if response contains single object. self._append_request_id(resp) def _append_request_id(self, resp): if isinstance(resp, requests.Response): # Extract 'x-openstack-request-id' from headers if # response is a Response object. request_id = resp.headers.get('x-openstack-request-id') else: # If resp is of type string. request_id = resp if request_id: self._request_ids.append(request_id) class _DictWithMeta(dict, _RequestIdMixin): def __init__(self, values, resp): super(_DictWithMeta, self).__init__(values) self._request_ids_setup() self._append_request_ids(resp) class _TupleWithMeta(tuple, _RequestIdMixin): def __new__(cls, values, resp): return super(_TupleWithMeta, cls).__new__(cls, values) def __init__(self, values, resp): self._request_ids_setup() self._append_request_ids(resp) class _StrWithMeta(str, _RequestIdMixin): def __new__(cls, value, resp): return super(_StrWithMeta, cls).__new__(cls, value) def __init__(self, values, resp): self._request_ids_setup() self._append_request_ids(resp) class _GeneratorWithMeta(_RequestIdMixin): def __init__(self, paginate_func, collection, path, **params): self.paginate_func = paginate_func self.collection = collection self.path = path self.params = params self.generator = None self._request_ids_setup() def _paginate(self): for r in self.paginate_func( self.collection, self.path, **self.params): yield r, r.request_ids def __iter__(self): return self # Python 3 compatibility def __next__(self): return self.next() def next(self): if not self.generator: self.generator = self._paginate() try: obj, req_id = next(self.generator) self._append_request_ids(req_id) except StopIteration: raise StopIteration() return obj class ClientBase(object): """Client for the OpenStack Neutron v2.0 API. :param string username: Username for authentication. (optional) :param string user_id: User ID for authentication. (optional) :param string password: Password for authentication. (optional) :param string token: Token for authentication. (optional) :param string tenant_name: DEPRECATED! Use project_name instead. :param string project_name: Project name. (optional) :param string tenant_id: DEPRECATED! Use project_id instead. :param string project_id: Project id. (optional) :param string auth_strategy: 'keystone' by default, 'noauth' for no authentication against keystone. (optional) :param string auth_url: Keystone service endpoint for authorization. :param string service_type: Network service type to pull from the keystone catalog (e.g. 'network') (optional) :param string endpoint_type: Network service endpoint type to pull from the keystone catalog (e.g. 'publicURL', 'internalURL', or 'adminURL') (optional) :param string region_name: Name of a region to select when choosing an endpoint from the service catalog. :param string endpoint_url: A user-supplied endpoint URL for the neutron service. Lazy-authentication is possible for API service calls if endpoint is set at instantiation.(optional) :param integer timeout: Allows customization of the timeout for client http requests. (optional) :param bool insecure: SSL certificate validation. (optional) :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). :param bool raise_errors: If True then exceptions caused by connection failure are propagated to the caller. (default: True) :param session: Keystone client auth session to use. (optional) :param auth: Keystone auth plugin to use. (optional) Example:: from neutronclient.v2_0 import client neutron = client.Client(username=USER, password=PASS, project_name=PROJECT_NAME, auth_url=KEYSTONE_URL) nets = neutron.list_networks() ... """ # API has no way to report plurals, so we have to hard code them # This variable should be overridden by a child class. EXTED_PLURALS = {} @debtcollector.renames.renamed_kwarg( 'tenant_id', 'project_id', replace=True) def __init__(self, **kwargs): """Initialize a new client for the Neutron v2.0 API.""" super(ClientBase, self).__init__() self.retries = kwargs.pop('retries', 0) self.raise_errors = kwargs.pop('raise_errors', True) self.httpclient = client.construct_http_client(**kwargs) self.version = '2.0' self.action_prefix = "/v%s" % (self.version) self.retry_interval = 1 def _handle_fault_response(self, status_code, response_body, resp): # Create exception with HTTP status code and message _logger.debug("Error message: %s", response_body) # Add deserialized error message to exception arguments try: des_error_body = self.deserialize(response_body, status_code) except Exception: # If unable to deserialized body it is probably not a # Neutron error des_error_body = {'message': response_body} error_body = self._convert_into_with_meta(des_error_body, resp) # Raise the appropriate exception exception_handler_v20(status_code, error_body) def do_request(self, method, action, body=None, headers=None, params=None): # Add format and project_id action = self.action_prefix + action if isinstance(params, dict) and params: params = utils.safe_encode_dict(params) action += '?' + urlparse.urlencode(params, doseq=1) if body: body = self.serialize(body) resp, replybody = self.httpclient.do_request(action, method, body=body, headers=headers) status_code = resp.status_code if status_code in (requests.codes.ok, requests.codes.created, requests.codes.accepted, requests.codes.no_content): data = self.deserialize(replybody, status_code) return self._convert_into_with_meta(data, resp) else: if not replybody: replybody = resp.reason self._handle_fault_response(status_code, replybody, resp) def get_auth_info(self): return self.httpclient.get_auth_info() def serialize(self, data): """Serializes a dictionary into JSON. A dictionary with a single key can be passed and it can contain any structure. """ if data is None: return None elif isinstance(data, dict): return serializer.Serializer().serialize(data) else: raise Exception(_("Unable to serialize object of type = '%s'") % type(data)) def deserialize(self, data, status_code): """Deserializes a JSON string into a dictionary.""" if not data: return data return serializer.Serializer().deserialize( data)['body'] def retry_request(self, method, action, body=None, headers=None, params=None): """Call do_request with the default retry configuration. Only idempotent requests should retry failed connection attempts. :raises: ConnectionFailed if the maximum # of retries is exceeded """ max_attempts = self.retries + 1 for i in range(max_attempts): try: return self.do_request(method, action, body=body, headers=headers, params=params) except (exceptions.ConnectionFailed, ksa_exc.ConnectionError): # Exception has already been logged by do_request() if i < self.retries: _logger.debug('Retrying connection to Neutron service') time.sleep(self.retry_interval) elif self.raise_errors: raise if self.retries: msg = (_("Failed to connect to Neutron server after %d attempts") % max_attempts) else: msg = _("Failed to connect Neutron server") raise exceptions.ConnectionFailed(reason=msg) def delete(self, action, body=None, headers=None, params=None): return self.retry_request("DELETE", action, body=body, headers=headers, params=params) def get(self, action, body=None, headers=None, params=None): return self.retry_request("GET", action, body=body, headers=headers, params=params) def post(self, action, body=None, headers=None, params=None): # Do not retry POST requests to avoid the orphan objects problem. return self.do_request("POST", action, body=body, headers=headers, params=params) def put(self, action, body=None, headers=None, params=None): return self.retry_request("PUT", action, body=body, headers=headers, params=params) def list(self, collection, path, retrieve_all=True, **params): if retrieve_all: res = [] request_ids = [] for r in self._pagination(collection, path, **params): res.extend(r[collection]) request_ids.extend(r.request_ids) return _DictWithMeta({collection: res}, request_ids) else: return _GeneratorWithMeta(self._pagination, collection, path, **params) def _pagination(self, collection, path, **params): if params.get('page_reverse', False): linkrel = 'previous' else: linkrel = 'next' next = True while next: res = self.get(path, params=params) yield res next = False try: for link in res['%s_links' % collection]: if link['rel'] == linkrel: query_str = urlparse.urlparse(link['href']).query params = urlparse.parse_qs(query_str) next = True break except KeyError: break def _convert_into_with_meta(self, item, resp): if item: if isinstance(item, dict): return _DictWithMeta(item, resp) elif isinstance(item, str): return _StrWithMeta(item, resp) else: return _TupleWithMeta((), resp) def get_resource_plural(self, resource): for k in self.EXTED_PLURALS: if self.EXTED_PLURALS[k] == resource: return k return resource + 's' def find_resource_by_id(self, resource, resource_id, cmd_resource=None, parent_id=None, fields=None): if not cmd_resource: cmd_resource = resource cmd_resource_plural = self.get_resource_plural(cmd_resource) resource_plural = self.get_resource_plural(resource) # TODO(amotoki): Use show_%s instead of list_%s obj_lister = getattr(self, "list_%s" % cmd_resource_plural) # perform search by id only if we are passing a valid UUID match = re.match(UUID_PATTERN, resource_id) collection = resource_plural if match: params = {'id': resource_id} if fields: params['fields'] = fields if parent_id: data = obj_lister(parent_id, **params) else: data = obj_lister(**params) if data and data[collection]: return data[collection][0] not_found_message = (_("Unable to find %(resource)s with id " "'%(id)s'") % {'resource': resource, 'id': resource_id}) # 404 is raised by exceptions.NotFound to simulate serverside behavior raise exceptions.NotFound(message=not_found_message) def _find_resource_by_name(self, resource, name, project_id=None, cmd_resource=None, parent_id=None, fields=None): if not cmd_resource: cmd_resource = resource cmd_resource_plural = self.get_resource_plural(cmd_resource) resource_plural = self.get_resource_plural(resource) obj_lister = getattr(self, "list_%s" % cmd_resource_plural) params = {'name': name} if fields: params['fields'] = fields if project_id: params['tenant_id'] = project_id if parent_id: data = obj_lister(parent_id, **params) else: data = obj_lister(**params) collection = resource_plural info = data[collection] if len(info) > 1: raise exceptions.NeutronClientNoUniqueMatch(resource=resource, name=name) elif len(info) == 0: not_found_message = (_("Unable to find %(resource)s with name " "'%(name)s'") % {'resource': resource, 'name': name}) # 404 is raised by exceptions.NotFound # to simulate serverside behavior raise exceptions.NotFound(message=not_found_message) else: return info[0] def find_resource(self, resource, name_or_id, project_id=None, cmd_resource=None, parent_id=None, fields=None): try: return self.find_resource_by_id(resource, name_or_id, cmd_resource, parent_id, fields) except exceptions.NotFound: try: return self._find_resource_by_name( resource, name_or_id, project_id, cmd_resource, parent_id, fields) except exceptions.NotFound: not_found_message = (_("Unable to find %(resource)s with name " "or id '%(name_or_id)s'") % {'resource': resource, 'name_or_id': name_or_id}) raise exceptions.NotFound( message=not_found_message) class Client(ClientBase): networks_path = "/networks" network_path = "/networks/%s" ports_path = "/ports" port_path = "/ports/%s" port_bindings_path = "/ports/%s/bindings" port_binding_path = "/ports/%s/bindings/%s" port_binding_path_activate = "/ports/%s/bindings/%s/activate" subnets_path = "/subnets" subnet_path = "/subnets/%s" onboard_network_subnets_path = "/subnetpools/%s/onboard_network_subnets" subnetpools_path = "/subnetpools" subnetpool_path = "/subnetpools/%s" address_scopes_path = "/address-scopes" address_scope_path = "/address-scopes/%s" quotas_path = "/quotas" quota_path = "/quotas/%s" quota_default_path = "/quotas/%s/default" quota_details_path = "/quotas/%s/details.json" extensions_path = "/extensions" extension_path = "/extensions/%s" routers_path = "/routers" 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" security_group_rule_path = "/security-group-rules/%s" segments_path = "/segments" segment_path = "/segments/%s" sfc_flow_classifiers_path = "/sfc/flow_classifiers" sfc_flow_classifier_path = "/sfc/flow_classifiers/%s" sfc_port_pairs_path = "/sfc/port_pairs" sfc_port_pair_path = "/sfc/port_pairs/%s" sfc_port_pair_groups_path = "/sfc/port_pair_groups" sfc_port_pair_group_path = "/sfc/port_pair_groups/%s" sfc_port_chains_path = "/sfc/port_chains" sfc_port_chain_path = "/sfc/port_chains/%s" sfc_service_graphs_path = "/sfc/service_graphs" sfc_service_graph_path = "/sfc/service_graphs/%s" endpoint_groups_path = "/vpn/endpoint-groups" endpoint_group_path = "/vpn/endpoint-groups/%s" vpnservices_path = "/vpn/vpnservices" vpnservice_path = "/vpn/vpnservices/%s" ipsecpolicies_path = "/vpn/ipsecpolicies" ipsecpolicy_path = "/vpn/ipsecpolicies/%s" ikepolicies_path = "/vpn/ikepolicies" ikepolicy_path = "/vpn/ikepolicies/%s" ipsec_site_connections_path = "/vpn/ipsec-site-connections" ipsec_site_connection_path = "/vpn/ipsec-site-connections/%s" lbaas_loadbalancers_path = "/lbaas/loadbalancers" lbaas_loadbalancer_path = "/lbaas/loadbalancers/%s" lbaas_loadbalancer_path_stats = "/lbaas/loadbalancers/%s/stats" lbaas_loadbalancer_path_status = "/lbaas/loadbalancers/%s/statuses" lbaas_listeners_path = "/lbaas/listeners" lbaas_listener_path = "/lbaas/listeners/%s" lbaas_l7policies_path = "/lbaas/l7policies" lbaas_l7policy_path = lbaas_l7policies_path + "/%s" lbaas_l7rules_path = lbaas_l7policy_path + "/rules" lbaas_l7rule_path = lbaas_l7rules_path + "/%s" lbaas_pools_path = "/lbaas/pools" lbaas_pool_path = "/lbaas/pools/%s" lbaas_healthmonitors_path = "/lbaas/healthmonitors" lbaas_healthmonitor_path = "/lbaas/healthmonitors/%s" lbaas_members_path = lbaas_pool_path + "/members" lbaas_member_path = lbaas_pool_path + "/members/%s" vips_path = "/lb/vips" vip_path = "/lb/vips/%s" pools_path = "/lb/pools" pool_path = "/lb/pools/%s" pool_path_stats = "/lb/pools/%s/stats" members_path = "/lb/members" member_path = "/lb/members/%s" health_monitors_path = "/lb/health_monitors" health_monitor_path = "/lb/health_monitors/%s" associate_pool_health_monitors_path = "/lb/pools/%s/health_monitors" disassociate_pool_health_monitors_path = ( "/lb/pools/%(pool)s/health_monitors/%(health_monitor)s") qos_queues_path = "/qos-queues" qos_queue_path = "/qos-queues/%s" agents_path = "/agents" agent_path = "/agents/%s" network_gateways_path = "/network-gateways" network_gateway_path = "/network-gateways/%s" gateway_devices_path = "/gateway-devices" gateway_device_path = "/gateway-devices/%s" service_providers_path = "/service-providers" metering_labels_path = "/metering/metering-labels" metering_label_path = "/metering/metering-labels/%s" metering_label_rules_path = "/metering/metering-label-rules" metering_label_rule_path = "/metering/metering-label-rules/%s" DHCP_NETS = '/dhcp-networks' DHCP_AGENTS = '/dhcp-agents' L3_ROUTERS = '/l3-routers' L3_AGENTS = '/l3-agents' LOADBALANCER_POOLS = '/loadbalancer-pools' LOADBALANCER_AGENT = '/loadbalancer-agent' AGENT_LOADBALANCERS = '/agent-loadbalancers' LOADBALANCER_HOSTING_AGENT = '/loadbalancer-hosting-agent' firewall_rules_path = "/fw/firewall_rules" firewall_rule_path = "/fw/firewall_rules/%s" firewall_policies_path = "/fw/firewall_policies" firewall_policy_path = "/fw/firewall_policies/%s" firewall_policy_insert_path = "/fw/firewall_policies/%s/insert_rule" firewall_policy_remove_path = "/fw/firewall_policies/%s/remove_rule" firewalls_path = "/fw/firewalls" firewall_path = "/fw/firewalls/%s" fwaas_firewall_groups_path = "/fwaas/firewall_groups" fwaas_firewall_group_path = "/fwaas/firewall_groups/%s" fwaas_firewall_rules_path = "/fwaas/firewall_rules" fwaas_firewall_rule_path = "/fwaas/firewall_rules/%s" fwaas_firewall_policies_path = "/fwaas/firewall_policies" fwaas_firewall_policy_path = "/fwaas/firewall_policies/%s" fwaas_firewall_policy_insert_path = \ "/fwaas/firewall_policies/%s/insert_rule" fwaas_firewall_policy_remove_path = \ "/fwaas/firewall_policies/%s/remove_rule" rbac_policies_path = "/rbac-policies" rbac_policy_path = "/rbac-policies/%s" qos_policies_path = "/qos/policies" 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" flavor_path = "/flavors/%s" service_profiles_path = "/service_profiles" service_profile_path = "/service_profiles/%s" flavor_profile_bindings_path = flavor_path + service_profiles_path flavor_profile_binding_path = flavor_path + service_profile_path availability_zones_path = "/availability_zones" auto_allocated_topology_path = "/auto-allocated-topology/%s" BGP_DRINSTANCES = "/bgp-drinstances" BGP_DRINSTANCE = "/bgp-drinstance/%s" BGP_DRAGENTS = "/bgp-dragents" BGP_DRAGENT = "/bgp-dragents/%s" bgp_speakers_path = "/bgp-speakers" bgp_speaker_path = "/bgp-speakers/%s" bgp_peers_path = "/bgp-peers" bgp_peer_path = "/bgp-peers/%s" network_ip_availabilities_path = '/network-ip-availabilities' network_ip_availability_path = '/network-ip-availabilities/%s' tags_path = "/%s/%s/tags" tag_path = "/%s/%s/tags/%s" trunks_path = "/trunks" trunk_path = "/trunks/%s" subports_path = "/trunks/%s/get_subports" subports_add_path = "/trunks/%s/add_subports" subports_remove_path = "/trunks/%s/remove_subports" bgpvpns_path = "/bgpvpn/bgpvpns" bgpvpn_path = "/bgpvpn/bgpvpns/%s" bgpvpn_network_associations_path =\ "/bgpvpn/bgpvpns/%s/network_associations" bgpvpn_network_association_path =\ "/bgpvpn/bgpvpns/%s/network_associations/%s" bgpvpn_router_associations_path = "/bgpvpn/bgpvpns/%s/router_associations" bgpvpn_router_association_path =\ "/bgpvpn/bgpvpns/%s/router_associations/%s" bgpvpn_port_associations_path = "/bgpvpn/bgpvpns/%s/port_associations" bgpvpn_port_association_path = "/bgpvpn/bgpvpns/%s/port_associations/%s" network_logs_path = "/log/logs" network_log_path = "/log/logs/%s" network_loggables_path = "/log/loggable-resources" # API has no way to report plurals, so we have to hard code them EXTED_PLURALS = {'routers': 'router', 'floatingips': 'floatingip', 'service_types': 'service_type', 'service_definitions': 'service_definition', 'security_groups': 'security_group', 'security_group_rules': 'security_group_rule', 'segments': 'segment', 'ipsecpolicies': 'ipsecpolicy', 'ikepolicies': 'ikepolicy', 'ipsec_site_connections': 'ipsec_site_connection', 'vpnservices': 'vpnservice', 'endpoint_groups': 'endpoint_group', 'vips': 'vip', 'pools': 'pool', 'members': 'member', 'health_monitors': 'health_monitor', 'quotas': 'quota', 'service_providers': 'service_provider', 'firewall_rules': 'firewall_rule', 'firewall_policies': 'firewall_policy', 'firewalls': 'firewall', 'fwaas_firewall_rules': 'fwaas_firewall_rule', 'fwaas_firewall_policies': 'fwaas_firewall_policy', 'fwaas_firewall_groups': 'fwaas_firewall_group', 'metering_labels': 'metering_label', 'metering_label_rules': 'metering_label_rule', 'loadbalancers': 'loadbalancer', 'listeners': 'listener', 'l7rules': 'l7rule', 'l7policies': 'l7policy', 'lbaas_l7policies': 'lbaas_l7policy', 'lbaas_pools': 'lbaas_pool', 'lbaas_healthmonitors': 'lbaas_healthmonitor', 'lbaas_members': 'lbaas_member', 'healthmonitors': 'healthmonitor', 'rbac_policies': 'rbac_policy', 'address_scopes': 'address_scope', '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', 'flavors': 'flavor', 'bgp_speakers': 'bgp_speaker', 'bgp_peers': 'bgp_peer', 'network_ip_availabilities': 'network_ip_availability', 'trunks': 'trunk', 'bgpvpns': 'bgpvpn', 'network_associations': 'network_association', 'router_associations': 'router_association', 'port_associations': 'port_association', 'flow_classifiers': 'flow_classifier', 'port_pairs': 'port_pair', 'port_pair_groups': 'port_pair_group', 'port_chains': 'port_chain', 'service_graphs': 'service_graph', 'logs': 'log', 'loggable_resources': 'loggable_resource', } def list_ext(self, collection, path, retrieve_all, **_params): """Client extension hook for list.""" return self.list(collection, path, retrieve_all, **_params) def show_ext(self, path, id, **_params): """Client extension hook for show.""" return self.get(path % id, params=_params) def create_ext(self, path, body=None): """Client extension hook for create.""" return self.post(path, body=body) def update_ext(self, path, id, body=None): """Client extension hook for update.""" return self.put(path % id, body=body) def delete_ext(self, path, id): """Client extension hook for delete.""" return self.delete(path % id) def get_quotas_tenant(self, **_params): """Fetch project info for following quota operation.""" return self.get(self.quota_path % 'tenant', params=_params) def list_quotas(self, **_params): """Fetch all projects' quotas.""" return self.get(self.quotas_path, params=_params) @debtcollector.renames.renamed_kwarg( 'tenant_id', 'project_id', replace=True) def show_quota(self, project_id, **_params): """Fetch information of a certain project's quotas.""" return self.get(self.quota_path % (project_id), params=_params) @debtcollector.renames.renamed_kwarg( 'tenant_id', 'project_id', replace=True) def show_quota_details(self, project_id, **_params): """Fetch information of a certain project's quota details.""" return self.get(self.quota_details_path % (project_id), params=_params) @debtcollector.renames.renamed_kwarg( 'tenant_id', 'project_id', replace=True) def show_quota_default(self, project_id, **_params): """Fetch information of a certain project's default quotas.""" return self.get(self.quota_default_path % (project_id), params=_params) @debtcollector.renames.renamed_kwarg( 'tenant_id', 'project_id', replace=True) def update_quota(self, project_id, body=None): """Update a project's quotas.""" return self.put(self.quota_path % (project_id), body=body) @debtcollector.renames.renamed_kwarg( 'tenant_id', 'project_id', replace=True) def delete_quota(self, project_id): """Delete the specified project's quota values.""" return self.delete(self.quota_path % (project_id)) def list_extensions(self, **_params): """Fetch a list of all extensions on server side.""" return self.get(self.extensions_path, params=_params) def show_extension(self, ext_alias, **_params): """Fetches information of a certain extension.""" return self.get(self.extension_path % ext_alias, params=_params) def list_ports(self, retrieve_all=True, **_params): """Fetches a list of all ports for a project.""" # Pass filters in "params" argument to do_request return self.list('ports', self.ports_path, retrieve_all, **_params) def show_port(self, port, **_params): """Fetches information of a certain port.""" return self.get(self.port_path % (port), params=_params) def create_port(self, body=None): """Creates a new port.""" return self.post(self.ports_path, body=body) def update_port(self, port, body=None, revision_number=None): """Updates a port.""" return self._update_resource(self.port_path % (port), body=body, revision_number=revision_number) def delete_port(self, port): """Deletes the specified port.""" return self.delete(self.port_path % (port)) def create_port_binding(self, port_id, body=None): """Creates a new port binding.""" return self.post(self.port_bindings_path % port_id, body=body) def delete_port_binding(self, port_id, host_id): """Deletes the specified port binding.""" return self.delete(self.port_binding_path % (port_id, host_id)) def show_port_binding(self, port_id, host_id, **_params): """Fetches information for a certain port binding.""" return self.get(self.port_binding_path % (port_id, host_id), params=_params) def list_port_bindings(self, port_id, retrieve_all=True, **_params): """Fetches a list of all bindings for a certain port.""" return self.list('port_bindings', self.port_bindings_path % port_id, retrieve_all, **_params) def activate_port_binding(self, port_id, host_id): """Activates a port binding.""" return self.put(self.port_binding_path_activate % (port_id, host_id)) def list_networks(self, retrieve_all=True, **_params): """Fetches a list of all networks for a project.""" # Pass filters in "params" argument to do_request return self.list('networks', self.networks_path, retrieve_all, **_params) def show_network(self, network, **_params): """Fetches information of a certain network.""" return self.get(self.network_path % (network), params=_params) def create_network(self, body=None): """Creates a new network.""" return self.post(self.networks_path, body=body) def update_network(self, network, body=None, revision_number=None): """Updates a network.""" return self._update_resource(self.network_path % (network), body=body, revision_number=revision_number) def delete_network(self, network): """Deletes the specified network.""" return self.delete(self.network_path % (network)) def list_subnets(self, retrieve_all=True, **_params): """Fetches a list of all subnets for a project.""" return self.list('subnets', self.subnets_path, retrieve_all, **_params) def show_subnet(self, subnet, **_params): """Fetches information of a certain subnet.""" return self.get(self.subnet_path % (subnet), params=_params) def create_subnet(self, body=None): """Creates a new subnet.""" return self.post(self.subnets_path, body=body) def update_subnet(self, subnet, body=None, revision_number=None): """Updates a subnet.""" return self._update_resource(self.subnet_path % (subnet), body=body, revision_number=revision_number) def delete_subnet(self, subnet): """Deletes the specified subnet.""" return self.delete(self.subnet_path % (subnet)) def list_subnetpools(self, retrieve_all=True, **_params): """Fetches a list of all subnetpools for a project.""" return self.list('subnetpools', self.subnetpools_path, retrieve_all, **_params) def show_subnetpool(self, subnetpool, **_params): """Fetches information of a certain subnetpool.""" return self.get(self.subnetpool_path % (subnetpool), params=_params) def create_subnetpool(self, body=None): """Creates a new subnetpool.""" return self.post(self.subnetpools_path, body=body) def update_subnetpool(self, subnetpool, body=None, revision_number=None): """Updates a subnetpool.""" return self._update_resource(self.subnetpool_path % (subnetpool), body=body, revision_number=revision_number) def delete_subnetpool(self, subnetpool): """Deletes the specified subnetpool.""" return self.delete(self.subnetpool_path % (subnetpool)) def list_routers(self, retrieve_all=True, **_params): """Fetches a list of all routers for a project.""" # Pass filters in "params" argument to do_request return self.list('routers', self.routers_path, retrieve_all, **_params) def show_router(self, router, **_params): """Fetches information of a certain router.""" return self.get(self.router_path % (router), params=_params) def create_router(self, body=None): """Creates a new router.""" return self.post(self.routers_path, body=body) def update_router(self, router, body=None, revision_number=None): """Updates a router.""" return self._update_resource(self.router_path % (router), body=body, revision_number=revision_number) def delete_router(self, router): """Deletes the specified router.""" return self.delete(self.router_path % (router)) def list_address_scopes(self, retrieve_all=True, **_params): """Fetches a list of all address scopes for a project.""" return self.list('address_scopes', self.address_scopes_path, retrieve_all, **_params) def show_address_scope(self, address_scope, **_params): """Fetches information of a certain address scope.""" return self.get(self.address_scope_path % (address_scope), params=_params) def create_address_scope(self, body=None): """Creates a new address scope.""" return self.post(self.address_scopes_path, body=body) def update_address_scope(self, address_scope, body=None): """Updates a address scope.""" return self.put(self.address_scope_path % (address_scope), body=body) def delete_address_scope(self, address_scope): """Deletes the specified address scope.""" return self.delete(self.address_scope_path % (address_scope)) def add_interface_router(self, router, body=None): """Adds an internal network interface to the specified router.""" return self.put((self.router_path % router) + "/add_router_interface", body=body) def remove_interface_router(self, router, body=None): """Removes an internal network interface from the specified router.""" return self.put((self.router_path % router) + "/remove_router_interface", body=body) def add_extra_routes_to_router(self, router, body=None): """Adds extra routes to the specified router.""" return self.put((self.router_path % router) + "/add_extraroutes", body=body) def remove_extra_routes_from_router(self, router, body=None): """Removes extra routes from the specified router.""" return self.put((self.router_path % router) + "/remove_extraroutes", body=body) def add_gateway_router(self, router, body=None): """Adds an external network gateway to the specified router.""" return self.put((self.router_path % router), body={'router': {'external_gateway_info': body}}) def remove_gateway_router(self, router): """Removes an external network gateway from the specified router.""" return self.put((self.router_path % router), body={'router': {'external_gateway_info': {}}}) def list_floatingips(self, retrieve_all=True, **_params): """Fetches a list of all floatingips for a project.""" # Pass filters in "params" argument to do_request return self.list('floatingips', self.floatingips_path, retrieve_all, **_params) def show_floatingip(self, floatingip, **_params): """Fetches information of a certain floatingip.""" return self.get(self.floatingip_path % (floatingip), params=_params) def create_floatingip(self, body=None): """Creates a new floatingip.""" return self.post(self.floatingips_path, body=body) def update_floatingip(self, floatingip, body=None, revision_number=None): """Updates a floatingip.""" return self._update_resource(self.floatingip_path % (floatingip), body=body, revision_number=revision_number) def delete_floatingip(self, floatingip): """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) def update_security_group(self, security_group, body=None, revision_number=None): """Updates a security group.""" return self._update_resource(self.security_group_path % security_group, body=body, revision_number=revision_number) def list_security_groups(self, retrieve_all=True, **_params): """Fetches a list of all security groups for a project.""" return self.list('security_groups', self.security_groups_path, retrieve_all, **_params) def show_security_group(self, security_group, **_params): """Fetches information of a certain security group.""" return self.get(self.security_group_path % (security_group), params=_params) def delete_security_group(self, security_group): """Deletes the specified security group.""" return self.delete(self.security_group_path % (security_group)) def create_security_group_rule(self, body=None): """Creates a new security group rule.""" return self.post(self.security_group_rules_path, body=body) def delete_security_group_rule(self, security_group_rule): """Deletes the specified security group rule.""" return self.delete(self.security_group_rule_path % (security_group_rule)) def list_security_group_rules(self, retrieve_all=True, **_params): """Fetches a list of all security group rules for a project.""" return self.list('security_group_rules', self.security_group_rules_path, retrieve_all, **_params) def show_security_group_rule(self, security_group_rule, **_params): """Fetches information of a certain security group rule.""" return self.get(self.security_group_rule_path % (security_group_rule), params=_params) def create_segment(self, body=None): """Creates a new segment.""" return self.post(self.segments_path, body=body) def update_segment(self, segment, body=None, revision_number=None): """Updates a segment.""" return self._update_resource(self.segment_path % segment, body=body, revision_number=revision_number) def list_segments(self, retrieve_all=True, **_params): """Fetches a list of all segments for a project.""" return self.list('segments', self.segments_path, retrieve_all, **_params) def show_segment(self, segment, **_params): """Fetches information of a certain segment.""" return self.get(self.segment_path % segment, params=_params) def delete_segment(self, segment): """Deletes the specified segment.""" return self.delete(self.segment_path % segment) def list_endpoint_groups(self, retrieve_all=True, **_params): """Fetches a list of all VPN endpoint groups for a project.""" return self.list('endpoint_groups', self.endpoint_groups_path, retrieve_all, **_params) def show_endpoint_group(self, endpointgroup, **_params): """Fetches information for a specific VPN endpoint group.""" return self.get(self.endpoint_group_path % endpointgroup, params=_params) def create_endpoint_group(self, body=None): """Creates a new VPN endpoint group.""" return self.post(self.endpoint_groups_path, body=body) def update_endpoint_group(self, endpoint_group, body=None): """Updates a VPN endpoint group.""" return self.put(self.endpoint_group_path % endpoint_group, body=body) def delete_endpoint_group(self, endpoint_group): """Deletes the specified VPN endpoint group.""" return self.delete(self.endpoint_group_path % endpoint_group) def list_vpnservices(self, retrieve_all=True, **_params): """Fetches a list of all configured VPN services for a project.""" return self.list('vpnservices', self.vpnservices_path, retrieve_all, **_params) def show_vpnservice(self, vpnservice, **_params): """Fetches information of a specific VPN service.""" return self.get(self.vpnservice_path % (vpnservice), params=_params) def create_vpnservice(self, body=None): """Creates a new VPN service.""" return self.post(self.vpnservices_path, body=body) def update_vpnservice(self, vpnservice, body=None): """Updates a VPN service.""" return self.put(self.vpnservice_path % (vpnservice), body=body) def delete_vpnservice(self, vpnservice): """Deletes the specified VPN service.""" return self.delete(self.vpnservice_path % (vpnservice)) def list_ipsec_site_connections(self, retrieve_all=True, **_params): """Fetches all configured IPsecSiteConnections for a project.""" return self.list('ipsec_site_connections', self.ipsec_site_connections_path, retrieve_all, **_params) def show_ipsec_site_connection(self, ipsecsite_conn, **_params): """Fetches information of a specific IPsecSiteConnection.""" return self.get( self.ipsec_site_connection_path % (ipsecsite_conn), params=_params ) def create_ipsec_site_connection(self, body=None): """Creates a new IPsecSiteConnection.""" return self.post(self.ipsec_site_connections_path, body=body) def update_ipsec_site_connection(self, ipsecsite_conn, body=None): """Updates an IPsecSiteConnection.""" return self.put( self.ipsec_site_connection_path % (ipsecsite_conn), body=body ) def delete_ipsec_site_connection(self, ipsecsite_conn): """Deletes the specified IPsecSiteConnection.""" return self.delete(self.ipsec_site_connection_path % (ipsecsite_conn)) def list_ikepolicies(self, retrieve_all=True, **_params): """Fetches a list of all configured IKEPolicies for a project.""" return self.list('ikepolicies', self.ikepolicies_path, retrieve_all, **_params) def show_ikepolicy(self, ikepolicy, **_params): """Fetches information of a specific IKEPolicy.""" return self.get(self.ikepolicy_path % (ikepolicy), params=_params) def create_ikepolicy(self, body=None): """Creates a new IKEPolicy.""" return self.post(self.ikepolicies_path, body=body) def update_ikepolicy(self, ikepolicy, body=None): """Updates an IKEPolicy.""" return self.put(self.ikepolicy_path % (ikepolicy), body=body) def delete_ikepolicy(self, ikepolicy): """Deletes the specified IKEPolicy.""" return self.delete(self.ikepolicy_path % (ikepolicy)) def list_ipsecpolicies(self, retrieve_all=True, **_params): """Fetches a list of all configured IPsecPolicies for a project.""" return self.list('ipsecpolicies', self.ipsecpolicies_path, retrieve_all, **_params) def show_ipsecpolicy(self, ipsecpolicy, **_params): """Fetches information of a specific IPsecPolicy.""" return self.get(self.ipsecpolicy_path % (ipsecpolicy), params=_params) def create_ipsecpolicy(self, body=None): """Creates a new IPsecPolicy.""" return self.post(self.ipsecpolicies_path, body=body) def update_ipsecpolicy(self, ipsecpolicy, body=None): """Updates an IPsecPolicy.""" return self.put(self.ipsecpolicy_path % (ipsecpolicy), body=body) def delete_ipsecpolicy(self, ipsecpolicy): """Deletes the specified IPsecPolicy.""" return self.delete(self.ipsecpolicy_path % (ipsecpolicy)) def list_loadbalancers(self, retrieve_all=True, **_params): """Fetches a list of all loadbalancers for a project.""" return self.list('loadbalancers', self.lbaas_loadbalancers_path, retrieve_all, **_params) def show_loadbalancer(self, lbaas_loadbalancer, **_params): """Fetches information for a load balancer.""" return self.get(self.lbaas_loadbalancer_path % (lbaas_loadbalancer), params=_params) def create_loadbalancer(self, body=None): """Creates a new load balancer.""" return self.post(self.lbaas_loadbalancers_path, body=body) def update_loadbalancer(self, lbaas_loadbalancer, body=None): """Updates a load balancer.""" return self.put(self.lbaas_loadbalancer_path % (lbaas_loadbalancer), body=body) def delete_loadbalancer(self, lbaas_loadbalancer): """Deletes the specified load balancer.""" return self.delete(self.lbaas_loadbalancer_path % (lbaas_loadbalancer)) def retrieve_loadbalancer_stats(self, loadbalancer, **_params): """Retrieves stats for a certain load balancer.""" return self.get(self.lbaas_loadbalancer_path_stats % (loadbalancer), params=_params) def retrieve_loadbalancer_status(self, loadbalancer, **_params): """Retrieves status for a certain load balancer.""" return self.get(self.lbaas_loadbalancer_path_status % (loadbalancer), params=_params) def list_listeners(self, retrieve_all=True, **_params): """Fetches a list of all lbaas_listeners for a project.""" return self.list('listeners', self.lbaas_listeners_path, retrieve_all, **_params) def show_listener(self, lbaas_listener, **_params): """Fetches information for a lbaas_listener.""" return self.get(self.lbaas_listener_path % (lbaas_listener), params=_params) def create_listener(self, body=None): """Creates a new lbaas_listener.""" return self.post(self.lbaas_listeners_path, body=body) def update_listener(self, lbaas_listener, body=None): """Updates a lbaas_listener.""" return self.put(self.lbaas_listener_path % (lbaas_listener), body=body) def delete_listener(self, lbaas_listener): """Deletes the specified lbaas_listener.""" return self.delete(self.lbaas_listener_path % (lbaas_listener)) def list_lbaas_l7policies(self, retrieve_all=True, **_params): """Fetches a list of all L7 policies for a listener.""" return self.list('l7policies', self.lbaas_l7policies_path, retrieve_all, **_params) def show_lbaas_l7policy(self, l7policy, **_params): """Fetches information of a certain listener's L7 policy.""" return self.get(self.lbaas_l7policy_path % l7policy, params=_params) def create_lbaas_l7policy(self, body=None): """Creates L7 policy for a certain listener.""" return self.post(self.lbaas_l7policies_path, body=body) def update_lbaas_l7policy(self, l7policy, body=None): """Updates L7 policy.""" return self.put(self.lbaas_l7policy_path % l7policy, body=body) def delete_lbaas_l7policy(self, l7policy): """Deletes the specified L7 policy.""" return self.delete(self.lbaas_l7policy_path % l7policy) def list_lbaas_l7rules(self, l7policy, retrieve_all=True, **_params): """Fetches a list of all rules for L7 policy.""" return self.list('rules', self.lbaas_l7rules_path % l7policy, retrieve_all, **_params) def show_lbaas_l7rule(self, l7rule, l7policy, **_params): """Fetches information of a certain L7 policy's rule.""" return self.get(self.lbaas_l7rule_path % (l7policy, l7rule), params=_params) def create_lbaas_l7rule(self, l7policy, body=None): """Creates rule for a certain L7 policy.""" return self.post(self.lbaas_l7rules_path % l7policy, body=body) def update_lbaas_l7rule(self, l7rule, l7policy, body=None): """Updates L7 rule.""" return self.put(self.lbaas_l7rule_path % (l7policy, l7rule), body=body) def delete_lbaas_l7rule(self, l7rule, l7policy): """Deletes the specified L7 rule.""" return self.delete(self.lbaas_l7rule_path % (l7policy, l7rule)) def list_lbaas_pools(self, retrieve_all=True, **_params): """Fetches a list of all lbaas_pools for a project.""" return self.list('pools', self.lbaas_pools_path, retrieve_all, **_params) def show_lbaas_pool(self, lbaas_pool, **_params): """Fetches information for a lbaas_pool.""" return self.get(self.lbaas_pool_path % (lbaas_pool), params=_params) def create_lbaas_pool(self, body=None): """Creates a new lbaas_pool.""" return self.post(self.lbaas_pools_path, body=body) def update_lbaas_pool(self, lbaas_pool, body=None): """Updates a lbaas_pool.""" return self.put(self.lbaas_pool_path % (lbaas_pool), body=body) def delete_lbaas_pool(self, lbaas_pool): """Deletes the specified lbaas_pool.""" return self.delete(self.lbaas_pool_path % (lbaas_pool)) def list_lbaas_healthmonitors(self, retrieve_all=True, **_params): """Fetches a list of all lbaas_healthmonitors for a project.""" return self.list('healthmonitors', self.lbaas_healthmonitors_path, retrieve_all, **_params) def show_lbaas_healthmonitor(self, lbaas_healthmonitor, **_params): """Fetches information for a lbaas_healthmonitor.""" return self.get(self.lbaas_healthmonitor_path % (lbaas_healthmonitor), params=_params) def create_lbaas_healthmonitor(self, body=None): """Creates a new lbaas_healthmonitor.""" return self.post(self.lbaas_healthmonitors_path, body=body) def update_lbaas_healthmonitor(self, lbaas_healthmonitor, body=None): """Updates a lbaas_healthmonitor.""" return self.put(self.lbaas_healthmonitor_path % (lbaas_healthmonitor), body=body) def delete_lbaas_healthmonitor(self, lbaas_healthmonitor): """Deletes the specified lbaas_healthmonitor.""" return self.delete(self.lbaas_healthmonitor_path % (lbaas_healthmonitor)) def list_lbaas_loadbalancers(self, retrieve_all=True, **_params): """Fetches a list of all lbaas_loadbalancers for a project.""" return self.list('loadbalancers', self.lbaas_loadbalancers_path, retrieve_all, **_params) def list_lbaas_members(self, lbaas_pool, retrieve_all=True, **_params): """Fetches a list of all lbaas_members for a project.""" return self.list('members', self.lbaas_members_path % lbaas_pool, retrieve_all, **_params) def show_lbaas_member(self, lbaas_member, lbaas_pool, **_params): """Fetches information of a certain lbaas_member.""" return self.get(self.lbaas_member_path % (lbaas_pool, lbaas_member), params=_params) def create_lbaas_member(self, lbaas_pool, body=None): """Creates a lbaas_member.""" return self.post(self.lbaas_members_path % lbaas_pool, body=body) def update_lbaas_member(self, lbaas_member, lbaas_pool, body=None): """Updates a lbaas_member.""" return self.put(self.lbaas_member_path % (lbaas_pool, lbaas_member), body=body) def delete_lbaas_member(self, lbaas_member, lbaas_pool): """Deletes the specified lbaas_member.""" return self.delete(self.lbaas_member_path % (lbaas_pool, lbaas_member)) def list_vips(self, retrieve_all=True, **_params): """Fetches a list of all load balancer vips for a project.""" # Pass filters in "params" argument to do_request return self.list('vips', self.vips_path, retrieve_all, **_params) def show_vip(self, vip, **_params): """Fetches information of a certain load balancer vip.""" return self.get(self.vip_path % (vip), params=_params) def create_vip(self, body=None): """Creates a new load balancer vip.""" return self.post(self.vips_path, body=body) def update_vip(self, vip, body=None): """Updates a load balancer vip.""" return self.put(self.vip_path % (vip), body=body) def delete_vip(self, vip): """Deletes the specified load balancer vip.""" return self.delete(self.vip_path % (vip)) def list_pools(self, retrieve_all=True, **_params): """Fetches a list of all load balancer pools for a project.""" # Pass filters in "params" argument to do_request return self.list('pools', self.pools_path, retrieve_all, **_params) def show_pool(self, pool, **_params): """Fetches information of a certain load balancer pool.""" return self.get(self.pool_path % (pool), params=_params) def create_pool(self, body=None): """Creates a new load balancer pool.""" return self.post(self.pools_path, body=body) def update_pool(self, pool, body=None): """Updates a load balancer pool.""" return self.put(self.pool_path % (pool), body=body) def delete_pool(self, pool): """Deletes the specified load balancer pool.""" return self.delete(self.pool_path % (pool)) def retrieve_pool_stats(self, pool, **_params): """Retrieves stats for a certain load balancer pool.""" return self.get(self.pool_path_stats % (pool), params=_params) def list_members(self, retrieve_all=True, **_params): """Fetches a list of all load balancer members for a project.""" # Pass filters in "params" argument to do_request return self.list('members', self.members_path, retrieve_all, **_params) def show_member(self, member, **_params): """Fetches information of a certain load balancer member.""" return self.get(self.member_path % (member), params=_params) def create_member(self, body=None): """Creates a new load balancer member.""" return self.post(self.members_path, body=body) def update_member(self, member, body=None): """Updates a load balancer member.""" return self.put(self.member_path % (member), body=body) def delete_member(self, member): """Deletes the specified load balancer member.""" return self.delete(self.member_path % (member)) def list_health_monitors(self, retrieve_all=True, **_params): """Fetches a list of all load balancer health monitors for a project. """ # Pass filters in "params" argument to do_request return self.list('health_monitors', self.health_monitors_path, retrieve_all, **_params) def show_health_monitor(self, health_monitor, **_params): """Fetches information of a certain load balancer health monitor.""" return self.get(self.health_monitor_path % (health_monitor), params=_params) def create_health_monitor(self, body=None): """Creates a new load balancer health monitor.""" return self.post(self.health_monitors_path, body=body) def update_health_monitor(self, health_monitor, body=None): """Updates a load balancer health monitor.""" return self.put(self.health_monitor_path % (health_monitor), body=body) def delete_health_monitor(self, health_monitor): """Deletes the specified load balancer health monitor.""" return self.delete(self.health_monitor_path % (health_monitor)) def associate_health_monitor(self, pool, body): """Associate specified load balancer health monitor and pool.""" return self.post(self.associate_pool_health_monitors_path % (pool), body=body) def disassociate_health_monitor(self, pool, health_monitor): """Disassociate specified load balancer health monitor and pool.""" path = (self.disassociate_pool_health_monitors_path % {'pool': pool, 'health_monitor': health_monitor}) return self.delete(path) def create_qos_queue(self, body=None): """Creates a new queue.""" return self.post(self.qos_queues_path, body=body) def list_qos_queues(self, **_params): """Fetches a list of all queues for a project.""" return self.get(self.qos_queues_path, params=_params) def show_qos_queue(self, queue, **_params): """Fetches information of a certain queue.""" return self.get(self.qos_queue_path % (queue), params=_params) def delete_qos_queue(self, queue): """Deletes the specified queue.""" return self.delete(self.qos_queue_path % (queue)) def list_agents(self, **_params): """Fetches agents.""" # Pass filters in "params" argument to do_request return self.get(self.agents_path, params=_params) def show_agent(self, agent, **_params): """Fetches information of a certain agent.""" return self.get(self.agent_path % (agent), params=_params) def update_agent(self, agent, body=None): """Updates an agent.""" return self.put(self.agent_path % (agent), body=body) def delete_agent(self, agent): """Deletes the specified agent.""" return self.delete(self.agent_path % (agent)) def list_network_gateways(self, **_params): """Retrieve network gateways.""" return self.get(self.network_gateways_path, params=_params) def show_network_gateway(self, gateway_id, **_params): """Fetch a network gateway.""" return self.get(self.network_gateway_path % gateway_id, params=_params) def create_network_gateway(self, body=None): """Create a new network gateway.""" return self.post(self.network_gateways_path, body=body) def update_network_gateway(self, gateway_id, body=None): """Update a network gateway.""" return self.put(self.network_gateway_path % gateway_id, body=body) def delete_network_gateway(self, gateway_id): """Delete the specified network gateway.""" return self.delete(self.network_gateway_path % gateway_id) def connect_network_gateway(self, gateway_id, body=None): """Connect a network gateway to the specified network.""" base_uri = self.network_gateway_path % gateway_id return self.put("%s/connect_network" % base_uri, body=body) def disconnect_network_gateway(self, gateway_id, body=None): """Disconnect a network from the specified gateway.""" base_uri = self.network_gateway_path % gateway_id return self.put("%s/disconnect_network" % base_uri, body=body) def list_gateway_devices(self, **_params): """Retrieve gateway devices.""" return self.get(self.gateway_devices_path, params=_params) def show_gateway_device(self, gateway_device_id, **_params): """Fetch a gateway device.""" return self.get(self.gateway_device_path % gateway_device_id, params=_params) def create_gateway_device(self, body=None): """Create a new gateway device.""" return self.post(self.gateway_devices_path, body=body) def update_gateway_device(self, gateway_device_id, body=None): """Updates a new gateway device.""" return self.put(self.gateway_device_path % gateway_device_id, body=body) def delete_gateway_device(self, gateway_device_id): """Delete the specified gateway device.""" return self.delete(self.gateway_device_path % gateway_device_id) def list_dhcp_agent_hosting_networks(self, network, **_params): """Fetches a list of dhcp agents hosting a network.""" return self.get((self.network_path + self.DHCP_AGENTS) % network, params=_params) def list_networks_on_dhcp_agent(self, dhcp_agent, **_params): """Fetches a list of networks hosted on a DHCP agent.""" return self.get((self.agent_path + self.DHCP_NETS) % dhcp_agent, params=_params) def add_network_to_dhcp_agent(self, dhcp_agent, body=None): """Adds a network to dhcp agent.""" return self.post((self.agent_path + self.DHCP_NETS) % dhcp_agent, body=body) def remove_network_from_dhcp_agent(self, dhcp_agent, network_id): """Remove a network from dhcp agent.""" return self.delete((self.agent_path + self.DHCP_NETS + "/%s") % ( dhcp_agent, network_id)) def list_l3_agent_hosting_routers(self, router, **_params): """Fetches a list of L3 agents hosting a router.""" return self.get((self.router_path + self.L3_AGENTS) % router, params=_params) def list_routers_on_l3_agent(self, l3_agent, **_params): """Fetches a list of routers hosted on an L3 agent.""" return self.get((self.agent_path + self.L3_ROUTERS) % l3_agent, params=_params) def add_router_to_l3_agent(self, l3_agent, body): """Adds a router to L3 agent.""" return self.post((self.agent_path + self.L3_ROUTERS) % l3_agent, body=body) def list_dragents_hosting_bgp_speaker(self, bgp_speaker, **_params): """Fetches a list of Dynamic Routing agents hosting a BGP speaker.""" return self.get((self.bgp_speaker_path + self.BGP_DRAGENTS) % bgp_speaker, params=_params) def add_bgp_speaker_to_dragent(self, bgp_dragent, body): """Adds a BGP speaker to Dynamic Routing agent.""" return self.post((self.agent_path + self.BGP_DRINSTANCES) % bgp_dragent, body=body) def remove_bgp_speaker_from_dragent(self, bgp_dragent, bgpspeaker_id): """Removes a BGP speaker from Dynamic Routing agent.""" return self.delete((self.agent_path + self.BGP_DRINSTANCES + "/%s") % (bgp_dragent, bgpspeaker_id)) def list_bgp_speaker_on_dragent(self, bgp_dragent, **_params): """Fetches a list of BGP speakers hosted by Dynamic Routing agent.""" return self.get((self.agent_path + self.BGP_DRINSTANCES) % bgp_dragent, params=_params) def list_firewall_rules(self, retrieve_all=True, **_params): """Fetches a list of all firewall rules for a project.""" # Pass filters in "params" argument to do_request return self.list('firewall_rules', self.firewall_rules_path, retrieve_all, **_params) def show_firewall_rule(self, firewall_rule, **_params): """Fetches information of a certain firewall rule.""" return self.get(self.firewall_rule_path % (firewall_rule), params=_params) def create_firewall_rule(self, body=None): """Creates a new firewall rule.""" return self.post(self.firewall_rules_path, body=body) def update_firewall_rule(self, firewall_rule, body=None): """Updates a firewall rule.""" return self.put(self.firewall_rule_path % (firewall_rule), body=body) def delete_firewall_rule(self, firewall_rule): """Deletes the specified firewall rule.""" return self.delete(self.firewall_rule_path % (firewall_rule)) def list_firewall_policies(self, retrieve_all=True, **_params): """Fetches a list of all firewall policies for a project.""" # Pass filters in "params" argument to do_request return self.list('firewall_policies', self.firewall_policies_path, retrieve_all, **_params) def show_firewall_policy(self, firewall_policy, **_params): """Fetches information of a certain firewall policy.""" return self.get(self.firewall_policy_path % (firewall_policy), params=_params) def create_firewall_policy(self, body=None): """Creates a new firewall policy.""" return self.post(self.firewall_policies_path, body=body) def update_firewall_policy(self, firewall_policy, body=None): """Updates a firewall policy.""" return self.put(self.firewall_policy_path % (firewall_policy), body=body) def delete_firewall_policy(self, firewall_policy): """Deletes the specified firewall policy.""" return self.delete(self.firewall_policy_path % (firewall_policy)) def firewall_policy_insert_rule(self, firewall_policy, body=None): """Inserts specified rule into firewall policy.""" return self.put(self.firewall_policy_insert_path % (firewall_policy), body=body) def firewall_policy_remove_rule(self, firewall_policy, body=None): """Removes specified rule from firewall policy.""" return self.put(self.firewall_policy_remove_path % (firewall_policy), body=body) def list_firewalls(self, retrieve_all=True, **_params): """Fetches a list of all firewalls for a project.""" # Pass filters in "params" argument to do_request return self.list('firewalls', self.firewalls_path, retrieve_all, **_params) def show_firewall(self, firewall, **_params): """Fetches information of a certain firewall.""" return self.get(self.firewall_path % (firewall), params=_params) def create_firewall(self, body=None): """Creates a new firewall.""" return self.post(self.firewalls_path, body=body) def update_firewall(self, firewall, body=None): """Updates a firewall.""" return self.put(self.firewall_path % (firewall), body=body) def delete_firewall(self, firewall): """Deletes the specified firewall.""" return self.delete(self.firewall_path % (firewall)) def list_fwaas_firewall_groups(self, retrieve_all=True, **_params): """Fetches a list of all firewall groups for a project""" return self.list('firewall_groups', self.fwaas_firewall_groups_path, retrieve_all, **_params) def show_fwaas_firewall_group(self, fwg, **_params): """Fetches information of a certain firewall group""" return self.get(self.fwaas_firewall_group_path % (fwg), params=_params) def create_fwaas_firewall_group(self, body=None): """Creates a new firewall group""" return self.post(self.fwaas_firewall_groups_path, body=body) def update_fwaas_firewall_group(self, fwg, body=None): """Updates a firewall group""" return self.put(self.fwaas_firewall_group_path % (fwg), body=body) def delete_fwaas_firewall_group(self, fwg): """Deletes the specified firewall group""" return self.delete(self.fwaas_firewall_group_path % (fwg)) def list_fwaas_firewall_rules(self, retrieve_all=True, **_params): """Fetches a list of all firewall rules for a project""" # Pass filters in "params" argument to do_request return self.list('firewall_rules', self.fwaas_firewall_rules_path, retrieve_all, **_params) def show_fwaas_firewall_rule(self, firewall_rule, **_params): """Fetches information of a certain firewall rule""" return self.get(self.fwaas_firewall_rule_path % (firewall_rule), params=_params) def create_fwaas_firewall_rule(self, body=None): """Creates a new firewall rule""" return self.post(self.fwaas_firewall_rules_path, body=body) def update_fwaas_firewall_rule(self, firewall_rule, body=None): """Updates a firewall rule""" return self.put(self.fwaas_firewall_rule_path % (firewall_rule), body=body) def delete_fwaas_firewall_rule(self, firewall_rule): """Deletes the specified firewall rule""" return self.delete(self.fwaas_firewall_rule_path % (firewall_rule)) def list_fwaas_firewall_policies(self, retrieve_all=True, **_params): """Fetches a list of all firewall policies for a project""" # Pass filters in "params" argument to do_request return self.list('firewall_policies', self.fwaas_firewall_policies_path, retrieve_all, **_params) def show_fwaas_firewall_policy(self, firewall_policy, **_params): """Fetches information of a certain firewall policy""" return self.get(self.fwaas_firewall_policy_path % (firewall_policy), params=_params) def create_fwaas_firewall_policy(self, body=None): """Creates a new firewall policy""" return self.post(self.fwaas_firewall_policies_path, body=body) def update_fwaas_firewall_policy(self, firewall_policy, body=None): """Updates a firewall policy""" return self.put(self.fwaas_firewall_policy_path % (firewall_policy), body=body) def delete_fwaas_firewall_policy(self, firewall_policy): """Deletes the specified firewall policy""" return self.delete(self.fwaas_firewall_policy_path % (firewall_policy)) def insert_rule_fwaas_firewall_policy(self, firewall_policy, body=None): """Inserts specified rule into firewall policy""" return self.put((self.fwaas_firewall_policy_insert_path % (firewall_policy)), body=body) def remove_rule_fwaas_firewall_policy(self, firewall_policy, body=None): """Removes specified rule from firewall policy""" return self.put((self.fwaas_firewall_policy_remove_path % (firewall_policy)), body=body) def remove_router_from_l3_agent(self, l3_agent, router_id): """Remove a router from l3 agent.""" return self.delete((self.agent_path + self.L3_ROUTERS + "/%s") % ( l3_agent, router_id)) def get_lbaas_agent_hosting_pool(self, pool, **_params): """Fetches a loadbalancer agent hosting a pool.""" return self.get((self.pool_path + self.LOADBALANCER_AGENT) % pool, params=_params) def list_pools_on_lbaas_agent(self, lbaas_agent, **_params): """Fetches a list of pools hosted by the loadbalancer agent.""" return self.get((self.agent_path + self.LOADBALANCER_POOLS) % lbaas_agent, params=_params) def get_lbaas_agent_hosting_loadbalancer(self, loadbalancer, **_params): """Fetches a loadbalancer agent hosting a loadbalancer.""" return self.get((self.lbaas_loadbalancer_path + self.LOADBALANCER_HOSTING_AGENT) % loadbalancer, params=_params) def list_loadbalancers_on_lbaas_agent(self, lbaas_agent, **_params): """Fetches a list of loadbalancers hosted by the loadbalancer agent.""" return self.get((self.agent_path + self.AGENT_LOADBALANCERS) % lbaas_agent, params=_params) def list_service_providers(self, retrieve_all=True, **_params): """Fetches service providers.""" # Pass filters in "params" argument to do_request return self.list('service_providers', self.service_providers_path, retrieve_all, **_params) def create_metering_label(self, body=None): """Creates a metering label.""" return self.post(self.metering_labels_path, body=body) def delete_metering_label(self, label): """Deletes the specified metering label.""" return self.delete(self.metering_label_path % (label)) def list_metering_labels(self, retrieve_all=True, **_params): """Fetches a list of all metering labels for a project.""" return self.list('metering_labels', self.metering_labels_path, retrieve_all, **_params) def show_metering_label(self, metering_label, **_params): """Fetches information of a certain metering label.""" return self.get(self.metering_label_path % (metering_label), params=_params) def create_metering_label_rule(self, body=None): """Creates a metering label rule.""" return self.post(self.metering_label_rules_path, body=body) def delete_metering_label_rule(self, rule): """Deletes the specified metering label rule.""" return self.delete(self.metering_label_rule_path % (rule)) def list_metering_label_rules(self, retrieve_all=True, **_params): """Fetches a list of all metering label rules for a label.""" return self.list('metering_label_rules', self.metering_label_rules_path, retrieve_all, **_params) def show_metering_label_rule(self, metering_label_rule, **_params): """Fetches information of a certain metering label rule.""" return self.get(self.metering_label_rule_path % (metering_label_rule), params=_params) def create_rbac_policy(self, body=None): """Create a new RBAC policy.""" return self.post(self.rbac_policies_path, body=body) def update_rbac_policy(self, rbac_policy_id, body=None): """Update a RBAC policy.""" return self.put(self.rbac_policy_path % rbac_policy_id, body=body) def list_rbac_policies(self, retrieve_all=True, **_params): """Fetch a list of all RBAC policies for a project.""" return self.list('rbac_policies', self.rbac_policies_path, retrieve_all, **_params) def show_rbac_policy(self, rbac_policy_id, **_params): """Fetch information of a certain RBAC policy.""" return self.get(self.rbac_policy_path % rbac_policy_id, params=_params) def delete_rbac_policy(self, rbac_policy_id): """Delete the specified RBAC policy.""" return self.delete(self.rbac_policy_path % rbac_policy_id) def list_qos_policies(self, retrieve_all=True, **_params): """Fetches a list of all qos policies for a project.""" # Pass filters in "params" argument to do_request return self.list('policies', self.qos_policies_path, retrieve_all, **_params) def show_qos_policy(self, qos_policy, **_params): """Fetches information of a certain qos policy.""" return self.get(self.qos_policy_path % qos_policy, params=_params) def create_qos_policy(self, body=None): """Creates a new qos policy.""" return self.post(self.qos_policies_path, body=body) def update_qos_policy(self, qos_policy, body=None, revision_number=None): """Updates a qos policy.""" return self._update_resource(self.qos_policy_path % qos_policy, body=body, revision_number=revision_number) def delete_qos_policy(self, qos_policy): """Deletes the specified qos policy.""" return self.delete(self.qos_policy_path % qos_policy) def list_qos_rule_types(self, retrieve_all=True, **_params): """List available qos rule types.""" return self.list('rule_types', self.qos_rule_types_path, retrieve_all, **_params) def list_bandwidth_limit_rules(self, policy_id, retrieve_all=True, **_params): """Fetches a list of all bandwidth limit rules for the given policy.""" return self.list('bandwidth_limit_rules', self.qos_bandwidth_limit_rules_path % policy_id, retrieve_all, **_params) def show_bandwidth_limit_rule(self, rule, policy, **_params): """Fetches information of a certain bandwidth limit rule.""" return self.get(self.qos_bandwidth_limit_rule_path % (policy, rule), params=_params) def create_bandwidth_limit_rule(self, policy, body=None): """Creates a new bandwidth limit rule.""" return self.post(self.qos_bandwidth_limit_rules_path % policy, body=body) def update_bandwidth_limit_rule(self, rule, policy, body=None): """Updates a bandwidth limit rule.""" return self.put(self.qos_bandwidth_limit_rule_path % (policy, rule), body=body) def delete_bandwidth_limit_rule(self, rule, policy): """Deletes a bandwidth limit rule.""" return self.delete(self.qos_bandwidth_limit_rule_path % (policy, rule)) def list_dscp_marking_rules(self, policy_id, retrieve_all=True, **_params): """Fetches a list of all DSCP marking rules for the given policy.""" return self.list('dscp_marking_rules', self.qos_dscp_marking_rules_path % policy_id, retrieve_all, **_params) def show_dscp_marking_rule(self, rule, policy, **_params): """Shows information of a certain DSCP marking rule.""" return self.get(self.qos_dscp_marking_rule_path % (policy, rule), params=_params) def create_dscp_marking_rule(self, policy, body=None): """Creates a new DSCP marking rule.""" return self.post(self.qos_dscp_marking_rules_path % policy, body=body) def update_dscp_marking_rule(self, rule, policy, body=None): """Updates a DSCP marking rule.""" return self.put(self.qos_dscp_marking_rule_path % (policy, rule), body=body) def delete_dscp_marking_rule(self, rule, policy): """Deletes a DSCP marking rule.""" return self.delete(self.qos_dscp_marking_rule_path % (policy, rule)) def list_minimum_bandwidth_rules(self, policy_id, retrieve_all=True, **_params): """Fetches a list of all minimum bandwidth rules for the given policy. """ return self.list('minimum_bandwidth_rules', self.qos_minimum_bandwidth_rules_path % policy_id, retrieve_all, **_params) def show_minimum_bandwidth_rule(self, rule, policy, body=None): """Fetches information of a certain minimum bandwidth rule.""" return self.get(self.qos_minimum_bandwidth_rule_path % (policy, rule), body=body) def create_minimum_bandwidth_rule(self, policy, body=None): """Creates a new minimum bandwidth rule.""" 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 % (policy, rule), body=body) def delete_minimum_bandwidth_rule(self, rule, policy): """Deletes a minimum bandwidth rule.""" 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) def delete_flavor(self, flavor): """Deletes the specified Neutron service flavor.""" return self.delete(self.flavor_path % (flavor)) def list_flavors(self, retrieve_all=True, **_params): """Fetches a list of all Neutron service flavors for a project.""" return self.list('flavors', self.flavors_path, retrieve_all, **_params) def show_flavor(self, flavor, **_params): """Fetches information for a certain Neutron service flavor.""" return self.get(self.flavor_path % (flavor), params=_params) def update_flavor(self, flavor, body): """Update a Neutron service flavor.""" return self.put(self.flavor_path % (flavor), body=body) def associate_flavor(self, flavor, body): """Associate a Neutron service flavor with a profile.""" return self.post(self.flavor_profile_bindings_path % (flavor), body=body) def disassociate_flavor(self, flavor, flavor_profile): """Disassociate a Neutron service flavor with a profile.""" return self.delete(self.flavor_profile_binding_path % (flavor, flavor_profile)) def create_service_profile(self, body=None): """Creates a new Neutron service flavor profile.""" return self.post(self.service_profiles_path, body=body) def delete_service_profile(self, flavor_profile): """Deletes the specified Neutron service flavor profile.""" return self.delete(self.service_profile_path % (flavor_profile)) def list_service_profiles(self, retrieve_all=True, **_params): """Fetches a list of all Neutron service flavor profiles.""" return self.list('service_profiles', self.service_profiles_path, retrieve_all, **_params) def show_service_profile(self, flavor_profile, **_params): """Fetches information for a certain Neutron service flavor profile.""" return self.get(self.service_profile_path % (flavor_profile), params=_params) def update_service_profile(self, service_profile, body): """Update a Neutron service profile.""" return self.put(self.service_profile_path % (service_profile), body=body) def list_availability_zones(self, retrieve_all=True, **_params): """Fetches a list of all availability zones.""" return self.list('availability_zones', self.availability_zones_path, retrieve_all, **_params) @debtcollector.renames.renamed_kwarg( 'tenant_id', 'project_id', replace=True) def get_auto_allocated_topology(self, project_id, **_params): """Fetch information about a project's auto-allocated topology.""" return self.get( self.auto_allocated_topology_path % project_id, params=_params) @debtcollector.renames.renamed_kwarg( 'tenant_id', 'project_id', replace=True) def delete_auto_allocated_topology(self, project_id, **_params): """Delete a project's auto-allocated topology.""" return self.delete( self.auto_allocated_topology_path % project_id, params=_params) @debtcollector.renames.renamed_kwarg( 'tenant_id', 'project_id', replace=True) def validate_auto_allocated_topology_requirements(self, project_id): """Validate requirements for getting an auto-allocated topology.""" return self.get_auto_allocated_topology(project_id, fields=['dry-run']) def list_bgp_speakers(self, retrieve_all=True, **_params): """Fetches a list of all BGP speakers for a project.""" return self.list('bgp_speakers', self.bgp_speakers_path, retrieve_all, **_params) def show_bgp_speaker(self, bgp_speaker_id, **_params): """Fetches information of a certain BGP speaker.""" return self.get(self.bgp_speaker_path % (bgp_speaker_id), params=_params) def create_bgp_speaker(self, body=None): """Creates a new BGP speaker.""" return self.post(self.bgp_speakers_path, body=body) def update_bgp_speaker(self, bgp_speaker_id, body=None): """Update a BGP speaker.""" return self.put(self.bgp_speaker_path % bgp_speaker_id, body=body) def delete_bgp_speaker(self, speaker_id): """Deletes the specified BGP speaker.""" return self.delete(self.bgp_speaker_path % (speaker_id)) def add_peer_to_bgp_speaker(self, speaker_id, body=None): """Adds a peer to BGP speaker.""" return self.put((self.bgp_speaker_path % speaker_id) + "/add_bgp_peer", body=body) def remove_peer_from_bgp_speaker(self, speaker_id, body=None): """Removes a peer from BGP speaker.""" return self.put((self.bgp_speaker_path % speaker_id) + "/remove_bgp_peer", body=body) def add_network_to_bgp_speaker(self, speaker_id, body=None): """Adds a network to BGP speaker.""" return self.put((self.bgp_speaker_path % speaker_id) + "/add_gateway_network", body=body) def remove_network_from_bgp_speaker(self, speaker_id, body=None): """Removes a network from BGP speaker.""" return self.put((self.bgp_speaker_path % speaker_id) + "/remove_gateway_network", body=body) def list_route_advertised_from_bgp_speaker(self, speaker_id, **_params): """Fetches a list of all routes advertised by BGP speaker.""" return self.get((self.bgp_speaker_path % speaker_id) + "/get_advertised_routes", params=_params) def list_bgp_peers(self, **_params): """Fetches a list of all BGP peers.""" return self.get(self.bgp_peers_path, params=_params) def show_bgp_peer(self, peer_id, **_params): """Fetches information of a certain BGP peer.""" return self.get(self.bgp_peer_path % peer_id, params=_params) def create_bgp_peer(self, body=None): """Create a new BGP peer.""" return self.post(self.bgp_peers_path, body=body) def update_bgp_peer(self, bgp_peer_id, body=None): """Update a BGP peer.""" return self.put(self.bgp_peer_path % bgp_peer_id, body=body) def delete_bgp_peer(self, peer_id): """Deletes the specified BGP peer.""" return self.delete(self.bgp_peer_path % peer_id) def list_network_ip_availabilities(self, retrieve_all=True, **_params): """Fetches IP availability information for all networks""" return self.list('network_ip_availabilities', self.network_ip_availabilities_path, retrieve_all, **_params) def show_network_ip_availability(self, network, **_params): """Fetches IP availability information for a specified network""" return self.get(self.network_ip_availability_path % (network), params=_params) def add_tag(self, resource_type, resource_id, tag, **_params): """Add a tag on the resource.""" return self.put(self.tag_path % (resource_type, resource_id, tag)) def replace_tag(self, resource_type, resource_id, body, **_params): """Replace tags on the resource.""" return self.put(self.tags_path % (resource_type, resource_id), body) def remove_tag(self, resource_type, resource_id, tag, **_params): """Remove a tag on the resource.""" return self.delete(self.tag_path % (resource_type, resource_id, tag)) def remove_tag_all(self, resource_type, resource_id, **_params): """Remove all tags on the resource.""" return self.delete(self.tags_path % (resource_type, resource_id)) def create_trunk(self, body=None): """Create a trunk port.""" return self.post(self.trunks_path, body=body) def update_trunk(self, trunk, body=None, revision_number=None): """Update a trunk port.""" return self._update_resource(self.trunk_path % trunk, body=body, revision_number=revision_number) def delete_trunk(self, trunk): """Delete a trunk port.""" return self.delete(self.trunk_path % (trunk)) def list_trunks(self, retrieve_all=True, **_params): """Fetch a list of all trunk ports.""" return self.list('trunks', self.trunks_path, retrieve_all, **_params) def show_trunk(self, trunk, **_params): """Fetch information for a certain trunk port.""" return self.get(self.trunk_path % (trunk), params=_params) def trunk_add_subports(self, trunk, body=None): """Add specified subports to the trunk.""" return self.put(self.subports_add_path % (trunk), body=body) def trunk_remove_subports(self, trunk, body=None): """Removes specified subports from the trunk.""" return self.put(self.subports_remove_path % (trunk), body=body) def trunk_get_subports(self, trunk, **_params): """Fetch a list of all subports attached to given trunk.""" return self.get(self.subports_path % (trunk), params=_params) def list_bgpvpns(self, retrieve_all=True, **_params): """Fetches a list of all BGP VPNs for a project""" return self.list('bgpvpns', self.bgpvpns_path, retrieve_all, **_params) def show_bgpvpn(self, bgpvpn, **_params): """Fetches information of a certain BGP VPN""" return self.get(self.bgpvpn_path % bgpvpn, params=_params) def create_bgpvpn(self, body=None): """Creates a new BGP VPN""" return self.post(self.bgpvpns_path, body=body) def update_bgpvpn(self, bgpvpn, body=None): """Updates a BGP VPN""" return self.put(self.bgpvpn_path % bgpvpn, body=body) def delete_bgpvpn(self, bgpvpn): """Deletes the specified BGP VPN""" return self.delete(self.bgpvpn_path % bgpvpn) def list_bgpvpn_network_assocs(self, bgpvpn, retrieve_all=True, **_params): """Fetches a list of network associations for a given BGP VPN.""" return self.list('network_associations', self.bgpvpn_network_associations_path % bgpvpn, retrieve_all, **_params) def show_bgpvpn_network_assoc(self, bgpvpn, net_assoc, **_params): """Fetches information of a certain BGP VPN's network association""" return self.get( self.bgpvpn_network_association_path % (bgpvpn, net_assoc), params=_params) def create_bgpvpn_network_assoc(self, bgpvpn, body=None): """Creates a new BGP VPN network association""" return self.post(self.bgpvpn_network_associations_path % bgpvpn, body=body) def update_bgpvpn_network_assoc(self, bgpvpn, net_assoc, body=None): """Updates a BGP VPN network association""" return self.put( self.bgpvpn_network_association_path % (bgpvpn, net_assoc), body=body) def delete_bgpvpn_network_assoc(self, bgpvpn, net_assoc): """Deletes the specified BGP VPN network association""" return self.delete( self.bgpvpn_network_association_path % (bgpvpn, net_assoc)) def list_bgpvpn_router_assocs(self, bgpvpn, retrieve_all=True, **_params): """Fetches a list of router associations for a given BGP VPN.""" return self.list('router_associations', self.bgpvpn_router_associations_path % bgpvpn, retrieve_all, **_params) def show_bgpvpn_router_assoc(self, bgpvpn, router_assoc, **_params): """Fetches information of a certain BGP VPN's router association""" return self.get( self.bgpvpn_router_association_path % (bgpvpn, router_assoc), params=_params) def create_bgpvpn_router_assoc(self, bgpvpn, body=None): """Creates a new BGP VPN router association""" return self.post(self.bgpvpn_router_associations_path % bgpvpn, body=body) def update_bgpvpn_router_assoc(self, bgpvpn, router_assoc, body=None): """Updates a BGP VPN router association""" return self.put( self.bgpvpn_router_association_path % (bgpvpn, router_assoc), body=body) def delete_bgpvpn_router_assoc(self, bgpvpn, router_assoc): """Deletes the specified BGP VPN router association""" return self.delete( self.bgpvpn_router_association_path % (bgpvpn, router_assoc)) def list_bgpvpn_port_assocs(self, bgpvpn, retrieve_all=True, **_params): """Fetches a list of port associations for a given BGP VPN.""" return self.list('port_associations', self.bgpvpn_port_associations_path % bgpvpn, retrieve_all, **_params) def show_bgpvpn_port_assoc(self, bgpvpn, port_assoc, **_params): """Fetches information of a certain BGP VPN's port association""" return self.get( self.bgpvpn_port_association_path % (bgpvpn, port_assoc), params=_params) def create_bgpvpn_port_assoc(self, bgpvpn, body=None): """Creates a new BGP VPN port association""" return self.post(self.bgpvpn_port_associations_path % bgpvpn, body=body) def update_bgpvpn_port_assoc(self, bgpvpn, port_assoc, body=None): """Updates a BGP VPN port association""" return self.put( self.bgpvpn_port_association_path % (bgpvpn, port_assoc), body=body) def delete_bgpvpn_port_assoc(self, bgpvpn, port_assoc): """Deletes the specified BGP VPN port association""" return self.delete( self.bgpvpn_port_association_path % (bgpvpn, port_assoc)) def create_sfc_port_pair(self, body=None): """Creates a new Port Pair.""" return self.post(self.sfc_port_pairs_path, body=body) def update_sfc_port_pair(self, port_pair, body=None): """Update a Port Pair.""" return self.put(self.sfc_port_pair_path % port_pair, body=body) def delete_sfc_port_pair(self, port_pair): """Deletes the specified Port Pair.""" return self.delete(self.sfc_port_pair_path % (port_pair)) def list_sfc_port_pairs(self, retrieve_all=True, **_params): """Fetches a list of all Port Pairs.""" return self.list('port_pairs', self.sfc_port_pairs_path, retrieve_all, **_params) def show_sfc_port_pair(self, port_pair, **_params): """Fetches information of a certain Port Pair.""" return self.get(self.sfc_port_pair_path % (port_pair), params=_params) def create_sfc_port_pair_group(self, body=None): """Creates a new Port Pair Group.""" return self.post(self.sfc_port_pair_groups_path, body=body) def update_sfc_port_pair_group(self, port_pair_group, body=None): """Update a Port Pair Group.""" return self.put(self.sfc_port_pair_group_path % port_pair_group, body=body) def delete_sfc_port_pair_group(self, port_pair_group): """Deletes the specified Port Pair Group.""" return self.delete(self.sfc_port_pair_group_path % (port_pair_group)) def list_sfc_port_pair_groups(self, retrieve_all=True, **_params): """Fetches a list of all Port Pair Groups.""" return self.list('port_pair_groups', self.sfc_port_pair_groups_path, retrieve_all, **_params) def show_sfc_port_pair_group(self, port_pair_group, **_params): """Fetches information of a certain Port Pair Group.""" return self.get(self.sfc_port_pair_group_path % (port_pair_group), params=_params) def create_sfc_port_chain(self, body=None): """Creates a new Port Chain.""" return self.post(self.sfc_port_chains_path, body=body) def update_sfc_port_chain(self, port_chain, body=None): """Update a Port Chain.""" return self.put(self.sfc_port_chain_path % port_chain, body=body) def delete_sfc_port_chain(self, port_chain): """Deletes the specified Port Chain.""" return self.delete(self.sfc_port_chain_path % (port_chain)) def list_sfc_port_chains(self, retrieve_all=True, **_params): """Fetches a list of all Port Chains.""" return self.list('port_chains', self.sfc_port_chains_path, retrieve_all, **_params) def show_sfc_port_chain(self, port_chain, **_params): """Fetches information of a certain Port Chain.""" return self.get(self.sfc_port_chain_path % (port_chain), params=_params) def create_sfc_flow_classifier(self, body=None): """Creates a new Flow Classifier.""" return self.post(self.sfc_flow_classifiers_path, body=body) def update_sfc_flow_classifier(self, flow_classifier, body=None): """Update a Flow Classifier.""" return self.put(self.sfc_flow_classifier_path % flow_classifier, body=body) def delete_sfc_flow_classifier(self, flow_classifier): """Deletes the specified Flow Classifier.""" return self.delete(self.sfc_flow_classifier_path % (flow_classifier)) def list_sfc_flow_classifiers(self, retrieve_all=True, **_params): """Fetches a list of all Flow Classifiers.""" return self.list('flow_classifiers', self.sfc_flow_classifiers_path, retrieve_all, **_params) def show_sfc_flow_classifier(self, flow_classifier, **_params): """Fetches information of a certain Flow Classifier.""" return self.get(self.sfc_flow_classifier_path % (flow_classifier), params=_params) def create_sfc_service_graph(self, body=None): """Create the specified Service Graph.""" return self.post(self.sfc_service_graphs_path, body=body) def update_sfc_service_graph(self, service_graph, body=None): """Update a Service Graph.""" return self.put(self.sfc_service_graph_path % service_graph, body=body) def delete_sfc_service_graph(self, service_graph): """Deletes the specified Service Graph.""" return self.delete(self.sfc_service_graph_path % service_graph) def list_sfc_service_graphs(self, retrieve_all=True, **_params): """Fetches a list of all Service Graphs.""" return self.list('service_graphs', self.sfc_service_graphs_path, retrieve_all, **_params) def show_sfc_service_graph(self, service_graph, **_params): """Fetches information of a certain Service Graph.""" return self.get(self.sfc_service_graph_path % service_graph, params=_params) def create_network_log(self, body=None): """Create a network log.""" return self.post(self.network_logs_path, body=body) def delete_network_log(self, net_log): """Delete a network log.""" return self.delete(self.network_log_path % net_log) def list_network_logs(self, retrieve_all=True, **_params): """Fetch a list of all network logs.""" return self.list( 'logs', self.network_logs_path, retrieve_all, **_params) def show_network_log(self, net_log, **_params): """Fetch information for a certain network log.""" return self.get(self.network_log_path % net_log, params=_params) def update_network_log(self, net_log, body=None): """Update a network log.""" return self.put(self.network_log_path % net_log, body=body) def list_network_loggable_resources(self, retrieve_all=True, **_params): """Fetch a list of supported resource types for network log.""" return self.list('loggable_resources', self.network_loggables_path, retrieve_all, **_params) def onboard_network_subnets(self, subnetpool, body=None): """Onboard the specified network's subnets into a subnet pool.""" return self.put(self.onboard_network_subnets_path % (subnetpool), body=body) def __init__(self, **kwargs): """Initialize a new client for the Neutron v2.0 API.""" super(Client, self).__init__(**kwargs) self._register_extensions(self.version) def _update_resource(self, path, **kwargs): revision_number = kwargs.pop('revision_number', None) if revision_number: headers = kwargs.setdefault('headers', {}) headers['If-Match'] = 'revision_number=%s' % revision_number return self.put(path, **kwargs) def extend_show(self, resource_singular, path, parent_resource): def _fx(obj, **_params): return self.show_ext(path, obj, **_params) def _parent_fx(obj, parent_id, **_params): return self.show_ext(path % parent_id, obj, **_params) fn = _fx if not parent_resource else _parent_fx setattr(self, "show_%s" % resource_singular, fn) def extend_list(self, resource_plural, path, parent_resource): def _fx(retrieve_all=True, **_params): return self.list_ext(resource_plural, path, retrieve_all, **_params) def _parent_fx(parent_id, retrieve_all=True, **_params): return self.list_ext(resource_plural, path % parent_id, retrieve_all, **_params) fn = _fx if not parent_resource else _parent_fx setattr(self, "list_%s" % resource_plural, fn) def extend_create(self, resource_singular, path, parent_resource): def _fx(body=None): return self.create_ext(path, body) def _parent_fx(parent_id, body=None): return self.create_ext(path % parent_id, body) fn = _fx if not parent_resource else _parent_fx setattr(self, "create_%s" % resource_singular, fn) def extend_delete(self, resource_singular, path, parent_resource): def _fx(obj): return self.delete_ext(path, obj) def _parent_fx(obj, parent_id): return self.delete_ext(path % parent_id, obj) fn = _fx if not parent_resource else _parent_fx setattr(self, "delete_%s" % resource_singular, fn) def extend_update(self, resource_singular, path, parent_resource): def _fx(obj, body=None): return self.update_ext(path, obj, body) def _parent_fx(obj, parent_id, body=None): return self.update_ext(path % parent_id, obj, body) fn = _fx if not parent_resource else _parent_fx setattr(self, "update_%s" % resource_singular, fn) def _extend_client_with_module(self, module, version): classes = inspect.getmembers(module, inspect.isclass) for cls_name, cls in classes: if hasattr(cls, 'versions'): if version not in cls.versions: continue parent_resource = getattr(cls, 'parent_resource', None) if issubclass(cls, client_extension.ClientExtensionList): self.extend_list(cls.resource_plural, cls.object_path, parent_resource) elif issubclass(cls, client_extension.ClientExtensionCreate): self.extend_create(cls.resource, cls.object_path, parent_resource) elif issubclass(cls, client_extension.ClientExtensionUpdate): self.extend_update(cls.resource, cls.resource_path, parent_resource) elif issubclass(cls, client_extension.ClientExtensionDelete): self.extend_delete(cls.resource, cls.resource_path, parent_resource) elif issubclass(cls, client_extension.ClientExtensionShow): self.extend_show(cls.resource, cls.resource_path, parent_resource) elif issubclass(cls, client_extension.NeutronClientExtension): setattr(self, "%s_path" % cls.resource_plural, cls.object_path) setattr(self, "%s_path" % cls.resource, cls.resource_path) self.EXTED_PLURALS.update({cls.resource_plural: cls.resource}) def _register_extensions(self, version): for name, module in itertools.chain( client_extension._discover_via_entry_points()): self._extend_client_with_module(module, version) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/neutronclient/version.py0000664000175000017500000000142600000000000022761 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # 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 pbr.version version_info = pbr.version.VersionInfo('python-neutronclient') __version__ = version_info.version_string() ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1709201317.233663 python-neutronclient-11.2.0/python_neutronclient.egg-info/0000775000175000017500000000000000000000000024012 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201317.0 python-neutronclient-11.2.0/python_neutronclient.egg-info/PKG-INFO0000664000175000017500000000572100000000000025114 0ustar00zuulzuul00000000000000Metadata-Version: 1.2 Name: python-neutronclient Version: 11.2.0 Summary: CLI and Client Library for OpenStack Networking Home-page: https://docs.openstack.org/python-neutronclient/latest/ Author: OpenStack Networking Project Author-email: openstack-discuss@lists.openstack.org License: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: https://governance.openstack.org/tc/badges/python-neutronclient.svg :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on Python bindings to the Neutron API ================================== .. image:: https://img.shields.io/pypi/v/python-neutronclient.svg :target: https://pypi.org/project/python-neutronclient/ :alt: Latest Version This is a client library for Neutron built on the Neutron API. It provides a Python API (the ``neutronclient`` module). .. note:: This project has been deprecated. The CLI code has been deleted and is not accessible anymore. The Python bindings are still in use by other projects but no new features will be added to this project. Any new feature should be proposed to OpenStack SDK and OpenStack Client. * License: Apache License, Version 2.0 * `PyPi`_ - package installation * `Online Documentation`_ * `Launchpad project`_ - release management * `Blueprints`_ - feature specifications * `Bugs`_ - issue tracking * `Source`_ * `Developer's Guide`_ .. _PyPi: https://pypi.org/project/python-neutronclient .. _Online Documentation: https://docs.openstack.org/python-neutronclient/latest/ .. _Launchpad project: https://launchpad.net/python-neutronclient .. _Blueprints: https://blueprints.launchpad.net/python-neutronclient .. _Bugs: https://bugs.launchpad.net/python-neutronclient .. _Source: https://opendev.org/openstack/python-neutronclient .. _Developer's Guide: http://docs.openstack.org/infra/manual/developers.html .. _Release Notes: https://docs.openstack.org/releasenotes/python-neutronclient Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Requires-Python: >=3.8 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201317.0 python-neutronclient-11.2.0/python_neutronclient.egg-info/SOURCES.txt0000664000175000017500000003377500000000000025715 0ustar00zuulzuul00000000000000.coveragerc .pylintrc .stestr.conf .zuul.yaml AUTHORS CONTRIBUTING.rst ChangeLog HACKING.rst LICENSE README.rst requirements.txt setup.cfg setup.py test-requirements.txt tox.ini doc/requirements.txt doc/source/conf.py doc/source/index.rst doc/source/cli/index.rst doc/source/cli/osc_plugins.rst doc/source/cli/osc/v2/bgp-dynamic-routing.rst doc/source/cli/osc/v2/firewall-group.rst doc/source/cli/osc/v2/firewall-policy.rst doc/source/cli/osc/v2/firewall-rule.rst doc/source/cli/osc/v2/network-log.rst doc/source/cli/osc/v2/networking-bgpvpn.rst doc/source/cli/osc/v2/networking-sfc.rst doc/source/cli/osc/v2/subnet-onboard.rst doc/source/cli/osc/v2/vpn-endpoint-group.rst doc/source/cli/osc/v2/vpn-ike-policy.rst doc/source/cli/osc/v2/vpn-ipsec-policy.rst doc/source/cli/osc/v2/vpn-ipsec-site-connection.rst doc/source/cli/osc/v2/vpn-service.rst doc/source/contributor/index.rst doc/source/contributor/transition_to_osc.rst doc/source/reference/index.rst neutronclient/__init__.py neutronclient/_i18n.py neutronclient/client.py neutronclient/version.py neutronclient/common/__init__.py neutronclient/common/clientmanager.py neutronclient/common/constants.py neutronclient/common/exceptions.py neutronclient/common/extension.py neutronclient/common/serializer.py neutronclient/common/utils.py neutronclient/common/validators.py neutronclient/neutron/__init__.py neutronclient/neutron/client.py neutronclient/neutron/v2_0/__init__.py neutronclient/neutron/v2_0/address_scope.py neutronclient/neutron/v2_0/agent.py neutronclient/neutron/v2_0/agentscheduler.py neutronclient/neutron/v2_0/auto_allocated_topology.py neutronclient/neutron/v2_0/availability_zone.py neutronclient/neutron/v2_0/dns.py neutronclient/neutron/v2_0/extension.py neutronclient/neutron/v2_0/floatingip.py neutronclient/neutron/v2_0/metering.py neutronclient/neutron/v2_0/network.py neutronclient/neutron/v2_0/network_ip_availability.py neutronclient/neutron/v2_0/port.py neutronclient/neutron/v2_0/purge.py neutronclient/neutron/v2_0/quota.py neutronclient/neutron/v2_0/rbac.py neutronclient/neutron/v2_0/router.py neutronclient/neutron/v2_0/securitygroup.py neutronclient/neutron/v2_0/servicetype.py neutronclient/neutron/v2_0/subnet.py neutronclient/neutron/v2_0/subnetpool.py neutronclient/neutron/v2_0/tag.py neutronclient/neutron/v2_0/bgp/__init__.py neutronclient/neutron/v2_0/bgp/dragentscheduler.py neutronclient/neutron/v2_0/bgp/peer.py neutronclient/neutron/v2_0/bgp/speaker.py neutronclient/neutron/v2_0/contrib/__init__.py neutronclient/neutron/v2_0/contrib/_fox_sockets.py neutronclient/neutron/v2_0/flavor/__init__.py neutronclient/neutron/v2_0/flavor/flavor.py neutronclient/neutron/v2_0/flavor/flavor_profile.py neutronclient/neutron/v2_0/fw/__init__.py neutronclient/neutron/v2_0/fw/firewall.py neutronclient/neutron/v2_0/fw/firewallpolicy.py neutronclient/neutron/v2_0/fw/firewallrule.py neutronclient/neutron/v2_0/lb/__init__.py neutronclient/neutron/v2_0/lb/healthmonitor.py neutronclient/neutron/v2_0/lb/member.py neutronclient/neutron/v2_0/lb/pool.py neutronclient/neutron/v2_0/lb/vip.py neutronclient/neutron/v2_0/lb/v2/__init__.py neutronclient/neutron/v2_0/lb/v2/healthmonitor.py neutronclient/neutron/v2_0/lb/v2/l7policy.py neutronclient/neutron/v2_0/lb/v2/l7rule.py neutronclient/neutron/v2_0/lb/v2/listener.py neutronclient/neutron/v2_0/lb/v2/loadbalancer.py neutronclient/neutron/v2_0/lb/v2/member.py neutronclient/neutron/v2_0/lb/v2/pool.py neutronclient/neutron/v2_0/qos/__init__.py neutronclient/neutron/v2_0/qos/bandwidth_limit_rule.py neutronclient/neutron/v2_0/qos/dscp_marking_rule.py neutronclient/neutron/v2_0/qos/minimum_bandwidth_rule.py neutronclient/neutron/v2_0/qos/policy.py neutronclient/neutron/v2_0/qos/rule.py neutronclient/neutron/v2_0/vpn/__init__.py neutronclient/neutron/v2_0/vpn/endpoint_group.py neutronclient/neutron/v2_0/vpn/ikepolicy.py neutronclient/neutron/v2_0/vpn/ipsec_site_connection.py neutronclient/neutron/v2_0/vpn/ipsecpolicy.py neutronclient/neutron/v2_0/vpn/utils.py neutronclient/neutron/v2_0/vpn/vpnservice.py neutronclient/osc/__init__.py neutronclient/osc/plugin.py neutronclient/osc/utils.py neutronclient/osc/v2/__init__.py neutronclient/osc/v2/utils.py neutronclient/osc/v2/dynamic_routing/__init__.py neutronclient/osc/v2/dynamic_routing/bgp_dragent.py neutronclient/osc/v2/dynamic_routing/bgp_peer.py neutronclient/osc/v2/dynamic_routing/bgp_speaker.py neutronclient/osc/v2/dynamic_routing/constants.py neutronclient/osc/v2/fwaas/__init__.py neutronclient/osc/v2/fwaas/constants.py neutronclient/osc/v2/fwaas/firewallgroup.py neutronclient/osc/v2/fwaas/firewallpolicy.py neutronclient/osc/v2/fwaas/firewallrule.py neutronclient/osc/v2/lbaas/__init__.py neutronclient/osc/v2/logging/__init__.py neutronclient/osc/v2/logging/network_log.py neutronclient/osc/v2/networking_bgpvpn/__init__.py neutronclient/osc/v2/networking_bgpvpn/bgpvpn.py neutronclient/osc/v2/networking_bgpvpn/constants.py neutronclient/osc/v2/networking_bgpvpn/network_association.py neutronclient/osc/v2/networking_bgpvpn/port_association.py neutronclient/osc/v2/networking_bgpvpn/resource_association.py neutronclient/osc/v2/networking_bgpvpn/router_association.py neutronclient/osc/v2/sfc/__init__.py neutronclient/osc/v2/sfc/sfc_flow_classifier.py neutronclient/osc/v2/sfc/sfc_port_chain.py neutronclient/osc/v2/sfc/sfc_port_pair.py neutronclient/osc/v2/sfc/sfc_port_pair_group.py neutronclient/osc/v2/sfc/sfc_service_graph.py neutronclient/osc/v2/subnet_onboard/__init__.py neutronclient/osc/v2/subnet_onboard/subnet_onboard.py neutronclient/osc/v2/vpnaas/__init__.py neutronclient/osc/v2/vpnaas/endpoint_group.py neutronclient/osc/v2/vpnaas/ikepolicy.py neutronclient/osc/v2/vpnaas/ipsec_site_connection.py neutronclient/osc/v2/vpnaas/ipsecpolicy.py neutronclient/osc/v2/vpnaas/utils.py neutronclient/osc/v2/vpnaas/vpnservice.py neutronclient/tests/__init__.py neutronclient/tests/unit/__init__.py neutronclient/tests/unit/test_casual_args.py neutronclient/tests/unit/test_command_meta.py neutronclient/tests/unit/test_exceptions.py neutronclient/tests/unit/test_http.py neutronclient/tests/unit/test_utils.py neutronclient/tests/unit/test_validators.py neutronclient/tests/unit/osc/__init__.py neutronclient/tests/unit/osc/v2/__init__.py neutronclient/tests/unit/osc/v2/fakes.py neutronclient/tests/unit/osc/v2/dynamic_routing/__init__.py neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_peer.py neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_speaker.py neutronclient/tests/unit/osc/v2/fwaas/__init__.py neutronclient/tests/unit/osc/v2/fwaas/common.py neutronclient/tests/unit/osc/v2/fwaas/fakes.py neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py neutronclient/tests/unit/osc/v2/lbaas/__init__.py neutronclient/tests/unit/osc/v2/logging/__init__.py neutronclient/tests/unit/osc/v2/logging/fakes.py neutronclient/tests/unit/osc/v2/logging/test_network_log.py neutronclient/tests/unit/osc/v2/networking_bgpvpn/__init__.py neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py neutronclient/tests/unit/osc/v2/sfc/__init__.py neutronclient/tests/unit/osc/v2/sfc/fakes.py neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py neutronclient/tests/unit/osc/v2/sfc/test_port_pair.py neutronclient/tests/unit/osc/v2/sfc/test_port_pair_group.py neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py neutronclient/tests/unit/osc/v2/subnet_onboard/__init__.py neutronclient/tests/unit/osc/v2/subnet_onboard/test_network_onboard_subnets.py neutronclient/tests/unit/osc/v2/vpnaas/__init__.py neutronclient/tests/unit/osc/v2/vpnaas/common.py neutronclient/tests/unit/osc/v2/vpnaas/fakes.py neutronclient/tests/unit/osc/v2/vpnaas/test_endpoint_group.py neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py neutronclient/tests/unit/osc/v2/vpnaas/test_ipsec_site_connection.py neutronclient/tests/unit/osc/v2/vpnaas/test_ipsecpolicy.py neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py neutronclient/v2_0/__init__.py neutronclient/v2_0/client.py python_neutronclient.egg-info/PKG-INFO python_neutronclient.egg-info/SOURCES.txt python_neutronclient.egg-info/dependency_links.txt python_neutronclient.egg-info/entry_points.txt python_neutronclient.egg-info/not-zip-safe python_neutronclient.egg-info/pbr.json python_neutronclient.egg-info/requires.txt python_neutronclient.egg-info/top_level.txt releasenotes/notes/.placeholder releasenotes/notes/Define-IpAddressAlreadyAllocatedClient-exception-e8600ca5ba1c7f45.yaml releasenotes/notes/add-aggressive-negotiation-mode-5218b1baff930eb8.yaml releasenotes/notes/add-auto-allocated-topology-delete-aaccd60bd0f2e7b2.yaml releasenotes/notes/add-get-me-a-network-5ab2d60bf6f257b1.yaml releasenotes/notes/add-l7-content-policies-capability-0f17cd06f044c83c.yaml releasenotes/notes/add-lb-status-tree-723f23c09617de3b.yaml releasenotes/notes/add-neutron-purge-a89e3d1179dce4b1.yaml releasenotes/notes/add-new-session-clear-option-3c0b78ebc133a10c.yaml releasenotes/notes/add-no-shared-option-to-qos-policy-update-56ac41fb3af7e309.yaml releasenotes/notes/add-osc-dynamic-routing-support-11130b2f440c0ac2.yaml releasenotes/notes/add-osc-trunk-commands-7e77283a369729c5.yaml releasenotes/notes/add-quota-default-show-c2ab35b791dcdcbc.yaml releasenotes/notes/add-rbac-qos-type-support-c42e31fadd7b.yaml releasenotes/notes/add-service-graph-ce4a25b3e32d70a6.yaml releasenotes/notes/add-sfc-commands.yaml releasenotes/notes/add-shared-pools-support-6f79b565afad3e47.yaml releasenotes/notes/add-subnet-onboard-e60772bc4984f698.yaml releasenotes/notes/add-support-to-floating-ip-port-forwardings-9dc838a5c5727eb7.yaml releasenotes/notes/add-tag-support-bad62d60ecc7075c.yaml releasenotes/notes/availability-zone-support-8e66f55e46b7ef9a.yaml releasenotes/notes/bgp-dynamic-routing-b97a1c81d3007049.yaml releasenotes/notes/bug-1676922-81341b70bc6f055a.yaml releasenotes/notes/bulk-delete-support-94a353db08efec8d.yaml releasenotes/notes/default-subnetpool-support-c0d34870e9d3e814.yaml releasenotes/notes/deprecate-bgp-speaker-show-dragents-2fcce99cf6bb5b60.yaml releasenotes/notes/deprecate-cli-7be1123817969439.yaml releasenotes/notes/direct-physical-vnic-port-create-736d8b2600faf22b.yaml releasenotes/notes/docs-improvements-17e31babe38e2962.yaml releasenotes/notes/drop-nuage-commands-df10aab6ccd77ed2.yaml releasenotes/notes/drop-python-2.7-f615ebae463b2143.yaml releasenotes/notes/drop-python-3-6-and-3-7-73767fa0bbe89a6e.yaml releasenotes/notes/drop-xml-support-41babecb1784d996.yaml releasenotes/notes/dscp_qos-4a26d3c0363624b0.yaml releasenotes/notes/extraroute-atomic-b11919d8e33b0d92.yaml releasenotes/notes/fix-exception-typeerror-4.1.0-b37d738146575ed5.yaml releasenotes/notes/fix-quota-update-zero-args-d596c4169c2d2e30.yaml releasenotes/notes/fix-rbac-create-command-dd40a474f0f092db.yaml releasenotes/notes/fix-token-endpoint-auth-support-26bf7ee12e4ec833.yaml releasenotes/notes/global_request_id-56856a93b982a6b3.yaml releasenotes/notes/keystonev3-7f9ede9c21b30841.yaml releasenotes/notes/log-request-id-64bef955b8292c18.yaml releasenotes/notes/minimum-packet-rate-34576b8fd98a3034.yaml releasenotes/notes/network-ip-availability-ac9a462f42fe9db4.yaml releasenotes/notes/neutron-cli-deprecation-398823c87270a296.yaml releasenotes/notes/no-new-binding-code-b03c9abbcaf2839e.yaml releasenotes/notes/osprofiler-support-9ba539761ae437e9.yaml releasenotes/notes/paket_rate_limit-1266a2a30f18727f.yaml releasenotes/notes/port-bindings-c3f36bd76ece0a71.yaml releasenotes/notes/qos_minimum_bandwidth-dc4adb23c51de30b.yaml releasenotes/notes/quota-update-for-LB-b21e7bc9e4a10f3e.yaml releasenotes/notes/quota-update-for-rbac-192a8e65bf481941.yaml releasenotes/notes/relnotes-from-3.0.0-d7306f5af5e3868d.yaml releasenotes/notes/remote_fwg-0f5362e5be8b2e84.yaml releasenotes/notes/remove-bgp-speaker-show-dragents-0a0db4b72b2feffc.yaml releasenotes/notes/remove-case-dependency-773ccb3237c38e81.yaml releasenotes/notes/remove-cli-code-53969e9aa927e530.yaml releasenotes/notes/remove-deprecated-option-b53f5d7e6a16ce95.yaml releasenotes/notes/remove-public-and-private-parameters-d683e7c30ecedc3b.yaml releasenotes/notes/return-request-id-to-caller-15b1d23a4ddc27a3.yaml releasenotes/notes/segments-8557f5b0caa5ee26.yaml releasenotes/notes/sfc-tap-service-function-support-a05242f25f79066b.yaml releasenotes/notes/show-tenant-id-admin-listing-dc13ee7eb889d418.yaml releasenotes/notes/start-using-reno-9081b3e4c1951fdb.yaml releasenotes/notes/support-bgpvpn-route-control-aeda3e698486f73b.yaml releasenotes/notes/support-firewall-group-resource-type-5ad1b69cabcb4aa6.yaml releasenotes/notes/support-fwaasv2-cli-7f21676c551f8ae0.yaml releasenotes/notes/support-logging-cli-cd02d3bb03367106.yaml releasenotes/notes/support-networking-bgpvpn-cli-fdd0cc3a5b14983d.yaml releasenotes/notes/support-routes-advertise-9356a38cf3e2fe5a.yaml releasenotes/notes/support-vni-in-networking-bgpvpn-cli-d284b73b40b79495.yaml releasenotes/notes/support-vpnaas-cli-9478fb7cfe603e26.yaml releasenotes/notes/tag-support-subnet-port-subnetpool-router-6250ec4714ee8690.yaml releasenotes/source/2023.1.rst releasenotes/source/2023.2.rst releasenotes/source/conf.py releasenotes/source/index.rst releasenotes/source/mitaka.rst releasenotes/source/newton.rst releasenotes/source/ocata.rst releasenotes/source/old_relnotes.rst releasenotes/source/pike.rst releasenotes/source/queens.rst releasenotes/source/rocky.rst releasenotes/source/stein.rst releasenotes/source/train.rst releasenotes/source/unreleased.rst releasenotes/source/ussuri.rst releasenotes/source/victoria.rst releasenotes/source/wallaby.rst releasenotes/source/xena.rst releasenotes/source/yoga.rst releasenotes/source/zed.rst releasenotes/source/_static/.placeholder releasenotes/source/_templates/.placeholder releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201317.0 python-neutronclient-11.2.0/python_neutronclient.egg-info/dependency_links.txt0000664000175000017500000000000100000000000030060 0ustar00zuulzuul00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201317.0 python-neutronclient-11.2.0/python_neutronclient.egg-info/entry_points.txt0000664000175000017500000002475100000000000027321 0ustar00zuulzuul00000000000000[openstack.cli.extension] neutronclient = neutronclient.osc.plugin [openstack.neutronclient.v2] bgp_dragent_add_speaker = neutronclient.osc.v2.dynamic_routing.bgp_dragent:AddBgpSpeakerToDRAgent bgp_dragent_list = neutronclient.osc.v2.dynamic_routing.bgp_dragent:ListDRAgent bgp_dragent_remove_speaker = neutronclient.osc.v2.dynamic_routing.bgp_dragent:RemoveBgpSpeakerFromDRAgent bgp_peer_create = neutronclient.osc.v2.dynamic_routing.bgp_peer:CreateBgpPeer bgp_peer_delete = neutronclient.osc.v2.dynamic_routing.bgp_peer:DeleteBgpPeer bgp_peer_list = neutronclient.osc.v2.dynamic_routing.bgp_peer:ListBgpPeer bgp_peer_set = neutronclient.osc.v2.dynamic_routing.bgp_peer:SetBgpPeer bgp_peer_show = neutronclient.osc.v2.dynamic_routing.bgp_peer:ShowBgpPeer bgp_speaker_add_network = neutronclient.osc.v2.dynamic_routing.bgp_speaker:AddNetworkToSpeaker bgp_speaker_add_peer = neutronclient.osc.v2.dynamic_routing.bgp_speaker:AddPeerToSpeaker bgp_speaker_create = neutronclient.osc.v2.dynamic_routing.bgp_speaker:CreateBgpSpeaker bgp_speaker_delete = neutronclient.osc.v2.dynamic_routing.bgp_speaker:DeleteBgpSpeaker bgp_speaker_list = neutronclient.osc.v2.dynamic_routing.bgp_speaker:ListBgpSpeaker bgp_speaker_list_advertised_routes = neutronclient.osc.v2.dynamic_routing.bgp_speaker:ListRoutesAdvertisedBySpeaker bgp_speaker_remove_network = neutronclient.osc.v2.dynamic_routing.bgp_speaker:RemoveNetworkFromSpeaker bgp_speaker_remove_peer = neutronclient.osc.v2.dynamic_routing.bgp_speaker:RemovePeerFromSpeaker bgp_speaker_set = neutronclient.osc.v2.dynamic_routing.bgp_speaker:SetBgpSpeaker bgp_speaker_show = neutronclient.osc.v2.dynamic_routing.bgp_speaker:ShowBgpSpeaker bgpvpn_create = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:CreateBgpvpn bgpvpn_delete = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:DeleteBgpvpn bgpvpn_list = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:ListBgpvpn bgpvpn_network_association_create = neutronclient.osc.v2.networking_bgpvpn.network_association:CreateBgpvpnNetAssoc bgpvpn_network_association_delete = neutronclient.osc.v2.networking_bgpvpn.network_association:DeleteBgpvpnNetAssoc bgpvpn_network_association_list = neutronclient.osc.v2.networking_bgpvpn.network_association:ListBgpvpnNetAssoc bgpvpn_network_association_show = neutronclient.osc.v2.networking_bgpvpn.network_association:ShowBgpvpnNetAssoc bgpvpn_port_association_create = neutronclient.osc.v2.networking_bgpvpn.port_association:CreateBgpvpnPortAssoc bgpvpn_port_association_delete = neutronclient.osc.v2.networking_bgpvpn.port_association:DeleteBgpvpnPortAssoc bgpvpn_port_association_list = neutronclient.osc.v2.networking_bgpvpn.port_association:ListBgpvpnPortAssoc bgpvpn_port_association_set = neutronclient.osc.v2.networking_bgpvpn.port_association:SetBgpvpnPortAssoc bgpvpn_port_association_show = neutronclient.osc.v2.networking_bgpvpn.port_association:ShowBgpvpnPortAssoc bgpvpn_port_association_unset = neutronclient.osc.v2.networking_bgpvpn.port_association:UnsetBgpvpnPortAssoc bgpvpn_router_association_create = neutronclient.osc.v2.networking_bgpvpn.router_association:CreateBgpvpnRouterAssoc bgpvpn_router_association_delete = neutronclient.osc.v2.networking_bgpvpn.router_association:DeleteBgpvpnRouterAssoc bgpvpn_router_association_list = neutronclient.osc.v2.networking_bgpvpn.router_association:ListBgpvpnRouterAssoc bgpvpn_router_association_set = neutronclient.osc.v2.networking_bgpvpn.router_association:SetBgpvpnRouterAssoc bgpvpn_router_association_show = neutronclient.osc.v2.networking_bgpvpn.router_association:ShowBgpvpnRouterAssoc bgpvpn_router_association_unset = neutronclient.osc.v2.networking_bgpvpn.router_association:UnsetBgpvpnRouterAssoc bgpvpn_set = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:SetBgpvpn bgpvpn_show = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:ShowBgpvpn bgpvpn_unset = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:UnsetBgpvpn firewall_group_create = neutronclient.osc.v2.fwaas.firewallgroup:CreateFirewallGroup firewall_group_delete = neutronclient.osc.v2.fwaas.firewallgroup:DeleteFirewallGroup firewall_group_list = neutronclient.osc.v2.fwaas.firewallgroup:ListFirewallGroup firewall_group_policy_add_rule = neutronclient.osc.v2.fwaas.firewallpolicy:FirewallPolicyInsertRule firewall_group_policy_create = neutronclient.osc.v2.fwaas.firewallpolicy:CreateFirewallPolicy firewall_group_policy_delete = neutronclient.osc.v2.fwaas.firewallpolicy:DeleteFirewallPolicy firewall_group_policy_list = neutronclient.osc.v2.fwaas.firewallpolicy:ListFirewallPolicy firewall_group_policy_remove_rule = neutronclient.osc.v2.fwaas.firewallpolicy:FirewallPolicyRemoveRule firewall_group_policy_set = neutronclient.osc.v2.fwaas.firewallpolicy:SetFirewallPolicy firewall_group_policy_show = neutronclient.osc.v2.fwaas.firewallpolicy:ShowFirewallPolicy firewall_group_policy_unset = neutronclient.osc.v2.fwaas.firewallpolicy:UnsetFirewallPolicy firewall_group_rule_create = neutronclient.osc.v2.fwaas.firewallrule:CreateFirewallRule firewall_group_rule_delete = neutronclient.osc.v2.fwaas.firewallrule:DeleteFirewallRule firewall_group_rule_list = neutronclient.osc.v2.fwaas.firewallrule:ListFirewallRule firewall_group_rule_set = neutronclient.osc.v2.fwaas.firewallrule:SetFirewallRule firewall_group_rule_show = neutronclient.osc.v2.fwaas.firewallrule:ShowFirewallRule firewall_group_rule_unset = neutronclient.osc.v2.fwaas.firewallrule:UnsetFirewallRule firewall_group_set = neutronclient.osc.v2.fwaas.firewallgroup:SetFirewallGroup firewall_group_show = neutronclient.osc.v2.fwaas.firewallgroup:ShowFirewallGroup firewall_group_unset = neutronclient.osc.v2.fwaas.firewallgroup:UnsetFirewallGroup network_log_create = neutronclient.osc.v2.logging.network_log:CreateNetworkLog network_log_delete = neutronclient.osc.v2.logging.network_log:DeleteNetworkLog network_log_list = neutronclient.osc.v2.logging.network_log:ListNetworkLog network_log_set = neutronclient.osc.v2.logging.network_log:SetNetworkLog network_log_show = neutronclient.osc.v2.logging.network_log:ShowNetworkLog network_loggable_resources_list = neutronclient.osc.v2.logging.network_log:ListLoggableResource network_onboard_subnets = neutronclient.osc.v2.subnet_onboard.subnet_onboard:NetworkOnboardSubnets 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 sfc_flow_classifier_set = neutronclient.osc.v2.sfc.sfc_flow_classifier:SetSfcFlowClassifier sfc_flow_classifier_show = neutronclient.osc.v2.sfc.sfc_flow_classifier:ShowSfcFlowClassifier sfc_port_chain_create = neutronclient.osc.v2.sfc.sfc_port_chain:CreateSfcPortChain sfc_port_chain_delete = neutronclient.osc.v2.sfc.sfc_port_chain:DeleteSfcPortChain sfc_port_chain_list = neutronclient.osc.v2.sfc.sfc_port_chain:ListSfcPortChain sfc_port_chain_set = neutronclient.osc.v2.sfc.sfc_port_chain:SetSfcPortChain sfc_port_chain_show = neutronclient.osc.v2.sfc.sfc_port_chain:ShowSfcPortChain sfc_port_chain_unset = neutronclient.osc.v2.sfc.sfc_port_chain:UnsetSfcPortChain sfc_port_pair_create = neutronclient.osc.v2.sfc.sfc_port_pair:CreateSfcPortPair sfc_port_pair_delete = neutronclient.osc.v2.sfc.sfc_port_pair:DeleteSfcPortPair sfc_port_pair_group_create = neutronclient.osc.v2.sfc.sfc_port_pair_group:CreateSfcPortPairGroup sfc_port_pair_group_delete = neutronclient.osc.v2.sfc.sfc_port_pair_group:DeleteSfcPortPairGroup sfc_port_pair_group_list = neutronclient.osc.v2.sfc.sfc_port_pair_group:ListSfcPortPairGroup sfc_port_pair_group_set = neutronclient.osc.v2.sfc.sfc_port_pair_group:SetSfcPortPairGroup sfc_port_pair_group_show = neutronclient.osc.v2.sfc.sfc_port_pair_group:ShowSfcPortPairGroup sfc_port_pair_group_unset = neutronclient.osc.v2.sfc.sfc_port_pair_group:UnsetSfcPortPairGroup sfc_port_pair_list = neutronclient.osc.v2.sfc.sfc_port_pair:ListSfcPortPair sfc_port_pair_set = neutronclient.osc.v2.sfc.sfc_port_pair:SetSfcPortPair sfc_port_pair_show = neutronclient.osc.v2.sfc.sfc_port_pair:ShowSfcPortPair sfc_service_graph_create = neutronclient.osc.v2.sfc.sfc_service_graph:CreateSfcServiceGraph sfc_service_graph_delete = neutronclient.osc.v2.sfc.sfc_service_graph:DeleteSfcServiceGraph sfc_service_graph_list = neutronclient.osc.v2.sfc.sfc_service_graph:ListSfcServiceGraph sfc_service_graph_set = neutronclient.osc.v2.sfc.sfc_service_graph:SetSfcServiceGraph sfc_service_graph_show = neutronclient.osc.v2.sfc.sfc_service_graph:ShowSfcServiceGraph vpn_endpoint_group_create = neutronclient.osc.v2.vpnaas.endpoint_group:CreateEndpointGroup vpn_endpoint_group_delete = neutronclient.osc.v2.vpnaas.endpoint_group:DeleteEndpointGroup vpn_endpoint_group_list = neutronclient.osc.v2.vpnaas.endpoint_group:ListEndpointGroup vpn_endpoint_group_set = neutronclient.osc.v2.vpnaas.endpoint_group:SetEndpointGroup vpn_endpoint_group_show = neutronclient.osc.v2.vpnaas.endpoint_group:ShowEndpointGroup vpn_ike_policy_create = neutronclient.osc.v2.vpnaas.ikepolicy:CreateIKEPolicy vpn_ike_policy_delete = neutronclient.osc.v2.vpnaas.ikepolicy:DeleteIKEPolicy vpn_ike_policy_list = neutronclient.osc.v2.vpnaas.ikepolicy:ListIKEPolicy vpn_ike_policy_set = neutronclient.osc.v2.vpnaas.ikepolicy:SetIKEPolicy vpn_ike_policy_show = neutronclient.osc.v2.vpnaas.ikepolicy:ShowIKEPolicy vpn_ipsec_policy_create = neutronclient.osc.v2.vpnaas.ipsecpolicy:CreateIPsecPolicy vpn_ipsec_policy_delete = neutronclient.osc.v2.vpnaas.ipsecpolicy:DeleteIPsecPolicy vpn_ipsec_policy_list = neutronclient.osc.v2.vpnaas.ipsecpolicy:ListIPsecPolicy vpn_ipsec_policy_set = neutronclient.osc.v2.vpnaas.ipsecpolicy:SetIPsecPolicy vpn_ipsec_policy_show = neutronclient.osc.v2.vpnaas.ipsecpolicy:ShowIPsecPolicy vpn_ipsec_site_connection_create = neutronclient.osc.v2.vpnaas.ipsec_site_connection:CreateIPsecSiteConnection vpn_ipsec_site_connection_delete = neutronclient.osc.v2.vpnaas.ipsec_site_connection:DeleteIPsecSiteConnection vpn_ipsec_site_connection_list = neutronclient.osc.v2.vpnaas.ipsec_site_connection:ListIPsecSiteConnection vpn_ipsec_site_connection_set = neutronclient.osc.v2.vpnaas.ipsec_site_connection:SetIPsecSiteConnection vpn_ipsec_site_connection_show = neutronclient.osc.v2.vpnaas.ipsec_site_connection:ShowIPsecSiteConnection vpn_service_create = neutronclient.osc.v2.vpnaas.vpnservice:CreateVPNService vpn_service_delete = neutronclient.osc.v2.vpnaas.vpnservice:DeleteVPNService vpn_service_list = neutronclient.osc.v2.vpnaas.vpnservice:ListVPNService vpn_service_set = neutronclient.osc.v2.vpnaas.vpnservice:SetVPNSercice vpn_service_show = neutronclient.osc.v2.vpnaas.vpnservice:ShowVPNService ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201317.0 python-neutronclient-11.2.0/python_neutronclient.egg-info/not-zip-safe0000664000175000017500000000000100000000000026240 0ustar00zuulzuul00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201317.0 python-neutronclient-11.2.0/python_neutronclient.egg-info/pbr.json0000664000175000017500000000005600000000000025471 0ustar00zuulzuul00000000000000{"git_version": "4e48e90", "is_release": true}././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201317.0 python-neutronclient-11.2.0/python_neutronclient.egg-info/requires.txt0000664000175000017500000000045700000000000026420 0ustar00zuulzuul00000000000000cliff>=3.4.0 debtcollector>=1.2.0 iso8601>=0.1.11 keystoneauth1>=3.8.0 netaddr>=0.7.18 openstacksdk>=1.5.0 os-client-config>=1.28.0 osc-lib>=1.12.0 oslo.i18n>=3.15.3 oslo.log>=3.36.0 oslo.serialization!=2.19.1,>=2.18.0 oslo.utils>=3.33.0 pbr!=2.1.0,>=2.0.0 python-keystoneclient>=3.8.0 requests>=2.14.2 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201317.0 python-neutronclient-11.2.0/python_neutronclient.egg-info/top_level.txt0000664000175000017500000000001600000000000026541 0ustar00zuulzuul00000000000000neutronclient ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2016604 python-neutronclient-11.2.0/releasenotes/0000775000175000017500000000000000000000000020517 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2416637 python-neutronclient-11.2.0/releasenotes/notes/0000775000175000017500000000000000000000000021647 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/.placeholder0000664000175000017500000000000000000000000024120 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000022500000000000011454 xustar0000000000000000127 path=python-neutronclient-11.2.0/releasenotes/notes/Define-IpAddressAlreadyAllocatedClient-exception-e8600ca5ba1c7f45.yaml 22 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/Define-IpAddressAlreadyAllocatedClient-exception-e8600000664000175000017500000000027100000000000033566 0ustar00zuulzuul00000000000000--- other: - | Define a new exception type ``IpAddressAlreadyAllocatedClient``. Users can catch this specific exception instead of the generic ``NeutronClientException``. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-aggressive-negotiation-mode-5218b1baff930eb8.yaml0000664000175000017500000000020000000000000033142 0ustar00zuulzuul00000000000000--- features: - | The ``--phase1-negotiation-mode`` option supports ``aggressive`` mode in VPNaaS ikepolicy commands. ././@PaxHeader0000000000000000000000000000020700000000000011454 xustar0000000000000000113 path=python-neutronclient-11.2.0/releasenotes/notes/add-auto-allocated-topology-delete-aaccd60bd0f2e7b2.yaml 22 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-auto-allocated-topology-delete-aaccd60bd0f2e7b2.y0000664000175000017500000000017100000000000033273 0ustar00zuulzuul00000000000000--- features: - The ``auto-allocated-topology-delete`` command allows users to delete the auto allocated topology. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-get-me-a-network-5ab2d60bf6f257b1.yaml0000664000175000017500000000045500000000000030636 0ustar00zuulzuul00000000000000--- features: - | CLI support for the "get-me-a-network" feature, which simplifies the process for launching an instance with basic network connectivity. * The ``auto-allocated-topology-show`` command provides the network of the automatically allocated topology for a tenant. ././@PaxHeader0000000000000000000000000000020700000000000011454 xustar0000000000000000113 path=python-neutronclient-11.2.0/releasenotes/notes/add-l7-content-policies-capability-0f17cd06f044c83c.yaml 22 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-l7-content-policies-capability-0f17cd06f044c83c.y0000664000175000017500000000034700000000000032720 0ustar00zuulzuul00000000000000--- features: - | CLI support for Layer 7 content policies and rules. * L7 policies can be defined for listeners along with the ability to set L7 policy order. * Multiple rules can be created for an L7 policy. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-lb-status-tree-723f23c09617de3b.yaml0000664000175000017500000000025700000000000030274 0ustar00zuulzuul00000000000000--- features: - | CLI support for load balancer status tree. * The ``lbaas-loadbalancer-status`` command provides the status tree of a specific load balancer.././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-neutron-purge-a89e3d1179dce4b1.yaml0000664000175000017500000000062100000000000030372 0ustar00zuulzuul00000000000000--- features: - | New command 'neutron purge ' will delete all supported resources owned by the given tenant, provided that the user has sufficient authorization and the resources in question are not shared, in use, or otherwise undeletable. Supported resources are: * Networks * Subnets * Routers * Ports * Floating IPs * Security Groups ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-new-session-clear-option-3c0b78ebc133a10c.yaml0000664000175000017500000000031600000000000032377 0ustar00zuulzuul00000000000000--- features: - | A new option ``--no-session-persistence`` has been added to the ``neutron lbaas-pool-update`` CLI to clear the session persistence with which the current pool is associated. ././@PaxHeader0000000000000000000000000000021600000000000011454 xustar0000000000000000120 path=python-neutronclient-11.2.0/releasenotes/notes/add-no-shared-option-to-qos-policy-update-56ac41fb3af7e309.yaml 22 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-no-shared-option-to-qos-policy-update-56ac41fb3af0000664000175000017500000000037400000000000033312 0ustar00zuulzuul00000000000000--- fixes: - | CLI support to set QoS policy as not shared if it was shared before. The ``qos-policy-update`` command include a ``--no-shared`` option. Closes `bug 1590942 `_. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-osc-dynamic-routing-support-11130b2f440c0ac2.yaml0000664000175000017500000000011400000000000032760 0ustar00zuulzuul00000000000000--- features: - | Add OSC plugin to support "Neutron Dynamic Routing" ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-osc-trunk-commands-7e77283a369729c5.yaml0000664000175000017500000000053600000000000031032 0ustar00zuulzuul00000000000000--- features: - | Add ``network trunk create``, ``network trunk list``, ``network trunk set``, ``network trunk unset``, ``network trunk delete`` and ``network subport list`` OSC commands for trunk resource along with client bindings. [Blueprint `vlan-aware-vms `_] ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-quota-default-show-c2ab35b791dcdcbc.yaml0000664000175000017500000000030300000000000031511 0ustar00zuulzuul00000000000000--- features: - | CLI support to display the default quota reserved for a tenant. * The ``quota-default-show`` command outputs the default quota of resources for a given tenant. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-rbac-qos-type-support-c42e31fadd7b.yaml0000664000175000017500000000031300000000000031425 0ustar00zuulzuul00000000000000--- features: - | CLI support for QoS policy RBAC. * The ``rbac-create`` command include a --type qos-policy option. * The ``rbac-list`` command output includes a new 'type' column. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-service-graph-ce4a25b3e32d70a6.yaml0000664000175000017500000000021700000000000030302 0ustar00zuulzuul00000000000000--- features: - | Added support for SFC Service Graph resource. Related RFE: https://bugs.launchpad.net/networking-sfc/+bug/1587486. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-sfc-commands.yaml0000664000175000017500000000042100000000000025630 0ustar00zuulzuul00000000000000--- features: - | Add OSC plugin support for the “Networking Service Function Chaining” feature commands along with client bindings. [Blueprint `openstackclient-cli-porting `_]././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-shared-pools-support-6f79b565afad3e47.yaml0000664000175000017500000000036000000000000031704 0ustar00zuulzuul00000000000000--- features: - | CLI support for Neutron-LBaaS v2 shared pools added. * Pools can be created independently from listeners. * Listeners can share the same default_pool. * Makes Layer 7 switching support much more useful. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-subnet-onboard-e60772bc4984f698.yaml0000664000175000017500000000032400000000000030305 0ustar00zuulzuul00000000000000--- features: - | Add ``network onboard subnets`` OSC command to enable subnet onboard support from the CLI [Blueprint `subnet-onboard `_] ././@PaxHeader0000000000000000000000000000022000000000000011447 xustar0000000000000000122 path=python-neutronclient-11.2.0/releasenotes/notes/add-support-to-floating-ip-port-forwardings-9dc838a5c5727eb7.yaml 22 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-support-to-floating-ip-port-forwardings-9dc838a5c0000664000175000017500000000010300000000000033473 0ustar00zuulzuul00000000000000--- features: - | Add support to floating ip port forwarding.././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/add-tag-support-bad62d60ecc7075c.yaml0000664000175000017500000000137600000000000030124 0ustar00zuulzuul00000000000000--- features: - | CLI support for tag. * The ``tag-add`` command sets a tag on the network resource. It also includes ``--resource-type``, ``--resource`` and ``--tag`` options. * The ``tag-replace`` command replaces tags on the network resource. It also includes ``--resource-type``, ``--resource`` and ``--tag`` options. More than one ``--tag`` options can be set. * The ``tag-remove`` command removes tags on the network resource. It also includes ``--resource-type``, ``--resource``, ``--tag`` and ``--all`` options. The ``--all`` option allow to remove all tags on the network resource. * The ``net-list`` command includes ``--tags``, ``--tags-any``, ``--not-tags`` and ``--not-tags-any`` options.././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/availability-zone-support-8e66f55e46b7ef9a.yaml0000664000175000017500000000051100000000000032210 0ustar00zuulzuul00000000000000--- features: - | CLI support for availability zones. * The ``availability-zone-list`` command provides a list of availability zones. * The ``net-create`` and ``router-create`` commands include a ``--availability-zone-hint`` option. * The ``agent-list`` command output includes availability zones. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/bgp-dynamic-routing-b97a1c81d3007049.yaml0000664000175000017500000000022600000000000030462 0ustar00zuulzuul00000000000000--- features: - | CLI support for the BGP dynamic routing functionality will help advertising neutron fixed-ips and dvr host routes via BGP.././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/bug-1676922-81341b70bc6f055a.yaml0000664000175000017500000000145200000000000026273 0ustar00zuulzuul00000000000000--- deprecations: - | The ``--public`` and ``--private`` attribute of Firewall-as-a-Service v2 have been deprecated. While the ``--public`` attribute will now be replaced by ``--share``, the ``--private`` attribute will be replaced by ``--no-share``. This is because of the similarity between the behavior of ``--public`` attribute in FireWall-as-a-Service and the ``--share`` attribute used in OpenStack. This deprecation affects the following CLIs. * openstack firewall group create * openstack firewall group set * openstack firewall group unset * openstack firewall policy create * openstack firewall policy set * openstack firewall policy unset * openstack firewall rule create * openstack firewall rule set * openstack firewall rule unset ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/bulk-delete-support-94a353db08efec8d.yaml0000664000175000017500000000036700000000000031033 0ustar00zuulzuul00000000000000--- features: - | CLI support for bulk delete. * By using this feature, multiple resource can be deleted using a single command. * Example: ``neutron router-delete router_a router_b`` deletes both router_a and router_b. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/default-subnetpool-support-c0d34870e9d3e814.yaml0000664000175000017500000000043000000000000032217 0ustar00zuulzuul00000000000000--- features: - | CLI support for default subnetpools. * The ``subnetpool-list`` and ``subnetpool-show`` command output includes the ``is_default`` field. * The ``subnetpool-create`` and ``subnetpool-update`` commands include a ``--is-default`` option. ././@PaxHeader0000000000000000000000000000021000000000000011446 xustar0000000000000000114 path=python-neutronclient-11.2.0/releasenotes/notes/deprecate-bgp-speaker-show-dragents-2fcce99cf6bb5b60.yaml 22 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/deprecate-bgp-speaker-show-dragents-2fcce99cf6bb5b60.0000664000175000017500000000052000000000000033224 0ustar00zuulzuul00000000000000--- deprecations: - | The ``openstack bgp speaker show dragents`` CLI is deprecated and will be removed in the future. Use ``openstack bgp dragent list --bgp-speaker `` CLI instead. features: - | The ``openstack bgp dragent list`` CLI is added to support showing the list of dynamic routing agents. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/deprecate-cli-7be1123817969439.yaml0000664000175000017500000000060500000000000027167 0ustar00zuulzuul00000000000000--- deprecations: - The neutron CLI is now deprecated. This is the signal that it is time to start using the openstack CLI. No new features will be added to the neutron CLI, though fixes to the CLI will be assessed on a case by case basis. Fixes to the API bindings, as well as development of new API bindings as well as OSC plugins are exempt from this deprecation. ././@PaxHeader0000000000000000000000000000020500000000000011452 xustar0000000000000000111 path=python-neutronclient-11.2.0/releasenotes/notes/direct-physical-vnic-port-create-736d8b2600faf22b.yaml 22 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/direct-physical-vnic-port-create-736d8b2600faf22b.yam0000664000175000017500000000036300000000000033033 0ustar00zuulzuul00000000000000--- features: - Added new 'direct-physical' vnic-type option for port-create CLI command. Passing this particular value allows for a port to be create with the vnic-type used for assigning SR-IOV physical functions to instances. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/docs-improvements-17e31babe38e2962.yaml0000664000175000017500000000021300000000000030420 0ustar00zuulzuul00000000000000--- other: - | Addition of CLI user documentation including output filters, extra options, and operation using os-client-config. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/drop-nuage-commands-df10aab6ccd77ed2.yaml0000664000175000017500000000006100000000000031075 0ustar00zuulzuul00000000000000--- upgrade: - Remove Nuage-specific commands. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/drop-python-2.7-f615ebae463b2143.yaml0000664000175000017500000000022300000000000027524 0ustar00zuulzuul00000000000000--- upgrade: - | Python 2.7 support has been dropped. The minimum version of Python now supported by python-neutronclient is Python 3.6. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/drop-python-3-6-and-3-7-73767fa0bbe89a6e.yaml0000664000175000017500000000020100000000000030666 0ustar00zuulzuul00000000000000--- upgrade: - | Python 3.6 & 3.7 support has been dropped. The minimum version of Python now supported is Python 3.8. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/drop-xml-support-41babecb1784d996.yaml0000664000175000017500000000016500000000000030312 0ustar00zuulzuul00000000000000--- upgrade: - XML request format support has been removed. deprecations: - request-format option is deprecated. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/dscp_qos-4a26d3c0363624b0.yaml0000664000175000017500000000026700000000000026411 0ustar00zuulzuul00000000000000--- prelude: > Adding new QoS DSCP marking rule commands. features: - New create, update, list, show, and delete commands are added for QoS DSCP marking rule functionality. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/extraroute-atomic-b11919d8e33b0d92.yaml0000664000175000017500000000017000000000000030341 0ustar00zuulzuul00000000000000--- features: - | New client methods: ``add_extra_routes_to_router`` and ``remove_extra_routes_from_router``. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/fix-exception-typeerror-4.1.0-b37d738146575ed5.yaml0000664000175000017500000000027600000000000032102 0ustar00zuulzuul00000000000000--- critical: - Fix a critical bug that when lazy translation is enabled NeutronClientException raises a TypeError (`bug 1552760 `_). ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/fix-quota-update-zero-args-d596c4169c2d2e30.yaml0000664000175000017500000000050700000000000032000 0ustar00zuulzuul00000000000000--- fixes: - | Fix CLI quota-update to return an error message for no args * ``quota-update`` CLI will return an error message ``Must specify a valid resource with new quota value`` if no argument is provided while executing it. If arguments are provided with CLI, no existing behavior is changed. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/fix-rbac-create-command-dd40a474f0f092db.yaml0000664000175000017500000000046300000000000031374 0ustar00zuulzuul00000000000000--- fixes: - Fix 'bug 1596750 ' that using 'rbac-create' without specifying 'target-tenant' will return 'Request Failed internal server error while processing your request'. Update the default value of the argument '--target-tenant' to '*' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/fix-token-endpoint-auth-support-26bf7ee12e4ec833.yaml0000664000175000017500000000041000000000000033221 0ustar00zuulzuul00000000000000--- fixes: - Fix `bug 1450414 `_ that authentication with via ``--os-token`` and ``--os-url`` options (or corresponding environment variables) does not work after keystone v3 API support. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/global_request_id-56856a93b982a6b3.yaml0000664000175000017500000000027100000000000030310 0ustar00zuulzuul00000000000000--- features: - | Adds a new ``global_request_id`` parameter to the Client constructors, which will pass that id on all requests as the ``X-OpenStack-Request-ID`` header. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/keystonev3-7f9ede9c21b30841.yaml0000664000175000017500000000031100000000000027062 0ustar00zuulzuul00000000000000--- deprecations: - | Keystone v3 support for CLI * Using 'tenant_id' and 'tenant_name' arguments in API bindings is deprecated. Use 'project_id' and 'project_name' arguments instead. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/log-request-id-64bef955b8292c18.yaml0000664000175000017500000000012200000000000027541 0ustar00zuulzuul00000000000000--- features: - Added support to log 'x-openstack-request-id' for each api call.././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/minimum-packet-rate-34576b8fd98a3034.yaml0000664000175000017500000000042500000000000030473 0ustar00zuulzuul00000000000000--- 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``. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/network-ip-availability-ac9a462f42fe9db4.yaml0000664000175000017500000000042400000000000031663 0ustar00zuulzuul00000000000000--- features: - | CLI support for network IP availability * The ``net-ip-availability-list`` command provides a list of IP usage statistics for all networks. * The ``net-ip-availability-show`` command provides IP usage stats for a specific network. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/neutron-cli-deprecation-398823c87270a296.yaml0000664000175000017500000000077700000000000031233 0ustar00zuulzuul00000000000000--- 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 `__ in the OSC documentation would help you. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/no-new-binding-code-b03c9abbcaf2839e.yaml0000664000175000017500000000055300000000000030711 0ustar00zuulzuul00000000000000--- 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. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/osprofiler-support-9ba539761ae437e9.yaml0000664000175000017500000000027400000000000030606 0ustar00zuulzuul00000000000000--- features: - | Add osprofiler support to the neutronclient python binding. If osprofiler is initiated, neutronclient sends a special HTTP header that contains trace info. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/paket_rate_limit-1266a2a30f18727f.yaml0000664000175000017500000000041100000000000030114 0ustar00zuulzuul00000000000000--- 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``. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/port-bindings-c3f36bd76ece0a71.yaml0000664000175000017500000000025700000000000027671 0ustar00zuulzuul00000000000000--- features: - | New client methods: ``create_port_binding``, ``delete_port_binding``, ``show_port_binding``, ``list_port_bindings`` and ``activate_port_binding``. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/qos_minimum_bandwidth-dc4adb23c51de30b.yaml0000664000175000017500000000017000000000000031525 0ustar00zuulzuul00000000000000--- features: - New create, update, list, show, and delete commands are added for the QoS minimum bandwidth rule. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/quota-update-for-LB-b21e7bc9e4a10f3e.yaml0000664000175000017500000000012300000000000030564 0ustar00zuulzuul00000000000000--- features: - | Quota of Loadbalancers and listeners can now be updated. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/quota-update-for-rbac-192a8e65bf481941.yaml0000664000175000017500000000010200000000000030713 0ustar00zuulzuul00000000000000--- features: - | Quota for RBAC policies can now be set. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/relnotes-from-3.0.0-d7306f5af5e3868d.yaml0000664000175000017500000000226300000000000030220 0ustar00zuulzuul00000000000000--- features: - Support os-client-config. OS_CLOUD environment variable is used for selecting named cloud configuration. - Support keystoneauth1 library which brings us better keystone v3 support. - Client command extension now supports a child resource. - New CLI for VPNaaS multiple local subnets. - New CLI for VPNaaS endpoint group API. - New CLI for flavor argument to loadbalancer v2 create. - New CLI for Neutron flavor framework. - Support creating floating IP on a specific subnet ID. - NSX gateway extension adds new transport type values (ipsec_gre and ipsec_stt). - New router-update option to update static routes (--route and --no-routes). - New allowed-address-pairs option to port-update upgrade: - Cisco-specific neutron client commands have been removed. These commands are ported to networking-cisco. - py26 support has been dropped. - py33 support has been dropped. fixes: - Name is no longer looked up on RBAC policies, RBAC policies have no name field so the name query to the server was always returning all entries since the name filter was ignored. (bug 1517818) other: - cliff-tablib has been removed from test dependencies. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/remote_fwg-0f5362e5be8b2e84.yaml0000664000175000017500000000021100000000000027104 0ustar00zuulzuul00000000000000--- features: - | Adds the remote source firewall group and the remote destination firewall group field to the firewall rules. ././@PaxHeader0000000000000000000000000000020500000000000011452 xustar0000000000000000111 path=python-neutronclient-11.2.0/releasenotes/notes/remove-bgp-speaker-show-dragents-0a0db4b72b2feffc.yaml 22 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/remove-bgp-speaker-show-dragents-0a0db4b72b2feffc.yam0000664000175000017500000000033000000000000033332 0ustar00zuulzuul00000000000000--- upgrade: - | The ``openstack bgp speaker show dragents`` CLI is removed. It was deprecated in the 7.1.0 release (Ussuri). Use ``openstack bgp dragent list --bgp-speaker `` CLI instead. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/remove-case-dependency-773ccb3237c38e81.yaml0000664000175000017500000000027000000000000031215 0ustar00zuulzuul00000000000000--- other: - | This patch provides user the support to use any form of casing, thus removing the specific UPPER/lower case inputs required by different neutron CLIs. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/remove-cli-code-53969e9aa927e530.yaml0000664000175000017500000000111400000000000027576 0ustar00zuulzuul00000000000000prelude: > | This new version of ``python-neutronclient`` does not include the command line interface code. The "neutron" script is no longer supported. This project only contains the OpenStack Client bindings that are currently being moved to OpenStack SDK _. deprecations: - | This project no longer provides CLI support. All code has been removed. Please use openstack CLI instead. See `openstack CLI command list `_. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/remove-deprecated-option-b53f5d7e6a16ce95.yaml0000664000175000017500000000015700000000000031745 0ustar00zuulzuul00000000000000--- deprecations: - | "admin-state-down" option was deprecated in Mitaka and has been removed in Newton. ././@PaxHeader0000000000000000000000000000021100000000000011447 xustar0000000000000000115 path=python-neutronclient-11.2.0/releasenotes/notes/remove-public-and-private-parameters-d683e7c30ecedc3b.yaml 22 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/remove-public-and-private-parameters-d683e7c30ecedc3b0000664000175000017500000000025400000000000033352 0ustar00zuulzuul00000000000000--- upgrade: - | The deprecated options ``--public`` and ``--private`` were dropped in FWaaS v2 related commands. Use ``--share`` and ``--no-share`` instead. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/return-request-id-to-caller-15b1d23a4ddc27a3.yaml0000664000175000017500000000010300000000000032260 0ustar00zuulzuul00000000000000--- features: - Neutron client returns 'x-openstack-request-id'. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/segments-8557f5b0caa5ee26.yaml0000664000175000017500000000022400000000000026655 0ustar00zuulzuul00000000000000--- features: - | New client methods: ``create_segment``, ``update_segment``, ``list_segments``, ``show_segment`` and ``delete_segment``. ././@PaxHeader0000000000000000000000000000020500000000000011452 xustar0000000000000000111 path=python-neutronclient-11.2.0/releasenotes/notes/sfc-tap-service-function-support-a05242f25f79066b.yaml 22 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/sfc-tap-service-function-support-a05242f25f79066b.yam0000664000175000017500000000013500000000000032762 0ustar00zuulzuul00000000000000--- features: - | Add OSC support to create Port pair group for Tap service functions. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/show-tenant-id-admin-listing-dc13ee7eb889d418.yaml0000664000175000017500000000041700000000000032445 0ustar00zuulzuul00000000000000--- features: - Show tenant_id when ``*-list`` command is run by admin. In neutron the list operations by admin retrieve all resources from all tenants. It is not easy to distinguish resources without tenant_id. This feature is useful for admin operations. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/start-using-reno-9081b3e4c1951fdb.yaml0000664000175000017500000000007100000000000030166 0ustar00zuulzuul00000000000000--- other: - Start using reno to manage release notes. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/support-bgpvpn-route-control-aeda3e698486f73b.yaml0000664000175000017500000000041000000000000032661 0ustar00zuulzuul00000000000000--- features: - | Add BGP VPN `port association `_ support to the CLI, which are introduced for BGP VPN interconnections by the ``bgpvpn-routes-control`` API extension. ././@PaxHeader0000000000000000000000000000021100000000000011447 xustar0000000000000000115 path=python-neutronclient-11.2.0/releasenotes/notes/support-firewall-group-resource-type-5ad1b69cabcb4aa6.yaml 22 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/support-firewall-group-resource-type-5ad1b69cabcb4aa60000664000175000017500000000026000000000000033545 0ustar00zuulzuul00000000000000--- features: - | CLI support for the "firewal_group" as a loggable resource type for logging feature, which is enhanced FWaaS functionality, as OSC plugin commands. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/support-fwaasv2-cli-7f21676c551f8ae0.yaml0000664000175000017500000000021500000000000030523 0ustar00zuulzuul00000000000000--- features: - CLI support for the "Firewall as a Service v2" feature, which is enhanced FWaaS functionality, as OSC plugin commands. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/support-logging-cli-cd02d3bb03367106.yaml0000664000175000017500000000025100000000000030551 0ustar00zuulzuul00000000000000--- features: - | CLI support for 'Logging' feature, which enable to collect packet logs for specified resource. Currently, only security-group can be logged. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/support-networking-bgpvpn-cli-fdd0cc3a5b14983d.yaml0000664000175000017500000000032400000000000033043 0ustar00zuulzuul00000000000000--- features: - CLI support for the "Neutron BGP VPN Interconnection" feature, which is an API extension to support inter-connection between L3VPNs/E-VPNs and Neutron resources, as OSC plugin commands. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/support-routes-advertise-9356a38cf3e2fe5a.yaml0000664000175000017500000000026000000000000032054 0ustar00zuulzuul00000000000000--- features: - | Add optional flag to control the advertisement in BGPVPNs of the routes defined on a Router resource (``bgpvpn-routes-control`` API extension). ././@PaxHeader0000000000000000000000000000021100000000000011447 xustar0000000000000000115 path=python-neutronclient-11.2.0/releasenotes/notes/support-vni-in-networking-bgpvpn-cli-d284b73b40b79495.yaml 22 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/support-vni-in-networking-bgpvpn-cli-d284b73b40b794950000664000175000017500000000036600000000000033022 0ustar00zuulzuul00000000000000--- features: - | CLI support for VXLAN VNI ID attribute in bgpvpn. An optional argument ``--vni`` is added to ``openstack bgpvpn`` commands to configure VXLAN Network Identifier when VXLAN encapsulation is used for the bgpvpn. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/support-vpnaas-cli-9478fb7cfe603e26.yaml0000664000175000017500000000021400000000000030533 0ustar00zuulzuul00000000000000--- features: - | CLI support for the "VPN as a Service" feature, which is enhanced VPNaaS functionality, as OSC plugin commands. ././@PaxHeader0000000000000000000000000000021600000000000011454 xustar0000000000000000120 path=python-neutronclient-11.2.0/releasenotes/notes/tag-support-subnet-port-subnetpool-router-6250ec4714ee8690.yaml 22 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/notes/tag-support-subnet-port-subnetpool-router-6250ec4714e0000664000175000017500000000015100000000000033431 0ustar00zuulzuul00000000000000--- features: - Tag operation for subnet, port, subnetpool and router resources are now supported. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2456641 python-neutronclient-11.2.0/releasenotes/source/0000775000175000017500000000000000000000000022017 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/2023.1.rst0000664000175000017500000000020200000000000023270 0ustar00zuulzuul00000000000000=========================== 2023.1 Series Release Notes =========================== .. release-notes:: :branch: stable/2023.1 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/2023.2.rst0000664000175000017500000000020200000000000023271 0ustar00zuulzuul00000000000000=========================== 2023.2 Series Release Notes =========================== .. release-notes:: :branch: stable/2023.2 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2456641 python-neutronclient-11.2.0/releasenotes/source/_static/0000775000175000017500000000000000000000000023445 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/_static/.placeholder0000664000175000017500000000000000000000000025716 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2456641 python-neutronclient-11.2.0/releasenotes/source/_templates/0000775000175000017500000000000000000000000024154 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/_templates/.placeholder0000664000175000017500000000000000000000000026425 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/conf.py0000664000175000017500000001467100000000000023327 0ustar00zuulzuul00000000000000# -*- 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. # Neutron Client Release Notes documentation build configuration file, # created by sphinx-quickstart on Tue Nov 3 17:40:50 2015. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # 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.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'reno.sphinxext', 'openstackdocstheme', ] # openstackdocstheme options openstackdocs_repo_name = 'openstack/python-neutronclient' openstackdocs_bug_project = 'python-neutronclient' openstackdocs_bug_tag = 'doc' openstackdocs_auto_name = False # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = 'Neutron Client Release Notes' copyright = '2015, Neutron Developers' # Release notes are version independent. # The full version, including alpha/beta/rc tags. release = '' # The short X.Y version. version = '' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all # documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'openstackdocs' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # html_extra_path = [] # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'NeutronReleaseNotesdoc' # -- Options for Internationalization output ------------------------------ locale_dirs = ['locale/'] ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/index.rst0000664000175000017500000000045700000000000023666 0ustar00zuulzuul00000000000000============================== Neutron Client Release Notes ============================== .. toctree:: :maxdepth: 1 unreleased 2023.2 2023.1 zed yoga xena wallaby victoria ussuri train stein rocky queens pike ocata newton mitaka old_relnotes ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2016604 python-neutronclient-11.2.0/releasenotes/source/locale/0000775000175000017500000000000000000000000023256 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2016604 python-neutronclient-11.2.0/releasenotes/source/locale/en_GB/0000775000175000017500000000000000000000000024230 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2456641 python-neutronclient-11.2.0/releasenotes/source/locale/en_GB/LC_MESSAGES/0000775000175000017500000000000000000000000026015 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po0000664000175000017500000002676300000000000031064 0ustar00zuulzuul00000000000000# Andi Chandler , 2022. #zanata # Andi Chandler , 2023. #zanata msgid "" msgstr "" "Project-Id-Version: Neutron Client Release Notes\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-09-08 20:18+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2023-07-28 12:44+0000\n" "Last-Translator: Andi Chandler \n" "Language-Team: English (United Kingdom)\n" "Language: en_GB\n" "X-Generator: Zanata 4.3.3\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" msgid "" "\"admin-state-down\" option was deprecated in Mitaka and has been removed in " "Newton." msgstr "" "\"admin-state-down\" option was deprecated in Mitaka and has been removed in " "Newton." msgid "10.0.0" msgstr "10.0.0" msgid "2.0" msgstr "2.0" msgid "2.2.0" msgstr "2.2.0" msgid "2.2.2" msgstr "2.2.2" msgid "2023.1 Series Release Notes" msgstr "2023.1 Series Release Notes" msgid "4.0.0" msgstr "4.0.0" msgid "4.1.0" msgstr "4.1.0" msgid "4.1.1" msgstr "4.1.1" msgid "4.1.2-15" msgstr "4.1.2-15" msgid "4.2.0" msgstr "4.2.0" msgid "5.0.0" msgstr "5.0.0" msgid "5.1.0" msgstr "5.1.0" msgid "6.0.0" msgstr "6.0.0" msgid "6.1.0" msgstr "6.1.0" msgid "6.1.1" msgstr "6.1.1" msgid "6.10.0" msgstr "6.10.0" msgid "6.11.0" msgstr "6.11.0" msgid "6.12.0" msgstr "6.12.0" msgid "6.14.0" msgstr "6.14.0" msgid "6.2.0" msgstr "6.2.0" msgid "6.3.0" msgstr "6.3.0" msgid "6.4.0" msgstr "6.4.0" msgid "6.5.0" msgstr "6.5.0" msgid "6.6.0" msgstr "6.6.0" msgid "6.7.0" msgstr "6.7.0" msgid "7.0.0" msgstr "7.0.0" msgid "7.1.0" msgstr "7.1.0" msgid "7.2.0" msgstr "7.2.0" msgid "7.2.1" msgstr "7.2.1" msgid "7.5.0" msgstr "7.5.0" msgid "7.7.0" msgstr "7.7.0" msgid "7.8.0" msgstr "7.8.0" msgid "8.0.0" msgstr "8.0.0" msgid "8.1.0" msgstr "8.1.0" msgid "8.2.0" msgstr "8.2.0" msgid "" "A new option ``--no-session-persistence`` has been added to the ``neutron " "lbaas-pool-update`` CLI to clear the session persistence with which the " "current pool is associated." msgstr "" "A new option ``--no-session-persistence`` has been added to the ``neutron " "lbaas-pool-update`` CLI to clear the session persistence with which the " "current pool is associated." msgid "" "Add BGP VPN `port association `_ support to the CLI, which are " "introduced for BGP VPN interconnections by the ``bgpvpn-routes-control`` API " "extension." msgstr "" "Add BGP VPN `port association `_ support to the CLI, which are " "introduced for BGP VPN interconnections by the ``bgpvpn-routes-control`` API " "extension." msgid "" "Add OSC plugin support for the “Networking Service Function Chaining” " "feature commands along with client bindings. [Blueprint `openstackclient-cli-" "porting `_]" msgstr "" "Add OSC plugin support for the “Networking Service Function Chaining” " "feature commands along with client bindings. [Blueprint `openstackclient-cli-" "porting `_]" msgid "Add OSC plugin to support \"Neutron Dynamic Routing\"" msgstr "Add OSC plugin to support \"Neutron Dynamic Routing\"" msgid "Add OSC support to create Port pair group for Tap service functions." msgstr "Add OSC support to create Port pair group for Tap service functions." msgid "" "Add ``network onboard subnets`` OSC command to enable subnet onboard support " "from the CLI [Blueprint `subnet-onboard `_]" msgstr "" "Add ``network onboard subnets`` OSC command to enable subnet onboard support " "from the CLI [Blueprint `subnet-onboard `_]" msgid "" "Add ``network trunk create``, ``network trunk list``, ``network trunk set``, " "``network trunk unset``, ``network trunk delete`` and ``network subport " "list`` OSC commands for trunk resource along with client bindings. " "[Blueprint `vlan-aware-vms `_]" msgstr "" "Add ``network trunk create``, ``network trunk list``, ``network trunk set``, " "``network trunk unset``, ``network trunk delete`` and ``network subport " "list`` OSC commands for trunk resource along with client bindings. " "[Blueprint `vlan-aware-vms `_]" msgid "" "Add optional flag to control the advertisement in BGPVPNs of the routes " "defined on a Router resource (``bgpvpn-routes-control`` API extension)." msgstr "" "Add optional flag to control the advertisement in BGPVPNs of the routes " "defined on a Router resource (``bgpvpn-routes-control`` API extension)." msgid "" "Add osprofiler support to the neutronclient python binding. If osprofiler is " "initiated, neutronclient sends a special HTTP header that contains trace " "info." msgstr "" "Add osprofiler support to the neutronclient python binding. If osprofiler is " "initiated, neutronclient sends a special HTTP header that contains trace " "info." msgid "Add support to floating ip port forwarding." msgstr "Add support to floating ip port forwarding." msgid "" "By using this feature, multiple resource can be deleted using a single " "command." msgstr "" "By using this feature, multiple resource can be deleted using a single " "command." msgid "" "CLI support for 'Logging' feature, which enable to collect packet logs for " "specified resource. Currently, only security-group can be logged." msgstr "" "CLI support for 'Logging' feature, which enable to collect packet logs for " "specified resource. Currently, only security-group can be logged." msgid "CLI support for Layer 7 content policies and rules." msgstr "CLI support for Layer 7 content policies and rules." msgid "CLI support for Neutron-LBaaS v2 shared pools added." msgstr "CLI support for Neutron-LBaaS v2 shared pools added." msgid "CLI support for QoS policy RBAC." msgstr "CLI support for QoS policy RBAC." msgid "Current Series Release Notes" msgstr "Current Series Release Notes" msgid "Mitaka Series Release Notes" msgstr "Mitaka Series Release Notes" msgid "Neutron Client Release Notes" msgstr "Neutron Client Release Notes" msgid "Newton Series Release Notes" msgstr "Newton Series Release Notes" msgid "Ocata Series Release Notes" msgstr "Ocata Series Release Notes" msgid "Old Release Notes" msgstr "Old Release Notes" msgid "Pike Series Release Notes" msgstr "Pike Series Release Notes" msgid "Queens Series Release Notes" msgstr "Queens Series Release Notes" msgid "Rocky Series Release Notes" msgstr "Rocky Series Release Notes" msgid "Stein Series Release Notes" msgstr "Stein Series Release Notes" msgid "The ``rbac-create`` command include a --type qos-policy option." msgstr "The ``rbac-create`` command include a --type qos-policy option." msgid "The ``rbac-list`` command output includes a new 'type' column." msgstr "The ``rbac-list`` command output includes a new 'type' column." msgid "" "The ``subnetpool-create`` and ``subnetpool-update`` commands include a ``--" "is-default`` option." msgstr "" "The ``subnetpool-create`` and ``subnetpool-update`` commands include a ``--" "is-default`` option." msgid "" "The ``subnetpool-list`` and ``subnetpool-show`` command output includes the " "``is_default`` field." msgstr "" "The ``subnetpool-list`` and ``subnetpool-show`` command output includes the " "``is_default`` field." msgid "" "The ``tag-add`` command sets a tag on the network resource. It also includes " "``--resource-type``, ``--resource`` and ``--tag`` options." msgstr "" "The ``tag-add`` command sets a tag on the network resource. It also includes " "``--resource-type``, ``--resource`` and ``--tag`` options." msgid "" "This patch provides user the support to use any form of casing, thus " "removing the specific UPPER/lower case inputs required by different neutron " "CLIs." msgstr "" "This patch provides users the support to use any form of casing, thus " "removing the specific UPPER/lower case inputs required by different Neutron " "CLIs." msgid "" "This project no longer provides CLI support. All code has been removed. " "Please use openstack CLI instead. See `openstack CLI command list `_." msgstr "" "This project no longer provides CLI support. All code has been removed. " "Please use OpenStack CLI instead. See `openstack CLI command list `_." msgid "Train Series Release Notes" msgstr "Train Series Release Notes" msgid "Upgrade Notes" msgstr "Upgrade Notes" msgid "" "Using 'tenant_id' and 'tenant_name' arguments in API bindings is deprecated. " "Use 'project_id' and 'project_name' arguments instead." msgstr "" "Using 'tenant_id' and 'tenant_name' arguments in API bindings is deprecated. " "Use 'project_id' and 'project_name' arguments instead." msgid "Ussuri Series Release Notes" msgstr "Ussuri Series Release Notes" msgid "Victoria Series Release Notes" msgstr "Victoria Series Release Notes" msgid "Wallaby Series Release Notes" msgstr "Wallaby Series Release Notes" msgid "XML request format support has been removed." msgstr "XML request format support has been removed." msgid "Xena Series Release Notes" msgstr "Xena Series Release Notes" msgid "Yoga Series Release Notes" msgstr "Yoga Series Release Notes" msgid "Zed Series Release Notes" msgstr "Zed Series Release Notes" msgid "add --endpoint-type and OS_ENDPOINT_TYPE to shell client" msgstr "add --endpoint-type and OS_ENDPOINT_TYPE to shell client" msgid "add Lbaas commands" msgstr "add Lbaas commands" msgid "add NVP queue and net gateway commands" msgstr "add NVP queue and net gateway commands" msgid "" "add ability to update security group name (requires 2013.2-Havana or later)" msgstr "" "add ability to update security group name (requires 2013.2-Havana or later)" msgid "add commands for DHCP and L3 agents scheduling" msgstr "add commands for DHCP and L3 agents scheduling" msgid "add commands for agent management extensions" msgstr "add commands for agent management extensions" msgid "add flake8 and pbr support for testing and building" msgstr "add flake8 and pbr support for testing and building" msgid "add security group commands" msgstr "add security group commands" msgid "allow options put after positional arguments" msgstr "allow options put after positional arguments" msgid "improved support for listing a large number of filtered subnets" msgstr "improved support for listing a large number of filtered subnets" msgid "made the publicURL the default endpoint instead of adminURL" msgstr "made the publicURL the default endpoint instead of adminURL" msgid "openstack firewall rule create" msgstr "openstack firewall rule create" msgid "openstack firewall rule set" msgstr "openstack firewall rule set" msgid "openstack firewall rule unset" msgstr "openstack firewall rule unset" msgid "py26 support has been dropped." msgstr "py26 support has been dropped." msgid "py33 support has been dropped." msgstr "py33 support has been dropped." msgid "request-format option is deprecated." msgstr "request-format option is deprecated." msgid "support Neutron API 2.0" msgstr "support Neutron API 2.0" msgid "support XML request format" msgstr "support XML request format" msgid "support pagination options" msgstr "support pagination options" ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/mitaka.rst0000664000175000017500000000023200000000000024014 0ustar00zuulzuul00000000000000=================================== Mitaka Series Release Notes =================================== .. release-notes:: :branch: origin/stable/mitaka ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/newton.rst0000664000175000017500000000023200000000000024060 0ustar00zuulzuul00000000000000=================================== Newton Series Release Notes =================================== .. release-notes:: :branch: origin/stable/newton ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/ocata.rst0000664000175000017500000000023000000000000023633 0ustar00zuulzuul00000000000000=================================== Ocata Series Release Notes =================================== .. release-notes:: :branch: origin/stable/ocata ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/old_relnotes.rst0000664000175000017500000000133400000000000025243 0ustar00zuulzuul00000000000000================= Old Release Notes ================= 2.2.2 ----- * improved support for listing a large number of filtered subnets * add --endpoint-type and OS_ENDPOINT_TYPE to shell client * made the publicURL the default endpoint instead of adminURL * add ability to update security group name (requires 2013.2-Havana or later) * add flake8 and pbr support for testing and building 2.2.0 ----- * add security group commands * add Lbaas commands * allow options put after positional arguments * add NVP queue and net gateway commands * add commands for agent management extensions * add commands for DHCP and L3 agents scheduling * support XML request format * support pagination options 2.0 ----- * support Neutron API 2.0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/pike.rst0000664000175000017500000000021700000000000023501 0ustar00zuulzuul00000000000000=================================== Pike Series Release Notes =================================== .. release-notes:: :branch: stable/pike ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/queens.rst0000664000175000017500000000022300000000000024046 0ustar00zuulzuul00000000000000=================================== Queens Series Release Notes =================================== .. release-notes:: :branch: stable/queens ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/rocky.rst0000664000175000017500000000022100000000000023673 0ustar00zuulzuul00000000000000=================================== Rocky Series Release Notes =================================== .. release-notes:: :branch: stable/rocky ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/stein.rst0000664000175000017500000000022100000000000023666 0ustar00zuulzuul00000000000000=================================== Stein Series Release Notes =================================== .. release-notes:: :branch: stable/stein ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/train.rst0000664000175000017500000000017600000000000023672 0ustar00zuulzuul00000000000000========================== Train Series Release Notes ========================== .. release-notes:: :branch: stable/train ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/unreleased.rst0000664000175000017500000000016000000000000024675 0ustar00zuulzuul00000000000000============================== Current Series Release Notes ============================== .. release-notes:: ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/ussuri.rst0000664000175000017500000000020200000000000024075 0ustar00zuulzuul00000000000000=========================== Ussuri Series Release Notes =========================== .. release-notes:: :branch: stable/ussuri ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/victoria.rst0000664000175000017500000000021200000000000024364 0ustar00zuulzuul00000000000000============================= Victoria Series Release Notes ============================= .. release-notes:: :branch: stable/victoria ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/wallaby.rst0000664000175000017500000000020600000000000024202 0ustar00zuulzuul00000000000000============================ Wallaby Series Release Notes ============================ .. release-notes:: :branch: stable/wallaby ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/xena.rst0000664000175000017500000000017200000000000023504 0ustar00zuulzuul00000000000000========================= Xena Series Release Notes ========================= .. release-notes:: :branch: stable/xena ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/yoga.rst0000664000175000017500000000020000000000000023500 0ustar00zuulzuul00000000000000========================= Yoga Series Release Notes ========================= .. release-notes:: :branch: unmaintained/yoga ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/releasenotes/source/zed.rst0000664000175000017500000000016600000000000023336 0ustar00zuulzuul00000000000000======================== Zed Series Release Notes ======================== .. release-notes:: :branch: stable/zed ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/requirements.txt0000664000175000017500000000151600000000000021315 0ustar00zuulzuul00000000000000# 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. pbr!=2.1.0,>=2.0.0 # Apache-2.0 cliff>=3.4.0 # Apache-2.0 debtcollector>=1.2.0 # Apache-2.0 iso8601>=0.1.11 # MIT netaddr>=0.7.18 # BSD openstacksdk>=1.5.0 # Apache-2.0 osc-lib>=1.12.0 # Apache-2.0 oslo.i18n>=3.15.3 # Apache-2.0 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.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 requests>=2.14.2 # Apache-2.0 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1709201317.2456641 python-neutronclient-11.2.0/setup.cfg0000664000175000017500000002677700000000000017672 0ustar00zuulzuul00000000000000[metadata] name = python-neutronclient summary = CLI and Client Library for OpenStack Networking 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.8 classifier = Environment :: OpenStack Intended Audience :: Developers Intended Audience :: Information Technology Intended Audience :: System Administrators License :: OSI Approved :: Apache Software License Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 [files] packages = neutronclient [entry_points] openstack.cli.extension = neutronclient = neutronclient.osc.plugin openstack.neutronclient.v2 = 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 sfc_flow_classifier_set = neutronclient.osc.v2.sfc.sfc_flow_classifier:SetSfcFlowClassifier sfc_flow_classifier_show = neutronclient.osc.v2.sfc.sfc_flow_classifier:ShowSfcFlowClassifier sfc_port_chain_create = neutronclient.osc.v2.sfc.sfc_port_chain:CreateSfcPortChain sfc_port_chain_delete = neutronclient.osc.v2.sfc.sfc_port_chain:DeleteSfcPortChain sfc_port_chain_list = neutronclient.osc.v2.sfc.sfc_port_chain:ListSfcPortChain sfc_port_chain_set = neutronclient.osc.v2.sfc.sfc_port_chain:SetSfcPortChain sfc_port_chain_show = neutronclient.osc.v2.sfc.sfc_port_chain:ShowSfcPortChain sfc_port_chain_unset = neutronclient.osc.v2.sfc.sfc_port_chain:UnsetSfcPortChain sfc_port_pair_create = neutronclient.osc.v2.sfc.sfc_port_pair:CreateSfcPortPair sfc_port_pair_delete = neutronclient.osc.v2.sfc.sfc_port_pair:DeleteSfcPortPair sfc_port_pair_list = neutronclient.osc.v2.sfc.sfc_port_pair:ListSfcPortPair sfc_port_pair_set = neutronclient.osc.v2.sfc.sfc_port_pair:SetSfcPortPair sfc_port_pair_show = neutronclient.osc.v2.sfc.sfc_port_pair:ShowSfcPortPair sfc_port_pair_group_create = neutronclient.osc.v2.sfc.sfc_port_pair_group:CreateSfcPortPairGroup sfc_port_pair_group_delete = neutronclient.osc.v2.sfc.sfc_port_pair_group:DeleteSfcPortPairGroup sfc_port_pair_group_list = neutronclient.osc.v2.sfc.sfc_port_pair_group:ListSfcPortPairGroup sfc_port_pair_group_set = neutronclient.osc.v2.sfc.sfc_port_pair_group:SetSfcPortPairGroup sfc_port_pair_group_show = neutronclient.osc.v2.sfc.sfc_port_pair_group:ShowSfcPortPairGroup sfc_port_pair_group_unset = neutronclient.osc.v2.sfc.sfc_port_pair_group:UnsetSfcPortPairGroup sfc_service_graph_create = neutronclient.osc.v2.sfc.sfc_service_graph:CreateSfcServiceGraph sfc_service_graph_delete = neutronclient.osc.v2.sfc.sfc_service_graph:DeleteSfcServiceGraph sfc_service_graph_set = neutronclient.osc.v2.sfc.sfc_service_graph:SetSfcServiceGraph sfc_service_graph_list = neutronclient.osc.v2.sfc.sfc_service_graph:ListSfcServiceGraph sfc_service_graph_show = neutronclient.osc.v2.sfc.sfc_service_graph:ShowSfcServiceGraph bgp_dragent_add_speaker = neutronclient.osc.v2.dynamic_routing.bgp_dragent:AddBgpSpeakerToDRAgent bgp_dragent_list = neutronclient.osc.v2.dynamic_routing.bgp_dragent:ListDRAgent bgp_dragent_remove_speaker = neutronclient.osc.v2.dynamic_routing.bgp_dragent:RemoveBgpSpeakerFromDRAgent bgp_peer_create = neutronclient.osc.v2.dynamic_routing.bgp_peer:CreateBgpPeer bgp_peer_delete = neutronclient.osc.v2.dynamic_routing.bgp_peer:DeleteBgpPeer bgp_peer_list = neutronclient.osc.v2.dynamic_routing.bgp_peer:ListBgpPeer bgp_peer_show = neutronclient.osc.v2.dynamic_routing.bgp_peer:ShowBgpPeer bgp_peer_set = neutronclient.osc.v2.dynamic_routing.bgp_peer:SetBgpPeer bgp_speaker_list_advertised_routes = neutronclient.osc.v2.dynamic_routing.bgp_speaker:ListRoutesAdvertisedBySpeaker bgp_speaker_create = neutronclient.osc.v2.dynamic_routing.bgp_speaker:CreateBgpSpeaker bgp_speaker_delete = neutronclient.osc.v2.dynamic_routing.bgp_speaker:DeleteBgpSpeaker bgp_speaker_list = neutronclient.osc.v2.dynamic_routing.bgp_speaker:ListBgpSpeaker bgp_speaker_add_network = neutronclient.osc.v2.dynamic_routing.bgp_speaker:AddNetworkToSpeaker bgp_speaker_remove_network = neutronclient.osc.v2.dynamic_routing.bgp_speaker:RemoveNetworkFromSpeaker bgp_speaker_add_peer = neutronclient.osc.v2.dynamic_routing.bgp_speaker:AddPeerToSpeaker bgp_speaker_remove_peer = neutronclient.osc.v2.dynamic_routing.bgp_speaker:RemovePeerFromSpeaker bgp_speaker_set = neutronclient.osc.v2.dynamic_routing.bgp_speaker:SetBgpSpeaker bgp_speaker_show = neutronclient.osc.v2.dynamic_routing.bgp_speaker:ShowBgpSpeaker firewall_group_create = neutronclient.osc.v2.fwaas.firewallgroup:CreateFirewallGroup firewall_group_delete = neutronclient.osc.v2.fwaas.firewallgroup:DeleteFirewallGroup firewall_group_list = neutronclient.osc.v2.fwaas.firewallgroup:ListFirewallGroup firewall_group_set = neutronclient.osc.v2.fwaas.firewallgroup:SetFirewallGroup firewall_group_show = neutronclient.osc.v2.fwaas.firewallgroup:ShowFirewallGroup firewall_group_unset = neutronclient.osc.v2.fwaas.firewallgroup:UnsetFirewallGroup firewall_group_policy_create = neutronclient.osc.v2.fwaas.firewallpolicy:CreateFirewallPolicy firewall_group_policy_delete = neutronclient.osc.v2.fwaas.firewallpolicy:DeleteFirewallPolicy firewall_group_policy_add_rule = neutronclient.osc.v2.fwaas.firewallpolicy:FirewallPolicyInsertRule firewall_group_policy_list = neutronclient.osc.v2.fwaas.firewallpolicy:ListFirewallPolicy firewall_group_policy_remove_rule = neutronclient.osc.v2.fwaas.firewallpolicy:FirewallPolicyRemoveRule firewall_group_policy_set = neutronclient.osc.v2.fwaas.firewallpolicy:SetFirewallPolicy firewall_group_policy_show = neutronclient.osc.v2.fwaas.firewallpolicy:ShowFirewallPolicy firewall_group_policy_unset = neutronclient.osc.v2.fwaas.firewallpolicy:UnsetFirewallPolicy firewall_group_rule_create = neutronclient.osc.v2.fwaas.firewallrule:CreateFirewallRule firewall_group_rule_delete = neutronclient.osc.v2.fwaas.firewallrule:DeleteFirewallRule firewall_group_rule_list = neutronclient.osc.v2.fwaas.firewallrule:ListFirewallRule firewall_group_rule_set = neutronclient.osc.v2.fwaas.firewallrule:SetFirewallRule firewall_group_rule_show = neutronclient.osc.v2.fwaas.firewallrule:ShowFirewallRule firewall_group_rule_unset = neutronclient.osc.v2.fwaas.firewallrule:UnsetFirewallRule bgpvpn_create = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:CreateBgpvpn bgpvpn_delete = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:DeleteBgpvpn bgpvpn_list = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:ListBgpvpn bgpvpn_set = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:SetBgpvpn bgpvpn_show = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:ShowBgpvpn bgpvpn_unset = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:UnsetBgpvpn bgpvpn_network_association_create = neutronclient.osc.v2.networking_bgpvpn.network_association:CreateBgpvpnNetAssoc bgpvpn_network_association_delete = neutronclient.osc.v2.networking_bgpvpn.network_association:DeleteBgpvpnNetAssoc bgpvpn_network_association_list = neutronclient.osc.v2.networking_bgpvpn.network_association:ListBgpvpnNetAssoc bgpvpn_network_association_show = neutronclient.osc.v2.networking_bgpvpn.network_association:ShowBgpvpnNetAssoc bgpvpn_router_association_create = neutronclient.osc.v2.networking_bgpvpn.router_association:CreateBgpvpnRouterAssoc bgpvpn_router_association_delete = neutronclient.osc.v2.networking_bgpvpn.router_association:DeleteBgpvpnRouterAssoc bgpvpn_router_association_list = neutronclient.osc.v2.networking_bgpvpn.router_association:ListBgpvpnRouterAssoc bgpvpn_router_association_set = neutronclient.osc.v2.networking_bgpvpn.router_association:SetBgpvpnRouterAssoc bgpvpn_router_association_show = neutronclient.osc.v2.networking_bgpvpn.router_association:ShowBgpvpnRouterAssoc bgpvpn_router_association_unset = neutronclient.osc.v2.networking_bgpvpn.router_association:UnsetBgpvpnRouterAssoc bgpvpn_port_association_create = neutronclient.osc.v2.networking_bgpvpn.port_association:CreateBgpvpnPortAssoc bgpvpn_port_association_set = neutronclient.osc.v2.networking_bgpvpn.port_association:SetBgpvpnPortAssoc bgpvpn_port_association_unset = neutronclient.osc.v2.networking_bgpvpn.port_association:UnsetBgpvpnPortAssoc bgpvpn_port_association_delete = neutronclient.osc.v2.networking_bgpvpn.port_association:DeleteBgpvpnPortAssoc bgpvpn_port_association_list = neutronclient.osc.v2.networking_bgpvpn.port_association:ListBgpvpnPortAssoc bgpvpn_port_association_show = neutronclient.osc.v2.networking_bgpvpn.port_association:ShowBgpvpnPortAssoc network_loggable_resources_list = neutronclient.osc.v2.logging.network_log:ListLoggableResource network_log_create = neutronclient.osc.v2.logging.network_log:CreateNetworkLog network_log_delete = neutronclient.osc.v2.logging.network_log:DeleteNetworkLog network_log_list = neutronclient.osc.v2.logging.network_log:ListNetworkLog network_log_set = neutronclient.osc.v2.logging.network_log:SetNetworkLog network_log_show = neutronclient.osc.v2.logging.network_log:ShowNetworkLog vpn_endpoint_group_create = neutronclient.osc.v2.vpnaas.endpoint_group:CreateEndpointGroup vpn_endpoint_group_delete = neutronclient.osc.v2.vpnaas.endpoint_group:DeleteEndpointGroup vpn_endpoint_group_list = neutronclient.osc.v2.vpnaas.endpoint_group:ListEndpointGroup vpn_endpoint_group_set = neutronclient.osc.v2.vpnaas.endpoint_group:SetEndpointGroup vpn_endpoint_group_show = neutronclient.osc.v2.vpnaas.endpoint_group:ShowEndpointGroup vpn_ike_policy_create = neutronclient.osc.v2.vpnaas.ikepolicy:CreateIKEPolicy vpn_ike_policy_delete = neutronclient.osc.v2.vpnaas.ikepolicy:DeleteIKEPolicy vpn_ike_policy_list = neutronclient.osc.v2.vpnaas.ikepolicy:ListIKEPolicy vpn_ike_policy_set = neutronclient.osc.v2.vpnaas.ikepolicy:SetIKEPolicy vpn_ike_policy_show = neutronclient.osc.v2.vpnaas.ikepolicy:ShowIKEPolicy vpn_ipsec_policy_create = neutronclient.osc.v2.vpnaas.ipsecpolicy:CreateIPsecPolicy vpn_ipsec_policy_delete = neutronclient.osc.v2.vpnaas.ipsecpolicy:DeleteIPsecPolicy vpn_ipsec_policy_list = neutronclient.osc.v2.vpnaas.ipsecpolicy:ListIPsecPolicy vpn_ipsec_policy_set = neutronclient.osc.v2.vpnaas.ipsecpolicy:SetIPsecPolicy vpn_ipsec_policy_show = neutronclient.osc.v2.vpnaas.ipsecpolicy:ShowIPsecPolicy vpn_service_create = neutronclient.osc.v2.vpnaas.vpnservice:CreateVPNService vpn_service_delete = neutronclient.osc.v2.vpnaas.vpnservice:DeleteVPNService vpn_service_list = neutronclient.osc.v2.vpnaas.vpnservice:ListVPNService vpn_service_set = neutronclient.osc.v2.vpnaas.vpnservice:SetVPNSercice vpn_service_show = neutronclient.osc.v2.vpnaas.vpnservice:ShowVPNService vpn_ipsec_site_connection_create = neutronclient.osc.v2.vpnaas.ipsec_site_connection:CreateIPsecSiteConnection vpn_ipsec_site_connection_delete = neutronclient.osc.v2.vpnaas.ipsec_site_connection:DeleteIPsecSiteConnection vpn_ipsec_site_connection_list = neutronclient.osc.v2.vpnaas.ipsec_site_connection:ListIPsecSiteConnection vpn_ipsec_site_connection_set = neutronclient.osc.v2.vpnaas.ipsec_site_connection:SetIPsecSiteConnection vpn_ipsec_site_connection_show = neutronclient.osc.v2.vpnaas.ipsec_site_connection:ShowIPsecSiteConnection network_onboard_subnets = neutronclient.osc.v2.subnet_onboard.subnet_onboard:NetworkOnboardSubnets [egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/setup.py0000664000175000017500000000127100000000000017541 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # 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 setuptools setuptools.setup( setup_requires=['pbr>=2.0.0'], pbr=True) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/test-requirements.txt0000664000175000017500000000073200000000000022271 0ustar00zuulzuul00000000000000hacking>=6.1.0,<6.2.0 # Apache-2.0 bandit!=1.6.0,>=1.1.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 fixtures>=3.0.0 # Apache-2.0/BSD flake8-import-order>=0.18.0,<0.19.0 # LGPLv3 oslotest>=3.2.0 # Apache-2.0 osprofiler>=2.3.0 # Apache-2.0 python-openstackclient>=3.12.0 # Apache-2.0 python-subunit>=1.0.0 # Apache-2.0/BSD requests-mock>=1.2.0 # Apache-2.0 stestr>=2.0.0 # Apache-2.0 testtools>=2.2.0 # MIT testscenarios>=0.4 # Apache-2.0/BSD tempest>=17.1.0 # Apache-2.0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1709201286.0 python-neutronclient-11.2.0/tox.ini0000664000175000017500000000613700000000000017350 0ustar00zuulzuul00000000000000[tox] envlist = py39,pep8 minversion = 3.18.0 skipsdist = False ignore_basepython_conflict = True [testenv] basepython = python3 setenv = VIRTUAL_ENV={envdir} LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=C PYTHONWARNINGS=default::DeprecationWarning usedevelop = True 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 = 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} allowlist_externals = bash [testenv:pep8] commands = flake8 {[testenv:bandit]commands} distribute = false [testenv:venv] commands = {posargs} [testenv:cover] setenv = {[testenv]setenv} PYTHON=coverage run --source neutronclient --parallel-mode commands = stestr run {posargs} coverage combine coverage html -d cover coverage xml -o cover/coverage.xml coverage report [testenv:docs] deps = -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} -r{toxinidir}/doc/requirements.txt commands = sphinx-build -W -b html doc/source doc/build/html [testenv:pdf-docs] envdir = {toxworkdir}/docs deps = {[testenv:docs]deps} allowlist_externals = make commands = sphinx-build -W -b latex doc/source doc/build/pdf make -C doc/build/pdf [testenv:releasenotes] deps = -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} -r{toxinidir}/doc/requirements.txt commands = sphinx-build -a -E -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [flake8] # E126 continuation line over-indented for hanging indent # E128 continuation line under-indented for visual indent # H405 multi line docstring summary not separated with an empty line # I202 Additional newline in a group of imports # N530 direct neutron imports not allowed # TODO(amotoki) check the following new rules should be fixed or ignored # E731 do not assign a lambda expression, use a def # W504 line break after binary operator ignore = E126,E128,E731,I202,H405,N530,W504 show-source = true exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,tools import-order-style = pep8 # H106: Don't put vim configuration in source files # H203: Use assertIs(Not)None to check for None # H204: Use assert(Not)Equal to check for equality # H205: Use assert(Greater|Less)(Equal) for comparison # H904: Delay string interpolations at logging calls enable-extensions=H106,H203,H204,H205,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,B105