python-openstackclient-3.14.0/0000775000175100017510000000000013232364654016340 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/.coveragerc0000666000175100017510000000011413232364361020452 0ustar zuulzuul00000000000000[run] branch = True source = openstackclient [report] ignore_errors = True python-openstackclient-3.14.0/.stestr.conf0000666000175100017510000000014513232364361020606 0ustar zuulzuul00000000000000[DEFAULT] test_path=${OS_TEST_PATH:-./openstackclient/tests/unit} top_dir=./ group_regex=([^\.]+\.)+ python-openstackclient-3.14.0/HACKING.rst0000666000175100017510000000600613232364361020135 0ustar zuulzuul00000000000000OpenStack Style Commandments ============================ - Step 1: Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/ - Step 2: Read on General ------- - thou shalt not violate causality in our time cone, or else Docstrings ---------- Docstrings should ONLY use triple-double-quotes (``"""``) Single-line docstrings should NEVER have extraneous whitespace between enclosing triple-double-quotes. Deviation! Sentence fragments do not have punctuation. Specifically in the command classes the one line docstring is also the help string for that command and those do not have periods. """A one line docstring looks like this""" Calling Methods --------------- Deviation! When breaking up method calls due to the 79 char line length limit, use the alternate 4 space indent. With the first argument on the succeeding line all arguments will then be vertically aligned. Use the same convention used with other data structure literals and terminate the method call with the last argument line ending with a comma and the closing paren on its own line indented to the starting line level. unnecessarily_long_function_name( 'string one', 'string two', kwarg1=constants.ACTIVE, kwarg2=['a', 'b', 'c'], ) Text encoding ------------- Note: this section clearly has not been implemented in this project yet, it is the intention to do so. All text within python code should be of type 'unicode'. WRONG: >>> s = 'foo' >>> s 'foo' >>> type(s) RIGHT: >>> u = u'foo' >>> u u'foo' >>> type(u) Transitions between internal unicode and external strings should always be immediately and explicitly encoded or decoded. All external text that is not explicitly encoded (database storage, commandline arguments, etc.) should be presumed to be encoded as utf-8. WRONG: infile = open('testfile', 'r') mystring = infile.readline() myreturnstring = do_some_magic_with(mystring) outfile.write(myreturnstring) RIGHT: infile = open('testfile', 'r') mystring = infile.readline() mytext = mystring.decode('utf-8') returntext = do_some_magic_with(mytext) returnstring = returntext.encode('utf-8') outfile.write(returnstring) Python 3.x Compatibility ------------------------ OpenStackClient strives to be Python 3.3 compatible. Common guidelines: * Convert print statements to functions: print statements should be converted to an appropriate log or other output mechanism. * Use six where applicable: x.iteritems is converted to six.iteritems(x) for example. Running Tests ------------- Note: Oh boy, are we behind on writing tests. But they are coming! The testing system is based on a combination of tox and testr. If you just want to run the whole suite, run `tox` and all will be fine. However, if you'd like to dig in a bit more, you might want to learn some things about testr itself. A basic walkthrough for OpenStack can be found at http://wiki.openstack.org/testr python-openstackclient-3.14.0/PKG-INFO0000664000175100017510000001316413232364654017442 0ustar zuulzuul00000000000000Metadata-Version: 1.1 Name: python-openstackclient Version: 3.14.0 Summary: OpenStack Command-line Client Home-page: https://docs.openstack.org/python-openstackclient/latest/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description-Content-Type: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: http://governance.openstack.org/badges/python-openstackclient.svg :target: http://governance.openstack.org/reference/tags/index.html .. Change things from this point on =============== OpenStackClient =============== .. image:: https://img.shields.io/pypi/v/python-openstackclient.svg :target: https://pypi.python.org/pypi/python-openstackclient/ :alt: Latest Version .. image:: https://img.shields.io/pypi/dm/python-openstackclient.svg :target: https://pypi.python.org/pypi/python-openstackclient/ :alt: Downloads OpenStackClient (aka OSC) is a command-line client for OpenStack that brings the command set for Compute, Identity, Image, Object Store and Block Storage APIs together in a single shell with a uniform command structure. The primary goal is to provide a unified shell command structure and a common language to describe operations in OpenStack. * `PyPi`_ - package installation * `Online Documentation`_ * `Launchpad project`_ - release management * `Blueprints`_ - feature specifications * `Bugs`_ - issue tracking * `Source`_ * `Developer` - getting started as a developer * `Contributing` - contributing code * `Testing` - testing code * IRC: #openstack-sdks on Freenode (irc.freenode.net) * License: Apache 2.0 .. _PyPi: https://pypi.python.org/pypi/python-openstackclient .. _Online Documentation: https://docs.openstack.org/python-openstackclient/latest/ .. _Launchpad project: https://launchpad.net/python-openstackclient .. _Blueprints: https://blueprints.launchpad.net/python-openstackclient .. _Bugs: https://bugs.launchpad.net/python-openstackclient .. _Source: https://git.openstack.org/cgit/openstack/python-openstackclient .. _Developer: https://docs.openstack.org/project-team-guide/project-setup/python.html .. _Contributing: https://docs.openstack.org/infra/manual/developers.html .. _Testing: https://docs.openstack.org/python-openstackclient/latest/contributor/developing.html#testing Getting Started =============== OpenStack Client can be installed from PyPI using pip:: pip install python-openstackclient There are a few variants on getting help. A list of global options and supported commands is shown with ``--help``:: openstack --help There is also a ``help`` command that can be used to get help text for a specific command:: openstack help openstack help server create If you want to make changes to the OpenStackClient for testing and contribution, make any changes and then run:: python setup.py develop or:: pip install -e . Configuration ============= The CLI is configured via environment variables and command-line options as listed in https://docs.openstack.org/python-openstackclient/latest/cli/authentication.html. Authentication using username/password is most commonly used:: export OS_AUTH_URL= export OS_IDENTITY_API_VERSION=3 export OS_PROJECT_NAME= export OS_PROJECT_DOMAIN_NAME= export OS_USERNAME= export OS_USER_DOMAIN_NAME= export OS_PASSWORD= # (optional) The corresponding command-line options look very similar:: --os-auth-url --os-identity-api-version 3 --os-project-name --os-project-domain-name --os-username --os-user-domain-name [--os-password ] If a password is not provided above (in plaintext), you will be interactively prompted to provide one securely. Authentication may also be performed using an already-acquired token and a URL pointing directly to the service API that presumably was acquired from the Service Catalog:: export OS_TOKEN= export OS_URL= The corresponding command-line options look very similar:: --os-token --os-url Platform: UNKNOWN Classifier: Environment :: OpenStack 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 :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 python-openstackclient-3.14.0/.zuul.yaml0000666000175100017510000001545413232364361020307 0ustar zuulzuul00000000000000- job: name: osc-tox-unit-tips parent: openstack-tox description: | Run unit tests for OpenStackClient with master branch of important libs. Takes advantage of the base tox job's install-siblings feature. required-projects: - openstack/cliff - openstack/keystoneauth - openstack/os-client-config - openstack/osc-lib - openstack/python-openstackclient - openstack/python-openstacksdk vars: tox_envlist: py27 # Set work dir to openstackclient so that if it's triggered by one of the # other repos the tests will run in the same place zuul_work_dir: src/git.openstack.org/openstack/python-openstackclient - job: name: osc-tox-py27-tips parent: openstack-tox-py27 description: | Run unit tests for OpenStackClient with master branch of important libs. Takes advantage of the base tox job's install-siblings feature. # The job only tests the latest and shouldn't be run on the stable branches branches: ^(?!stable) required-projects: - openstack/cliff - openstack/keystoneauth - openstack/os-client-config - openstack/osc-lib - openstack/python-openstackclient - openstack/python-openstacksdk vars: # Set work dir to openstackclient so that if it's triggered by one of the # other repos the tests will run in the same place zuul_work_dir: src/git.openstack.org/openstack/python-openstackclient - job: name: osc-tox-py35-tips parent: openstack-tox-py35 description: | Run unit tests for OpenStackClient with master branch of important libs. Takes advantage of the base tox job's install-siblings feature. # The job only tests the latest and shouldn't be run on the stable branches branches: ^(?!stable) required-projects: - openstack/cliff - openstack/keystoneauth - openstack/os-client-config - openstack/osc-lib - openstack/python-openstackclient - openstack/python-openstacksdk vars: # Set work dir to openstackclient so that if it's triggered by one of the # other repos the tests will run in the same place zuul_work_dir: src/git.openstack.org/openstack/python-openstackclient - job: name: osc-functional-devstack-base parent: devstack description: | Base job for devstack-based functional tests pre-run: playbooks/osc-devstack/pre.yaml run: playbooks/osc-devstack/run.yaml post-run: playbooks/osc-devstack/post.yaml required-projects: - name: openstack/swift roles: - zuul: openstack-infra/devstack timeout: 9000 irrelevant-files: - ^.*\.rst$ - ^doc/.*$ - ^releasenotes/.*$ vars: devstack_localrc: SWIFT_HASH: '1234123412341234' LIBS_FROM_GIT: python-openstackclient # NOTE(dtroyer): OSC needs to support Image v1 for a while yet so re-enable GLANCE_V1_ENABLED: true # NOTE(dtroyer): Functional tests need a bit more volume headroom VOLUME_BACKING_FILE_SIZE: 20G devstack_local_conf: post-config: $CINDER_CONF: DEFAULT: # NOTE(dtroyer): OSC needs to support Volume v1 for a while yet so re-enable enable_v1_api: true devstack_services: ceilometer-acentral: false ceilometer-acompute: false ceilometer-alarm-evaluator: false ceilometer-alarm-notifier: false ceilometer-anotification: false ceilometer-api: false ceilometer-collector: false horizon: false s-account: true s-container: true s-object: true s-proxy: true osc_environment: PYTHONUNBUFFERED: 'true' OS_CLOUD: devstack-admin tox_install_siblings: false zuul_work_dir: src/git.openstack.org/openstack/python-openstackclient # The Neutron bits are here rather than in osc-functional-devstack-base to # simplify removing Neutron in the osc-functional-devstack-n-net job. - job: name: osc-functional-devstack parent: osc-functional-devstack-base timeout: 7800 vars: devstack_plugins: # NOTE(amotoki): Some neutron features are enabled by devstack plugin neutron: https://git.openstack.org/openstack/neutron devstack_services: neutron-segments: true q-metering: true q-qos: true tox_envlist: functional - job: name: osc-functional-devstack-n-net parent: osc-functional-devstack-base timeout: 7800 vars: devstack_localrc: FLAT_INTERFACE: br_flat PUBLIC_INTERFACE: br_pub devstack_services: n-cell: true n-net: true neutron: false neutron-segments: false q-agt: false q-dhcp: false q-l3: false q-meta: false q-metering: false q-qos: false q-svc: false tox_envlist: functional - job: name: osc-functional-devstack-tips parent: osc-functional-devstack timeout: 7800 required-projects: - openstack/cliff - openstack/keystoneauth - openstack/os-client-config - openstack/osc-lib - openstack/python-openstackclient - openstack/python-openstacksdk vars: devstack_localrc: USE_PYTHON3: true LIBS_FROM_GIT: python-openstackclient,python-openstacksdk,osc-lib,os-client-config # This is insufficient, but leaving it here as a reminder of what may # someday be all we need to make this work # disable_python3_package swift DISABLED_PYTHON3_PACKAGES: swift devstack_services: # Swift is not ready for python3 yet: At a minimum keystonemiddleware needs # to be installed in the py2 env, there are probably other things too... s-account: false s-container: false s-object: false s-proxy: false tox_envlist: functional - project-template: name: osc-tox-unit-tips check: jobs: - osc-tox-py27-tips - osc-tox-py35-tips gate: jobs: - osc-tox-py27-tips - osc-tox-py35-tips - project: name: openstack/python-openstackclient templates: - openstackclient-plugin-jobs - osc-tox-unit-tips check: jobs: - osc-functional-devstack # - osc-functional-devstack-n-net: # voting: false # # The job testing nova-network no longer works before Pike, and # # should be disabled until the New Way of testing against old clouds # # is ready and backported # branches: ^(?!stable/(newton|ocata)).*$ - osc-functional-devstack-tips: voting: false # The functional-tips job only tests the latest and shouldn't be run # on the stable branches branches: ^(?!stable) gate: jobs: - osc-functional-devstack python-openstackclient-3.14.0/CONTRIBUTING.rst0000666000175100017510000000107713232364361021003 0ustar zuulzuul00000000000000If 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-openstackclient python-openstackclient-3.14.0/.mailmap0000666000175100017510000000014313232364361017754 0ustar zuulzuul00000000000000 python-openstackclient-3.14.0/ChangeLog0000664000175100017510000031565613232364651020127 0ustar zuulzuul00000000000000CHANGES ======= 3.14.0 ------ * Updated from global requirements * Fix use of new openstacksdk connection * Rework Network client config for new SDK Connection * Replace assert with condition * Updated from global requirements * Corrected spelling mistake * Updated from global requirements * Fix indentation in authentication.rst * Partially Revert "Update new documentation PTI jobs" * Use Zuul v3 fetch-subunit-output * Updated from global requirements * Updated from global requirements * Add floating IP qos\_policy actions * Updated from global requirements * Check that Glance returns image data before processing it * Allow ports filtering with device\_id * Update new documentation PTI jobs * flavor: clarify --swap description * Switch to use stestr directly * Fix func tests: Ensure to pass OS\_CLOUD envvar * Updated from global requirements 3.13.0 ------ * Send 'changes-since' instead of 'changes\_since' query parameter * Fix SDK Connection creation alternative to Profile * Remove -U from pip install * openstack subnet create fails when tags is None * Avoid tox\_install.sh for constraints support * Make py27 and py35 versions and template of unit-tips jobs * Add cliff and keystoneauth to tips jobs * Remove a bunch of things we promised to remove in 2H 2017 * Release note cleanup * Set correct designate endpoint in docs * Make osc-tox-unit-tips work on other repos * Allow port list to shown undefined attributes * Updated from global requirements * Fix file mode on network-topology.rst * Add support for endpoing filter commands * Remove hard-coded policy choices for creating a server group * Fix credentials in create, update and list * Remove setting of version/release from releasenotes * Prepare for os-clinet-config to go away * Add logic to handle old and new sdk constructor * Updated from global requirements * Network: Add interfaces info in router show * Updated from global requirements * Show detailed message of neutron exception * Add RemoveNetwork command to server * Replace %r with %s on printing string variable * Updated from global requirements * Neutron agent delete: remove the wrong argument * Display Network QoS rule type details * Network: Add supports rbac target-all-projects * Updated from global requirements * Rehome test units lib * Zuul: add file extension to playbook path * Add python-rsdclient into plugin list * Add server rescue unit tests * Zuul job updates * Add missing parameters on openstack server rescue * Added AddNetwork command to server * Convert 'server' commands to use autoprogram * Native DevStack jobs * Add wrapper around ostestr * Accept 0 for --min-disk and --min-ram * Move more jobs in-repo * Attempt to de-race qos policy * Allow creating security rules without protocol * Move base functional test job in-repo * Switch to $USER in post\_test\_hooks * Avoid default mutable values in arguments * Be robust on import plugin module * auto-generate docs for v3 identity resources * Updated from global requirements * Support creating unaddress neutron port * Optimize getting endpoint list * Support icmp-type and icmp-code to be set as zero * Fix 'project purge' deletes ALL images problem * Update the documentation link for doc migration * Updated from global requirements * Add "volume service list --host" functional test case * Add functional test cases for "volume qos associate/disassociate" * Unroll the network qos policy functional tests * Add python-zunclient plugin * Attempt to work around chronically failing server issues with aggregates and qos * Fix subunit collection in functional tests with ostestr>=1.0.0 * Updates for stestr * Updated from global requirements * Updated from global requirements * Correct import of keystoneauth1 session * Skip Volume v1 functional tests if v1 not present * Fix output for subnet show * Useless line of code in shell.py * Updated from global requirements * Updated from global requirements * Update image cli doc and fix some typos * Updated from global requirements * Convert remaining network functional tests to JSON * Convert network qos functional tests to JSON * Convert network security group functional tests to JSON * Fix "openstack image unset" command's help message typo * flake8-import-order: Ensure to place project imports last * Implied Roles * Updated from global requirements * auto-generate object docs * Revert "Disable karborclient until a fixed version is released" * Use flake8-import-order plugin * Allow PD as Subnetpool during Subnet creations * Imported Translations from Zanata * Convert network segment functional tests to JSON * Update release/stable branch table in docs * Update reno for stable/pike * Add .htaccess for docs migration * Add new commands for karbor osc plugin * Updated from global requirements * Replace guildelines with guidelines * Updated from global requirements * Updated from global requirements * Updated from global requirements * network functest: Remove condition for segment test * Use instance variables for subnet tests * Skip object-store functional tests when Swift is not available 3.12.0 ------ * Add optional parameter "user\_id" and "type" to list credentials * network tag UT: avoid using mix-in test class * wrong values in openstack quota show command * Update the documentation link for doc migration * Network tag support * Updated from global requirements * Release note cleanup for 3.12.0 * Updated from global requirements * Updated from global requirements * Add domain parameter to Identity Provider * Start using 'cliff.sphinxext' * Updated from global requirements * Clean up the changes of os.environ in functional tests * Minor followup to network agent docs * Fix dynamic names in network functional tests * Disable karborclient until a fixed version is released * Add support for virtio-forwarder VNIC type * Fix 'domain' filter not work well in some commands * Fix column names for server list --no-name-lookup * Updated from global requirements * image-list should support filters 'name','status' * Add 'data\_plane\_status' option to Port classes * Fix unit test failures related to new os-client-config and osc-lib * Network L3 Router Commands for OSC * Add server list -n and --no-name-lookup arguments * Use openstackdocstheme in release note * Add the other commands for karbor osc plugin * Allow objects to be streamed to stdout * Add new parameter "is\_default" to Network QoS policy * Fix man page build * Add missing barbican commands * Added 'openstack image set --visibility' * Add python-octaviaclient plugin * Remove inaccurate mapping of 'host-meta' in csv * Updated from global requirements * Updated from global requirements * switch to openstackdocstheme * Use identity auth v3 the README examples * Updated from global requirements * update the docs URLs in the readme * move auto-generated api docs into contributor tree * reorganize existing documentation according to the new standard layout * Enable some off-by-default checks * Now OSC server create check keys in --nic * When creating a trust, send role\_ids instead or role\_names * Add direction field to QoS bandwidth limit * Show neutron tags in OSC network show * Add support for Karbor Plugin * Add project purge command to osc * Don't show hint about vlan transparent in network set * Add default-quota to subnet pool commands * Updated from global requirements * Fix Mapping Guide Error * Updated from global requirements * volume functest: ensure snapshots deleted when volume delete * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Trivial fix typos * Replace "Display Name" by "Name" in volume list * JSON-ify image functional tests * Use \_get\_token\_resource in role assignment list * Updated from global requirements * Create server with security group ID and name * Refactor Extension show and list command * Updated from global requirements * Convert image functional tests into JSON format * Convert volume functional tests into JSON format * Make block-device-mapping more stable and clear * Correct the "extra spec" command openstack * Updated from global requirements * Ignore more exceptions in quota list * Rework floating ip functional tests 3.11.0 ------ * Do not always init compute\_client when doint port list * Skip floating ip attach functional test on nova-net * Updated from global requirements 3.10.0 ------ * Funcional tests: quota list * Nova-net functional tests: aggregates * Functional tests: Identity v2 and DevStack * Updated from global requirements * Fix volume qos spec list * Nova net functional tests round 3 * Nova net functional tests round 2 * Nova net functional tests round 1 * Fix Nova-net netowrk commands * Fix quota functional tests for nova-net * Fix server create with nova-net * Updated from global requirements * Functional test for subnet\_pool * Fix NoneType error for volume snapshot create command * Improve no-auth path * Remove ipdb installation in tox debug section * Make test\_server.py more elegant and simple * Fix network list functional test * Explicitly set 'builders' option * Low-level Compute v2 API: floating ip pool * Low-level Compute v2 API: network * Split network tests * Updated from global requirements * Low-level Compute v2 API: floating ip * Low-level Compute v2 API: security group rules * Low-level Compute v2 API: security group * Add document about renaming OS\_ENDPOINT\_TYPE to OS\_INTERFACE * Split floating IP tests * Update to tox.ini * Add --network and --port to server create * Updated from global requirements * Split security group tests * Allow override of distributed router flag * Clean up password prompt work-arounds * "floating ip set/unset port" for OSC * Add "qos-policy" option to "port create" & "port set" * Structure FindFloatingIP() to work without ip\_cache * Enable to specify which fixed-ip to add to a vm * Correct flavor associate/disassociate commands in Mapping Guide * Help/docs cleanups: marker, limit, ip-address metavars * Release notes cleanup for 3.10.0 release * Enable to add/remove port to/from a server * Introduce neutron flavor associate, disassociate to OSC * Add help commands withouth auth in functional * Fix block-device-mapping when volume\_size is empty * Enable to create legacy router * Trivial Fix * Updated from global requirements * Use Sphinx 1.5 warning-is-error * doc: Correct Sphinx warnings * doc: Remove local fork of apidoc * Change noauth strategy for plugin loading * Fix volume transfers request commands * Doc: Fix link in network flavors * OSC Extension Show * Remove log translations * Fix Trivial Changes in [1] * Support to add/remove multi users for "group add/remove user" * Simplify logic around option lists in port set * Enable to specify which vm fixed-ip to publish * Introduce Neutron DHCP agent commands to OSC * docs: Don't include ChangeLog * OSC Network Flavor Profile * Make MAC address of port updatable * Non-Admin can't list own projects * Updated from global requirements * Narrow expected responses for CheckUserInGroup * Add extra filtering options to qos policy list * Adds missing flavor information in the server list long command * Functional test for ip\_availability * OSC Quota List * Fix reference in network flavor create command reference * Refactor ServerTests and ServerEventTests functional test classes * Fix "security group list" command to display project ID properly * Trivial Fix * Jsonify meter and meter rule functional tests * Revert "Fix port command for SDK >0.9.10" * Fix handling the use\_default\_subnet\_pool attribute * Add sort support to project list * Add the bgp agent type to network agent command * Remove py34 tox env and pypi classifier * command list: Move network meter appropriately * Add server event list and show commands 3.9.0 ----- * Updated from global requirements * Cleanup release notes for 3.9.0 release * Trivial Fix * add neutron CLI to decoder * Normalize the gnocchiclient docs entry * Add "--private-key" option for "keypair create" * Trivial Fix * Updated from global requirements * Jsonify network flavor functional tests * Nit: Trivial doc formatting fix for network flavor * Use \*\_as\_ids instead \*\_as\_list * Add a validation about options for server migrate command * Updated from global requirements * Update doc/source/command-objects/image.rst * Port set/unset SecGroup Bug Fix * Fix output of ListSecurityGroupRule * openstack image create : --file and --volume exclude each other * Fix can not set is\_default in network * Support --no-property in "volume set" command * Revert unit tests for quota commands * Support list commands by group name keyword * Auto allocated topology for OSC * minor tweaks to mapping table * add keystone and glance -> osc mapping * Fix "endpoint list" help message * Show openstacksdk version info in "module list" * OSC Network Flavor * Fix properties format for volume qos in volume v1 * Rework port functional tests on json output format * add volume->osc mapping * add swift and nova to osc mapping * Add Cinder v3 client support for volumes * TODO cleanup: osc-lib * Remove text about OSC as a plugin requirement * Remove unused logging import * Remove remaining uses of SDK Proxy.session * Finish converting server functional tests to JSON format * Remove quota set workaround for SDK <0.9.13 * Fix image selection in server function tests * Fix "server create" command failed when --nic auto or none * Use public and unified method get\_console\_url() * Handle log message interpolation by the logger in compute/ * Handle log message interpolation by the logger in network/ * Handle log message interpolation by the logger in identity/ * Updated from global requirements * Overwrite/Clear Flavor property * Refactor volume functional test in volume v1 * Updated from global requirements * Updated from global requirements * Modify error handling for role and group commands * Fix --parents and --children options in project show * Add --fixed-ip option to the port list command * Fix wrong behavior of parsing plugin service name * Fix "module list --all" failed * NIT: replace os with openstack in command example * mention the final ocata osc version in releasenotes * SDK refactor: Set "is\_admin\_state\_up" for network agent * TODO cleanup: OSC\_Config * Add mitaka release notes to master * Update reno for stable/ocata 3.8.1 ----- * Add relnotes for the two recent bug fixes * Fix network create --project * Fix address scope list --share 3.8.0 ----- * Fix sphinx errors * Updated from global requirements * Cleanup for 3.8.0 release * Switch server create to block\_device\_mapping\_v2 * Support "--no-property" option in volume snapshot set * Adds domain specification for SetUser * Add options to "server list" command * Fix Identity functional tests to not require OS\_AUTH\_URL * change assert\_show\_fields to not fail on new fields * Add server\_boot\_from\_volume() test * Fix 'mapping set' return value * Add server test for image and flavor lookups * Updated from global requirements * Use image client for images instead of compute * Update container format choices * Handle 403 error on creating trust * SDK refactor: Prepare security group commands * Add meter rule to OSC * Update devref about "--no-property" * Fix OSC networking commands help errors * Functional tests debug support * Switch to use cleanup method in functional test * Fix functional test for creating subnet * Functional test for router * Functional test for subnet * Functional test for volume qos * Remove the fixed set of choices for network\_type * Add plugin adoption for trove * Error in the return of command server show, create * Error in the return of command 'volume qos create' * Functional test for volume snapshot * Update functional test for aggregate * Updated from global requirements 3.7.0 ----- * Release 3.7.0 cleanup * Fix quota set command error for SDK > 0.9.10 * SDK refactor: Prepare network agent commands * Updated from global requirements * unskip port test * Use git+file urls instead of directories * Fix quota show --default command * Fix network functional tests for sdk 0.9.12 * Fix floating IP delete and show by IP * Add "encryption-\*" options in volume type commands * Fix subnet creating failure in functional test * fix functional tests for network agents * Fix security group rule list for NEtwork v2 * Install from /opt/stack/new instead of git.o.o * Fix quota show output * unskip network qos rule type functional test * Fix image member unit tests occasional failures * Fix flavor create help re swap size units * Fix Network QoS rule CLI attrs parsing * Add unit test for multi volume types delete * add support for running tests with master dependencies * To display image size in human friendly format * Updated from global requirements * Add support for Network QoS rule commands * Make 'object save' fast again * Fix Octavia gate breakage caused by \_get\_columns() * functional test for volume * Fix port command for SDK >0.9.10 * Fix filter error in os volume list * Add --project and --project-domain option to "volume snapshot list" * add domain id to expected IdP fields, unskip tests * skip tests related to SDK 0912 and keystone IdP change * Functional tests - flavor * Add options to allow filtering on agent list * Fix network service provider functional test * Fix "ip availability show" command * Updated from global requirements * Fix creating a private flavor with ID auto * Functional tests - port * Add support for Glance 'update image members' feature * Fixes image api URL endpoint for certain scenario * Remove unneeded methods from OS\_Config class * Error handling for delete commands in identity * Update the description format * Add ":option:\` \`" in the help message * OSC Network Meter * Beef up floating IP functional tests * Beef up address scope functional tests * Beef up network functional tests * update server migrate '--wait' description * Revert "WIP: Skip broken functional tests..." * Updated from global requirements * Fix a spelling error * Fix typo in release notes * Add unit tests for usage commands in compute v2 * Test-requirements.txt: Bump Hacking to 0.12 * Updated from global requirements * WIP: Skip broken functional tests.. * To support '--project' and '--project-domain' options * Add support for QoS rule type commands * Update earliest-version number format in release notes * Should support 'auto' and 'none' as network parameter when boot instances * Fix all missing "os to openstack" transformation * Add '--type'and other options to network rbac list 3.6.0 ----- * Fix the missing os in command in example * Add 'allowed address pairs' option to 'port create/set/unset' * change os in command example to openstack(3) * change os in command example to openstack(2) * change os in command example to openstack * Add support for clearing router gateway * Introduce overwrite functionality in \`\`osc router set\`\` * Add one test for "backup set" command * Add doc for Searchlight client * Tivial:update the description format in volume\_snapshot.py * Add filtering options to the address scope list command * Add support for setting router gateway * Add ploop to supported disk formats * SDK refactor: Prepare network commands * Updated from global requirements * [TrivialFix] Fix typo error 3.5.0 ----- * SDK Refactor: Prepare port commands * 3.5.0 release note cleanup * Updated from global requirements * Add two consistency group commands * SDK Refactor: Prepare router commands * Add "--remote-source" option to "volume snapshot create" command * update plugins documentation * Add extra filtering options to floating ip list * Correct missspellings of secret * Add '--force' option to 'volume snapshot delete' command * Modified API calls in os usage * Trivial: update volume-qos.rst * Add "consistency-group-snapshot" option to consistency group create * Add "consistency group set" command * Add --default option to "volume type list" * Add some options to "volume create" command * Revert "Remove marker and loop from "image list" command" * Remove auth\_with\_unscoped\_saml decorator * SDK Refactor: Prepare ip availability commands * Adjust the code sequence in consistency\_group.py * Avoid duplicated project\_id when show network resources * Add "dns-name" option to "os port create" and "os port set" * Add "consistency group show" command * Add "consistency group delete" command * Updated from global requirements * Updated from global requirements * Correct reraising of exception * Add '--project' and '--project-domain' options to os cmds * Add functional test for volume service * Add network service provider list to OSC * Add \`--enable/disable-port-security\` option to \`port set\` and \`port create\` * Add unit tests for server create in computev2 * Trivial:modify one parameter * Refactor availability zone functional test * Add QoS support to Network object * Introduce overwrite functionality in \`\`osc subnet set\`\` * Functional test for configuration * Functional test for aggregate * Refactor module functional test * Add choices for option '--policy' * Fix description errors in volume fakes * DevRef fix for network qos policy * Add options to "volume snapshot list" command * Show team and repo badges on README * Functional test for agent * Add "volume host set" command * Updated from global requirements * Functional test for server group * clean up image choices and help text * Add "--type" and "--retype-policy" options to "volume set" command * TrivialFix in helpMessage for readability * Updated from global requirements * Add "Is Public" column in volume type list * Remove outdated comments in volume unit test * Fill the missing colon * Add "volume host failover" command * Sort list images by name by default * SDK Refactor: Prepare security group rule commands * SDK Refactor: Prepare network rbac commands * SDK Refactor: Prepare network qos policy commands * SDK Refactor: Prepare subnet commands * Add commands for "consistency group snapshot" 3.4.1 ----- * Add relnote for release 3.4.1 * Use project\_domain\_id only in password auth * Using v2 as the default version of Glance * Add "consistency group create" command 3.4.0 ----- * translate all command help strings * Updated from global requirements * 3.4.0 release note cleanup * Do proper deprecation for security group rule create * Outdated test data clean up in volume * TrivialFix: Insert blank space for readability * Updated from global requirements * Updated from global requirements * Add '--network' and other options to floating ip list * Show disk format vhdx in help * network.common.NetworkAndComputeShowOne: catch HttpException * Updated from global requirements * Add 'description' option * Add 'all-projects' option to 'volume backup list' * Add options to "volume backup list" command * Updated from global requirements * Not appropriate name sg rule attribute * SDK refactor: Prepare floating ip commands * Refactor "snapshot" commands * Updated from global requirements * Add filtering options --name,--enable,--disable to router list * Support --provider-\* options in the network list command * Add --long option and more columns to the hypervisor list command * Adds information about private key generation for instance access * Updated coverage configuration file * Avoid duplicated project\_id when show network * Updated from global requirements * update openstackclient page url * update volume and zone commands * Improve a network testcase * Use FakeImage class to replace duplicated image info in volume test * Updated from global requirements * Correct help string of the subnet pool list options * Allow input the QoS policy name in network rbac create command * Updated from global requirements * Add option to allow filtering by mac-address on port list * Updated from global requirements * Warning for empty password set for user create/set * Reset allocation pools to [] instead of '' * Rename variable to avoid shadowing of built-in name * Add "--read-only" and "--read-write" options in "volume set" * Add "volume migrate" command * Add description field port create & port set * Add support make a router HA * Add necessary info to Floating IP list * properly format error messages for volume resizing * Updated from global requirements * Update the doc for Zaqar v2 * Updated from global requirements * Add direction and protocol options to os security group rule list cmd * Updated from global requirements * Add a new column and a new option the 'os port list' cmd * Add security groups options to "port create/set/unset" * Fix --shared/block-migration options in server migrate command * Add network support for Network QoS policies * Fix router unset --route option * Redefine set/unset command devref * Refactor image v1 unit tests with FakeImage class 3.3.0 ----- * More 3.3.0 release notes * Improve output of supported API versions * Enable release notes translation * Updated from global requirements * Mask passwords in debug logs for auth\_config\_hook * SDK Refactor: Prepare subnet pool commands * SDK Refactor: Prepare network segment commands * SDK Refactor: Prepare address scope commands * Updated from global requirements * Refactor qos spec unit test in volume v1 * Add --ha option to os router create command * Updated from global requirements * Document \`openstack complete\` help and usage * Add example in the doc when using Identity v3 * Updated from global requirements * Update default nova api version to 2.1 * Remove beta label for network segment resource * Add and modify options for "volume create" command * Implement "consistency group list" command * Updated from global requirements * fix doc information in the limit.rst * Replace 'MagicMock' with 'Mock' * Add translation markers for object commands * Add option "--name" to command "openstack object create" * Add default limit for container/object * Add command option parameter in console-url.rst * Updated from global requirements * Add warning message for --state option of set command in volume * Align '=' for developing.rst and newton.rst * Updated from global requirements * remove square backet to required parameter * Remove reference to CLI Ref in osc doc * Add option markup in osc doc * Fix typo in osc doc * Add functional test for snapshot in volume v1 * Support "--no" option in aggregate set * Updated from global requirements * Add --description to Neutron commands * Add unit tests for backup commands in volume v1 * Use assertGreater replace assertTrue * Fix unset commands to pass normally when nothing specified * Add square bracket to option parameter * Updated from global requirements * Implement "volume transfer request show/accept" command * Align '=' for image.rst * Add "volume backup set" command in volume v2 * Add filtering options to os network list command * Updated from global requirements * Fix "volume unset" command pass normally when nothing specified * Use correct router add/remove interface methods * Refactor volume unit test with FakeVolume class in volume v1 * replace metavar "volume-id" with "volume" to avoid ambiguity * Overwrite/Clear support for subnets * Introduce overwrite functionality in \`\`osc port set\`\` * Remove unnecessary setUp * Add 'description' option to os subnet (pool) create/set cmd * Add --description to Create/Set Network * Clean up docs and notes for 3.3.0 release * Provide support to list ports by network * Add filtering options to os subnet pool list command * Add filtering options to os subnet list command * Fix quota-update issue in LBaaS * Fix Quota Support for HMs * Correct login name deduction in SshServer * router list if availability\_zone ext not enabled * Support mark volume as bootable in volume set * Doc, help and message updates for port unset * Replace 'MagicMock' with 'Mock' * Support listing specified server's ports * Fix openstack quota set/show --class not work * Support fetching network project default quota * Add functional tests for unset multiple volume type props * Set quota "per\_volume\_gigabytes", "backup\_gigabytes" and "backups" * Unit tests of quota command refactor * Trivial: Rename ListTransferRequests to ListTransferRequest * Display hypervisor information without uptime * Fix regular expression for uptime in hypervisor show * Add unit test for volume type in volume v1 * Implement "volume transfer request delete" command * Implement "volume transfer request create" command * Error handling of multi REST API calls for "snapshot set" command * Add "--limit" and "--marker" options to "volume list" command * Support error handling for delete commands in volume v1 * Multi REST API calls error handling of "volume unset" command * remove the old post\_test\_hook * remove duplicate unit test * unwedge the gate * Add network segment create, delete and set support * move all functional tests to tests module * move unit tests to new "unit" test module * Defer auth prompting until it is actually needed * standardize release note page ordering * Do not show "os-volume-type-access:is\_public" property of volume type * better functional test collection * format token expires time to prevent json loading datetime data * Update reno for stable/newton * Use assertIn(A, B) instead of assertTrue(A in B ) * Updated from global requirements * Rearrange integration tests * Updated from global requirements 3.2.0 ----- * Updated from global requirements * Add importing file to import warnings * Provide fallback prompt function for current osc-lib * Fix auth prompt brokenness * Updated from global requirements * Cleanup after install 3.1.0 ----- * Fix six typos * Updated from global requirements * Clean imports in code * Updated from global requirements * Restore default auth-type for token/endpoint * Updated from global requirements * [docs] fix incorrect rst markups * Clean up FakeClient classes in volume fakes 3.0.1 ----- * Work around a version clash issue with os-client-config * Fix post and periodic jobs 3.0.0 ----- * Updated from global requirements * Add Subnet service-types to subnets * Integ test cleanup * Fix up last-minute imports to use osc-lib * document locale and language support tips * Add shell integration test * Gate-unbreaking combo review * Add "volume service set" command * update requirements and test requirements * Fix errors in volume set/unset image properties unit tests * Rename backup commands in volume v1 and v2 * Add support for domain specific roles * Fix OSC identity v3 functional tests * Implement "network agent set" command * Add '--dhcp' and '--no-dhcp' options to os subnet list cmd * Add --ip-version filtering option to subnet.rst * Support multi REST API calls error handling for "volume set" command * Updated from global requirements * osc-lib: shell * Implement network agents functionality * Show "target\_project\_id" attribute properly for network rbac object * Add unit tests for group commands in identity v3 * Updated from global requirements * Updated from global requirements * Remove an outdated directory in tox.ini * Add support of setting volume's state * Implement "network rbac set" command * Add a document for required options * Refactor identity v3 unit tests with fake class * Updated from global requirements * OS\_DEFAULT\_DOMAIN must be an ID * Updated from global requirements * Document network trunk commands * Update the description of project in releasenotes * Updated from global requirements * Pass security group id to novaclient while adding security group to server * Implement network rbac create and delete commands * Allow setting quotas for server groups and server group members * Add support for deleting volumes with associated snapshots * arguments are not locale decoded into Unicode * Use identity fake classes instead of old unit tests data * Remove temporary code in ClientManager * Use assertEqual() instead of assertDictEqual() * Add options to "volume type list" command * Add "--marker" and "--limit" options to "snapshot list" * Unit test of credential in identityv3 * Add assignment list to v2 identity and deprecate alternate listing * Rework clientmanager * Clarification of option name rules * Remove execute permission on a few files * Fix error for find\_service() in identity * Standardize import format * Remove discover from test-requirements * Add Support for showing flavor access list * Support to get server rdp/serial/mks type console url * Updated from global requirements * Set identity v3 client in networkv2 fake * Show project access for volume type * Transfer "ip floating CRUD" to "floating ip CRUD" * Updated from global requirements * Exchange the check order for the dhcp and no-dhcp * Support bulk deletion for delete commands in identityv3 * Updated from global requirements * Unskip the tests affected by warlock 1.3.0 * Follow upper constraints for all tox targets * Add create\_one\_image\_member() in FakeImage class and update test * Update doc for credential in indentityv3 * Updated from global requirements * Allow format selection in get\_opts * Change to plural form of object in multi delete error message in networkv2 * Support error handling for delete commands in volumev2 * Make set/unset commands pass normally when nothing specified in identityv3 * Temp work around for missing select\_auth\_plugin() * Add "--project" option to "volume type create" command * Change the wrong import order * Modify some help and error messages in ec2creds identityv2 * image list: Add Checksum column * Add Python3.5 to setup.cfg tox.ini * Add "--incremental" option to "backup create" command in volume v2 * Pass security group id to novaclient * Make the doc build reproducible * Modify compute agent set command * Use FakeProject and FakeDomain classes in unit tests of networkv2 * Add missing "Volume version 2 only" message in backup.rst * Remove useless dest of option in volume v1&v2 * Updated from global requirements * remove unused LOG * Updated from global requirements * Remove FakeService.get\_services * Add notes, modify notes in fakes docstring * Add network-topolopy support * Unskip tests caused by bug 1599333 * Added a note on how to test changes * Correct reraising of exception * modify notes in the FakeHypervisorStats docstring * fix one spelling mistake and two help messages * "server list": "Image Name", "Image ID" columns * Add '--force' option to 'backup delete' command in volumev2 * Add "--property" option to "snapshot create" command in volumev2 * fix some spelling mistakes in doc/ * skip failing tests due to bug 1599333 is fixed * Deduplicate get\_opts methods * Add python-neutronclient to OSC plugins * fix a few spelling mistakes * Remove useless dest of option in "snapshot create" command * Add missing '(name only)' message for keypair in computev2 * Refactor unit tests for project and domain with fake classes in identityv3 * Transfer "ip fixed add/remove" to "server add/remove fixed ip" * Transfer "ip floating add/remove" to "server add/remove floating ip" * Transfer "ip floating pool list" to "floating ip pool list" * Updated from global requirements * Add command to unset information from ports * Add "--snapshot" option to "backup create" command in volumev2 * update plugin documentation * osc-lib: api.auth * Add command to unset information from Subnet-pools * Fix doc issue for "compute agent list" command * Add port security option to network commands * Add "--property" option to "flavor create" command * Add command to unset information from Subnets * Add "--force" option to "volume qos delete" command * Support bulk deletion for delete commands in computev2 * Update Fakes.py and unit tests for commands in identity V2.0 * Modify few words and change output format for command "ip floating list" * skip image tag tests * Change "ID only" to "name or ID" for backup commands * Add command to unset information from Routers * Add "--force" option to "backup create" command in volumev2 * Make set/unset command in volume pass normally when nothing specified * Modify some unusual help messages in computev2 * Implement rbac list and show command * Add unit tests for "host list" and "host show" commands * Fix several flake8 code style issues in compute tests * Make code more compact for get\_list\_opts function * Remove code forgotten in cb28fb55884a9be7cd70c37343181116cf000a42 * Support multi-delete for commands in identity V2 * Fix the problem of router delete * Updated from global requirements * Improve server functional tests * Standardize logger usage of catalog in identity * Use resource id when name given for identity show * Fix typo in openstackclient/network/v2 * Remove OSCGenericPassword plugin * Refactor unit test of "compute service list" command * Add FakeObject classes to fakes.py, update unit tests in identity V2 * Fix errors for "host set" command * Fix token/endpoint auth plugin * Updated from global requirements * Add "--project" option to the "flavor create" command * Fix a missing i18n support in security\_group\_rule.py * Make set/unset commands in compute/image/common return normally when nothing specified * Improve masking of secrets in configuration show * Refactor setting defaults for some scope parameters * Refactor check\_valid\_auth\_options function * Make the print info support i18n * Support bulk deletion for "flavor/aggregate delete" * Add "--device-owner" option to "port list" * use env vars to specify OS\_IDENTITY\_API\_VERSION * Support JSON data for port binding profile * support multi-delete for volume-type * Standardize logger usage * Use osc\_lib in server\_image.py * Error handling of "router delete" command * Do not prompt for scope options with default scoped tokens * Updated from global requirements * Modify help msg and docs in identity * Make set/unset command in identity and image pass normally when nothing specified * move release note to correct directory * Fix console url show command broken in microversion case * Support bulk deletion for delete commands in networkv2 * Add "--password-prompt" to user.rst * Modify doc issues about property option of aggregate * Add functional test for "aggregate unset" command * Add doc for logger usage * Fix help msg of identity endpoint * Finish osc-lib transition for command.py * Fix volume functional tests * Setup deprecate msg for command.py * Add default IP version and fix help messages for "ip availability list" * Support bulk deletion for commands that exist in both network and compute * Standardize logger usage in volume * Remove blank line in release notes * Add release note for network endpoint type bugfix * Fix missing i18n supports in api/ and shell.py * Fix foundation copyrights * Ensure endpoint type is used for network commands * Support compute service force down/up * Fix errors in \`\`set/unset flavor\`\` unit tests * Fix i18n problems for common files in identity * osc-lib: timing * osc-lib: command * osc-lib: parseractions * osc-lib: logs * osc-lib: utils * osc-lib: exceptions * Add "--network-segment" option to "subnet create" * Fix errors in flavor unit tests * Fix image delete multiple arguments error * Trivial: Fix coding style in examples in doc * Add geneve provider network type * Use osc-lib and set up deprecation warnings * Updated from global requirements * Moving authentication from keystoneclient to keystoneauth * Updated from global requirements * Fix network * Remove duplicate file logger formatter setting * Make set/unset commands in network return normally when nothing specified * Clean up fakes.py in volumev2 * Fix compute service set command * Modify unit tests of compute agent delete * Error handling for KeyValueAction class * Set up 3.x release notes 2.6.0 ----- * Release note cleanups for 2.6.0 * Fix i18n supports in commom * Add Tox prerequisites and installation * Update unit test test\_extension with fake class * Support error handling for "port delete" command * Fix i18n support problems in identity * Add functional tests for IP availability * Fix release note links to (now) external docs * Fix errors for "volume type unset" command * fix keypair help msg * Add newline to strings in stdout/stderr.write() * modify server group * fix image unset * Add server set/unset unit test cases * Updated from global requirements * Add support for volume transfer request list * Refactor SetService --enable/disable option * Make set/unset commands in volume return normally when nothing specified * Imported Translations from Zanata * Add network availability for osc * Move server image create command to its own resource file * Modify the style of translated messages * Check port name in set port tests * Fix wrong test in flavor unit tests * Fix some missing i18n support problems in compute * Updated from global requirements * Support multiple argument for compute agent delete command * Update v2 endpoint show help * Fix --enable options on commands * Add support for removing flavor-access * Trivial: Remove duplicated line in man page * Updated from global requirements * Modify lowercase to uppercase * Updated from global requirements * Trivial: Fix i18n support in network/common.py * Fix unit test for volume commands in volumev2 * include old release notes in reno * add unit test for compute agent command * Add FakeQos class and update unit test for qos\_specs in VolumeV2 * Updated from global requirements * Fix i18n support in cinder * Add support for setting flavor-access * Support to set server state * Add "image unset" command * Fix output and error log in server.py * Support deleting multi address scopes in networkv2 * Fix functest "test\_server\_metadata()" in test\_sever.py * Fix help message for "server group delete" command * Add network segment command object * [compute] Add server backup function * i18n support for leftover exception messages in volume * Do not require an scope when setting a password * fix endpoint show help 2.5.0 ----- * keystone: fix catalog output when region is unset * Release notes cleanup * Refactor service unit tests * Search by user defined ID for service providers * Updated from global requirements * Fix i18n support for help and error messages in compute * Search by user defined ID for identity providers * i18n support for help and error messages in cinder * Add FakeType class and update volumetype test in VolumeV2 * Add some functional tests for commands in VolumeV2 * Updated from global requirements * Add FakeSnapshot class and update snapshot test in VolumeV2 * Add functional tests for server group in ComputeV2 * Fix image tests to use warlock resources * Avoid TypeError on message object additions * Add network support for "quota set" * Fix i18n support for help and log.warning in image * Updated from global requirements * Refactor TestVolumeShow with FakeVolume * Add FakeBackup class and updata backup unittest in volumeV2 * Add ip version filter to subnet list * Added CONTRIBUTING.rst file * Add VLAN Transparent option to \`\`osc network\`\` * Fix i18n support for help and error msg in network * Refactor TestRemoveProjectImage with FakeImage class * Added --no-route to the router set command * Updated from global requirements * Changed the nomenclature of credentials command * Additional network protocol support * Refactor TestImageList with FakeImage class * Refactor TestAddProjectToImage with FakeImage class * remove #noqa from i18n imports * Pep8 environment to run on delta code only * Refactor TestVolumeList with FakeVolume * Fix functional test for floatingip add/remove in ComputeV2 * Implement "address scope set" command * Implement "address scope show" command * Implement "address scope list" command * Implement "address scope delete" command * Implement "address scope create" command * Add unit tests for "server show" command * Updated from global requirements * Use find\_resource() instead of get() in \_prep\_server\_detail() * Ignore domain related config when using with keystone v2 * Fix functional test failures * Map server power state num to meanful string * Updated from global requirements * Trivial: Remove unuseful comments for assertRaise() checking * Remove unnecessary type conversions in network unit tests * Ignore domain related config when using with keystone v2 * Fix network router type display * bump timeout to prevent gate failures * Added "name" parameter to the help message * Add a unit test for "flavor create" command * Add describe of overwrite options behavior into devref * remove assert in favor an if/else * Spec to Implement IP Availability * Make "flavor show" command to show a private flavor properly * Documentation updates * Replace tempest-lib with tempest.lib * add a bandit environment to tox * Fix error in flavor set/unset command * Add functional tests for commands of floating ip * Fixes BadRequest when no --pool-prefix given * Support for volume service list * Doc: Add network resource descriptions * Devref: Command Beta * Support quota show for current project * Fix server group document issue * Add commands of clustering service to doc * Add new share and default parms to subnet pool cmds * Updated from global requirements * Fixed subnet command host route output * Trivial: Fix an omited i18n issue * Update tests for server * Add "server group show" command * Add "server group list" command * Add "server group delete" command * Add "server group create" command * Support X.latest format for OS\_COMPUTE\_API\_VERSION * Fix mutable default arguments in tests 2.4.0 ----- * Rename --profile to --os-profile * Updated from global requirements * Update keypair tests * Fix client certificate/key support for Network v2 commands * Imported Translations from Zanata * Deduplicate CLI output parser code in test.py * Add provider network options to osc network set * Clean up for next release * Add options to security group rule list * Fix router set --route option * Initialize neutron client with region name * Updated from global requirements * Remove methods argument from vloume/v2/fakes.py * State i18() changes and help messages improved * Add support for removing volume-type-access * Fix wrong attribute name and add functional test for --snapshot * Remove methods argument from FakeHypervisorStats * Propagate AttributeErrors when lazily loading plugins * Add external network options to osc network set * Trivial: Fix incorrect comment text * Enhance exception handling for "network delete" command * Append existing information during port set * Use CommandFailed exception from tempest\_lib * Updated from global requirements * Fix prefixes output for subnet pool list * Doc: Unify repeatable option comments * Remove fake methods code from compute network * Add Testing Ref in README.rst * Add project options to security group rule create * Add network options to security group rule create * Add support for setting volume-type-access * Move keys() methods in each resource class to FakeResource * Add --address-scope option "subnet pool create/set" * Fix pep8 fail that crept in * use correct manager for volume snapshots * Fix SSL/TLS verification for network commands * Doc: Fix network command documentation issues * Append existing information during subnet set * TrivialFix: Rename provider segment option * Updated from global requirements * Updated from global requirements * Clean up release notes since 2.2.0 release * TrivialFix: Fix help messages for port set * Add option to clear information from ports * Make snapshot and backup name optional * Prefer assertEqual/assertIn over assertOutput/assertInOutput * Correct addCleanup use in functests * Support client certificate/key * Add provider network options to osc network create * Add external network options to osc network create * Fix typos in docstrings and comments * Improve tmpfile cleanup in functests * Remove unused method cleanup\_tmpfile * Use fixtures and addCleanup instead of tearDown * Log hint when --enable present with --disable-reason * Trivial: Rename FakehypervisorStats to FakeHypervisorStats * Add name option to 'port set' * rxtx factor should be a float * Don't mask authorization errors * Add default value to pool-prefix in Subnet-pool * Devref: Options with Multiple Values * Doc: Add missing command objects * Add --project to "subnet pool create" * Follow Boolean Option rule * Add fixed keypair create functional test * Fix subnet pool prefix length option * Wrong param type in compute-service.rst * Remove unused method 'from\_response' * Aggregate object should be "grouping of compute hosts" * Docs cleanup: volume command help * Docs cleanup: volume type * Docs cleanup: sort subnet commands * Refactor security group rule list to use SDK * Added functional tests for 'service provider' v3 commands * Add unit tests for compute v2 aggregate * Add "aggregate unset" to osc * Subnet: Add "subnet set" command using SDK * [Floating IP] Neutron support for "ip floating create" command * Support security group name for --src-group * Refactor security group rule create to use SDK * Trivial: Fix typo in common/limits.py * Fix "server unset" document issue * Use assert\_called\_once\_with() instead of assert\_called\_with() * Add Subnet add/remove support to router * Remove superfluous variable assignment statements * Style fix for one line docstring according to flake8 * Add "router remove port" to osc * Add "router add port" to osc * Updated from global requirements * Image API v2: make volume\_type optional * Improve error for token issue command without auth * Devref: Document OSC interfaces available to plugins * Fix keypair create --public-key * Functional tests for openstackclient help messages * Trivial-Fix : Add a ' to the choices documentation * update docs with status of plugins * Fix options in port create/set * Updated from global requirements * Add option to allow filtering by router on port list * Add support for deleting Image-property * Add support for setting Image-property * Sort commands in docs * Doc: Fix documentation errors for command object * Support "--long" option in ListService * Use assertItemsEqual() instead of assertListEqual() * Trivial: Add release note for "subnet pool create" command * Fix dict.keys() compatibility for python 3 * Add doc describing how to handle API errors * Add project options to security group create * Add incompatibility info for "ip floating list" command * Enhance list extension unit test * Trivial: Reorder classes in identity v3 in alphabetical order * Update reno for stable/mitaka * Add "os subnet create" command using SDK * Refactor security group create to use SDK * Refactor security group show to use SDK * Add subnet pool functional tests * Fixed command list * Trivial: Use 'SSH' rather than 'Ssh' * [Identity] Check return value is None in identity v3 unit tests * Add --reason for disable service * Remove FakeFlavorResource class * Add support of setting snapshot state * Add port functional tests * Add 'port set' command * [Subnet pool] Add 'subnet pool create' command support * [Subnet pool] Add 'subnet pool set' command support * Trivial: Fix incorrect comments in compute fakes.py * remove py26 workaround in osc * [Identity] Check return value is None in identity v3 unit tests * Add port list command * Trivial: Remove useless return * Use \_get\_columns() to obtain columns in network.py * Add release note for security group set refactor * Test take\_action() instead of run() in unit tests * Updated from global requirements * Add 'port create' command * Add subnet functional tests * Updated from global requirements * Updated from global requirements * " openstack server image create " doesn't print proper info 2.2.0 ----- * Fix test\_aggregate functional test * [Volume] Check return value is None in volume unit tests * Fix incorrect unit test for router * Refactor security group set to use SDK * Updated from global requirements * Trivial: Reorder unit tests in alphabetical order in volume tests * [Image] Check return value is None in image unit tests * Support "network create" command in nova network * Add test cases to test some commands with '--wait' and fix bug * Devref: Options with Choices * Clean up unnecessary import of urlparse module * Trivial: Update image\_list v2 docs * Fix regression in interactive client mode * Fix 'code-block' tag format issues * TrivialOrder: Rearrange Class Names * add a checklist for creating a new plugin * Trivial: Reorder flavor op order in flavor.py * Subnet: Add "subnet delete" command using SDK * fix: Exception message includes unnecessary class args * Refactor security group list to use SDK * take\_action() method from command.Command shouldn't return * Trivial: Reorder unit tests in test\_type.py * Fix return value of "image set" command * [Compute] Check return value is None in compute unit tests * Router: Add --route and --clear-routes options to "router set" command * Add MultiKeyValueAction to custom parser action * Make SetAggregate inherit from cliff.Command * Make SetAgent inherit from cliff.Command * Make SetSecurityGroup inherit from cliff.Command * Make SetFlavor and UnsetFlavor inherit from cliff.Command * Add missing command/configuration object * Updated from global requirements * [compute] Add set host command * Add shell --profile option to trigger osprofiler from CLI * update heat object and command doc * Add some test cases for "server list" command * Floating IP: Neutron support for "ip floating show" command * Improve tox to show coverage report on same window * Py3 replace dict.iteritems with six.iteritems * Updated from global requirements * Defaults are ignored with flake8 * Fixed a bunch of spacing * Add "security group rule show" command * Fix wrong return value in TestDeleteFloatingIPNetwork * Use update\_parser\_common() in ShowNetwork * [compute] Support restore server * [compute] Add unit test for keypair * Use instanceof instead of type * Add "os subnet show" command using SDK * Initialize \_keys in \_\_init\_\_() in FakeFlavorResource * Add unit tests for 'hypervisor stats' command * Clean redundant argument to dict.get * Add functional tests for "volume" commands v2 * Add functional tests for "image" command v2 * Updated from global requirements * Add unit test for "flavor show" command * Refactor: Set "project\_id" for FakeXXX in a consistent style * Fix Mutable default argument * gitignore .idea * Trivial: Rename subnet\_pool.rst to subnet-pool.rst * Replace string format arguments with function parameters * Support unscoped token request * Use assertIsNone() instead of assertEqual(None, xxx) * Don't use Mock.called\_once\_with that does not exist * Floating IP: Fix "ip floating list" in neutron network * Subnet Pool: Add "subnet pool show" command * Subnet Pool: Add "subnet pool list" command * Remove unused test-requirments * Subnet Pool: Add "subnet pool delete" command * Support "network show" command in nova network * Support "network list" command in nova network * Add release note for "network delete" command for nova network * Define FakeFloatingIP class in tests/compute for nova network commands * Add release note for "ip floating delete/list" commands for neutron network * Fix 'openstack --help' fails if clouds.yaml cannot be read * Rename parameter "identifier" to "network" in network commands * Use assertRaises() to check if an exception is raised * Support "network delete" command in nova network * Floating IP: Neutron support for "ip floating list" command * Floating IP: Neutron support for "ip floating delete" command * Updated from global requirements * Add quota functional tests * Add NetworkAndCompute Lister and ShowOne classes * Fix identity test\_role functional tests * Trivial: Fix a typo in test\_network.py * Updated from global requirements * Refactor network AZ exception handling * Refactor security group rule delete to use SDK * Identity: Fix DisplayCommandBase comments for cliff ShowOne subclass tests * Identity: Fix DisplayCommandBase comments for cliff Lister subclass tests * Identity: Fix DisplayCommandBase comments for cliff Command subclass tests * Trivial: Fix "abstractmethod" to "abstract method" * Fix DisplayCommandBase comments for cliff ShowOne subclass tests * Add "token revoke" for identity v3 * Fix DisplayCommandBase comments for cliff Lister subclass tests * Fix DisplayCommandBase comments for cliff Command subclass tests * Updated from global requirements * Add release note for custom logging feature * Add release note for recursive delete * Add unit tests for "hypervisor show" command * Compute: Fix DisplayCommandBase comments for cliff ShowOne subclass tests * Compute: Fix DisplayCommandBase comments for cliff Lister subclass tests * Compute: Fix DisplayCommandBase comments for cliff Command subclass tests * Remove identity\_client.projects definition in TestSecurityGroup * Define security\_group\_rules mock in FakeComputev2Client * Move security\_groups mock definition to FakeComputev2Client * Fix formatting in release 2.0.0 notes * Fix some release note formatting * Add recursive object delete for containers * Refactor security group functional tests * Add functional tests for snapshots * Add support for triggering an crash dump * Add unit tests for "hypervisor list" command * Allow custom log levels for other loggers 2.1.0 ----- * Use assert\_not\_called() in common tests * Minor typo in help text * Fix a spell typos * Add --marker option to "image list" command * Add limit option to "image list" command * Remove marker and loop from "image list" command * Trivial: Reorder test class in test\_volume.py into alphabetical order * Fix wrong type of volume attachments in FakeVolume * Refactor TestVolumeCreate to use FakeVolume * Refactor security group delete to use SDK * Add "os port show" command * Support listing network availability zones * Trivial: Fix wrong comment in test\_image.py * Network: Abstract get\_body() out to be a private helper * Drop log\_method decorator * Updated from global requirements * Consume openstackclient.common.command in subnet/port * Fix showing network quotas for a project * Add missing release notes * log take\_action parameters in a single place * Revert "Skip identity v2 functional tests" * Skip identity v2 functional tests * Add availability zone support for router commands * Update translation setup * Add availability zone support for network commands * Allow wait\_for\_delete to work for all clients * Updated from global requirements * Return names in list role assignments * Remove the Tuskar client * Use correct terminology for subnets * Updated from global requirements * Add releasenote for 'subnet list' command support * Add router functional tests * Subnet List * Updated from global requirements * Refactor abstract columns and datalist out in image and object test cases * Updated from global requirements * Add python-searchlightclient to list of adopters * Refactor abstract columns and datalist out in compute test cases * log\_method: get logger from decorated method if unspecified * Set up logger of each command by metaclass * Refactor: Abstract columns and datalist out in volume test cases * Add support to delete the ports * Initialize activation status * Imported Translations from Zanata * Updated from global requirements * Doc: Network is supported for extension object * Change --owner to --project in image commands * Support listing volume availability zones * Refactor "os availability zone list" * Changed the abstract columns and datalists from test cases of common and Identity * Updated from global requirements * Support non-interactive user password update * Use assertTrue/False instead of assertEqual(T/F) * Replace assertEqual(\*, None) with assertIsNone in tests * Updated from global requirements * Further improve output for "os security group show" * Delete the unused LOG configure code * Refactor network endpoint enablement checking * Implementation for project unset cmd for python-openstackclient * Enabling domain lookup for project set v3 command * Docstring should say 'default' if option is default * Trivial: Remove useless string\_to\_bool() * Refactor: Initialize parser in setUp() in TestNonNegativeAction * Refactor: Initialize parser in setUp() in TestKeyValueAction * Replace assertEqual(None, \*) with assertIsNone(\*) * Functional tests for security group rule * Improve output for "os security group show" * Add all regions to cloud configuration * Updated from global requirements * Add owner validation for "openstack image create/set" * TestServerGeneral: Add test for \_prep\_server\_detail() * TestServerGeneral: Add test for \_format\_servers\_list\_networks() * Trivial: Remove useless return from files in image and volume * Trivial: Remove useless return from files in network * Add support to list all security group rules * Replace assertEqual(None, \*) with assertIsNone in tests * Trivial: Remove useless return from files in compute * Add image re/deactivate commands * Router: Add "router show" command using SDK * Router: Add "router set" command using SDK * Refactor TestImageCreate with FakeImage class * Updated from global requirements * Router: Add "router delete" command using SDK * Network: Improve no option test for "network create" * Router: Add "router create" command using SDK * Remote security group name not displayed for rule * when fetching object store properties use lower() * Doc: Add optional command specs process * Removes MANIFEST.in as it is not needed explicitely by PBR * Updated from global requirements * Deprecated tox -downloadcache option removed * Router: Add "router list" command using SDK * Router: Add class FakeRouter to test "router xxx" command * Trivial: Improve unclear comments in test\_server.py * Make --image parameter optional in "server rebuild" * Trivial: Fix parameter name typo in network.rst * Trivial: Do not use plural format in command parameter in "network delete" * Map some of the SDK field names * TestServerGeneral: Add test for \_format\_servers\_list\_power\_state() * Remove python-neutronclient requirement * Fix poorly named test mocks * Remove old code after sdk integration * SDK integration extensions and server create networks * Add unit test for TestServerList to test --long option * Add multi deletion testcase for "openstack image delete" * Refactor TestImageDelete with FakeImage * Remove unuseful test data in test\_netwrok.py * Migrate network client to SDK * Migrate "network show" command to use SDK * Migrate "network set" command to use SDK * Migrate "network delete" command to use SDK * Migrate "network create" command to use SDK * Fix "sevice show" cannot catch NoUniqueMatch Exception * The format\_exc method does not take an exception * Migrate "network list" command to new version using SDK * Trivial: Coding style fix in test\_flavor.py * Use FakeVolume in server test cases * Use FakeImage in server test cases * Add source security group support to create rule * SDK integration: Add a temporary method to create network client using sdk * Introduce class FakeNetwork to fake one or more networks * Use formatter in server.py for "server list" tests * Updated from global requirements * Trivial: Import network.common as network\_common in server.py * Refactor network test: Remove unusful test code * Refactor TestShowNetwork: Use TestNetwork in TestShowNetwork * Refactor TestSetNetwork: Use TestNetwork in TestSetNetwork * Refactor TestListNetwork: Use TestNetwork in TestListNetwork * Refactor TestDeleteNetwork: Use TestNetwork in TestDeleteNetwork * Refactor TestCreateNetwork: Setup identity client in setUp() in TestCreateNetworkIdentityV2 * Refactor TestCreateNetwork: Setup identity client in setUp() in TestCreateNetworkIdentityV3 * Refactor TestCreateNetwork: Setup cmd in setUp() in TestCreateNetworkIdentityV2 * Refactor TestCreateNetwork: Setup cmd in setUp() in TestCreateNetworkIdentityV3 * Refactor TestCreateNetwork: Split TestCreateNetwork into two classes for identity v2 and v3 * Refactor network test: Introduce TestNetworkv2 and TestNetwork to improve unit test of network * Trivial: Remove unuseful doc of "network list" command * Trivial: Improve doc for "server create" command * Updated from global requirements * Fix exception when doing volume set operation 2.0.0 ----- * Trivial: Reorder doc of "server shelve" command to keep alphabetic order * Convert 2.0 release notes to reno format * Add reno for release notes management * Add multi deletion testcase for openstack volume delete * Add class TestServerList to provide basic unit test for "server list" command * Enable setup\_servers\_mock() to take attributes param * Introduce FakeImage class * Switch to ksa Session * Add release notes for 2.0.0 * Support "server list" searching by both image name and ID * Support "server list" searching by both flavor name and ID * autodocument commands from plugins using stevedore.sphinxext * Remove list output from "compute service set" * Add --limit option to "server list" command * Add --marker option to "server list" command * Updated from global requirements * Add a changelog to see all changes into tagged releases * Integrating mistralclient with openstackclient * Add testcases for compute.v2.service * Consistency of the --all argument for snapshots * Introduce FakeVolume class * Add unit testcases for "openstack flavor delete" * Add project name/ID validation for "openstack quota show" * Add status column for "openstack image list" * Change the home-page value in setup.cfg * Remove old fake flavor data * Use FakeFlavor in TestServerCreate * User FakeFlavor in TestServerResize * Use FakeFlavor in TestFlavorUnset * Use FakeFlavor in TestFlavorSet * Use FakeFlavor in TestFlavorList * Introduce class FakeFlavor to fake one or more flavors * Refactor: Move FakeFlavorResource to compute\_fakes.py * Refactor: Abstract datalist out in TestFlavorList to avoid redundant code * Refactor: Abstract columns out in TestFlavorList to avoid redundant code * Add "openstack server unshelve" into OSC * Fix a bug of "openstack volume delete" * Use Block Storage instead of Volume * Add unit tests for "server stop" command * Add unit tests for "server start" command * Add unit tests for "server resume" command * Add unit tests for "server suspend" command * Add unit tests for "server unlock" command * Add unit tests for "server lock" command * Add unit tests for "server unpause" command * Abstract a helper function for server.xxx() tests * Add multiple servers test case to TestServerDelete * Use setup\_servers\_mock() in the base class in TestServerDelete * Move setup\_servers\_mock() to class TestServer * Trivial: Fix typo in find() in network * Trivial: Fix a typo * Change 'Object Store' to 'Object Storage' * Use is\_public to set access of volume type * Refactor: Order of security group class names * Move FakeServer to tests.common.v2.compute.fakes * Trivial: Add missing doc for parameter in wait\_for\_delete() * Add functional tests for network crud * Remove py26 support * Doc: Update and add IP address * Doc: Add security group and security group rule * Enable "openstack server resume" command to take multiple servers * Enable "openstack server suspend" command to take multiple servers * Add "openstack server shelve" into OSC * Trivial: Fix wrong doc for wait\_for\_status() * Updated from global requirements * Remove the old fake server data * Use class FakeServer in TestServerResize * Use class FakeServer in TestServerImageCreate * Use class FakeServer in TestServerDelete * Use class FakeServer in TestServerCreate * Add command wrapper doc * Trivial: Remove doc for non-existing param in format\_dict() * Unable to set some compute quotas * Add --volume to Image \`create\` * Have configuration tests support OCC * Add unit tests for "server pause" command * Introduce random server faking mechanism * Enable FakeResource to fake methods * Allow error status to be specified * Remove deprecated 'project usage list' command * Remove LICENSE APPENDIX 1.9.0 ----- * Add release notes for 1.9.0 * Improve "server list" command to have the same output as "nova list" * Enable "openstack server unlock" command to take multiple servers * Enable "openstack server lock" command to take multiple servers * Enable "openstack server unpause" command to take multiple servers * Add capability to update description of an IdP * validate non-ascii values for swift properties * Trivial: Fix wrong param name in comment * Split the vol\_id from a dev mapping * better format remote IDs for identity providers * Trivial: Fix wrong param name in comment * Trivial cleanup: Use plural format for "server delete" doc * Set default network api to 2.0 instead of 2 * Fix the bug of "openstack console log show" * Enable "openstack server pause" command to take multiple servers * Change method to get the user\_id * Use fake server name instead of id when testing "server\_name" param * Fix a bug about "openstack server list --user" * Add --owner to \`image create\` * Trivial: Fix wrong comment of \_format\_servers\_list\_networks() * Add "server stop" command to osc * Add "server start" command to osc * Allow int version numbers in the clouds.yaml * Import the module not the class * Add project-name/-id validation for the OSC "openstack quota set" * Imported Translations from Zanata * Fix the bug of "openstack usage show" * Rename context.py to logs.py * Allow debug to be set in configuration file * Updated from global requirements * Trivial clean up: Add doc for "osc server lock/unlock" * Trivial clean up: do not use plural form in command arguments * Fix issue when displaying image\_member * Add Command Options guideline doc * remove url from v3 regions * Support pagination params for flavor list 1.8.0 ----- * Add release notes for 1.8.0 * Updated from global requirements * Follow-on for volume list - add tests, clean help * Add compute service delete * Add filtering by project/user for 'openstack volume list' * Updated from global requirements * Move session and fixtures to keystoneauth1 * Remove cliff-tablib from requirements.txt * Updated from global requirements * Updated from global requirements * Mask the sensitive values in debug log * Fix functional tests for Python 3.4 * Fix up object-store show commands * Change Identity API default version to 3 * Add a table showing all the openstack plugin objects * unwedge the gate * Fix a typo in commands.rst * Fix typos in authentication.rst * Updated from global requirements * Add test for role list --inherited * Fix non-ascii issue with object commands * Add ID column to compute service list * image set should not show the resource * Add tags to \`image set\` * Clean up Image v2 image set command * Evaluate --inherited in role list * Set object store arg order in docs * Update the plugin docs * add set/unset support for objects in object store * add support for set/unset of container properties * Updated from global requirements * Rename swift account commands * Add one parenthesis * cleanup account ids from container commands * Add support for showing account details * Add support for updating swift account properties * Add tests for find\_resource() * Imported Translations from Zanata * Mark arguments for 'credential' commands as required * attempt to find resource by listing * Additional exception handling for find\_resource * Add shields.io version/downloads links/badges into README.rst * docs: pip install -e needs an argument * Glance \`image set\` Resolve Fracturing 1.7.0 ----- * Add release notes for 1.7.0 * Use format\_list instead of format\_dict when listing images * Format an images properties and tags * Add image create support for image v2 * Change ignore-errors to ignore\_errors * Imported Translations from Zanata * Remove backticks from help in role commands * Move option logging back to start if initialize\_app() * Set default auth plugin back to 'password' * Updated from global requirements * Image fix bug with --volume * set image api to 1 for functional tests * Updated from global requirements * Use \`discover\_extensions\` for novaclient * Imported Translations from Transifex * Use novaclient.client.Client for initialization Nova client * Add filtering by user for 'openstack server list' * Add support for listing servers of other projects * Support listing users by group name * Fix compute API version snafu * Properly handle port arguments for ICMP * Use a common decorator to log 'take\_action' activation * Fix 'auhentication' spelling error/mistake * Volume v2 list does not show server name * Ignore flavor and image find errors on server show * Create log configuration class * default OS\_VOLUME\_API\_VERSION to v2 * Automate flavors, networks, and image get * unwedge the osc gate * additional functional tests for identity providers * Adds documentation on weekly meeting * Update the plugin docs for designate * Added note to install openstackclient * Override the debug default and help text * Running 'limits show' returns nothing * Optimize log formatting * Extract log level from configuration file * Move options to log level out of shell.py * Move set warnings filters to logging module * Updated from global requirements * Updated from global requirements * Updated from global requirements * Add tests for volume quota set 1.6.0 ----- * Use correct domain to find project * Updated from global requirements * Skip functional test: test\_server\_up * Updated from global requirements * Remove non-existing hacking deviations from doc * Update plugin documentation * Set up every time record log in file * Add release notes for 1.6.0 * Add developer documentation * Add --inherited to the role docs * Rename command docs to remove underscores * Inherited info/option when listing role assignment * Alphabetize setup.cfg * Add set feature to volume type v2 * Add list feature to volume v2 * Fixes inherited role assignments CRUD calls * Fix quota show when there is no project id * Add functional test for volume type create --property * Imported Translations from Transifex * Updated from global requirements * Added a new function test for volume type set * Introduce functional test for Identity Provider * Add domain scoping in 'role assignment list' * Removed unnecessary assignment of function result Joined lines together * New test for configuration show --mask * add new test for configuration show unmask * Minor Documentation changes for code samples * Set OS\_VOLUME\_API\_VERSION before running functional tests * Added test for \`volume type show\` * Add functional tests for volume type list * New test for configuration show * Imported Translations from Transifex * Updated from global requirements * Fix quota set failed problem * Add support for volume v2 commands * Add configuration show command * Imported Translations from Transifex * Add plugin interface version * Fix --os-auth-plugin in auth\_with\_unscoped\_saml * add doc for floatingip * Updated from global requirements * Fix yet more documentation warnings * Make trustee/trustor/project searchable by ID * Add create and list for volume type v2 * add image member commands for image API * Fix the way auth\_type default value is overriden * Format volume type properties when showing * Rename type.py to volume\_type.py * Removes trailing blank in trust show * Add volume type show for volume v1 * --property should be required in \`os unset\` commands * More minor docs fixes * Minor identity documentation change * Add functional tests server reboot * Add functional tests server IP attach and detach * Add details to the documentation * Making --property as required when openstack flavor unset * Do not set default versions in parsed args * Add functional tests for servers that require wait * Updated from global requirements * enhance tests for user v3 * Remove unnecessary test extension mock * Remove requirements.txt from tox.ini * add functional tests for identity v3 * Add functional tests for volume qos * Support multiple volume qos delete * add functional tests for identity v2 * add --project-domain option for user v3 * only return endpoints that have url * Fix the way we call find\_resource when only using ID * Fix image save with API v2 * Rename endpoint type to interface * Updated from global requirements * temporarily skip help tests * Drop py33 support for Liberty * Fix interactive password prompt * Updated from global requirements * Fix wrong mock method call * add functional tests for identity v2 * Fixes modules index generated by Sphinx * Imported Translations from Transifex * Fix address parsing for server ssh command * openstack catalog list always returns publicURL for internalURL and adminURL * Remove the --dhcp option to network list * Remove testing of cliff command line options * add functional tests for identity v3 * Add --os-endpoint-type cli optional argument * Show which aggregate a hypervisor is member of * Move update code from image create command * Fix examples with cacert * Updated from global requirements * Add support for volume API v2 QoS commands * Add tests for 'list' and 'show' for volume qos v1 * Alphabetize tests for v1 qos\_specs * Add docs for QoS specs * No need for get\_parser on QoS list * Alphabetize QoS specs * Add support for volume API v1 QoS commands * fix confused domain argument for network create v2 * fix typo in network.rst * Updated from global requirements * Updated from global requirements * Add support to inherited project role grant calls * Updated from global requirements * fix typo for server create in server.rst * Fix typo in user.rst * Update 1.4.0 release notes * Refactor option handling for user|group|project domain scoping * Updated from global requirements 1.5.0 ----- * Add release notes for 1.5.0 * reference corect ec2 helper function * Add functional tests for image set * Updated from global requirements 1.4.0 ----- * Improve the hint message * Fix the typo in \`openstackclient/shell.py\` * Add functional tests for volume set size * Add functional tests for server CRUD * Add functional tests for flavor metadata * Add flavor functional test * Add oidc plugin for listing federation projects * Skip trying to set project\_domain\_id if not using password * Updated from global requirements * Updated from global requirements * Add functional tests for security group CRUD * Enables retrieval of project's parents and subtree * Imported Translations from Transifex * Include links to developer workflow documentation * Enable specifying domain for group and role commands * Not use the deprecated argument * Add support for volume backup v2 command * Create 1.4.0 release notes * Updated from global requirements * Add support for volume snapshot v2 command * Allow --insecure to override --os-cacert * Clean up ec2 credentials help text * Add functional tests for volume set and unset * Add domain support for ec2creds in v3 identity * Add EC2 support for identity v3 API * Imported Translations from Transifex * Add a reference to the IRC channels * Change Credentials header to Blob from data * Get rid of oslo\_i18n deprecation notice * Fix security group list command * Rework shell tests * Add image functional tests * Add volume functional tests * Ignore cover directory from git * Set tenant options on parsed namespace * Add support for volume v2 API * add domain scope arguments to v3 role add in doc * project create is missing --parent in doc * add --domain argument to v3 project set * Add --wait to server delete * Use ostestr for test runs * Add cli tests for --verify and friends * Small tweaks to osc plugin docs * Fix shell tests 1.3.0 ----- * Create 1.3.0 release notes * Add support for v2 image set command * Adds python-tuskarclient to list of plugins * Remove oslo serialization requirement * Remove oslo incubator config * Add missing properties to image set command * Add some comments about current plugin support * Remove checks for None dates in keypair functional tests * Fix client error while rescuing an instance * Add support for keypair functional tests * Fix insecure/verify options * Use format options for functional tests * Fix functional test gate * Updated from global requirements * Enable specifing domains in "role add" * Send the correct user-agent to Keystone * Updated from global requirements * Security group rule delete broken * Updated from global requirements * Imported Translations from Transifex * Don't create empty quota set requests * Updated from global requirements * Add os-client-config cli tests * minor syntax error in tox.ini * Add image show tests * Minor fix to openstack image show command 1.2.0 ----- * Create 1.2.0 release notes * Fix tiny typo in comment message * Minor logging/debug cleanups * Redo 1.1.0 release notes * Remove unique class names because they are scoped * Raise exception if no session is created * Reduce parameters to base class execute * Functional tests run in many environments * Remove references to venv * Add a doc that dictates backwards incompatible changes * Remove run\_tests.sh * Security group rule create fails * Fix security group create description bug * Adds support for container selection for backup * Create 1.1.0 release notes 1.1.0 ----- * Handle the pagination for image list * Refactor utility to find identity resources * Imported Translations from Transifex * remove unnecessary conditionals * Update the docs for new nic options * Begin documenting --os-cloud * Add --os-cloud support * Imported Translations from Transifex * Re-organize functional tests * Role operations should not require list object permission * Print warning on authentication error * Fix skipped image create attribute location attr * Uncap library requirements for liberty * Defer client imports * Better help for --nic in create server * Add support to specify volume quotas per volume type * Add docs for service provider CRUD * Federation Service Providers CRUD operations * Add warning message if unknown version supplied * Fix session timing * Add support for showing limits of a specific project * Suppress warnings user can't fix * Use glanceclient's inbuilt images find * Updated from global requirements * Imported Translations from Transifex * Add support to remote\_id * Add parent field to project creation * Add project and domain params to network create * Add a doc about authenticating against v3 * Add the ability to set and unset flavor properties * Use cliff deferred help instead of homemade one * Base TokenEndpoint plugin on keystoneclient's 1.0.3 ----- * Create 1.0.3 release notes * Move OSC auth plugins so they can be found * Add identity v3 catalog show * Update README * Imported Translations from Transifex * Add identity v3 catalog list * Fix catalog list when region name is absent * Add ability for diplaying hypervisor statistics * Add 'uptime' in 'hypervisor show' * Raise AttributeError for unknown attributes * Add hypervisor docs * Don't hack the image url * Fix embarrassing typo in man page * Updated from global requirements * Fix identity v2 catalog list * Fix help messages * Handle novaclient >2.20.0 * Fix auth-required for help command * change oslo namespace to avoid warning * Updated from global requirements * Revert "Skip functional tests until they are fixed" * Rename --verify for server resize to avoid conflict * Fix error msg in sort\_items * Skip functional tests until they are fixed * Restrict groups and users from changing domains * Do not allow user to change domain of a project * Implement trust in identity v3 api * Imported Translations from Transifex * Change volume create --snapshot-id to --snapshot * Check volume status before extending size * Adding default user\_domain\_id parameter only when using password auth * Add sort support to image list * tenant\_id to project\_id in server show * Added capabilities/options to 'openstack flavor list' command to match capabilities already provided by 'nova flavor-list': * Improving the help of the lock command * Updated from global requirements * Change test order to avoid incompatibliity * Add network support to quota show * Add filter to image list * Add the ability to extend volumes in \`osc volume set\` * fix the wrong order of assertEqual args * Add 'find by name' to --nic for creating server * Remove ignore portion of tox.ini * fix object list command naming * Begin low-level API for Network v2 * Command docs: network * Add region name for identity and volume clients * Begin low-level API for Image v1 and v2 1.0.2 ----- * Fix doc building errors * Create 1.0.2 release notes * Imported Translations from Transifex * Add missing oslo-config to requirements * Update service clist commands for v2 and v3 * Default user domain id and project domain id * Add helpful messages when authN'ing with password * Add version url config workaround * Use session for neutron client * Imported Translations from Transifex * Deprecate project usage list command * Copy wiki content to index page * Copy HIG from wiki * Tweaks to the catalog doc and show command * Fine tune some of the helps commands * Command doc: policy * Updated from global requirements * Upgrade hacking to 0.10 * Command docs: add service * fix some small issues in catalog show * Rework role list v2 for --user and --project * Add versioning to the docs that missed it * Updated from global requirements * Command doc: access token * Request token authorize * Command doc: snapshot * Fix up snapshot command * Command doc: image * Request token creation docs + tweaks * Command doc: consumer * Allow user list to filter by project * Command doc: federation protocol * Command doc: identity provider * Command doc: mapping * Command doc: backup * Fixup backup list output * Command docs: volume * Update the command list * Command doc: volume type * tweak the server command docs * Check if service.name available before access * Command docs: group * Add endpoint v3 docs * Command docs: ec2 credentials * Rename column to \`default project id\` for long listing v3 user * Add missing content for token commands * Add docs for usage show/list * Command docs: flavor * Command docs: domain * Command docs: region * Add docs for listing availability zones * Bunch of formatting tweaks to server-image docs * type should be required for v2.0 service create * Command object docs: container, object * Catch exception when getting quota * Rename \`os project usage list\` to \`os usage list\` * Add usage show command * Fix a few issues with 'usage list' * Compute calls ignore region selection * add doc for group command * add doc for role assignment command * add doc for domain command * Allow service description to be set for KS V3 * Revert some docs changes from multi-delete * add multi-delete support for identity * add multi-delete support for compute/image/net/volume * Properly format 'attached to' column list when listing volumes * Don't import form keystoneclient.openstack.common * list availability zones for compute * Updated from global requirements * Tweaks after the fact 1.0.1 ----- * Release 1.0.1 * Followup for ec2 credentials command fix * Fix ec2 credentials commands for new auth * Workflow documentation is now in infra-manual 1.0.0 ----- * Command object docs: catalog, credentials, endpoint, region, token * Safely pop project parent id * Add documentation of interactive mode * 1.0.0 release notes * Command object docs: server, server image * Add the ability to list projects based on a user * Add support for domains when deleting identity v3 resources * Command object docs: project, role, user * Updated from global requirements * Command object docs: aggregate, console \*, keypair * Begin copying wiki command list here * Enhance the theming for modules page * Fix volume create --image * add keystone v3 region object * Updated from global requirements * Add --or-show support for v3 identity resources * Add authentication description doc * Add environment variable in the os-auth-type help * Liberalize version matching a bit * Add more session/api examples * Add an API example base and functional test base * Look harder to find DevStack * Add arg to 'server image create' tests * Add additional support for --or-show * Remove links from oauth consumers * Remove links from federation related commands in identity v3 * cleanup files that are created for swift functional tests * Tests work fine with random PYTHONHASHSEED * Updated from global requirements * Swap remaining assertEqual arguments * Add --or-show option to user create * Add cliff-tablib to requirements * Use fixtures from keystoneclient for static data * Unscoped federated user-specific commands * Fix server create for boot-from-volume * Adjust some logging levels * Change --os-auth-plugin to --os-auth-type * Beef up object-store tests * Include support for using oslo debugger in tests * Clean up shell authentication * Fix token issue after auth changeup * only generate one clientmanager instance in interactive mode * Remove ClientManager.\_service\_catalog * Remove now-unnecessary client creation hacks * use jsonutils in oslo.serialization instead of keystoneclient * Close files on server create, add tests * Close files on image create * Move plugin stuff to clientmanager * Update use of open() in object API * Put pbr and six first in requirements list * Add plugin to support token-endpoint auth * Remove 'links' section from several v3 Identity objects * Fix issue token for v3 * Updated from global requirements * Fix operation on clouds with availability-zones * Allow --domain to be used for identity commands without lookup * Add translation markers for user v2 actions * Add domain parameters to user show for Identity V3 * Mark identity v2 resources for translation * Support for keystone auth plugins * Add 'command list' command * CRUD operations for federated protocols * Update for cliff commandmanager >=1.6.1 * Update compute server messages for translation * Implement CRUD operations for Mapping objects * Fix issues with object related commands * Update gitignore * Add some code-blocks to the docs * Place the command to generate docs on one line * Remove duplicate env function in shell.py * Pass in domain and project as positional args, not kwargs * Create a whole slew of functional tests for identity * Add functional tests to osc * Move object-store commands to low-level API * Add low-level API base class * Test top-to-bottom: object-store containers * Updated from global requirements * utils.find\_resource does not catch right exception * Remove unused reference to keyring * v3 credential set always needs --user option * Use oslo.utils * Change help text for image save command * Fixing typo and improving docstring of find\_domain * Updated from global requirements * Acknowlege git.o.o as OpenStack's git server * Add service catalog commands * Return current user/project for user/project show commands * Add support for 'file' format objects * Add preliminary save container support * Add preliminary support for downloading objects * Stop using intersphinx * Updated from global requirements 0.4.1 ----- * Update docs and release notes for 0.4.1 release * Use Keystone client session.Session * Add action 'user password set' for identiy v3 * Unordered dicts and lists causes variable results * Leverage openstack.common.importutils for import\_class * Multiple args for object and container commands * Sync with oslo-incubator and add importutils * assertEquals order wrong * Work toward Python 3.4 support and testing * Make Identity client load like the others * Fix server add security group * Fix security group list for non-admin * Change app.restapi to app.client\_manager.session * Add i18n module to openstackclient * Create message variables for exceptions * Add oslo.i18n as a dependency * Updated from global requirements * Network use enable/disable vs admin state up/down * add service/interface/region filter for endpoint v3 * add tests for identity v3 endpoint * add tests for identity v3 domain * a mistake in tests/identity/v3/test\_role.py * Add commands for object upload and delete * test\_find\_resource fails if run alone * Use oslosphinx to generate documentation * user create v2.0 depends on tenantId in response * Updated from global requirements * v3 endpoint set shouldn't always need service option * Add container create and delete support * Cleanup README.rst * fix typo in identity/v3/endpoint.py * Add network extension list * More make\_client() logging cleanup * Change V2 image tests to actually run V2 image code * Add more columns to image list output * Normalize more help strings * Fix PEP8 E302 errors * Fix IDP commands * Update help text for some network commands * Change object API\_NAME to 'object\_store' * Add Python 3 support * Fix server resize * Add basic timing support * Clean up make\_client() logging * Domain administrator cannot do project operations * Replaced some UTF-8 characters with ASCII characters * Python 3: do not compare a list to a zip object * Allow network find to use alternate name * Move network stuff to v2 instead of v2\_0 * Catch SystemExit for parse args * Add support to list volume extensions * Python 3: remove a useless code to safe\_encode() * Add support to list compute extensions * Remove keyring support from openstackclient * trust authentication * Python 3: do not use \_\_builtin\_\_ * Updated from global requirements * Remove backslash usage from a few tests * Sort/clean setup.cfg * Rename token classes to match command * Fix PEP8 E126 and E202 errors * Fix PEP8 E265 errors * Fix PEP8 H405 errors * Fixed typos in the identity client * Network CRUD * Updated from global requirements * sync oslo bits 0.4.0 ----- * Update docs and release notes for 0.4.0 * Updated from global requirements * Complete Identity v3 list command filters * Change the token verb to issue/revoke * Update docs template * Add a docs job to tox.ini * Fix find\_resource for keystone and cinder * Image create and set command updates and tests * Refactor oauth1 code for updates * Updated from global requirements * Clean up logging levels * Ignore most of the new hacking 0.9.2 rules * Refactor role list subcommand for identity v3 api * Add support for extension list * Add role assignments list support to identity v3 * Add token delete command for identity v2 * Fixed several typos throughout the codebase * replace string format arguments with function parameters * Add tests for identity endpoints * Change volume create --volume-type to --type * Fix server image create * Display all server log when --lines option is None * Fix help message for \`ip floating delete\` * volume type create should display properties * Skip auth in cinderclient * Updated from global requirements * Implement CRUD operations for Identity Providers * Updated from global requirements * move read\_blob\_file\_contents to utils * Pass arguments to v3 keystoneclient by kwarg * Fix the project option to user list so it filters * Make endpoint commands more consistent * Correct display of project/tenant id on display of credentials * Produce a useful error message for NoUniqueMatch * identity v3 allow project list filtering by domain * Updated from global requirements * Fix 'keypair show' command output * add interface and url to endpoint list * Fixed spelling error, compatability to compatibility * Fixed Spelling errors - compatability to compatibility * Fixed spelling errors - occurance to occurence * Make bash comple command best effort to authorize * Add ability to set key value pairs in projects * Updated from global requirements * Add --volume option to image create command * Update release notes for 0.3.1 * In anticipation of network agents, rename compute 0.3.1 ----- * Use cacert values when creating identity client * Updated from global requirements * Fix volume commands with multiple regions * Add ability to prompt for passwords for user create and set * Fix some help strings * Fix format errors in nova security group rule list * Update oslo incubator bits * Python 3: the content of a FakeResponse must be bytes * Rename Openstack to OpenStack * FakeResponse: use a default status code * Python 3: fix a syntax error * Use six.iteritems() rather than dict.iteritems() * Remove tox locale overrides * Glance client no longer isa http client * Fix misspellings in python openstackclient * Add token create subcommand for identity v3 api * Updated from global requirements * Fix keyring issue where there were name space problems * Remove remaining print statements * Remove copyright from empty files * Add token create subcommand for identity v2 api * Sync with global requirements * Fix errant underscores * Add support for specifying custom domains * Fix image set properties error * Displaying curl commands for nova and cinder calls * Closes-Bug: #1262322 Make links clickable * Closes-Bug: #1262321 Remove the unimplemented post\_process method call 0.3.0 ----- * Release notes for 0.3.0 release * Remove mox3 requirement * Updated from global requirements * Update docs for plugins and release notes * Add missing requests and six requirements * Add module list command * Update OSC's CommandManager subclass * Bring RESTApi closer to ithe imminent keystoneclient.Session * Add return Closes-Bug: 1246356 * Restore Object API name 'object-store' * Expand support for command extensions * Fix typo * Support building wheels (PEP-427) * Add server image create command * Complete basic test infrastructure * change execute to run * Update URL for global hacking doc and fix typos * Remove httpretty from test requirements * Updated from global requirements * Do lookups for user, project in volume create * Adjust to non-deprecated names in Keyring 1.6.+ * Updated from global requirements * Sync oslo-incubator for py33 fixes * Add options to support TLS certificate verification * Updated from global requirements * Add object-store show commands 0.2.2 ----- * Update release notes for 0.2.2 * Sort entrypoints in setup.cfg * Fix security group entrypoints * Delay authentication to handle commands that do not require it * Identity v3 tests * Prepare for Identity v3 tests * Add to clientmanager tests * Add Identity v2 role and service tests * Refactor fake data for projects and users * Update tox.ini for new tox 1.6 config * Update requirements.txt and test-requirements.txt * Object API commands using our REST API layer * Create a new base REST API interface * Re-order oauth commands and sync with keystoneclient * Add Identity v2 user tests * Add Identity v2 project tests * Updated from global requirements 0.2.1 ----- * Add release notes in docs * Sync with global requirements 0.2.0 ----- * Change version reporting to use pbr * Modify run\_tests.sh to just run tox 0.2.rc1 ------- * Prep for 0.2 release (0.2.rc1) 0.2.alpha1 ---------- * Remove 'oauth authorization show' function from identity v3 * Remove tenant round 3 - other commands * Remove tenant round 2 - Identity API * Remove tenant round 1 - global options * Add server ssh command * Begin Python 3 compatability * Add security group commands * Add server resize command * Add server migrate command * Add server commands: (un)lock, (un)rescue, (un)set, add/remove volume * Add usage command for compute api * Add server diagnose for compute api * Fix --password in server rebuild * Change volume manager to volume type, unset property for type * Clean up properties (metadata) formatting * Add password field to set user * Add aggregate commands * Complete Image v1 * Add quota commands * Add list and delete authorizations for oauth commands * Add --catalog to service show * Update openstack-common.conf format * Add show limits command * Remove api = apiName calls from each method * Add authenticate method to oauth code * Sync install\_venv\_common from oslo * Update documentation with info about setup.cfg * Add EC2 credentials CRUD * Finish up v3 role commands * Add methods for user and group interactions * Move tests into project package * Remove python3 incompatible exception syntax * Add OAuth support for Identity V3 * Fix py26 tests: assertDictEqual * Remove explicit distribute depend * Add volume backup commands * python3: Introduce py33 to tox.ini * Rename requires files to standard names * Fix identity v2.0 entry point * Tweak volume commands and add k=v argparse action * Add domain and description to user for v3 identity * Migrate to pbr * Migrate to flake8 * Fix flake8 errors in anticipation of flake8 patch * Rename all instances of 'metadata' to 'property' * Switch to noun-verb command forms * Add console commands * Adds image \`create\` and \`delete\` functionality * Add fixed-ip and floating-ip commands * Add compute keypair commands * metadata is one word * Add policy to identity v3 * Add metadata support for volume * Make entry point strings readable * Add extra-specs support for volume-type * Add endpoint v3 functionality * Add service v3 support for identity * Add functionality for add-role commands * Add a simple extension hook * Removed unused imports * Add role v3 support to identity in openstack client * Added compute hypervisor support * Add optional arguments to volume list command * Turn down requests logging level * Add force-delete option for volumes * Add snapshot support for v1 volume * add domain, credential to identity v3 api * Add volume support for openstack client * Add compute hosts support * Clean up args and help strings in server commands * Change create flavor to use default arguments * Add metadata support for volume type * Added compute service support * Add quota v1 support for volume * Added compute flavor support * Remove underscore * Added compute agent support * Correct the version mapping to image service * Add volume test cases and structure * Add Cinder API V1 Support * Multiple API version support * Update .coveragerc * Sync latest openstack-common * Upgraded to PEP8 1.3.3 to stay aligned with Nova, etc * Copy cfg and iniparser from oslo-incubator * Clean up test\_shell so that the tests are captured though the test framework * Remove old/unsupported options from run\_tests help message * Use install\_venv\_common.py from oslo * Updated README to reflect latest changes * Ensure that image and identity clients are constructed properly * First pass at adding compute unit tests * v3 identity - group and project api * Fix test runner run\_tests.sh is broken * Use the cliff framework's ShowOne as intended for \`show image\` * Sync latest openstack-common updates * Standardize on a copyright header and ensure all files have them * Remove incorrect 'raise' * Migrate from nose to testr * Clean up test environment and remove unused imports * Updated gitignore and manifest * Adds Glance API v2 support * Move from unittest2 to testtools * Increment minimum required keystoneclient version number * bug 1091029 * Remove upper bounds on openstack dependencies * Fixes setup compatibility issue on Windows * Add OpenStack trove classifier for PyPI * Add cliff prereqs * Update compute client bits * Fix PEP8 issues * Document the use of keyring * Add nosehtmloutput as a test dependency * Keyring support for openstackclient * Secure password prompt (docs) * Use PyPI for client libs * If no password in env or command line, try prompting * Add read\_versioninfo method * Fixed a typo in the rst docs * Add post-tag versioning * Update Contributing blurb in the docs * Create tests for shell interface * Refactor cliff.Command.run() * Fix pep8 issues * Move docs to doc * minor fixes * removing print call in roles get\_data * Documented python setup.py develop * Fix 'set user' command * Add role CRUD commands * Add endpoint CRUD commands * Added :: to readme.rst to format correctly * Clean up tenant and server * Added conf.py so Sphinx docs will build * Document how to install the client * Moved test related packages to test-requires * Update service commands * Add user CRUD commands * Updating Readme Document * correcting ordering of imports * fix authentication setup in interactive mode and improve error handling so tracebacks are not printed twice * Revise command boolean flags * Move get\_client\_class() to common.utils * Add tenant CRUD commands * Add API versioning support * look at the command the user is going to run before trying to authenticate them * Add copyright notices and update dates * Add tenant commands, work on service * More identity client config * Remove printt * Add Identity to ClientManager * Fix "help" command and implement "list server" and "show server" * Adding HACKING doc to project * Change binary name to 'openstack' * Auto generate AUTHORS for python-openstackclient * Adding name to Authors and updating a bad URL. More to get my gerrit workflow up * Shell init & logging 0.1 --- * Reset project version to 0.1 * Add openstack-common and test infrastructure * Cleanup auth client path * Add 'list service' command and common modules * Add token auth to shell and README * Begin to add Keystone auth * Change to argparse to match cliff 0.2 * Clean up command output * Use cliff * Set up common utils * Add openstackclient bits * First commit python-openstackclient-3.14.0/README.rst0000666000175100017510000000761613232364361020036 0ustar zuulzuul00000000000000======================== Team and repository tags ======================== .. image:: http://governance.openstack.org/badges/python-openstackclient.svg :target: http://governance.openstack.org/reference/tags/index.html .. Change things from this point on =============== OpenStackClient =============== .. image:: https://img.shields.io/pypi/v/python-openstackclient.svg :target: https://pypi.python.org/pypi/python-openstackclient/ :alt: Latest Version .. image:: https://img.shields.io/pypi/dm/python-openstackclient.svg :target: https://pypi.python.org/pypi/python-openstackclient/ :alt: Downloads OpenStackClient (aka OSC) is a command-line client for OpenStack that brings the command set for Compute, Identity, Image, Object Store and Block Storage APIs together in a single shell with a uniform command structure. The primary goal is to provide a unified shell command structure and a common language to describe operations in OpenStack. * `PyPi`_ - package installation * `Online Documentation`_ * `Launchpad project`_ - release management * `Blueprints`_ - feature specifications * `Bugs`_ - issue tracking * `Source`_ * `Developer` - getting started as a developer * `Contributing` - contributing code * `Testing` - testing code * IRC: #openstack-sdks on Freenode (irc.freenode.net) * License: Apache 2.0 .. _PyPi: https://pypi.python.org/pypi/python-openstackclient .. _Online Documentation: https://docs.openstack.org/python-openstackclient/latest/ .. _Launchpad project: https://launchpad.net/python-openstackclient .. _Blueprints: https://blueprints.launchpad.net/python-openstackclient .. _Bugs: https://bugs.launchpad.net/python-openstackclient .. _Source: https://git.openstack.org/cgit/openstack/python-openstackclient .. _Developer: https://docs.openstack.org/project-team-guide/project-setup/python.html .. _Contributing: https://docs.openstack.org/infra/manual/developers.html .. _Testing: https://docs.openstack.org/python-openstackclient/latest/contributor/developing.html#testing Getting Started =============== OpenStack Client can be installed from PyPI using pip:: pip install python-openstackclient There are a few variants on getting help. A list of global options and supported commands is shown with ``--help``:: openstack --help There is also a ``help`` command that can be used to get help text for a specific command:: openstack help openstack help server create If you want to make changes to the OpenStackClient for testing and contribution, make any changes and then run:: python setup.py develop or:: pip install -e . Configuration ============= The CLI is configured via environment variables and command-line options as listed in https://docs.openstack.org/python-openstackclient/latest/cli/authentication.html. Authentication using username/password is most commonly used:: export OS_AUTH_URL= export OS_IDENTITY_API_VERSION=3 export OS_PROJECT_NAME= export OS_PROJECT_DOMAIN_NAME= export OS_USERNAME= export OS_USER_DOMAIN_NAME= export OS_PASSWORD= # (optional) The corresponding command-line options look very similar:: --os-auth-url --os-identity-api-version 3 --os-project-name --os-project-domain-name --os-username --os-user-domain-name [--os-password ] If a password is not provided above (in plaintext), you will be interactively prompted to provide one securely. Authentication may also be performed using an already-acquired token and a URL pointing directly to the service API that presumably was acquired from the Service Catalog:: export OS_TOKEN= export OS_URL= The corresponding command-line options look very similar:: --os-token --os-url python-openstackclient-3.14.0/LICENSE0000666000175100017510000002363713232364361017355 0ustar zuulzuul00000000000000 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. python-openstackclient-3.14.0/.testr.conf0000666000175100017510000000060413232364361020423 0ustar zuulzuul00000000000000[DEFAULT] test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ ${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./openstackclient/tests/unit} $LISTOPT $IDOPTION test_id_option=--load-list $IDFILE test_list_option=--list group_regex=([^\.]+\.)+ python-openstackclient-3.14.0/examples/0000775000175100017510000000000013232364654020156 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/examples/common.py0000777000175100017510000001657713232364361022040 0ustar zuulzuul00000000000000#!/usr/bin/env python # common.py - Common bits for API examples # 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. """ API Examples This is a collection of common functions used by the example scripts. It may also be run directly as a script to do basic testing of itself. common.object_parser() provides the common set of command-line arguments used in the library CLIs for setting up authentication. This should make playing with the example scripts against a running OpenStack simpler. common.configure_logging() provides the same basic logging control as the OSC shell. common.make_session() does the minimal loading of a Keystone authentication plugin and creates a Keystone client Session. """ import argparse import logging import os import sys import traceback from keystoneauth1 import session as ks_session from osc_lib.api import auth CONSOLE_MESSAGE_FORMAT = '%(levelname)s: %(name)s %(message)s' DEFAULT_VERBOSE_LEVEL = 1 USER_AGENT = 'osc-examples' PARSER_DESCRIPTION = 'A demonstration framework' DEFAULT_IDENTITY_API_VERSION = '2.0' _logger = logging.getLogger(__name__) # --debug sets this True dump_stack_trace = False # Generally useful stuff often found in a utils module def env(*vars, **kwargs): """Search for the first defined of possibly many env vars Returns the first environment variable defined in vars, or returns the default defined in kwargs. """ for v in vars: value = os.environ.get(v, None) if value: return value return kwargs.get('default', '') # Common Example functions def base_parser(parser): """Set up some of the common CLI options These are the basic options that match the library CLIs so command-line/environment setups for those also work with these demonstration programs. """ # Global arguments parser.add_argument( '--os-cloud', metavar='', dest='cloud', default=env('OS_CLOUD'), help='Cloud name in clouds.yaml (Env: OS_CLOUD)', ) parser.add_argument( '--os-region-name', metavar='', dest='region_name', default=env('OS_REGION_NAME'), help='Authentication region name (Env: OS_REGION_NAME)', ) parser.add_argument( '--os-cacert', metavar='', dest='cacert', default=env('OS_CACERT'), help='CA certificate bundle file (Env: OS_CACERT)', ) parser.add_argument( '--os-default-domain', metavar='', default='default', help='Default domain ID, default=default (Env: OS_DEFAULT_DOMAIN)', ) verify_group = parser.add_mutually_exclusive_group() verify_group.add_argument( '--verify', action='store_true', help='Verify server certificate (default)', ) verify_group.add_argument( '--insecure', action='store_true', help='Disable server certificate verification', ) parser.add_argument( '--timing', default=False, action='store_true', help="Print API call timing info", ) parser.add_argument( '-v', '--verbose', action='count', dest='verbose_level', default=1, help='Increase verbosity of output. Can be repeated.', ) parser.add_argument( '--debug', default=False, action='store_true', help='show tracebacks on errors', ) parser.add_argument( 'rest', nargs='*', help='the rest of the args', ) return parser def configure_logging(opts): """Typical app logging setup Based on OSC/cliff """ global dump_stack_trace root_logger = logging.getLogger('') # Requests logs some stuff at INFO that we don't want # unless we have DEBUG requests_log = logging.getLogger("requests") requests_log.setLevel(logging.ERROR) # Other modules we don't want DEBUG output for so # don't reset them below iso8601_log = logging.getLogger("iso8601") iso8601_log.setLevel(logging.ERROR) # Always send higher-level messages to the console via stderr console = logging.StreamHandler(sys.stderr) formatter = logging.Formatter(CONSOLE_MESSAGE_FORMAT) console.setFormatter(formatter) root_logger.addHandler(console) # Set logging to the requested level dump_stack_trace = False if opts.verbose_level == 0: # --quiet root_logger.setLevel(logging.ERROR) elif opts.verbose_level == 1: # This is the default case, no --debug, --verbose or --quiet root_logger.setLevel(logging.WARNING) elif opts.verbose_level == 2: # One --verbose root_logger.setLevel(logging.INFO) elif opts.verbose_level >= 3: # Two or more --verbose root_logger.setLevel(logging.DEBUG) requests_log.setLevel(logging.DEBUG) if opts.debug: # --debug forces traceback dump_stack_trace = True root_logger.setLevel(logging.DEBUG) requests_log.setLevel(logging.DEBUG) return def make_session(opts, **kwargs): """Create our base session using simple auth from ksc plugins The arguments required in opts varies depending on the auth plugin that is used. This example assumes Identity v2 will be used and selects token auth if both os_url and os_token have been provided, otherwise it uses password. :param Namespace opts: A parser options Namespace containing the authentication options to be used :param dict kwargs: Additional options passed directly to Session constructor """ # If no auth type is named by the user, select one based on # the supplied options auth_plugin_name = auth.select_auth_plugin(opts) (auth_plugin, auth_params) = auth.build_auth_params( auth_plugin_name, opts, ) auth_p = auth_plugin.load_from_options(**auth_params) session = ks_session.Session( auth=auth_p, **kwargs ) return session # Top-level functions def run(opts): """Default run command""" # Do some basic testing here sys.stdout.write("Default run command\n") sys.stdout.write("Verbose level: %s\n" % opts.verbose_level) sys.stdout.write("Debug: %s\n" % opts.debug) sys.stdout.write("dump_stack_trace: %s\n" % dump_stack_trace) def setup(): """Parse command line and configure logging""" opts = base_parser( auth.build_auth_plugins_option_parser( argparse.ArgumentParser(description='Object API Example') ) ).parse_args() configure_logging(opts) return opts def main(opts, run): try: return run(opts) except Exception as e: if dump_stack_trace: _logger.error(traceback.format_exc(e)) else: _logger.error('Exception raised: ' + str(e)) return 1 if __name__ == "__main__": opts = setup() sys.exit(main(opts, run)) python-openstackclient-3.14.0/examples/osc-lib.py0000777000175100017510000000673613232364361022074 0ustar zuulzuul00000000000000#!/usr/bin/env python # osc-lib.py - Example using OSC as a library # 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 Library Examples This script shows the basic use of the OpenStackClient ClientManager as a library. """ import argparse import logging import sys import common from os_client_config import config as cloud_config from openstackclient.common import clientmanager LOG = logging.getLogger('') def run(opts): """Run the examples""" # Do configuration file handling cc = cloud_config.OpenStackConfig() LOG.debug("defaults: %s", cc.defaults) cloud = cc.get_one_cloud( cloud=opts.cloud, argparse=opts, ) LOG.debug("cloud cfg: %s", cloud.config) # Loop through extensions to get API versions # Currently API versions are statically selected. Once discovery # is working this can go away... api_version = {} for mod in clientmanager.PLUGIN_MODULES: version_opt = getattr(opts, mod.API_VERSION_OPTION, None) if version_opt: api = mod.API_NAME api_version[api] = version_opt # Set up certificate verification and CA bundle # NOTE(dtroyer): This converts from the usual OpenStack way to the single # requests argument and is an app-specific thing because # we want to be like OpenStackClient. if opts.cacert: verify = opts.cacert else: verify = not opts.insecure # Get a ClientManager # Collect the auth and config options together and give them to # ClientManager and it will wrangle all of the goons into place. client_manager = clientmanager.ClientManager( cli_options=cloud, verify=verify, api_version=api_version, ) # At this point we have a working client manager with a configured # session and authentication plugin. From here on it is the app # making the decisions. Need to talk to two clouds? Make another # client manager with different opts. Or use a config file and load it # directly into the plugin. This example doesn't show that (yet). # Do useful things with it # Look in the object store c_list = client_manager.object_store.container_list() print("Name\tCount\tBytes") for c in c_list: print("%s\t%d\t%d" % (c['name'], c['count'], c['bytes'])) if len(c_list) > 0: # See what is in the first container o_list = client_manager.object_store.object_list(c_list[0]['name']) print("\nObject") for o in o_list: print("%s" % o) # Look at the compute flavors flavor_list = client_manager.compute.flavors.list() print("\nFlavors:") for f in flavor_list: print("%s" % f) if __name__ == "__main__": parser = argparse.ArgumentParser(description='ClientManager Example') opts = common.base_parser( clientmanager.build_plugin_option_parser(parser), ).parse_args() common.configure_logging(opts) sys.exit(common.main(opts, run)) python-openstackclient-3.14.0/examples/object_api.py0000777000175100017510000000714513232364361022636 0ustar zuulzuul00000000000000#!/usr/bin/env python # object_api.py - Example object-store API usage # 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. """ Object Store API Examples This script shows the basic use of the low-level Object Store API """ import argparse import logging import sys import common from os_client_config import config as cloud_config from openstackclient.api import object_store_v1 as object_store from openstackclient.identity import client as identity_client LOG = logging.getLogger('') def run(opts): """Run the examples""" # Look for configuration file # To support token-flow we have no required values # print "options: %s" % self.options cloud = cloud_config.OpenStackConfig().get_one_cloud( cloud=opts.cloud, argparse=opts, ) LOG.debug("cloud cfg: %s", cloud.config) # Set up certificate verification and CA bundle # NOTE(dtroyer): This converts from the usual OpenStack way to the single # requests argument and is an app-specific thing because # we want to be like OpenStackClient. if opts.cacert: verify = opts.cacert else: verify = not opts.insecure # get a session # common.make_session() does all the ugly work of mapping # CLI options/env vars to the required plugin arguments. # The returned session will have a configured auth object # based on the selected plugin's available options. # So to do...oh, just go to api.auth.py and look at what it does. session = common.make_session(cloud, verify=verify) # Extract an endpoint auth_ref = session.auth.get_auth_ref(session) if opts.url: endpoint = opts.url else: endpoint = auth_ref.service_catalog.url_for( service_type='object-store', endpoint_type='public', ) # At this point we have a working session with a configured authentication # plugin. From here on it is the app making the decisions. Need to # talk to two clouds? Go back and make another session but with opts # set to different credentials. Or use a config file and load it # directly into the plugin. This example doesn't show that (yet). # Want to work ahead? Look into the plugin load_from_*() methods # (start in keystoneclient/auth/base.py). # This example is for the Object Store API so make one obj_api = object_store.APIv1( session=session, service_type='object-store', endpoint=endpoint, ) # Do useful things with it c_list = obj_api.container_list() print("Name\tCount\tBytes") for c in c_list: print("%s\t%d\t%d" % (c['name'], c['count'], c['bytes'])) if len(c_list) > 0: # See what is in the first container o_list = obj_api.object_list(c_list[0]['name']) print("\nObject") for o in o_list: print("%s" % o) if __name__ == "__main__": opts = common.base_parser( identity_client.build_option_parser( argparse.ArgumentParser(description='Object API Example') ) ).parse_args() common.configure_logging(opts) sys.exit(common.main(opts, run)) python-openstackclient-3.14.0/tox.ini0000666000175100017510000001203413232364361017650 0ustar zuulzuul00000000000000[tox] minversion = 2.3 envlist = py35,py27,pep8 skipdist = True [testenv] usedevelop = True install_command = pip install {opts} {packages} setenv = VIRTUAL_ENV={envdir} OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 OS_TEST_TIMEOUT=60 deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -r{toxinidir}/test-requirements.txt -r{toxinidir}/requirements.txt commands = stestr run {posargs} whitelist_externals = stestr [testenv:fast8] # Use same environment directory as pep8 env to save space and install time envdir = {toxworkdir}/pep8 commands = {toxinidir}/tools/fast8.sh [testenv:pep8] commands = flake8 bandit -r openstackclient -x tests -s B105,B106,B107,B401,B404,B603,B606,B607,B110,B605,B101 [testenv:bandit] # This command runs the bandit security linter against the openstackclient # codebase minus the tests directory. Some tests are being excluded to # reduce the number of positives before a team inspection, and to ensure a # passing gate job for initial addition. The excluded tests are: # B105-B107: hardcoded password checks - likely to generate false positives # in a gate environment # B401: import subprocess - not necessarily a security issue; this plugin is # mainly used for penetration testing workflow # B603,B606: process without shell - not necessarily a security issue; this # plugin is mainly used for penetration testing workflow # B607: start process with a partial path - this should be a project level # decision # NOTE(elmiko): The following tests are being excluded specifically for # python-openstackclient, they are being excluded to ensure that voting jobs # in the project and in bandit integration tests continue to pass. These # tests have generated issue within the project and should be investigated # by the project. # B110: try, except, pass detected - possible security issue; this should be # investigated by the project for possible exploitation # B605: process with a shell - possible security issue; this should be # investigated by the project for possible exploitation # B101: use of assert - this code will be removed when compiling to optimized # byte code commands = bandit -r openstackclient -x tests -s B105,B106,B107,B401,B404,B603,B606,B607,B110,B605,B101 [testenv:unit-tips] commands = pip install -q -U -e "git+file://{toxinidir}/../cliff#egg=cliff" pip install -q -U -e "git+file://{toxinidir}/../keystoneauth#egg=keystoneauth" pip install -q -U -e "git+file://{toxinidir}/../osc-lib#egg=osc_lib" pip install -q -U -e "git+file://{toxinidir}/../os-client-config#egg=os_client_config" pip install -q -e "git+file://{toxinidir}/../python-openstacksdk#egg=openstacksdk" pip freeze stestr run {posargs} whitelist_externals = stestr [testenv:functional] setenv = OS_TEST_PATH=./openstackclient/tests/functional passenv = OS_* whitelist_externals = openstackclient/tests/functional/run_stestr.sh commands = {toxinidir}/openstackclient/tests/functional/run_stestr.sh {posargs} [testenv:functional-tips] setenv = OS_TEST_PATH=./openstackclient/tests/functional passenv = OS_* whitelist_externals = openstackclient/tests/functional/run_stestr.sh commands = pip install -q -U -e "git+file://{toxinidir}/../cliff#egg=cliff" pip install -q -U -e "git+file://{toxinidir}/../keystoneauth#egg=keystoneauth" pip install -q -U -e "git+file://{toxinidir}/../osc-lib#egg=osc_lib" pip install -q -U -e "git+file://{toxinidir}/../os-client-config#egg=os_client_config" pip install -q -U -e "git+file://{toxinidir}/../python-openstacksdk#egg=openstacksdk" pip freeze {toxinidir}/openstackclient/tests/functional/run_stestr.sh {posargs} [testenv:venv] commands = {posargs} [testenv:cover] setenv = VIRTUAL_ENV={envdir} PYTHON=coverage run --source openstackclient --parallel-mode commands = stestr -q run {posargs} coverage combine coverage html -d cover coverage xml -o cover/coverage.xml [testenv:debug] passenv = OS_* commands = oslo_debug_helper -t openstackclient/tests {posargs} [testenv:docs] deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -r{toxinidir}/requirements.txt -r{toxinidir}/doc/requirements.txt commands = python setup.py build_sphinx [testenv:releasenotes] deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -r{toxinidir}/requirements.txt -r{toxinidir}/doc/requirements.txt commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [flake8] show-source = True # H203: Use assertIs(Not)None to check for None enable-extensions = H203 exclude = .git,.tox,dist,doc,*lib/python*,*egg,build,tools # If 'ignore' is not set there are default errors and warnings that are set # Doc: http://flake8.readthedocs.org/en/latest/config.html#default ignore = __ import-order-style = pep8 application_import_names = openstackclient python-openstackclient-3.14.0/setup.cfg0000666000175100017510000012310013232364654020160 0ustar zuulzuul00000000000000[metadata] name = python-openstackclient summary = OpenStack Command-line Client description-file = README.rst author = OpenStack author-email = openstack-dev@lists.openstack.org home-page = https://docs.openstack.org/python-openstackclient/latest/ classifier = Environment :: OpenStack Intended Audience :: Information Technology Intended Audience :: System Administrators License :: OSI Approved :: Apache Software License Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.5 [files] packages = openstackclient [entry_points] console_scripts = openstack = openstackclient.shell:main keystoneauth1.plugin = token_endpoint = openstackclient.api.auth_plugin:TokenEndpoint openstack.cli = command_list = openstackclient.common.module:ListCommand module_list = openstackclient.common.module:ListModule openstack.cli.base = compute = openstackclient.compute.client identity = openstackclient.identity.client image = openstackclient.image.client network = openstackclient.network.client object_store = openstackclient.object.client volume = openstackclient.volume.client openstack.common = availability_zone_list = openstackclient.common.availability_zone:ListAvailabilityZone configuration_show = openstackclient.common.configuration:ShowConfiguration extension_list = openstackclient.common.extension:ListExtension extension_show = openstackclient.common.extension:ShowExtension limits_show = openstackclient.common.limits:ShowLimits project_purge = openstackclient.common.project_purge:ProjectPurge quota_list = openstackclient.common.quota:ListQuota quota_set = openstackclient.common.quota:SetQuota quota_show = openstackclient.common.quota:ShowQuota openstack.compute.v2 = compute_agent_create = openstackclient.compute.v2.agent:CreateAgent compute_agent_delete = openstackclient.compute.v2.agent:DeleteAgent compute_agent_list = openstackclient.compute.v2.agent:ListAgent compute_agent_set = openstackclient.compute.v2.agent:SetAgent aggregate_add_host = openstackclient.compute.v2.aggregate:AddAggregateHost aggregate_create = openstackclient.compute.v2.aggregate:CreateAggregate aggregate_delete = openstackclient.compute.v2.aggregate:DeleteAggregate aggregate_list = openstackclient.compute.v2.aggregate:ListAggregate aggregate_remove_host = openstackclient.compute.v2.aggregate:RemoveAggregateHost aggregate_set = openstackclient.compute.v2.aggregate:SetAggregate aggregate_show = openstackclient.compute.v2.aggregate:ShowAggregate aggregate_unset = openstackclient.compute.v2.aggregate:UnsetAggregate compute_service_delete = openstackclient.compute.v2.service:DeleteService compute_service_list = openstackclient.compute.v2.service:ListService compute_service_set = openstackclient.compute.v2.service:SetService console_log_show = openstackclient.compute.v2.console:ShowConsoleLog console_url_show = openstackclient.compute.v2.console:ShowConsoleURL flavor_create = openstackclient.compute.v2.flavor:CreateFlavor flavor_delete = openstackclient.compute.v2.flavor:DeleteFlavor flavor_list = openstackclient.compute.v2.flavor:ListFlavor flavor_show = openstackclient.compute.v2.flavor:ShowFlavor flavor_set = openstackclient.compute.v2.flavor:SetFlavor flavor_unset = openstackclient.compute.v2.flavor:UnsetFlavor host_list = openstackclient.compute.v2.host:ListHost host_set = openstackclient.compute.v2.host:SetHost host_show = openstackclient.compute.v2.host:ShowHost hypervisor_list = openstackclient.compute.v2.hypervisor:ListHypervisor hypervisor_show = openstackclient.compute.v2.hypervisor:ShowHypervisor hypervisor_stats_show = openstackclient.compute.v2.hypervisor_stats:ShowHypervisorStats ip_fixed_add = openstackclient.compute.v2.fixedip:AddFixedIP ip_fixed_remove = openstackclient.compute.v2.fixedip:RemoveFixedIP ip_floating_add = openstackclient.compute.v2.floatingip:AddFloatingIP ip_floating_remove = openstackclient.compute.v2.floatingip:RemoveFloatingIP keypair_create = openstackclient.compute.v2.keypair:CreateKeypair keypair_delete = openstackclient.compute.v2.keypair:DeleteKeypair keypair_list = openstackclient.compute.v2.keypair:ListKeypair keypair_show = openstackclient.compute.v2.keypair:ShowKeypair server_add_fixed_ip = openstackclient.compute.v2.server:AddFixedIP server_add_floating_ip = openstackclient.compute.v2.server:AddFloatingIP server_add_port = openstackclient.compute.v2.server:AddPort server_add_network = openstackclient.compute.v2.server:AddNetwork server_add_security_group = openstackclient.compute.v2.server:AddServerSecurityGroup server_add_volume = openstackclient.compute.v2.server:AddServerVolume server_create = openstackclient.compute.v2.server:CreateServer server_delete = openstackclient.compute.v2.server:DeleteServer server_list = openstackclient.compute.v2.server:ListServer server_lock = openstackclient.compute.v2.server:LockServer server_migrate = openstackclient.compute.v2.server:MigrateServer server_pause = openstackclient.compute.v2.server:PauseServer server_reboot = openstackclient.compute.v2.server:RebootServer server_rebuild = openstackclient.compute.v2.server:RebuildServer server_remove_fixed_ip = openstackclient.compute.v2.server:RemoveFixedIP server_remove_floating_ip = openstackclient.compute.v2.server:RemoveFloatingIP server_remove_port = openstackclient.compute.v2.server:RemovePort server_remove_network = openstackclient.compute.v2.server:RemoveNetwork server_remove_security_group = openstackclient.compute.v2.server:RemoveServerSecurityGroup server_remove_volume = openstackclient.compute.v2.server:RemoveServerVolume server_rescue = openstackclient.compute.v2.server:RescueServer server_resize = openstackclient.compute.v2.server:ResizeServer server_restore = openstackclient.compute.v2.server:RestoreServer server_resume = openstackclient.compute.v2.server:ResumeServer server_set = openstackclient.compute.v2.server:SetServer server_shelve = openstackclient.compute.v2.server:ShelveServer server_show = openstackclient.compute.v2.server:ShowServer server_ssh = openstackclient.compute.v2.server:SshServer server_start = openstackclient.compute.v2.server:StartServer server_stop = openstackclient.compute.v2.server:StopServer server_suspend = openstackclient.compute.v2.server:SuspendServer server_dump_create = openstackclient.compute.v2.server:CreateServerDump server_unlock = openstackclient.compute.v2.server:UnlockServer server_unpause = openstackclient.compute.v2.server:UnpauseServer server_unrescue = openstackclient.compute.v2.server:UnrescueServer server_unset = openstackclient.compute.v2.server:UnsetServer server_unshelve = openstackclient.compute.v2.server:UnshelveServer server_backup_create = openstackclient.compute.v2.server_backup:CreateServerBackup server_event_list = openstackclient.compute.v2.server_event:ListServerEvent server_event_show = openstackclient.compute.v2.server_event:ShowServerEvent server_group_create = openstackclient.compute.v2.server_group:CreateServerGroup server_group_delete = openstackclient.compute.v2.server_group:DeleteServerGroup server_group_list = openstackclient.compute.v2.server_group:ListServerGroup server_group_show = openstackclient.compute.v2.server_group:ShowServerGroup server_image_create = openstackclient.compute.v2.server_image:CreateServerImage usage_list = openstackclient.compute.v2.usage:ListUsage usage_show = openstackclient.compute.v2.usage:ShowUsage openstack.identity.v2 = catalog_list = openstackclient.identity.v2_0.catalog:ListCatalog catalog_show = openstackclient.identity.v2_0.catalog:ShowCatalog ec2_credentials_create = openstackclient.identity.v2_0.ec2creds:CreateEC2Creds ec2_credentials_delete = openstackclient.identity.v2_0.ec2creds:DeleteEC2Creds ec2_credentials_list = openstackclient.identity.v2_0.ec2creds:ListEC2Creds ec2_credentials_show = openstackclient.identity.v2_0.ec2creds:ShowEC2Creds endpoint_create = openstackclient.identity.v2_0.endpoint:CreateEndpoint endpoint_delete = openstackclient.identity.v2_0.endpoint:DeleteEndpoint endpoint_list = openstackclient.identity.v2_0.endpoint:ListEndpoint endpoint_show = openstackclient.identity.v2_0.endpoint:ShowEndpoint project_create = openstackclient.identity.v2_0.project:CreateProject project_delete = openstackclient.identity.v2_0.project:DeleteProject project_list = openstackclient.identity.v2_0.project:ListProject project_set = openstackclient.identity.v2_0.project:SetProject project_show = openstackclient.identity.v2_0.project:ShowProject project_unset = openstackclient.identity.v2_0.project:UnsetProject role_add = openstackclient.identity.v2_0.role:AddRole role_create = openstackclient.identity.v2_0.role:CreateRole role_delete = openstackclient.identity.v2_0.role:DeleteRole role_list = openstackclient.identity.v2_0.role:ListRole role_remove = openstackclient.identity.v2_0.role:RemoveRole role_show = openstackclient.identity.v2_0.role:ShowRole role_assignment_list = openstackclient.identity.v2_0.role_assignment:ListRoleAssignment service_create = openstackclient.identity.v2_0.service:CreateService service_delete = openstackclient.identity.v2_0.service:DeleteService service_list = openstackclient.identity.v2_0.service:ListService service_show = openstackclient.identity.v2_0.service:ShowService token_issue = openstackclient.identity.v2_0.token:IssueToken token_revoke = openstackclient.identity.v2_0.token:RevokeToken user_create = openstackclient.identity.v2_0.user:CreateUser user_delete = openstackclient.identity.v2_0.user:DeleteUser user_list = openstackclient.identity.v2_0.user:ListUser user_set = openstackclient.identity.v2_0.user:SetUser user_show = openstackclient.identity.v2_0.user:ShowUser user_role_list = openstackclient.identity.v2_0.role:ListUserRole openstack.identity.v3 = access_token_create = openstackclient.identity.v3.token:CreateAccessToken catalog_list = openstackclient.identity.v3.catalog:ListCatalog catalog_show = openstackclient.identity.v3.catalog:ShowCatalog consumer_create = openstackclient.identity.v3.consumer:CreateConsumer consumer_delete = openstackclient.identity.v3.consumer:DeleteConsumer consumer_list = openstackclient.identity.v3.consumer:ListConsumer consumer_set = openstackclient.identity.v3.consumer:SetConsumer consumer_show = openstackclient.identity.v3.consumer:ShowConsumer credential_create = openstackclient.identity.v3.credential:CreateCredential credential_delete = openstackclient.identity.v3.credential:DeleteCredential credential_list = openstackclient.identity.v3.credential:ListCredential credential_set = openstackclient.identity.v3.credential:SetCredential credential_show = openstackclient.identity.v3.credential:ShowCredential domain_create = openstackclient.identity.v3.domain:CreateDomain domain_delete = openstackclient.identity.v3.domain:DeleteDomain domain_list = openstackclient.identity.v3.domain:ListDomain domain_set = openstackclient.identity.v3.domain:SetDomain domain_show = openstackclient.identity.v3.domain:ShowDomain ec2_credentials_create = openstackclient.identity.v3.ec2creds:CreateEC2Creds ec2_credentials_delete = openstackclient.identity.v3.ec2creds:DeleteEC2Creds ec2_credentials_list = openstackclient.identity.v3.ec2creds:ListEC2Creds ec2_credentials_show = openstackclient.identity.v3.ec2creds:ShowEC2Creds endpoint_add_project = openstackclient.identity.v3.endpoint:AddProjectToEndpoint endpoint_create = openstackclient.identity.v3.endpoint:CreateEndpoint endpoint_delete = openstackclient.identity.v3.endpoint:DeleteEndpoint endpoint_list = openstackclient.identity.v3.endpoint:ListEndpoint endpoint_remove_project = openstackclient.identity.v3.endpoint:RemoveProjectFromEndpoint endpoint_set = openstackclient.identity.v3.endpoint:SetEndpoint endpoint_show = openstackclient.identity.v3.endpoint:ShowEndpoint group_add_user = openstackclient.identity.v3.group:AddUserToGroup group_contains_user = openstackclient.identity.v3.group:CheckUserInGroup group_create = openstackclient.identity.v3.group:CreateGroup group_delete = openstackclient.identity.v3.group:DeleteGroup group_list = openstackclient.identity.v3.group:ListGroup group_remove_user = openstackclient.identity.v3.group:RemoveUserFromGroup group_set = openstackclient.identity.v3.group:SetGroup group_show = openstackclient.identity.v3.group:ShowGroup identity_provider_create = openstackclient.identity.v3.identity_provider:CreateIdentityProvider identity_provider_delete = openstackclient.identity.v3.identity_provider:DeleteIdentityProvider identity_provider_list = openstackclient.identity.v3.identity_provider:ListIdentityProvider identity_provider_set = openstackclient.identity.v3.identity_provider:SetIdentityProvider identity_provider_show = openstackclient.identity.v3.identity_provider:ShowIdentityProvider implied_role_create = openstackclient.identity.v3.implied_role:CreateImpliedRole implied_role_delete = openstackclient.identity.v3.implied_role:DeleteImpliedRole implied_role_list = openstackclient.identity.v3.implied_role:ListImpliedRole mapping_create = openstackclient.identity.v3.mapping:CreateMapping mapping_delete = openstackclient.identity.v3.mapping:DeleteMapping mapping_list = openstackclient.identity.v3.mapping:ListMapping mapping_set = openstackclient.identity.v3.mapping:SetMapping mapping_show = openstackclient.identity.v3.mapping:ShowMapping policy_create = openstackclient.identity.v3.policy:CreatePolicy policy_delete = openstackclient.identity.v3.policy:DeletePolicy policy_list = openstackclient.identity.v3.policy:ListPolicy policy_set = openstackclient.identity.v3.policy:SetPolicy policy_show = openstackclient.identity.v3.policy:ShowPolicy project_create = openstackclient.identity.v3.project:CreateProject project_delete = openstackclient.identity.v3.project:DeleteProject project_list = openstackclient.identity.v3.project:ListProject project_set = openstackclient.identity.v3.project:SetProject project_show = openstackclient.identity.v3.project:ShowProject federation_protocol_create = openstackclient.identity.v3.federation_protocol:CreateProtocol federation_protocol_delete = openstackclient.identity.v3.federation_protocol:DeleteProtocol federation_protocol_list = openstackclient.identity.v3.federation_protocol:ListProtocols federation_protocol_set = openstackclient.identity.v3.federation_protocol:SetProtocol federation_protocol_show = openstackclient.identity.v3.federation_protocol:ShowProtocol federation_domain_list = openstackclient.identity.v3.unscoped_saml:ListAccessibleDomains federation_project_list = openstackclient.identity.v3.unscoped_saml:ListAccessibleProjects region_create = openstackclient.identity.v3.region:CreateRegion region_delete = openstackclient.identity.v3.region:DeleteRegion region_list = openstackclient.identity.v3.region:ListRegion region_set = openstackclient.identity.v3.region:SetRegion region_show = openstackclient.identity.v3.region:ShowRegion request_token_authorize = openstackclient.identity.v3.token:AuthorizeRequestToken request_token_create = openstackclient.identity.v3.token:CreateRequestToken role_add = openstackclient.identity.v3.role:AddRole role_create = openstackclient.identity.v3.role:CreateRole role_delete = openstackclient.identity.v3.role:DeleteRole role_list = openstackclient.identity.v3.role:ListRole role_remove = openstackclient.identity.v3.role:RemoveRole role_show = openstackclient.identity.v3.role:ShowRole role_set = openstackclient.identity.v3.role:SetRole role_assignment_list = openstackclient.identity.v3.role_assignment:ListRoleAssignment service_create = openstackclient.identity.v3.service:CreateService service_delete = openstackclient.identity.v3.service:DeleteService service_list = openstackclient.identity.v3.service:ListService service_show = openstackclient.identity.v3.service:ShowService service_set = openstackclient.identity.v3.service:SetService service_provider_create = openstackclient.identity.v3.service_provider:CreateServiceProvider service_provider_delete = openstackclient.identity.v3.service_provider:DeleteServiceProvider service_provider_list = openstackclient.identity.v3.service_provider:ListServiceProvider service_provider_set = openstackclient.identity.v3.service_provider:SetServiceProvider service_provider_show = openstackclient.identity.v3.service_provider:ShowServiceProvider token_issue = openstackclient.identity.v3.token:IssueToken token_revoke = openstackclient.identity.v3.token:RevokeToken trust_create = openstackclient.identity.v3.trust:CreateTrust trust_delete = openstackclient.identity.v3.trust:DeleteTrust trust_list = openstackclient.identity.v3.trust:ListTrust trust_show = openstackclient.identity.v3.trust:ShowTrust user_create = openstackclient.identity.v3.user:CreateUser user_delete = openstackclient.identity.v3.user:DeleteUser user_list = openstackclient.identity.v3.user:ListUser user_set = openstackclient.identity.v3.user:SetUser user_password_set = openstackclient.identity.v3.user:SetPasswordUser user_show = openstackclient.identity.v3.user:ShowUser openstack.image.v1 = image_create = openstackclient.image.v1.image:CreateImage image_delete = openstackclient.image.v1.image:DeleteImage image_list = openstackclient.image.v1.image:ListImage image_save = openstackclient.image.v1.image:SaveImage image_set = openstackclient.image.v1.image:SetImage image_show = openstackclient.image.v1.image:ShowImage openstack.image.v2 = image_add_project = openstackclient.image.v2.image:AddProjectToImage image_create = openstackclient.image.v2.image:CreateImage image_delete = openstackclient.image.v2.image:DeleteImage image_list = openstackclient.image.v2.image:ListImage image_remove_project = openstackclient.image.v2.image:RemoveProjectImage image_save = openstackclient.image.v2.image:SaveImage image_show = openstackclient.image.v2.image:ShowImage image_set = openstackclient.image.v2.image:SetImage image_unset = openstackclient.image.v2.image:UnsetImage openstack.network.v2 = address_scope_create = openstackclient.network.v2.address_scope:CreateAddressScope address_scope_delete = openstackclient.network.v2.address_scope:DeleteAddressScope address_scope_list = openstackclient.network.v2.address_scope:ListAddressScope address_scope_set = openstackclient.network.v2.address_scope:SetAddressScope address_scope_show = openstackclient.network.v2.address_scope:ShowAddressScope floating_ip_create = openstackclient.network.v2.floating_ip:CreateFloatingIP floating_ip_delete = openstackclient.network.v2.floating_ip:DeleteFloatingIP floating_ip_list = openstackclient.network.v2.floating_ip:ListFloatingIP floating_ip_set = openstackclient.network.v2.floating_ip:SetFloatingIP floating_ip_show = openstackclient.network.v2.floating_ip:ShowFloatingIP floating_ip_unset = openstackclient.network.v2.floating_ip:UnsetFloatingIP floating_ip_pool_list = openstackclient.network.v2.floating_ip_pool:ListFloatingIPPool ip_availability_list = openstackclient.network.v2.ip_availability:ListIPAvailability ip_availability_show = openstackclient.network.v2.ip_availability:ShowIPAvailability ip_floating_create = openstackclient.network.v2.floating_ip:CreateIPFloating ip_floating_delete = openstackclient.network.v2.floating_ip:DeleteIPFloating ip_floating_list = openstackclient.network.v2.floating_ip:ListIPFloating ip_floating_show = openstackclient.network.v2.floating_ip:ShowIPFloating ip_floating_pool_list = openstackclient.network.v2.floating_ip_pool:ListIPFloatingPool network_agent_add_network = openstackclient.network.v2.network_agent:AddNetworkToAgent network_agent_add_router = openstackclient.network.v2.network_agent:AddRouterToAgent network_agent_delete = openstackclient.network.v2.network_agent:DeleteNetworkAgent network_agent_list = openstackclient.network.v2.network_agent:ListNetworkAgent network_agent_remove_network = openstackclient.network.v2.network_agent:RemoveNetworkFromAgent network_agent_remove_router = openstackclient.network.v2.network_agent:RemoveRouterFromAgent network_agent_set = openstackclient.network.v2.network_agent:SetNetworkAgent network_agent_show = openstackclient.network.v2.network_agent:ShowNetworkAgent network_auto_allocated_topology_create = openstackclient.network.v2.network_auto_allocated_topology:CreateAutoAllocatedTopology network_auto_allocated_topology_delete = openstackclient.network.v2.network_auto_allocated_topology:DeleteAutoAllocatedTopology network_flavor_add_profile = openstackclient.network.v2.network_flavor:AddNetworkFlavorToProfile network_flavor_create = openstackclient.network.v2.network_flavor:CreateNetworkFlavor network_flavor_delete = openstackclient.network.v2.network_flavor:DeleteNetworkFlavor network_flavor_list = openstackclient.network.v2.network_flavor:ListNetworkFlavor network_flavor_remove_profile = openstackclient.network.v2.network_flavor:RemoveNetworkFlavorFromProfile network_flavor_set = openstackclient.network.v2.network_flavor:SetNetworkFlavor network_flavor_show = openstackclient.network.v2.network_flavor:ShowNetworkFlavor network_flavor_profile_create = openstackclient.network.v2.network_flavor_profile:CreateNetworkFlavorProfile network_flavor_profile_delete = openstackclient.network.v2.network_flavor_profile:DeleteNetworkFlavorProfile network_flavor_profile_list = openstackclient.network.v2.network_flavor_profile:ListNetworkFlavorProfile network_flavor_profile_set = openstackclient.network.v2.network_flavor_profile:SetNetworkFlavorProfile network_flavor_profile_show = openstackclient.network.v2.network_flavor_profile:ShowNetworkFlavorProfile network_create = openstackclient.network.v2.network:CreateNetwork network_delete = openstackclient.network.v2.network:DeleteNetwork network_list = openstackclient.network.v2.network:ListNetwork network_set = openstackclient.network.v2.network:SetNetwork network_show = openstackclient.network.v2.network:ShowNetwork network_unset = openstackclient.network.v2.network:UnsetNetwork network_meter_create = openstackclient.network.v2.network_meter:CreateMeter network_meter_delete = openstackclient.network.v2.network_meter:DeleteMeter network_meter_list = openstackclient.network.v2.network_meter:ListMeter network_meter_show = openstackclient.network.v2.network_meter:ShowMeter network_meter_rule_create = openstackclient.network.v2.network_meter_rule:CreateMeterRule network_meter_rule_delete = openstackclient.network.v2.network_meter_rule:DeleteMeterRule network_meter_rule_list = openstackclient.network.v2.network_meter_rule:ListMeterRule network_meter_rule_show = openstackclient.network.v2.network_meter_rule:ShowMeterRule network_qos_policy_create = openstackclient.network.v2.network_qos_policy:CreateNetworkQosPolicy network_qos_policy_delete = openstackclient.network.v2.network_qos_policy:DeleteNetworkQosPolicy network_qos_policy_list = openstackclient.network.v2.network_qos_policy:ListNetworkQosPolicy network_qos_policy_set = openstackclient.network.v2.network_qos_policy:SetNetworkQosPolicy network_qos_policy_show = openstackclient.network.v2.network_qos_policy:ShowNetworkQosPolicy network_qos_rule_create = openstackclient.network.v2.network_qos_rule:CreateNetworkQosRule network_qos_rule_delete = openstackclient.network.v2.network_qos_rule:DeleteNetworkQosRule network_qos_rule_list = openstackclient.network.v2.network_qos_rule:ListNetworkQosRule network_qos_rule_set = openstackclient.network.v2.network_qos_rule:SetNetworkQosRule network_qos_rule_show = openstackclient.network.v2.network_qos_rule:ShowNetworkQosRule network_qos_rule_type_list = openstackclient.network.v2.network_qos_rule_type:ListNetworkQosRuleType network_qos_rule_type_show = openstackclient.network.v2.network_qos_rule_type:ShowNetworkQosRuleType network_rbac_create = openstackclient.network.v2.network_rbac:CreateNetworkRBAC network_rbac_delete = openstackclient.network.v2.network_rbac:DeleteNetworkRBAC network_rbac_list = openstackclient.network.v2.network_rbac:ListNetworkRBAC network_rbac_set = openstackclient.network.v2.network_rbac:SetNetworkRBAC network_rbac_show = openstackclient.network.v2.network_rbac:ShowNetworkRBAC network_segment_create = openstackclient.network.v2.network_segment:CreateNetworkSegment network_segment_delete = openstackclient.network.v2.network_segment:DeleteNetworkSegment network_segment_list = openstackclient.network.v2.network_segment:ListNetworkSegment network_segment_set = openstackclient.network.v2.network_segment:SetNetworkSegment network_segment_show = openstackclient.network.v2.network_segment:ShowNetworkSegment network_service_provider_list = openstackclient.network.v2.network_service_provider:ListNetworkServiceProvider port_create = openstackclient.network.v2.port:CreatePort port_delete = openstackclient.network.v2.port:DeletePort port_list = openstackclient.network.v2.port:ListPort port_set = openstackclient.network.v2.port:SetPort port_show = openstackclient.network.v2.port:ShowPort port_unset = openstackclient.network.v2.port:UnsetPort router_add_port = openstackclient.network.v2.router:AddPortToRouter router_add_subnet = openstackclient.network.v2.router:AddSubnetToRouter router_create = openstackclient.network.v2.router:CreateRouter router_delete = openstackclient.network.v2.router:DeleteRouter router_list = openstackclient.network.v2.router:ListRouter router_remove_port = openstackclient.network.v2.router:RemovePortFromRouter router_remove_subnet = openstackclient.network.v2.router:RemoveSubnetFromRouter router_set = openstackclient.network.v2.router:SetRouter router_show = openstackclient.network.v2.router:ShowRouter router_unset = openstackclient.network.v2.router:UnsetRouter security_group_create = openstackclient.network.v2.security_group:CreateSecurityGroup security_group_delete = openstackclient.network.v2.security_group:DeleteSecurityGroup security_group_list = openstackclient.network.v2.security_group:ListSecurityGroup security_group_set = openstackclient.network.v2.security_group:SetSecurityGroup security_group_show = openstackclient.network.v2.security_group:ShowSecurityGroup security_group_rule_create = openstackclient.network.v2.security_group_rule:CreateSecurityGroupRule security_group_rule_delete = openstackclient.network.v2.security_group_rule:DeleteSecurityGroupRule security_group_rule_list = openstackclient.network.v2.security_group_rule:ListSecurityGroupRule security_group_rule_show = openstackclient.network.v2.security_group_rule:ShowSecurityGroupRule subnet_create = openstackclient.network.v2.subnet:CreateSubnet subnet_delete = openstackclient.network.v2.subnet:DeleteSubnet subnet_list = openstackclient.network.v2.subnet:ListSubnet subnet_set = openstackclient.network.v2.subnet:SetSubnet subnet_show = openstackclient.network.v2.subnet:ShowSubnet subnet_unset = openstackclient.network.v2.subnet:UnsetSubnet subnet_pool_create = openstackclient.network.v2.subnet_pool:CreateSubnetPool subnet_pool_delete = openstackclient.network.v2.subnet_pool:DeleteSubnetPool subnet_pool_list = openstackclient.network.v2.subnet_pool:ListSubnetPool subnet_pool_set = openstackclient.network.v2.subnet_pool:SetSubnetPool subnet_pool_show = openstackclient.network.v2.subnet_pool:ShowSubnetPool subnet_pool_unset = openstackclient.network.v2.subnet_pool:UnsetSubnetPool openstack.object_store.v1 = object_store_account_set = openstackclient.object.v1.account:SetAccount object_store_account_show = openstackclient.object.v1.account:ShowAccount object_store_account_unset = openstackclient.object.v1.account:UnsetAccount container_create = openstackclient.object.v1.container:CreateContainer container_delete = openstackclient.object.v1.container:DeleteContainer container_list = openstackclient.object.v1.container:ListContainer container_save = openstackclient.object.v1.container:SaveContainer container_set = openstackclient.object.v1.container:SetContainer container_show = openstackclient.object.v1.container:ShowContainer container_unset = openstackclient.object.v1.container:UnsetContainer object_create = openstackclient.object.v1.object:CreateObject object_delete = openstackclient.object.v1.object:DeleteObject object_list = openstackclient.object.v1.object:ListObject object_save = openstackclient.object.v1.object:SaveObject object_set = openstackclient.object.v1.object:SetObject object_show = openstackclient.object.v1.object:ShowObject object_unset = openstackclient.object.v1.object:UnsetObject openstack.volume.v1 = backup_create = openstackclient.volume.v1.backup:CreateBackup backup_delete = openstackclient.volume.v1.backup:DeleteBackup backup_list = openstackclient.volume.v1.backup:ListBackup backup_restore = openstackclient.volume.v1.backup:RestoreBackup backup_show = openstackclient.volume.v1.backup:ShowBackup snapshot_create = openstackclient.volume.v1.snapshot:CreateSnapshot snapshot_delete = openstackclient.volume.v1.snapshot:DeleteSnapshot snapshot_list = openstackclient.volume.v1.snapshot:ListSnapshot snapshot_set = openstackclient.volume.v1.snapshot:SetSnapshot snapshot_show = openstackclient.volume.v1.snapshot:ShowSnapshot snapshot_unset = openstackclient.volume.v1.snapshot:UnsetSnapshot volume_create = openstackclient.volume.v1.volume:CreateVolume volume_delete = openstackclient.volume.v1.volume:DeleteVolume volume_list = openstackclient.volume.v1.volume:ListVolume volume_migrate = openstackclient.volume.v1.volume:MigrateVolume volume_set = openstackclient.volume.v1.volume:SetVolume volume_show = openstackclient.volume.v1.volume:ShowVolume volume_unset = openstackclient.volume.v1.volume:UnsetVolume volume_backup_create = openstackclient.volume.v1.backup:CreateVolumeBackup volume_backup_delete = openstackclient.volume.v1.backup:DeleteVolumeBackup volume_backup_list = openstackclient.volume.v1.backup:ListVolumeBackup volume_backup_restore = openstackclient.volume.v1.backup:RestoreVolumeBackup volume_backup_show = openstackclient.volume.v1.backup:ShowVolumeBackup volume_snapshot_create = openstackclient.volume.v1.volume_snapshot:CreateVolumeSnapshot volume_snapshot_delete = openstackclient.volume.v1.volume_snapshot:DeleteVolumeSnapshot volume_snapshot_list = openstackclient.volume.v1.volume_snapshot:ListVolumeSnapshot volume_snapshot_set = openstackclient.volume.v1.volume_snapshot:SetVolumeSnapshot volume_snapshot_show = openstackclient.volume.v1.volume_snapshot:ShowVolumeSnapshot volume_snapshot_unset = openstackclient.volume.v1.volume_snapshot:UnsetVolumeSnapshot volume_type_create = openstackclient.volume.v1.volume_type:CreateVolumeType volume_type_delete = openstackclient.volume.v1.volume_type:DeleteVolumeType volume_type_list = openstackclient.volume.v1.volume_type:ListVolumeType volume_type_set = openstackclient.volume.v1.volume_type:SetVolumeType volume_type_show = openstackclient.volume.v1.volume_type:ShowVolumeType volume_type_unset = openstackclient.volume.v1.volume_type:UnsetVolumeType volume_qos_associate = openstackclient.volume.v1.qos_specs:AssociateQos volume_qos_create = openstackclient.volume.v1.qos_specs:CreateQos volume_qos_delete = openstackclient.volume.v1.qos_specs:DeleteQos volume_qos_disassociate = openstackclient.volume.v1.qos_specs:DisassociateQos volume_qos_list = openstackclient.volume.v1.qos_specs:ListQos volume_qos_set = openstackclient.volume.v1.qos_specs:SetQos volume_qos_show = openstackclient.volume.v1.qos_specs:ShowQos volume_qos_unset = openstackclient.volume.v1.qos_specs:UnsetQos volume_service_list = openstackclient.volume.v1.service:ListService volume_service_set = openstackclient.volume.v1.service:SetService volume_transfer_request_accept = openstackclient.volume.v1.volume_transfer_request:AcceptTransferRequest volume_transfer_request_create = openstackclient.volume.v1.volume_transfer_request:CreateTransferRequest volume_transfer_request_delete = openstackclient.volume.v1.volume_transfer_request:DeleteTransferRequest volume_transfer_request_list = openstackclient.volume.v1.volume_transfer_request:ListTransferRequest volume_transfer_request_show = openstackclient.volume.v1.volume_transfer_request:ShowTransferRequest openstack.volume.v2 = backup_create = openstackclient.volume.v2.backup:CreateBackup backup_delete = openstackclient.volume.v2.backup:DeleteBackup backup_list = openstackclient.volume.v2.backup:ListBackup backup_restore = openstackclient.volume.v2.backup:RestoreBackup backup_show = openstackclient.volume.v2.backup:ShowBackup consistency_group_add_volume = openstackclient.volume.v2.consistency_group:AddVolumeToConsistencyGroup consistency_group_create = openstackclient.volume.v2.consistency_group:CreateConsistencyGroup consistency_group_delete = openstackclient.volume.v2.consistency_group:DeleteConsistencyGroup consistency_group_list = openstackclient.volume.v2.consistency_group:ListConsistencyGroup consistency_group_remove_volume = openstackclient.volume.v2.consistency_group:RemoveVolumeFromConsistencyGroup consistency_group_set = openstackclient.volume.v2.consistency_group:SetConsistencyGroup consistency_group_show = openstackclient.volume.v2.consistency_group:ShowConsistencyGroup consistency_group_snapshot_create = openstackclient.volume.v2.consistency_group_snapshot:CreateConsistencyGroupSnapshot consistency_group_snapshot_delete = openstackclient.volume.v2.consistency_group_snapshot:DeleteConsistencyGroupSnapshot consistency_group_snapshot_list = openstackclient.volume.v2.consistency_group_snapshot:ListConsistencyGroupSnapshot consistency_group_snapshot_show = openstackclient.volume.v2.consistency_group_snapshot:ShowConsistencyGroupSnapshot snapshot_create = openstackclient.volume.v2.snapshot:CreateSnapshot snapshot_delete = openstackclient.volume.v2.snapshot:DeleteSnapshot snapshot_list = openstackclient.volume.v2.snapshot:ListSnapshot snapshot_set = openstackclient.volume.v2.snapshot:SetSnapshot snapshot_show = openstackclient.volume.v2.snapshot:ShowSnapshot snapshot_unset = openstackclient.volume.v2.snapshot:UnsetSnapshot volume_create = openstackclient.volume.v2.volume:CreateVolume volume_delete = openstackclient.volume.v2.volume:DeleteVolume volume_list = openstackclient.volume.v2.volume:ListVolume volume_migrate = openstackclient.volume.v2.volume:MigrateVolume volume_set = openstackclient.volume.v2.volume:SetVolume volume_show = openstackclient.volume.v2.volume:ShowVolume volume_unset = openstackclient.volume.v2.volume:UnsetVolume volume_backup_create = openstackclient.volume.v2.backup:CreateVolumeBackup volume_backup_delete = openstackclient.volume.v2.backup:DeleteVolumeBackup volume_backup_list = openstackclient.volume.v2.backup:ListVolumeBackup volume_backup_restore = openstackclient.volume.v2.backup:RestoreVolumeBackup volume_backup_set = openstackclient.volume.v2.backup:SetVolumeBackup volume_backup_show = openstackclient.volume.v2.backup:ShowVolumeBackup volume_host_failover = openstackclient.volume.v2.volume_host:FailoverVolumeHost volume_host_set = openstackclient.volume.v2.volume_host:SetVolumeHost volume_snapshot_create = openstackclient.volume.v2.volume_snapshot:CreateVolumeSnapshot volume_snapshot_delete = openstackclient.volume.v2.volume_snapshot:DeleteVolumeSnapshot volume_snapshot_list = openstackclient.volume.v2.volume_snapshot:ListVolumeSnapshot volume_snapshot_set = openstackclient.volume.v2.volume_snapshot:SetVolumeSnapshot volume_snapshot_show = openstackclient.volume.v2.volume_snapshot:ShowVolumeSnapshot volume_snapshot_unset = openstackclient.volume.v2.volume_snapshot:UnsetVolumeSnapshot volume_type_create = openstackclient.volume.v2.volume_type:CreateVolumeType volume_type_delete = openstackclient.volume.v2.volume_type:DeleteVolumeType volume_type_list = openstackclient.volume.v2.volume_type:ListVolumeType volume_type_set = openstackclient.volume.v2.volume_type:SetVolumeType volume_type_show = openstackclient.volume.v2.volume_type:ShowVolumeType volume_type_unset = openstackclient.volume.v2.volume_type:UnsetVolumeType volume_qos_associate = openstackclient.volume.v2.qos_specs:AssociateQos volume_qos_create = openstackclient.volume.v2.qos_specs:CreateQos volume_qos_delete = openstackclient.volume.v2.qos_specs:DeleteQos volume_qos_disassociate = openstackclient.volume.v2.qos_specs:DisassociateQos volume_qos_list = openstackclient.volume.v2.qos_specs:ListQos volume_qos_set = openstackclient.volume.v2.qos_specs:SetQos volume_qos_show = openstackclient.volume.v2.qos_specs:ShowQos volume_qos_unset = openstackclient.volume.v2.qos_specs:UnsetQos volume_service_list = openstackclient.volume.v2.service:ListService volume_service_set = openstackclient.volume.v2.service:SetService volume_transfer_request_accept = openstackclient.volume.v2.volume_transfer_request:AcceptTransferRequest volume_transfer_request_create = openstackclient.volume.v2.volume_transfer_request:CreateTransferRequest volume_transfer_request_delete = openstackclient.volume.v2.volume_transfer_request:DeleteTransferRequest volume_transfer_request_list = openstackclient.volume.v2.volume_transfer_request:ListTransferRequest volume_transfer_request_show = openstackclient.volume.v2.volume_transfer_request:ShowTransferRequest openstack.volume.v3 = consistency_group_add_volume = openstackclient.volume.v2.consistency_group:AddVolumeToConsistencyGroup consistency_group_create = openstackclient.volume.v2.consistency_group:CreateConsistencyGroup consistency_group_delete = openstackclient.volume.v2.consistency_group:DeleteConsistencyGroup consistency_group_list = openstackclient.volume.v2.consistency_group:ListConsistencyGroup consistency_group_remove_volume = openstackclient.volume.v2.consistency_group:RemoveVolumeFromConsistencyGroup consistency_group_set = openstackclient.volume.v2.consistency_group:SetConsistencyGroup consistency_group_show = openstackclient.volume.v2.consistency_group:ShowConsistencyGroup consistency_group_snapshot_create = openstackclient.volume.v2.consistency_group_snapshot:CreateConsistencyGroupSnapshot consistency_group_snapshot_delete = openstackclient.volume.v2.consistency_group_snapshot:DeleteConsistencyGroupSnapshot consistency_group_snapshot_list = openstackclient.volume.v2.consistency_group_snapshot:ListConsistencyGroupSnapshot consistency_group_snapshot_show = openstackclient.volume.v2.consistency_group_snapshot:ShowConsistencyGroupSnapshot volume_create = openstackclient.volume.v2.volume:CreateVolume volume_delete = openstackclient.volume.v2.volume:DeleteVolume volume_list = openstackclient.volume.v2.volume:ListVolume volume_migrate = openstackclient.volume.v2.volume:MigrateVolume volume_set = openstackclient.volume.v2.volume:SetVolume volume_show = openstackclient.volume.v2.volume:ShowVolume volume_unset = openstackclient.volume.v2.volume:UnsetVolume volume_backup_create = openstackclient.volume.v2.backup:CreateVolumeBackup volume_backup_delete = openstackclient.volume.v2.backup:DeleteVolumeBackup volume_backup_list = openstackclient.volume.v2.backup:ListVolumeBackup volume_backup_restore = openstackclient.volume.v2.backup:RestoreVolumeBackup volume_backup_set = openstackclient.volume.v2.backup:SetVolumeBackup volume_backup_show = openstackclient.volume.v2.backup:ShowVolumeBackup volume_host_set = openstackclient.volume.v2.volume_host:SetVolumeHost volume_snapshot_create = openstackclient.volume.v2.volume_snapshot:CreateVolumeSnapshot volume_snapshot_delete = openstackclient.volume.v2.volume_snapshot:DeleteVolumeSnapshot volume_snapshot_list = openstackclient.volume.v2.volume_snapshot:ListVolumeSnapshot volume_snapshot_set = openstackclient.volume.v2.volume_snapshot:SetVolumeSnapshot volume_snapshot_show = openstackclient.volume.v2.volume_snapshot:ShowVolumeSnapshot volume_snapshot_unset = openstackclient.volume.v2.volume_snapshot:UnsetVolumeSnapshot volume_type_create = openstackclient.volume.v2.volume_type:CreateVolumeType volume_type_delete = openstackclient.volume.v2.volume_type:DeleteVolumeType volume_type_list = openstackclient.volume.v2.volume_type:ListVolumeType volume_type_set = openstackclient.volume.v2.volume_type:SetVolumeType volume_type_show = openstackclient.volume.v2.volume_type:ShowVolumeType volume_type_unset = openstackclient.volume.v2.volume_type:UnsetVolumeType volume_qos_associate = openstackclient.volume.v2.qos_specs:AssociateQos volume_qos_create = openstackclient.volume.v2.qos_specs:CreateQos volume_qos_delete = openstackclient.volume.v2.qos_specs:DeleteQos volume_qos_disassociate = openstackclient.volume.v2.qos_specs:DisassociateQos volume_qos_list = openstackclient.volume.v2.qos_specs:ListQos volume_qos_set = openstackclient.volume.v2.qos_specs:SetQos volume_qos_show = openstackclient.volume.v2.qos_specs:ShowQos volume_qos_unset = openstackclient.volume.v2.qos_specs:UnsetQos volume_service_list = openstackclient.volume.v2.service:ListService volume_service_set = openstackclient.volume.v2.service:SetService volume_transfer_request_accept = openstackclient.volume.v2.volume_transfer_request:AcceptTransferRequest volume_transfer_request_create = openstackclient.volume.v2.volume_transfer_request:CreateTransferRequest volume_transfer_request_delete = openstackclient.volume.v2.volume_transfer_request:DeleteTransferRequest volume_transfer_request_list = openstackclient.volume.v2.volume_transfer_request:ListTransferRequest volume_transfer_request_show = openstackclient.volume.v2.volume_transfer_request:ShowTransferRequest [pbr] autodoc_tree_index_modules = True autodoc_tree_excludes = setup.py openstackclient/volume/v3 openstackclient/tests/ openstackclient/tests/* api_doc_dir = contributor/api [build_sphinx] builders = html,man all-files = 1 warning-is-error = 1 source-dir = doc/source build-dir = doc/build [upload_sphinx] upload-dir = doc/build/html [wheel] universal = 1 [extract_messages] keywords = _ gettext ngettext l_ lazy_gettext mapping_file = babel.cfg output_file = openstackclient/locale/openstackclient.pot [update_catalog] domain = openstackclient output_dir = openstackclient/locale input_file = openstackclient/locale/openstackclient.pot [compile_catalog] directory = openstackclient/locale domain = openstackclient [egg_info] tag_build = tag_date = 0 python-openstackclient-3.14.0/setup.py0000666000175100017510000000200613232364361020045 0ustar zuulzuul00000000000000# 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. # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools # In python < 2.7.4, a lazy loading of package `pbr` will break # setuptools if some other modules registered functions in `atexit`. # solution from: http://bugs.python.org/issue15881#msg170215 try: import multiprocessing # noqa except ImportError: pass setuptools.setup( setup_requires=['pbr>=2.0.0'], pbr=True) python-openstackclient-3.14.0/openstackclient/0000775000175100017510000000000013232364654021526 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/object/0000775000175100017510000000000013232364654022774 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/object/v1/0000775000175100017510000000000013232364654023322 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/object/v1/container.py0000666000175100017510000001751713232364361025666 0ustar zuulzuul00000000000000# Copyright 2013 Nebula 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. # """Container v1 action implementations""" import logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateContainer(command.Lister): _description = _("Create new container") def get_parser(self, prog_name): parser = super(CreateContainer, self).get_parser(prog_name) parser.add_argument( 'containers', metavar='', nargs="+", help=_('New container name(s)'), ) return parser def take_action(self, parsed_args): results = [] for container in parsed_args.containers: if len(container) > 256: LOG.warning( _('Container name is %s characters long, the default limit' ' is 256'), len(container)) data = self.app.client_manager.object_store.container_create( container=container, ) results.append(data) columns = ("account", "container", "x-trans-id") return (columns, (utils.get_dict_properties( s, columns, formatters={}, ) for s in results)) class DeleteContainer(command.Command): _description = _("Delete container") def get_parser(self, prog_name): parser = super(DeleteContainer, self).get_parser(prog_name) parser.add_argument( '--recursive', '-r', action='store_true', default=False, help=_('Recursively delete objects and container'), ) parser.add_argument( 'containers', metavar='', nargs="+", help=_('Container(s) to delete'), ) return parser def take_action(self, parsed_args): for container in parsed_args.containers: if parsed_args.recursive: objs = self.app.client_manager.object_store.object_list( container=container) for obj in objs: self.app.client_manager.object_store.object_delete( container=container, object=obj['name'], ) self.app.client_manager.object_store.container_delete( container=container, ) class ListContainer(command.Lister): _description = _("List containers") def get_parser(self, prog_name): parser = super(ListContainer, self).get_parser(prog_name) parser.add_argument( "--prefix", metavar="", help=_("Filter list using "), ) parser.add_argument( "--marker", metavar="", help=_("Anchor for paging"), ) parser.add_argument( "--end-marker", metavar="", help=_("End anchor for paging"), ) parser.add_argument( "--limit", metavar="", type=int, help=_("Limit the number of containers returned"), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( '--all', action='store_true', default=False, help=_('List all containers (default is 10000)'), ) return parser def take_action(self, parsed_args): if parsed_args.long: columns = ('Name', 'Bytes', 'Count') else: columns = ('Name',) kwargs = {} if parsed_args.prefix: kwargs['prefix'] = parsed_args.prefix if parsed_args.marker: kwargs['marker'] = parsed_args.marker if parsed_args.end_marker: kwargs['end_marker'] = parsed_args.end_marker if parsed_args.limit: kwargs['limit'] = parsed_args.limit if parsed_args.all: kwargs['full_listing'] = True data = self.app.client_manager.object_store.container_list( **kwargs ) return (columns, (utils.get_dict_properties( s, columns, formatters={}, ) for s in data)) class SaveContainer(command.Command): _description = _("Save container contents locally") def get_parser(self, prog_name): parser = super(SaveContainer, self).get_parser(prog_name) parser.add_argument( 'container', metavar='', help=_('Container to save'), ) return parser def take_action(self, parsed_args): self.app.client_manager.object_store.container_save( container=parsed_args.container, ) class SetContainer(command.Command): _description = _("Set container properties") def get_parser(self, prog_name): parser = super(SetContainer, self).get_parser(prog_name) parser.add_argument( 'container', metavar='', help=_('Container to modify'), ) parser.add_argument( "--property", metavar="", required=True, action=parseractions.KeyValueAction, help=_("Set a property on this container " "(repeat option to set multiple properties)") ) return parser def take_action(self, parsed_args): self.app.client_manager.object_store.container_set( parsed_args.container, properties=parsed_args.property, ) class ShowContainer(command.ShowOne): _description = _("Display container details") def get_parser(self, prog_name): parser = super(ShowContainer, self).get_parser(prog_name) parser.add_argument( 'container', metavar='', help=_('Container to display'), ) return parser def take_action(self, parsed_args): data = self.app.client_manager.object_store.container_show( container=parsed_args.container, ) if 'properties' in data: data['properties'] = utils.format_dict(data.pop('properties')) return zip(*sorted(six.iteritems(data))) class UnsetContainer(command.Command): _description = _("Unset container properties") def get_parser(self, prog_name): parser = super(UnsetContainer, self).get_parser(prog_name) parser.add_argument( 'container', metavar='', help=_('Container to modify'), ) parser.add_argument( '--property', metavar='', required=True, action='append', default=[], help=_('Property to remove from container ' '(repeat option to remove multiple properties)'), ) return parser def take_action(self, parsed_args): self.app.client_manager.object_store.container_unset( parsed_args.container, properties=parsed_args.property, ) python-openstackclient-3.14.0/openstackclient/object/v1/object.py0000666000175100017510000002311313232364361025137 0ustar zuulzuul00000000000000# Copyright 2013 Nebula 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. # """Object v1 action implementations""" import logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateObject(command.Lister): _description = _("Upload object to container") def get_parser(self, prog_name): parser = super(CreateObject, self).get_parser(prog_name) parser.add_argument( 'container', metavar='', help=_('Container for new object'), ) parser.add_argument( 'objects', metavar='', nargs="+", help=_('Local filename(s) to upload'), ) parser.add_argument( '--name', metavar='', help=_('Upload a file and rename it. ' 'Can only be used when uploading a single object') ) return parser def take_action(self, parsed_args): if parsed_args.name: if len(parsed_args.objects) > 1: msg = _('Attempting to upload multiple objects and ' 'using --name is not permitted') raise exceptions.CommandError(msg) results = [] for obj in parsed_args.objects: if len(obj) > 1024: LOG.warning( _('Object name is %s characters long, default limit' ' is 1024'), len(obj)) data = self.app.client_manager.object_store.object_create( container=parsed_args.container, object=obj, name=parsed_args.name, ) results.append(data) columns = ("object", "container", "etag") return (columns, (utils.get_dict_properties( s, columns, formatters={}, ) for s in results)) class DeleteObject(command.Command): _description = _("Delete object from container") def get_parser(self, prog_name): parser = super(DeleteObject, self).get_parser(prog_name) parser.add_argument( 'container', metavar='', help=_('Delete object(s) from '), ) parser.add_argument( 'objects', metavar='', nargs="+", help=_('Object(s) to delete'), ) return parser def take_action(self, parsed_args): for obj in parsed_args.objects: self.app.client_manager.object_store.object_delete( container=parsed_args.container, object=obj, ) class ListObject(command.Lister): _description = _("List objects") def get_parser(self, prog_name): parser = super(ListObject, self).get_parser(prog_name) parser.add_argument( "container", metavar="", help=_("Container to list"), ) parser.add_argument( "--prefix", metavar="", help=_("Filter list using "), ) parser.add_argument( "--delimiter", metavar="", help=_("Roll up items with "), ) parser.add_argument( "--marker", metavar="", help=_("Anchor for paging"), ) parser.add_argument( "--end-marker", metavar="", help=_("End anchor for paging"), ) parser.add_argument( "--limit", metavar="", type=int, help=_("Limit the number of objects returned"), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( '--all', action='store_true', default=False, help=_('List all objects in container (default is 10000)'), ) return parser def take_action(self, parsed_args): if parsed_args.long: columns = ( 'Name', 'Bytes', 'Hash', 'Content Type', 'Last Modified', ) else: columns = ('Name',) kwargs = {} if parsed_args.prefix: kwargs['prefix'] = parsed_args.prefix if parsed_args.delimiter: kwargs['delimiter'] = parsed_args.delimiter if parsed_args.marker: kwargs['marker'] = parsed_args.marker if parsed_args.end_marker: kwargs['end_marker'] = parsed_args.end_marker if parsed_args.limit: kwargs['limit'] = parsed_args.limit if parsed_args.all: kwargs['full_listing'] = True data = self.app.client_manager.object_store.object_list( container=parsed_args.container, **kwargs ) return (columns, (utils.get_dict_properties( s, columns, formatters={}, ) for s in data)) class SaveObject(command.Command): _description = _("Save object locally") def get_parser(self, prog_name): parser = super(SaveObject, self).get_parser(prog_name) parser.add_argument( "--file", metavar="", help=_("Destination filename (defaults to object name); using '-'" " as the filename will print the file to stdout"), ) parser.add_argument( 'container', metavar='', help=_('Download from '), ) parser.add_argument( "object", metavar="", help=_("Object to save"), ) return parser def take_action(self, parsed_args): self.app.client_manager.object_store.object_save( container=parsed_args.container, object=parsed_args.object, file=parsed_args.file, ) class SetObject(command.Command): _description = _("Set object properties") def get_parser(self, prog_name): parser = super(SetObject, self).get_parser(prog_name) parser.add_argument( 'container', metavar='', help=_('Modify from '), ) parser.add_argument( 'object', metavar='', help=_('Object to modify'), ) parser.add_argument( "--property", metavar="", required=True, action=parseractions.KeyValueAction, help=_("Set a property on this object " "(repeat option to set multiple properties)") ) return parser def take_action(self, parsed_args): self.app.client_manager.object_store.object_set( parsed_args.container, parsed_args.object, properties=parsed_args.property, ) class ShowObject(command.ShowOne): _description = _("Display object details") def get_parser(self, prog_name): parser = super(ShowObject, self).get_parser(prog_name) parser.add_argument( 'container', metavar='', help=_('Display from '), ) parser.add_argument( 'object', metavar='', help=_('Object to display'), ) return parser def take_action(self, parsed_args): data = self.app.client_manager.object_store.object_show( container=parsed_args.container, object=parsed_args.object, ) if 'properties' in data: data['properties'] = utils.format_dict(data.pop('properties')) return zip(*sorted(six.iteritems(data))) class UnsetObject(command.Command): _description = _("Unset object properties") def get_parser(self, prog_name): parser = super(UnsetObject, self).get_parser(prog_name) parser.add_argument( 'container', metavar='', help=_('Modify from '), ) parser.add_argument( 'object', metavar='', help=_('Object to modify'), ) parser.add_argument( '--property', metavar='', required=True, action='append', default=[], help=_('Property to remove from object ' '(repeat option to remove multiple properties)'), ) return parser def take_action(self, parsed_args): self.app.client_manager.object_store.object_unset( parsed_args.container, parsed_args.object, properties=parsed_args.property, ) python-openstackclient-3.14.0/openstackclient/object/v1/account.py0000666000175100017510000000457213232364361025335 0ustar zuulzuul00000000000000# 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. # """Account v1 action implementations""" from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import utils import six from openstackclient.i18n import _ class SetAccount(command.Command): _description = _("Set account properties") def get_parser(self, prog_name): parser = super(SetAccount, self).get_parser(prog_name) parser.add_argument( "--property", metavar="", required=True, action=parseractions.KeyValueAction, help=_("Set a property on this account " "(repeat option to set multiple properties)") ) return parser def take_action(self, parsed_args): self.app.client_manager.object_store.account_set( properties=parsed_args.property, ) class ShowAccount(command.ShowOne): _description = _("Display account details") def take_action(self, parsed_args): data = self.app.client_manager.object_store.account_show() if 'properties' in data: data['properties'] = utils.format_dict(data.pop('properties')) return zip(*sorted(six.iteritems(data))) class UnsetAccount(command.Command): _description = _("Unset account properties") def get_parser(self, prog_name): parser = super(UnsetAccount, self).get_parser(prog_name) parser.add_argument( '--property', metavar='', required=True, action='append', default=[], help=_('Property to remove from account ' '(repeat option to remove multiple properties)'), ) return parser def take_action(self, parsed_args): self.app.client_manager.object_store.account_unset( properties=parsed_args.property, ) python-openstackclient-3.14.0/openstackclient/object/v1/__init__.py0000666000175100017510000000000013232364361025416 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/object/client.py0000666000175100017510000000314613232364361024625 0ustar zuulzuul00000000000000# Copyright 2013 Nebula 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. # """Object client""" from osc_lib import utils from openstackclient.api import object_store_v1 DEFAULT_API_VERSION = '1' API_VERSION_OPTION = 'os_object_api_version' API_NAME = 'object_store' API_VERSIONS = { '1': 'openstackclient.object.client.ObjectClientv1', } def make_client(instance): """Returns an object-store API client.""" endpoint = instance.get_endpoint_for_service_type( 'object-store', region_name=instance.region_name, interface=instance.interface, ) client = object_store_v1.APIv1( session=instance.session, service_type='object-store', endpoint=endpoint, ) return client def build_option_parser(parser): """Hook to add global options""" parser.add_argument( '--os-object-api-version', metavar='', default=utils.env('OS_OBJECT_API_VERSION'), help='Object API version, default=' + DEFAULT_API_VERSION + ' (Env: OS_OBJECT_API_VERSION)') return parser python-openstackclient-3.14.0/openstackclient/object/__init__.py0000666000175100017510000000000013232364361025070 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/network/0000775000175100017510000000000013232364654023217 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/network/common.py0000666000175100017510000001763013232364361025065 0ustar zuulzuul00000000000000# 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 logging import openstack.exceptions from osc_lib.command import command from osc_lib import exceptions import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) @six.add_metaclass(abc.ABCMeta) class NetworkAndComputeCommand(command.Command): """Network and Compute Command Command class for commands that support implementation via the network or compute endpoint. Such commands have different implementations for take_action() and may even have different arguments. """ def take_action(self, parsed_args): if self.app.client_manager.is_network_endpoint_enabled(): return self.take_action_network(self.app.client_manager.network, parsed_args) else: return self.take_action_compute(self.app.client_manager.compute, parsed_args) def get_parser(self, prog_name): LOG.debug('get_parser(%s)', prog_name) parser = super(NetworkAndComputeCommand, self).get_parser(prog_name) parser = self.update_parser_common(parser) LOG.debug('common parser: %s', parser) if self.app.client_manager.is_network_endpoint_enabled(): return self.update_parser_network(parser) else: return self.update_parser_compute(parser) def update_parser_common(self, parser): """Default is no updates to parser.""" return parser def update_parser_network(self, parser): """Default is no updates to parser.""" return parser def update_parser_compute(self, parser): """Default is no updates to parser.""" return parser @abc.abstractmethod def take_action_network(self, client, parsed_args): """Override to do something useful.""" pass @abc.abstractmethod def take_action_compute(self, client, parsed_args): """Override to do something useful.""" pass @six.add_metaclass(abc.ABCMeta) class NetworkAndComputeDelete(NetworkAndComputeCommand): """Network and Compute Delete Delete class for commands that support implementation via the network or compute endpoint. Such commands have different implementations for take_action() and may even have different arguments. This class supports bulk deletion, and error handling following the rules in doc/source/command-errors.rst. """ def take_action(self, parsed_args): ret = 0 resources = getattr(parsed_args, self.resource, []) for r in resources: self.r = r try: if self.app.client_manager.is_network_endpoint_enabled(): self.take_action_network(self.app.client_manager.network, parsed_args) else: self.take_action_compute(self.app.client_manager.compute, parsed_args) except Exception as e: msg = _("Failed to delete %(resource)s with name or ID " "'%(name_or_id)s': %(e)s") % { "resource": self.resource, "name_or_id": r, "e": e, } LOG.error(msg) ret += 1 if ret: total = len(resources) msg = _("%(num)s of %(total)s %(resource)ss failed to delete.") % { "num": ret, "total": total, "resource": self.resource, } raise exceptions.CommandError(msg) @six.add_metaclass(abc.ABCMeta) class NetworkAndComputeLister(command.Lister): """Network and Compute Lister Lister class for commands that support implementation via the network or compute endpoint. Such commands have different implementations for take_action() and may even have different arguments. """ def take_action(self, parsed_args): if self.app.client_manager.is_network_endpoint_enabled(): return self.take_action_network(self.app.client_manager.network, parsed_args) else: return self.take_action_compute(self.app.client_manager.compute, parsed_args) def get_parser(self, prog_name): LOG.debug('get_parser(%s)', prog_name) parser = super(NetworkAndComputeLister, self).get_parser(prog_name) parser = self.update_parser_common(parser) LOG.debug('common parser: %s', parser) if self.app.client_manager.is_network_endpoint_enabled(): return self.update_parser_network(parser) else: return self.update_parser_compute(parser) def update_parser_common(self, parser): """Default is no updates to parser.""" return parser def update_parser_network(self, parser): """Default is no updates to parser.""" return parser def update_parser_compute(self, parser): """Default is no updates to parser.""" return parser @abc.abstractmethod def take_action_network(self, client, parsed_args): """Override to do something useful.""" pass @abc.abstractmethod def take_action_compute(self, client, parsed_args): """Override to do something useful.""" pass @six.add_metaclass(abc.ABCMeta) class NetworkAndComputeShowOne(command.ShowOne): """Network and Compute ShowOne ShowOne class for commands that support implementation via the network or compute endpoint. Such commands have different implementations for take_action() and may even have different arguments. """ def take_action(self, parsed_args): try: if self.app.client_manager.is_network_endpoint_enabled(): return self.take_action_network( self.app.client_manager.network, parsed_args) else: return self.take_action_compute( self.app.client_manager.compute, parsed_args) except openstack.exceptions.HttpException as exc: msg = _("Error while executing command: %s") % exc.message if exc.details: msg += ", " + six.text_type(exc.details) raise exceptions.CommandError(msg) def get_parser(self, prog_name): LOG.debug('get_parser(%s)', prog_name) parser = super(NetworkAndComputeShowOne, self).get_parser(prog_name) parser = self.update_parser_common(parser) LOG.debug('common parser: %s', parser) if self.app.client_manager.is_network_endpoint_enabled(): return self.update_parser_network(parser) else: return self.update_parser_compute(parser) def update_parser_common(self, parser): """Default is no updates to parser.""" return parser def update_parser_network(self, parser): """Default is no updates to parser.""" return parser def update_parser_compute(self, parser): """Default is no updates to parser.""" return parser @abc.abstractmethod def take_action_network(self, client, parsed_args): """Override to do something useful.""" pass @abc.abstractmethod def take_action_compute(self, client, parsed_args): """Override to do something useful.""" pass python-openstackclient-3.14.0/openstackclient/network/utils.py0000666000175100017510000000303213232364361024724 0ustar zuulzuul00000000000000# 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. # # Transform compute security group rule for display. def transform_compute_security_group_rule(sg_rule): info = {} info.update(sg_rule) from_port = info.pop('from_port') to_port = info.pop('to_port') if isinstance(from_port, int) and isinstance(to_port, int): port_range = {'port_range': "%u:%u" % (from_port, to_port)} elif from_port is None and to_port is None: port_range = {'port_range': ""} else: port_range = {'port_range': "%s:%s" % (from_port, to_port)} info.update(port_range) if 'cidr' in info['ip_range']: info['ip_range'] = info['ip_range']['cidr'] else: info['ip_range'] = '' if info['ip_protocol'] is None: info['ip_protocol'] = '' elif info['ip_protocol'].lower() == 'icmp': info['port_range'] = '' group = info.pop('group') if 'name' in group: info['remote_security_group'] = group['name'] else: info['remote_security_group'] = '' return info python-openstackclient-3.14.0/openstackclient/network/sdk_utils.py0000666000175100017510000000451113232364361025570 0ustar zuulzuul00000000000000# 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 six def get_osc_show_columns_for_sdk_resource( sdk_resource, osc_column_map, invisible_columns=None ): """Get and filter the display and attribute columns for an SDK resource. Common utility function for preparing the output of an OSC show command. Some of the columns may need to get renamed, others made invisible. :param sdk_resource: An SDK resource :param osc_column_map: A hash of mappings for display column names :param invisible_columns: A list of invisible column names :returns: Two tuples containing the names of the display and attribute columns """ if getattr(sdk_resource, 'allow_get', None) is not None: resource_dict = sdk_resource.to_dict( body=True, headers=False, ignore_none=False) else: resource_dict = sdk_resource # Build the OSC column names to display for the SDK resource. attr_map = {} display_columns = list(resource_dict.keys()) invisible_columns = [] if invisible_columns is None else invisible_columns for col_name in invisible_columns: if col_name in display_columns: display_columns.remove(col_name) for sdk_attr, osc_attr in six.iteritems(osc_column_map): if sdk_attr in display_columns: attr_map[osc_attr] = sdk_attr display_columns.remove(sdk_attr) if osc_attr not in display_columns: display_columns.append(osc_attr) sorted_display_columns = sorted(display_columns) # Build the SDK attribute names for the OSC column names. attr_columns = [] for column in sorted_display_columns: new_column = attr_map[column] if column in attr_map else column attr_columns.append(new_column) return tuple(sorted_display_columns), tuple(attr_columns) python-openstackclient-3.14.0/openstackclient/network/client.py0000666000175100017510000000562413232364361025053 0ustar zuulzuul00000000000000# 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 openstack import connection # NOTE(dtroyer): Attempt an import to detect if the SDK installed is new # enough to not use Profile. If so, use that. try: from openstack.config import loader as config # noqa profile = None except ImportError: from openstack import profile from osc_lib import utils from openstackclient.i18n import _ LOG = logging.getLogger(__name__) DEFAULT_API_VERSION = '2.0' API_VERSION_OPTION = 'os_network_api_version' API_NAME = "network" API_VERSIONS = { "2.0": "openstack.connection.Connection", "2": "openstack.connection.Connection", } def make_client(instance): """Returns a network proxy""" if getattr(instance, "sdk_connection", None) is None: if profile is None: # If the installed OpenStackSDK is new enough to not require a # Profile obejct and osc-lib is not new enough to have created # it for us, make an SDK Connection. # NOTE(dtroyer): This can be removed when this bit is in the # released osc-lib in requirements.txt. conn = connection.Connection( config=instance._cli_options, session=instance.session, ) else: # Fall back to the original Connection creation prof = profile.Profile() prof.set_region(API_NAME, instance.region_name) prof.set_version(API_NAME, instance._api_version[API_NAME]) prof.set_interface(API_NAME, instance.interface) conn = connection.Connection( authenticator=instance.session.auth, verify=instance.session.verify, cert=instance.session.cert, profile=prof, ) instance.sdk_connection = conn conn = instance.sdk_connection LOG.debug('Connection: %s', conn) LOG.debug('Network client initialized using OpenStack SDK: %s', conn.network) return conn.network def build_option_parser(parser): """Hook to add global options""" parser.add_argument( '--os-network-api-version', metavar='', default=utils.env('OS_NETWORK_API_VERSION'), help=_("Network API version, default=%s " "(Env: OS_NETWORK_API_VERSION)") % DEFAULT_API_VERSION ) return parser python-openstackclient-3.14.0/openstackclient/network/v2/0000775000175100017510000000000013232364654023546 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/network/v2/network_flavor_profile.py0000666000175100017510000002063113232364361030701 0ustar zuulzuul00000000000000# 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 openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils LOG = logging.getLogger(__name__) def _get_columns(item): column_map = { 'is_enabled': 'enabled', 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) def _get_attrs(client_manager, parsed_args): attrs = {} if parsed_args.description is not None: attrs['description'] = parsed_args.description if parsed_args.driver is not None: attrs['driver'] = parsed_args.driver if parsed_args.metainfo is not None: attrs['metainfo'] = parsed_args.metainfo if parsed_args.enable: attrs['enabled'] = True if parsed_args.disable: attrs['enabled'] = False if 'project' in parsed_args and parsed_args.project is not None: identity_client = client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id return attrs # TODO(ndahiwade): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateNetworkFlavorProfile(command.ShowOne): _description = _("Create new network flavor profile") def get_parser(self, prog_name): parser = super(CreateNetworkFlavorProfile, self).get_parser(prog_name) parser.add_argument( '--project', metavar="", help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--description', metavar="", help=_("Description for the flavor profile") ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_("Enable the flavor profile") ) enable_group.add_argument( '--disable', action='store_true', help=_("Disable the flavor profile") ) parser.add_argument( '--driver', help=_("Python module path to driver. This becomes " "required if --metainfo is missing and vice versa") ) parser.add_argument( '--metainfo', help=_("Metainfo for the flavor profile. This becomes " "required if --driver is missing and vice versa") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_attrs(self.app.client_manager, parsed_args) if parsed_args.driver is None and parsed_args.metainfo is None: msg = _("Either --driver or --metainfo or both are required") raise exceptions.CommandError(msg) obj = client.create_service_profile(**attrs) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters={}) return (display_columns, data) class DeleteNetworkFlavorProfile(command.Command): _description = _("Delete network flavor profile") def get_parser(self, prog_name): parser = super(DeleteNetworkFlavorProfile, self).get_parser(prog_name) parser.add_argument( 'flavor_profile', metavar='', nargs='+', help=_("Flavor profile(s) to delete (ID only)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for flavor_profile in parsed_args.flavor_profile: try: obj = client.find_service_profile(flavor_profile, ignore_missing=False) client.delete_service_profile(obj) except Exception as e: result += 1 LOG.error(_("Failed to delete flavor profile with " "ID '%(flavor_profile)s': %(e)s"), {"flavor_profile": flavor_profile, "e": e}) if result > 0: total = len(parsed_args.flavor_profile) msg = (_("%(result)s of %(total)s flavor_profiles failed " "to delete.") % {"result": result, "total": total}) raise exceptions.CommandError(msg) class ListNetworkFlavorProfile(command.Lister): _description = _("List network flavor profile(s)") def take_action(self, parsed_args): client = self.app.client_manager.network columns = ( 'id', 'driver', 'is_enabled', 'metainfo', 'description', ) column_headers = ( 'ID', 'Driver', 'Enabled', 'Metainfo', 'Description', ) data = client.service_profiles() return (column_headers, (utils.get_item_properties( s, columns, ) for s in data)) # TODO(ndahiwade): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class SetNetworkFlavorProfile(command.Command): _description = _("Set network flavor profile properties") def get_parser(self, prog_name): parser = super(SetNetworkFlavorProfile, self).get_parser(prog_name) parser.add_argument( 'flavor_profile', metavar="", help=_("Flavor profile to update (ID only)") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--description', metavar="", help=_("Description for the flavor profile") ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_("Enable the flavor profile") ) enable_group.add_argument( '--disable', action='store_true', help=_("Disable the flavor profile") ) parser.add_argument( '--driver', help=_("Python module path to driver. This becomes " "required if --metainfo is missing and vice versa") ) parser.add_argument( '--metainfo', help=_("Metainfo for the flavor profile. This becomes " "required if --driver is missing and vice versa") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_service_profile(parsed_args.flavor_profile, ignore_missing=False) attrs = _get_attrs(self.app.client_manager, parsed_args) client.update_service_profile(obj, **attrs) class ShowNetworkFlavorProfile(command.ShowOne): _description = _("Display network flavor profile details") def get_parser(self, prog_name): parser = super(ShowNetworkFlavorProfile, self).get_parser(prog_name) parser.add_argument( 'flavor_profile', metavar='', help=_("Flavor profile to display (ID only)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_service_profile(parsed_args.flavor_profile, ignore_missing=False) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return (display_columns, data) python-openstackclient-3.14.0/openstackclient/network/v2/subnet_pool.py0000666000175100017510000004136513232364361026457 0ustar zuulzuul00000000000000# 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 pool action implementations""" import copy 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 openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils from openstackclient.network.v2 import _tag LOG = logging.getLogger(__name__) def _get_columns(item): column_map = { 'default_prefix_length': 'default_prefixlen', 'is_shared': 'shared', 'maximum_prefix_length': 'max_prefixlen', 'minimum_prefix_length': 'min_prefixlen', 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) _formatters = { 'prefixes': utils.format_list, 'tags': utils.format_list, } def _get_attrs(client_manager, parsed_args): attrs = {} network_client = client_manager.network if parsed_args.name is not None: attrs['name'] = str(parsed_args.name) if parsed_args.prefixes is not None: attrs['prefixes'] = parsed_args.prefixes if parsed_args.default_prefix_length is not None: attrs['default_prefixlen'] = parsed_args.default_prefix_length if parsed_args.min_prefix_length is not None: attrs['min_prefixlen'] = parsed_args.min_prefix_length if parsed_args.max_prefix_length is not None: attrs['max_prefixlen'] = parsed_args.max_prefix_length if parsed_args.address_scope is not None: attrs['address_scope_id'] = network_client.find_address_scope( parsed_args.address_scope, ignore_missing=False).id if 'no_address_scope' in parsed_args and parsed_args.no_address_scope: attrs['address_scope_id'] = None if parsed_args.default: attrs['is_default'] = True if parsed_args.no_default: attrs['is_default'] = False if 'share' in parsed_args and parsed_args.share: attrs['shared'] = True if 'no_share' in parsed_args and parsed_args.no_share: attrs['shared'] = False # "subnet pool set" command doesn't support setting project. if 'project' in parsed_args and parsed_args.project is not None: identity_client = client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id if parsed_args.description is not None: attrs['description'] = parsed_args.description if parsed_args.default_quota is not None: attrs['default_quota'] = int(parsed_args.default_quota) return attrs def _add_prefix_options(parser, for_create=False): parser.add_argument( '--pool-prefix', metavar='', dest='prefixes', action='append', required=for_create, help=_("Set subnet pool prefixes (in CIDR notation) " "(repeat option to set multiple prefixes)") ) parser.add_argument( '--default-prefix-length', metavar='', type=int, action=parseractions.NonNegativeAction, help=_("Set subnet pool default prefix length") ) parser.add_argument( '--min-prefix-length', metavar='', action=parseractions.NonNegativeAction, type=int, help=_("Set subnet pool minimum prefix length") ) parser.add_argument( '--max-prefix-length', metavar='', type=int, action=parseractions.NonNegativeAction, help=_("Set subnet pool maximum prefix length") ) def _add_default_options(parser): default_group = parser.add_mutually_exclusive_group() default_group.add_argument( '--default', action='store_true', help=_("Set this as a default subnet pool"), ) default_group.add_argument( '--no-default', action='store_true', help=_("Set this as a non-default subnet pool"), ) # TODO(rtheis): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateSubnetPool(command.ShowOne): _description = _("Create subnet pool") def get_parser(self, prog_name): parser = super(CreateSubnetPool, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_("Name of the new subnet pool") ) _add_prefix_options(parser, for_create=True) parser.add_argument( '--project', metavar='', help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--address-scope', metavar='', help=_("Set address scope associated with the subnet pool " "(name or ID), prefixes must be unique across address " "scopes") ) _add_default_options(parser) shared_group = parser.add_mutually_exclusive_group() shared_group.add_argument( '--share', action='store_true', help=_("Set this subnet pool as shared"), ) shared_group.add_argument( '--no-share', action='store_true', help=_("Set this subnet pool as not shared"), ) parser.add_argument( '--description', metavar='', help=_("Set subnet pool description") ) parser.add_argument( '--default-quota', type=int, metavar='', help=_("Set default quota for subnet pool as the number of" "IP addresses allowed in a subnet")), _tag.add_tag_option_to_parser_for_create(parser, _('subnet pool')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_attrs(self.app.client_manager, parsed_args) # NeutronServer expects prefixes to be a List if "prefixes" not in attrs: attrs['prefixes'] = [] obj = client.create_subnet_pool(**attrs) # tags cannot be set when created, so tags need to be set later. _tag.update_tags_for_set(client, obj, parsed_args) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters=_formatters) return (display_columns, data) class DeleteSubnetPool(command.Command): _description = _("Delete subnet pool(s)") def get_parser(self, prog_name): parser = super(DeleteSubnetPool, self).get_parser(prog_name) parser.add_argument( 'subnet_pool', metavar='', nargs='+', help=_("Subnet pool(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for pool in parsed_args.subnet_pool: try: obj = client.find_subnet_pool(pool, ignore_missing=False) client.delete_subnet_pool(obj) except Exception as e: result += 1 LOG.error(_("Failed to delete subnet pool with " "name or ID '%(pool)s': %(e)s"), {'pool': pool, 'e': e}) if result > 0: total = len(parsed_args.subnet_pool) msg = (_("%(result)s of %(total)s subnet pools failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) # TODO(rtheis): Use only the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class ListSubnetPool(command.Lister): _description = _("List subnet pools") def get_parser(self, prog_name): parser = super(ListSubnetPool, self).get_parser(prog_name) parser.add_argument( '--long', action='store_true', default=False, help=_("List additional fields in output") ) shared_group = parser.add_mutually_exclusive_group() shared_group.add_argument( '--share', action='store_true', help=_("List subnet pools shared between projects"), ) shared_group.add_argument( '--no-share', action='store_true', help=_("List subnet pools not shared between projects"), ) default_group = parser.add_mutually_exclusive_group() default_group.add_argument( '--default', action='store_true', help=_("List subnet pools used as the default external " "subnet pool"), ) default_group.add_argument( '--no-default', action='store_true', help=_("List subnet pools not used as the default external " "subnet pool") ) parser.add_argument( '--project', metavar='', help=_("List subnet pools according to their project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--name', metavar='', help=_("List only subnet pools of given name in output") ) parser.add_argument( '--address-scope', metavar='', help=_("List only subnet pools of given address scope " "in output (name or ID)") ) _tag.add_tag_filtering_option_to_parser(parser, _('subnet pools')) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity network_client = self.app.client_manager.network filters = {} if parsed_args.share: filters['shared'] = True filters['is_shared'] = True elif parsed_args.no_share: filters['shared'] = False filters['is_shared'] = False if parsed_args.default: filters['is_default'] = True elif parsed_args.no_default: filters['is_default'] = False if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id filters['tenant_id'] = project_id filters['project_id'] = project_id if parsed_args.name is not None: filters['name'] = parsed_args.name if parsed_args.address_scope: address_scope = network_client.find_address_scope( parsed_args.address_scope, ignore_missing=False) filters['address_scope_id'] = address_scope.id _tag.get_tag_filtering_args(parsed_args, filters) data = network_client.subnet_pools(**filters) headers = ('ID', 'Name', 'Prefixes') columns = ('id', 'name', 'prefixes') if parsed_args.long: headers += ('Default Prefix Length', 'Address Scope', 'Default Subnet Pool', 'Shared', 'Tags') columns += ('default_prefix_length', 'address_scope_id', 'is_default', 'is_shared', 'tags') return (headers, (utils.get_item_properties( s, columns, formatters=_formatters, ) for s in data)) # TODO(rtheis): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class SetSubnetPool(command.Command): _description = _("Set subnet pool properties") def get_parser(self, prog_name): parser = super(SetSubnetPool, self).get_parser(prog_name) parser.add_argument( 'subnet_pool', metavar='', help=_("Subnet pool to modify (name or ID)") ) parser.add_argument( '--name', metavar='', help=_("Set subnet pool name") ) _add_prefix_options(parser) address_scope_group = parser.add_mutually_exclusive_group() address_scope_group.add_argument( '--address-scope', metavar='', help=_("Set address scope associated with the subnet pool " "(name or ID), prefixes must be unique across address " "scopes") ) address_scope_group.add_argument( '--no-address-scope', action='store_true', help=_("Remove address scope associated with the subnet pool") ) _add_default_options(parser) parser.add_argument( '--description', metavar='', help=_("Set subnet pool description") ) parser.add_argument( '--default-quota', type=int, metavar='', help=_("Set default quota for subnet pool as the number of" "IP addresses allowed in a subnet")), _tag.add_tag_option_to_parser_for_set(parser, _('subnet pool')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_subnet_pool(parsed_args.subnet_pool, ignore_missing=False) attrs = _get_attrs(self.app.client_manager, parsed_args) # Existing prefixes must be a subset of the new prefixes. if 'prefixes' in attrs: attrs['prefixes'].extend(obj.prefixes) if attrs: client.update_subnet_pool(obj, **attrs) # tags is a subresource and it needs to be updated separately. _tag.update_tags_for_set(client, obj, parsed_args) class ShowSubnetPool(command.ShowOne): _description = _("Display subnet pool details") def get_parser(self, prog_name): parser = super(ShowSubnetPool, self).get_parser(prog_name) parser.add_argument( 'subnet_pool', metavar='', help=_("Subnet pool to display (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_subnet_pool( parsed_args.subnet_pool, ignore_missing=False ) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters=_formatters) return (display_columns, data) class UnsetSubnetPool(command.Command): _description = _("Unset subnet pool properties") def get_parser(self, prog_name): parser = super(UnsetSubnetPool, self).get_parser(prog_name) parser.add_argument( '--pool-prefix', metavar='', action='append', dest='prefixes', help=_('Remove subnet pool prefixes (in CIDR notation). ' '(repeat option to unset multiple prefixes).'), ) parser.add_argument( 'subnet_pool', metavar="", help=_("Subnet pool to modify (name or ID)") ) _tag.add_tag_option_to_parser_for_unset(parser, _('subnet pool')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_subnet_pool( parsed_args.subnet_pool, ignore_missing=False) tmp_prefixes = copy.deepcopy(obj.prefixes) attrs = {} if parsed_args.prefixes: for prefix in parsed_args.prefixes: try: tmp_prefixes.remove(prefix) except ValueError: msg = _( "Subnet pool does not " "contain prefix %s") % prefix raise exceptions.CommandError(msg) attrs['prefixes'] = tmp_prefixes if attrs: client.update_subnet_pool(obj, **attrs) # tags is a subresource and it needs to be updated separately. _tag.update_tags_for_unset(client, obj, parsed_args) python-openstackclient-3.14.0/openstackclient/network/v2/floating_ip.py0000666000175100017510000005021313232364361026411 0ustar zuulzuul00000000000000# 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. # """IP Floating action implementations""" import logging from openstack import exceptions as sdk_exceptions from openstack.network.v2 import floating_ip as _floating_ip from osc_lib.command import command from osc_lib import utils from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import common from openstackclient.network import sdk_utils def _get_network_columns(item): column_map = { 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) def _get_columns(item): columns = list(item.keys()) if 'tenant_id' in columns: columns.remove('tenant_id') columns.append('project_id') return tuple(sorted(columns)) def _get_attrs(client_manager, parsed_args): attrs = {} network_client = client_manager.network # Name of a network could be empty string. if parsed_args.network is not None: network = network_client.find_network(parsed_args.network, ignore_missing=False) attrs['floating_network_id'] = network.id if parsed_args.subnet: subnet = network_client.find_subnet(parsed_args.subnet, ignore_missing=False) attrs['subnet_id'] = subnet.id if parsed_args.port: port = network_client.find_port(parsed_args.port, ignore_missing=False) attrs['port_id'] = port.id if parsed_args.floating_ip_address: attrs['floating_ip_address'] = parsed_args.floating_ip_address if parsed_args.fixed_ip_address: attrs['fixed_ip_address'] = parsed_args.fixed_ip_address if parsed_args.qos_policy: attrs['qos_policy_id'] = network_client.find_qos_policy( parsed_args.qos_policy, ignore_missing=False).id if parsed_args.description is not None: attrs['description'] = parsed_args.description if parsed_args.project: identity_client = client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id return attrs def _find_floating_ip( session, name_or_id, ignore_missing=True, **params ): """Find a floating IP by IP or ID The SDK's find_ip() can only locate a floating IP by ID so we have to do this ourselves. """ def _get_one_match(name_or_id): """Given a list of results, return the match""" the_result = None ip_list = list(_floating_ip.FloatingIP.list(session, **params)) for maybe_result in ip_list: id_value = maybe_result.id ip_value = maybe_result.floating_ip_address if (id_value == name_or_id) or (ip_value == name_or_id): # Only allow one resource to be found. If we already # found a match, raise an exception to show it. if the_result is None: the_result = maybe_result else: msg = "More than one %s exists with the name '%s'." msg = (msg % (_floating_ip.FloatingIP, name_or_id)) raise sdk_exceptions.DuplicateResource(msg) return the_result # Try to short-circuit by looking directly for a matching ID. try: match = _floating_ip.FloatingIP.existing(id=name_or_id, **params) return match.get(session) except sdk_exceptions.NotFoundException: pass result = _get_one_match(name_or_id) if result is not None: return result if ignore_missing: return None raise sdk_exceptions.ResourceNotFound( "No %s found for %s" % (_floating_ip.FloatingIP.__name__, name_or_id)) class CreateFloatingIP(common.NetworkAndComputeShowOne): _description = _("Create floating IP") def update_parser_common(self, parser): # In Compute v2 network, floating IPs could be allocated from floating # IP pools, which are actually external networks. So deprecate the # parameter "pool", and use "network" instead. parser.add_argument( 'network', metavar='', help=_("Network to allocate floating IP from (name or ID)") ) return parser def update_parser_network(self, parser): parser.add_argument( '--subnet', metavar='', help=_("Subnet on which you want to create the floating IP " "(name or ID)") ) parser.add_argument( '--port', metavar='', help=_("Port to be associated with the floating IP " "(name or ID)") ) parser.add_argument( '--floating-ip-address', metavar='', dest='floating_ip_address', help=_("Floating IP address") ) parser.add_argument( '--fixed-ip-address', metavar='', dest='fixed_ip_address', help=_("Fixed IP address mapped to the floating IP") ) parser.add_argument( '--qos-policy', metavar='', help=_("Attach QoS policy to the floating IP (name or ID)") ) parser.add_argument( '--description', metavar='', help=_('Set floating IP description') ) parser.add_argument( '--project', metavar='', help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) return parser def take_action_network(self, client, parsed_args): attrs = _get_attrs(self.app.client_manager, parsed_args) obj = client.create_ip(**attrs) display_columns, columns = _get_network_columns(obj) data = utils.get_item_properties(obj, columns) return (display_columns, data) def take_action_compute(self, client, parsed_args): obj = client.api.floating_ip_create(parsed_args.network) columns = _get_columns(obj) data = utils.get_dict_properties(obj, columns) return (columns, data) class CreateIPFloating(CreateFloatingIP): _description = _("Create floating IP") # TODO(tangchen): Remove this class and ``ip floating create`` command # two cycles after Mitaka. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action_network(self, client, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "floating ip create" instead.')) return super(CreateIPFloating, self).take_action_network( client, parsed_args) def take_action_compute(self, client, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "floating ip create" instead.')) return super(CreateIPFloating, self).take_action_compute( client, parsed_args) class DeleteFloatingIP(common.NetworkAndComputeDelete): _description = _("Delete floating IP(s)") # Used by base class to find resources in parsed_args. resource = 'floating_ip' r = None def update_parser_common(self, parser): parser.add_argument( 'floating_ip', metavar="", nargs="+", help=_("Floating IP(s) to delete (IP address or ID)") ) return parser def take_action_network(self, client, parsed_args): obj = _find_floating_ip( self.app.client_manager.sdk_connection.session, self.r, ignore_missing=False, ) client.delete_ip(obj) def take_action_compute(self, client, parsed_args): client.api.floating_ip_delete(self.r) class DeleteIPFloating(DeleteFloatingIP): _description = _("Delete floating IP(s)") # TODO(tangchen): Remove this class and ``ip floating delete`` command # two cycles after Mitaka. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action_network(self, client, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "floating ip delete" instead.')) return super(DeleteIPFloating, self).take_action_network( client, parsed_args) def take_action_compute(self, client, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "floating ip delete" instead.')) return super(DeleteIPFloating, self).take_action_compute( client, parsed_args) class ListFloatingIP(common.NetworkAndComputeLister): # TODO(songminglong): Use SDK resource mapped attribute names once # the OSC minimum requirements include SDK 1.0 _description = _("List floating IP(s)") def update_parser_network(self, parser): parser.add_argument( '--network', metavar='', help=_("List floating IP(s) according to " "given network (name or ID)") ) parser.add_argument( '--port', metavar='', help=_("List floating IP(s) according to " "given port (name or ID)") ) parser.add_argument( '--fixed-ip-address', metavar='', help=_("List floating IP(s) according to " "given fixed IP address") ) parser.add_argument( '--long', action='store_true', default=False, help=_("List additional fields in output") ) parser.add_argument( '--status', metavar='', choices=['ACTIVE', 'DOWN'], help=_("List floating IP(s) according to " "given status ('ACTIVE', 'DOWN')") ) parser.add_argument( '--project', metavar='', help=_("List floating IP(s) according to " "given project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--router', metavar='', help=_("List floating IP(s) according to " "given router (name or ID)") ) return parser def take_action_network(self, client, parsed_args): network_client = self.app.client_manager.network identity_client = self.app.client_manager.identity columns = ( 'id', 'floating_ip_address', 'fixed_ip_address', 'port_id', 'floating_network_id', 'project_id', ) headers = ( 'ID', 'Floating IP Address', 'Fixed IP Address', 'Port', 'Floating Network', 'Project', ) if parsed_args.long: columns = columns + ( 'router_id', 'status', 'description', ) headers = headers + ( 'Router', 'Status', 'Description', ) query = {} if parsed_args.network is not None: network = network_client.find_network(parsed_args.network, ignore_missing=False) query['floating_network_id'] = network.id if parsed_args.port is not None: port = network_client.find_port(parsed_args.port, ignore_missing=False) query['port_id'] = port.id if parsed_args.fixed_ip_address is not None: query['fixed_ip_address'] = parsed_args.fixed_ip_address if parsed_args.status: query['status'] = parsed_args.status if parsed_args.project is not None: project = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ) query['tenant_id'] = project.id query['project_id'] = project.id if parsed_args.router is not None: router = network_client.find_router(parsed_args.router, ignore_missing=False) query['router_id'] = router.id data = client.ips(**query) return (headers, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) def take_action_compute(self, client, parsed_args): columns = ( 'ID', 'IP', 'Fixed IP', 'Instance ID', 'Pool', ) headers = ( 'ID', 'Floating IP Address', 'Fixed IP Address', 'Server', 'Pool', ) data = client.api.floating_ip_list() return (headers, (utils.get_dict_properties( s, columns, formatters={}, ) for s in data)) class ListIPFloating(ListFloatingIP): _description = _("List floating IP(s)") # TODO(tangchen): Remove this class and ``ip floating list`` command # two cycles after Mitaka. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action_network(self, client, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "floating ip list" instead.')) return super(ListIPFloating, self).take_action_network( client, parsed_args) def take_action_compute(self, client, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "floating ip list" instead.')) return super(ListIPFloating, self).take_action_compute( client, parsed_args) class SetFloatingIP(command.Command): _description = _("Set floating IP Properties") def get_parser(self, prog_name): parser = super(SetFloatingIP, self).get_parser(prog_name) parser.add_argument( 'floating_ip', metavar='', help=_("Floating IP to associate (IP address or ID)")) parser.add_argument( '--port', metavar='', required=True, help=_("Assocaite the floating IP with port (name or ID)")), parser.add_argument( '--fixed-ip-address', metavar='', dest='fixed_ip_address', help=_("Fixed IP of the port " "(required only if port has multiple IPs)") ) qos_policy_group = parser.add_mutually_exclusive_group() qos_policy_group.add_argument( '--qos-policy', metavar='', help=_("Attach QoS policy to the floating IP (name or ID)") ) qos_policy_group.add_argument( '--no-qos-policy', action='store_true', help=_("Remove the QoS policy attached to the floating IP") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = {} # TODO(sindhu) Use client.find_ip() once SDK 0.9.15 is released obj = _find_floating_ip( self.app.client_manager.sdk_connection.session, parsed_args.floating_ip, ignore_missing=False, ) port = client.find_port(parsed_args.port, ignore_missing=False) attrs['port_id'] = port.id if parsed_args.fixed_ip_address: attrs['fixed_ip_address'] = parsed_args.fixed_ip_address if parsed_args.qos_policy: attrs['qos_policy_id'] = client.find_qos_policy( parsed_args.qos_policy, ignore_missing=False).id if 'no_qos_policy' in parsed_args and parsed_args.no_qos_policy: attrs['qos_policy_id'] = None client.update_ip(obj, **attrs) class ShowFloatingIP(common.NetworkAndComputeShowOne): _description = _("Display floating IP details") def update_parser_common(self, parser): parser.add_argument( 'floating_ip', metavar="", help=_("Floating IP to display (IP address or ID)") ) return parser def take_action_network(self, client, parsed_args): obj = _find_floating_ip( self.app.client_manager.sdk_connection.session, parsed_args.floating_ip, ignore_missing=False, ) display_columns, columns = _get_network_columns(obj) data = utils.get_item_properties(obj, columns) return (display_columns, data) def take_action_compute(self, client, parsed_args): obj = client.api.floating_ip_find(parsed_args.floating_ip) columns = _get_columns(obj) data = utils.get_dict_properties(obj, columns) return (columns, data) class ShowIPFloating(ShowFloatingIP): _description = _("Display floating IP details") # TODO(tangchen): Remove this class and ``ip floating show`` command # two cycles after Mitaka. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action_network(self, client, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "floating ip show" instead.')) return super(ShowIPFloating, self).take_action_network( client, parsed_args) def take_action_compute(self, client, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "floating ip show" instead.')) return super(ShowIPFloating, self).take_action_compute( client, parsed_args) class UnsetFloatingIP(command.Command): _description = _("Unset floating IP Properties") def get_parser(self, prog_name): parser = super(UnsetFloatingIP, self).get_parser(prog_name) parser.add_argument( 'floating_ip', metavar='', help=_("Floating IP to disassociate (IP address or ID)")) parser.add_argument( '--port', action='store_true', default=False, help=_("Disassociate any port associated with the floating IP") ) parser.add_argument( '--qos-policy', action='store_true', default=False, help=_("Remove the QoS policy attached to the floating IP") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network # TODO(sindhu) Use client.find_ip() once SDK 0.9.15 is released obj = _find_floating_ip( self.app.client_manager.sdk_connection.session, parsed_args.floating_ip, ignore_missing=False, ) attrs = {} if parsed_args.port: attrs['port_id'] = None if parsed_args.qos_policy: attrs['qos_policy_id'] = None if attrs: client.update_ip(obj, **attrs) python-openstackclient-3.14.0/openstackclient/network/v2/_tag.py0000666000175100017510000001034113232364361025026 0ustar zuulzuul00000000000000# 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 openstackclient.i18n import _ class _CommaListAction(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): setattr(namespace, self.dest, values.split(',')) def add_tag_filtering_option_to_parser(parser, collection_name): parser.add_argument( '--tags', metavar='[,,...]', action=_CommaListAction, help=_('List %s which have all given tag(s) ' '(Comma-separated list of tags)') % collection_name ) parser.add_argument( '--any-tags', metavar='[,,...]', action=_CommaListAction, help=_('List %s which have any given tag(s) ' '(Comma-separated list of tags)') % collection_name ) parser.add_argument( '--not-tags', metavar='[,,...]', action=_CommaListAction, help=_('Exclude %s which have all given tag(s) ' '(Comma-separated list of tags)') % collection_name ) parser.add_argument( '--not-any-tags', metavar='[,,...]', action=_CommaListAction, help=_('Exclude %s which have any given tag(s) ' '(Comma-separated list of tags)') % collection_name ) def get_tag_filtering_args(parsed_args, args): if parsed_args.tags: args['tags'] = ','.join(parsed_args.tags) if parsed_args.any_tags: args['any_tags'] = ','.join(parsed_args.any_tags) if parsed_args.not_tags: args['not_tags'] = ','.join(parsed_args.not_tags) if parsed_args.not_any_tags: args['not_any_tags'] = ','.join(parsed_args.not_any_tags) def add_tag_option_to_parser_for_create(parser, resource_name): tag_group = parser.add_mutually_exclusive_group() tag_group.add_argument( '--tag', action='append', dest='tags', metavar='', help=_("Tag to be added to the %s " "(repeat option to set multiple tags)") % resource_name ) tag_group.add_argument( '--no-tag', action='store_true', help=_("No tags associated with the %s") % resource_name ) def add_tag_option_to_parser_for_set(parser, resource_name): parser.add_argument( '--tag', action='append', dest='tags', metavar='', help=_("Tag to be added to the %s " "(repeat option to set multiple tags)") % resource_name ) parser.add_argument( '--no-tag', action='store_true', help=_("Clear tags associated with the %s. Specify both " "--tag and --no-tag to overwrite current tags") % resource_name ) def update_tags_for_set(client, obj, parsed_args): if parsed_args.no_tag: tags = set() else: tags = set(obj.tags or []) if parsed_args.tags: tags |= set(parsed_args.tags) if set(obj.tags or []) != tags: client.set_tags(obj, list(tags)) def add_tag_option_to_parser_for_unset(parser, resource_name): tag_group = parser.add_mutually_exclusive_group() tag_group.add_argument( '--tag', action='append', dest='tags', metavar='', help=_("Tag to be removed from the %s " "(repeat option to remove multiple tags)") % resource_name) tag_group.add_argument( '--all-tag', action='store_true', help=_("Clear all tags associated with the %s") % resource_name) def update_tags_for_unset(client, obj, parsed_args): tags = set(obj.tags) if parsed_args.all_tag: tags = set() if parsed_args.tags: tags -= set(parsed_args.tags) if set(obj.tags) != tags: client.set_tags(obj, list(tags)) python-openstackclient-3.14.0/openstackclient/network/v2/network_rbac.py0000666000175100017510000002364313232364361026605 0ustar zuulzuul00000000000000# 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. # """RBAC action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils LOG = logging.getLogger(__name__) def _get_columns(item): column_map = { 'target_tenant': 'target_project_id', 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) def _get_attrs(client_manager, parsed_args): attrs = {} attrs['object_type'] = parsed_args.type attrs['action'] = parsed_args.action network_client = client_manager.network if parsed_args.type == 'network': object_id = network_client.find_network( parsed_args.rbac_object, ignore_missing=False).id if parsed_args.type == 'qos_policy': object_id = network_client.find_qos_policy( parsed_args.rbac_object, ignore_missing=False).id attrs['object_id'] = object_id identity_client = client_manager.identity if parsed_args.target_project is not None: project_id = identity_common.find_project( identity_client, parsed_args.target_project, parsed_args.target_project_domain, ).id elif parsed_args.target_all_projects: project_id = '*' attrs['target_tenant'] = project_id if parsed_args.project is not None: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id return attrs # TODO(abhiraut): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateNetworkRBAC(command.ShowOne): _description = _("Create network RBAC policy") def get_parser(self, prog_name): parser = super(CreateNetworkRBAC, self).get_parser(prog_name) parser.add_argument( 'rbac_object', metavar="", help=_("The object to which this RBAC policy affects (name or ID)") ) parser.add_argument( '--type', metavar="", required=True, choices=['qos_policy', 'network'], help=_('Type of the object that RBAC policy ' 'affects ("qos_policy" or "network")') ) parser.add_argument( '--action', metavar="", required=True, choices=['access_as_external', 'access_as_shared'], help=_('Action for the RBAC policy ' '("access_as_external" or "access_as_shared")') ) target_project_group = parser.add_mutually_exclusive_group( required=True) target_project_group.add_argument( '--target-project', metavar="", help=_('The project to which the RBAC policy ' 'will be enforced (name or ID)') ) target_project_group.add_argument( '--target-all-projects', action='store_true', help=_('Allow creating RBAC policy for all projects.') ) parser.add_argument( '--target-project-domain', metavar='', help=_('Domain the target project belongs to (name or ID). ' 'This can be used in case collisions between project names ' 'exist.'), ) parser.add_argument( '--project', metavar="", help=_('The owner project (name or ID)') ) identity_common.add_project_domain_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_rbac_policy(**attrs) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return display_columns, data class DeleteNetworkRBAC(command.Command): _description = _("Delete network RBAC policy(s)") def get_parser(self, prog_name): parser = super(DeleteNetworkRBAC, self).get_parser(prog_name) parser.add_argument( 'rbac_policy', metavar="", nargs='+', help=_("RBAC policy(s) to delete (ID only)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for rbac in parsed_args.rbac_policy: try: obj = client.find_rbac_policy(rbac, ignore_missing=False) client.delete_rbac_policy(obj) except Exception as e: result += 1 LOG.error(_("Failed to delete RBAC policy with " "ID '%(rbac)s': %(e)s"), {'rbac': rbac, 'e': e}) if result > 0: total = len(parsed_args.rbac_policy) msg = (_("%(result)s of %(total)s RBAC policies failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListNetworkRBAC(command.Lister): _description = _("List network RBAC policies") def get_parser(self, prog_name): parser = super(ListNetworkRBAC, self).get_parser(prog_name) parser.add_argument( '--type', metavar='', choices=['qos_policy', 'network'], help=_('List network RBAC policies according to ' 'given object type ("qos_policy" or "network")') ) parser.add_argument( '--action', metavar='', choices=['access_as_external', 'access_as_shared'], help=_('List network RBAC policies according to given ' 'action ("access_as_external" or "access_as_shared")') ) 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 columns = ( 'id', 'object_type', 'object_id', ) column_headers = ( 'ID', 'Object Type', 'Object ID', ) query = {} if parsed_args.long: columns += ('action',) column_headers += ('Action',) if parsed_args.type is not None: query['object_type'] = parsed_args.type if parsed_args.action is not None: query['action'] = parsed_args.action data = client.rbac_policies(**query) return (column_headers, (utils.get_item_properties( s, columns, ) for s in data)) # TODO(abhiraut): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class SetNetworkRBAC(command.Command): _description = _("Set network RBAC policy properties") def get_parser(self, prog_name): parser = super(SetNetworkRBAC, self).get_parser(prog_name) parser.add_argument( 'rbac_policy', metavar="", help=_("RBAC policy to be modified (ID only)") ) parser.add_argument( '--target-project', metavar="", help=_('The project to which the RBAC policy ' 'will be enforced (name or ID)') ) parser.add_argument( '--target-project-domain', metavar='', help=_('Domain the target project belongs to (name or ID). ' 'This can be used in case collisions between project names ' 'exist.'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_rbac_policy(parsed_args.rbac_policy, ignore_missing=False) attrs = {} if parsed_args.target_project: identity_client = self.app.client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.target_project, parsed_args.target_project_domain, ).id attrs['target_tenant'] = project_id client.update_rbac_policy(obj, **attrs) class ShowNetworkRBAC(command.ShowOne): _description = _("Display network RBAC policy details") def get_parser(self, prog_name): parser = super(ShowNetworkRBAC, self).get_parser(prog_name) parser.add_argument( 'rbac_policy', metavar="", help=_("RBAC policy (ID only)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_rbac_policy(parsed_args.rbac_policy, ignore_missing=False) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return display_columns, data python-openstackclient-3.14.0/openstackclient/network/v2/network_auto_allocated_topology.py0000666000175100017510000001110113232364361032574 0ustar zuulzuul00000000000000# 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. # """Auto-allocated Topology Implementations""" import logging from osc_lib.command import command from osc_lib import utils from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils LOG = logging.getLogger(__name__) def _get_columns(item): column_map = { 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) def _format_check_resource_columns(): return ('dry_run',) def _format_check_resource(item): item_id = getattr(item, 'id', False) if item_id == 'dry-run=pass': item.check_resource = 'pass' return item def _get_attrs(client_manager, parsed_args): attrs = {} if parsed_args.project: identity_client = client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id if parsed_args.check_resources: attrs['check_resources'] = True return attrs # TODO(ankur-gupta-f): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateAutoAllocatedTopology(command.ShowOne): _description = _("Create the auto allocated topology for project") def get_parser(self, prog_name): parser = super(CreateAutoAllocatedTopology, self).get_parser(prog_name) parser.add_argument( '--project', metavar='', help=_("Return the auto allocated topology for a given project. " "Default is current project") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--check-resources', action='store_true', help=_("Validate the requirements for auto allocated topology. " "Does not return a topology.") ) parser.add_argument( '--or-show', action='store_true', default=True, help=_("If topology exists returns the topology's " "information (Default)") ) return parser def check_resource_topology(self, client, parsed_args): obj = client.validate_auto_allocated_topology(parsed_args.project) columns = _format_check_resource_columns() data = utils.get_item_properties(_format_check_resource(obj), columns, formatters={}) return (columns, data) def get_topology(self, client, parsed_args): obj = client.get_auto_allocated_topology(parsed_args.project) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters={}) return (display_columns, data) def take_action(self, parsed_args): client = self.app.client_manager.network if parsed_args.check_resources: columns, data = self.check_resource_topology(client, parsed_args) else: columns, data = self.get_topology(client, parsed_args) return (columns, data) # TODO(ankur-gupta-f): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class DeleteAutoAllocatedTopology(command.Command): _description = _("Delete auto allocated topology for project") def get_parser(self, prog_name): parser = super(DeleteAutoAllocatedTopology, self).get_parser(prog_name) parser.add_argument( '--project', metavar='', help=_('Delete auto allocated topology for a given project. ' 'Default is the current project') ) identity_common.add_project_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network client.delete_auto_allocated_topology(parsed_args.project) python-openstackclient-3.14.0/openstackclient/network/v2/security_group_rule.py0000666000175100017510000005641613232364361030243 0ustar zuulzuul00000000000000# 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. # """Security Group Rule action implementations""" import argparse import logging from osc_lib.cli import parseractions from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import common from openstackclient.network import sdk_utils from openstackclient.network import utils as network_utils LOG = logging.getLogger(__name__) def _format_security_group_rule_show(obj): data = network_utils.transform_compute_security_group_rule(obj) return zip(*sorted(six.iteritems(data))) def _format_network_port_range(rule): # Display port range or ICMP type and code. For example: # - ICMP type: 'type=3' # - ICMP type and code: 'type=3:code=0' # - ICMP code: Not supported # - Matching port range: '443:443' # - Different port range: '22:24' # - Single port: '80:80' # - No port range: '' port_range = '' if _is_icmp_protocol(rule['protocol']): if rule['port_range_min']: port_range += 'type=' + str(rule['port_range_min']) if rule['port_range_max']: port_range += ':code=' + str(rule['port_range_max']) elif rule['port_range_min'] or rule['port_range_max']: port_range_min = str(rule['port_range_min']) port_range_max = str(rule['port_range_max']) if rule['port_range_min'] is None: port_range_min = port_range_max if rule['port_range_max'] is None: port_range_max = port_range_min port_range = port_range_min + ':' + port_range_max return port_range def _get_columns(item): column_map = { 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) def _convert_to_lowercase(string): return string.lower() def _is_icmp_protocol(protocol): # NOTE(rtheis): Neutron has deprecated protocol icmpv6. # However, while the OSC CLI doesn't document the protocol, # the code must still handle it. In addition, handle both # protocol names and numbers. if protocol in ['icmp', 'icmpv6', 'ipv6-icmp', '1', '58']: return True else: return False # TODO(abhiraut): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateSecurityGroupRule(common.NetworkAndComputeShowOne): _description = _("Create a new security group rule") def update_parser_common(self, parser): parser.add_argument( 'group', metavar='', help=_("Create rule in this security group (name or ID)") ) remote_group = parser.add_mutually_exclusive_group() remote_group.add_argument( "--remote-ip", metavar="", help=_("Remote IP address block (may use CIDR notation; " "default for IPv4 rule: 0.0.0.0/0)"), ) remote_group.add_argument( "--remote-group", metavar="", help=_("Remote security group (name or ID)"), ) # Handle deprecated options # NOTE(dtroyer): --src-ip and --src-group were deprecated in Nov 2016. # Do not remove before 4.x release or Nov 2017. remote_group.add_argument( "--src-ip", metavar="", help=argparse.SUPPRESS, ) remote_group.add_argument( "--src-group", metavar="", help=argparse.SUPPRESS, ) return parser def update_parser_network(self, parser): parser.add_argument( '--description', metavar='', help=_("Set security group rule description") ) parser.add_argument( '--dst-port', metavar='', action=parseractions.RangeAction, help=_("Destination port, may be a single port or a starting and " "ending port range: 137:139. Required for IP protocols TCP " "and UDP. Ignored for ICMP IP protocols.") ) parser.add_argument( '--icmp-type', metavar='', type=int, help=_("ICMP type for ICMP IP protocols") ) parser.add_argument( '--icmp-code', metavar='', type=int, help=_("ICMP code for ICMP IP protocols") ) # NOTE(rtheis): Support either protocol option name for now. # However, consider deprecating and then removing --proto in # a future release. protocol_group = parser.add_mutually_exclusive_group() protocol_group.add_argument( '--protocol', metavar='', type=_convert_to_lowercase, help=_("IP protocol (ah, dccp, egp, esp, gre, icmp, igmp, " "ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, " "ipv6-opts, ipv6-route, ospf, pgm, rsvp, sctp, tcp, " "udp, udplite, vrrp and integer representations [0-255] " "or any; default: tcp)") ) protocol_group.add_argument( '--proto', metavar='', type=_convert_to_lowercase, help=argparse.SUPPRESS ) direction_group = parser.add_mutually_exclusive_group() direction_group.add_argument( '--ingress', action='store_true', help=_("Rule applies to incoming network traffic (default)") ) direction_group.add_argument( '--egress', action='store_true', help=_("Rule applies to outgoing network traffic") ) parser.add_argument( '--ethertype', metavar='', choices=['IPv4', 'IPv6'], help=_("Ethertype of network traffic " "(IPv4, IPv6; default: based on IP protocol)") ) parser.add_argument( '--project', metavar='', help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) return parser def update_parser_compute(self, parser): parser.add_argument( '--dst-port', metavar='', default=(0, 0), action=parseractions.RangeAction, help=_("Destination port, may be a single port or a starting and " "ending port range: 137:139. Required for IP protocols TCP " "and UDP. Ignored for ICMP IP protocols.") ) # NOTE(rtheis): Support either protocol option name for now. # However, consider deprecating and then removing --proto in # a future release. protocol_group = parser.add_mutually_exclusive_group() protocol_group.add_argument( '--protocol', metavar='', choices=['icmp', 'tcp', 'udp'], type=_convert_to_lowercase, help=_("IP protocol (icmp, tcp, udp; default: tcp)") ) protocol_group.add_argument( '--proto', metavar='', choices=['icmp', 'tcp', 'udp'], type=_convert_to_lowercase, help=argparse.SUPPRESS ) return parser def _get_protocol(self, parsed_args): protocol = 'tcp' if parsed_args.protocol is not None: protocol = parsed_args.protocol if parsed_args.proto is not None: protocol = parsed_args.proto if protocol == 'any': protocol = None return protocol def _is_ipv6_protocol(self, protocol): # NOTE(rtheis): Neutron has deprecated protocol icmpv6. # However, while the OSC CLI doesn't document the protocol, # the code must still handle it. In addition, handle both # protocol names and numbers. if (protocol is not None and protocol.startswith('ipv6-') or protocol in ['icmpv6', '41', '43', '44', '58', '59', '60']): return True else: return False def take_action_network(self, client, parsed_args): # Get the security group ID to hold the rule. security_group_id = client.find_security_group( parsed_args.group, ignore_missing=False ).id # Build the create attributes. attrs = {} attrs['protocol'] = self._get_protocol(parsed_args) if parsed_args.description is not None: attrs['description'] = parsed_args.description # NOTE(rtheis): A direction must be specified and ingress # is the default. if parsed_args.ingress or not parsed_args.egress: attrs['direction'] = 'ingress' if parsed_args.egress: attrs['direction'] = 'egress' # NOTE(rtheis): Use ethertype specified else default based # on IP protocol. if parsed_args.ethertype: attrs['ethertype'] = parsed_args.ethertype elif self._is_ipv6_protocol(attrs['protocol']): attrs['ethertype'] = 'IPv6' else: attrs['ethertype'] = 'IPv4' # NOTE(rtheis): Validate the port range and ICMP type and code. # It would be ideal if argparse could do this. if parsed_args.dst_port and (parsed_args.icmp_type or parsed_args.icmp_code): msg = _('Argument --dst-port not allowed with arguments ' '--icmp-type and --icmp-code') raise exceptions.CommandError(msg) if parsed_args.icmp_type is None and parsed_args.icmp_code is not None: msg = _('Argument --icmp-type required with argument --icmp-code') raise exceptions.CommandError(msg) is_icmp_protocol = _is_icmp_protocol(attrs['protocol']) if not is_icmp_protocol and (parsed_args.icmp_type or parsed_args.icmp_code): msg = _('ICMP IP protocol required with arguments ' '--icmp-type and --icmp-code') raise exceptions.CommandError(msg) # NOTE(rtheis): For backwards compatibility, continue ignoring # the destination port range when an ICMP IP protocol is specified. if parsed_args.dst_port and not is_icmp_protocol: attrs['port_range_min'] = parsed_args.dst_port[0] attrs['port_range_max'] = parsed_args.dst_port[1] if parsed_args.icmp_type is not None and parsed_args.icmp_type >= 0: attrs['port_range_min'] = parsed_args.icmp_type if parsed_args.icmp_code is not None and parsed_args.icmp_code >= 0: attrs['port_range_max'] = parsed_args.icmp_code # NOTE(dtroyer): --src-ip and --src-group were deprecated in Nov 2016. # Do not remove before 4.x release or Nov 2017. if not (parsed_args.remote_group is None and parsed_args.src_group is None): attrs['remote_group_id'] = client.find_security_group( parsed_args.remote_group or parsed_args.src_group, ignore_missing=False ).id if parsed_args.src_group: LOG.warning( _("The %(old)s option is deprecated, " "please use %(new)s instead."), {'old': '--src-group', 'new': '--remote-group'}, ) elif not (parsed_args.remote_ip is None and parsed_args.src_ip is None): attrs['remote_ip_prefix'] = ( parsed_args.remote_ip or parsed_args.src_ip ) if parsed_args.src_ip: LOG.warning( _("The %(old)s option is deprecated, " "please use %(new)s instead."), {'old': '--src-ip', 'new': '--remote-ip'}, ) elif attrs['ethertype'] == 'IPv4': attrs['remote_ip_prefix'] = '0.0.0.0/0' attrs['security_group_id'] = security_group_id if parsed_args.project is not None: identity_client = self.app.client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id # Create and show the security group rule. obj = client.create_security_group_rule(**attrs) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return (display_columns, data) def take_action_compute(self, client, parsed_args): group = client.api.security_group_find(parsed_args.group) protocol = self._get_protocol(parsed_args) if protocol == 'icmp': from_port, to_port = -1, -1 else: from_port, to_port = parsed_args.dst_port # NOTE(dtroyer): --src-ip and --src-group were deprecated in Nov 2016. # Do not remove before 4.x release or Nov 2017. remote_ip = None if not (parsed_args.remote_group is None and parsed_args.src_group is None): parsed_args.remote_group = client.api.security_group_find( parsed_args.remote_group or parsed_args.src_group, )['id'] if parsed_args.src_group: LOG.warning( _("The %(old)s option is deprecated, " "please use %(new)s instead."), {'old': '--src-group', 'new': '--remote-group'}, ) if not (parsed_args.remote_ip is None and parsed_args.src_ip is None): remote_ip = parsed_args.remote_ip or parsed_args.src_ip if parsed_args.src_ip: LOG.warning( _("The %(old)s option is deprecated, " "please use %(new)s instead."), {'old': '--src-ip', 'new': '--remote-ip'}, ) else: remote_ip = '0.0.0.0/0' obj = client.api.security_group_rule_create( security_group_id=group['id'], ip_protocol=protocol, from_port=from_port, to_port=to_port, remote_ip=remote_ip, remote_group=parsed_args.remote_group, ) return _format_security_group_rule_show(obj) class DeleteSecurityGroupRule(common.NetworkAndComputeDelete): _description = _("Delete security group rule(s)") # Used by base class to find resources in parsed_args. resource = 'rule' r = None def update_parser_common(self, parser): parser.add_argument( 'rule', metavar='', nargs="+", help=_("Security group rule(s) to delete (ID only)") ) return parser def take_action_network(self, client, parsed_args): obj = client.find_security_group_rule( self.r, ignore_missing=False) client.delete_security_group_rule(obj) def take_action_compute(self, client, parsed_args): client.api.security_group_rule_delete(self.r) class ListSecurityGroupRule(common.NetworkAndComputeLister): _description = _("List security group rules") def _format_network_security_group_rule(self, rule): """Transform the SDK SecurityGroupRule object to a dict The SDK object gets in the way of reformatting columns... Create port_range column from port_range_min and port_range_max """ rule = rule.to_dict() rule['port_range'] = _format_network_port_range(rule) return rule def update_parser_common(self, parser): parser.add_argument( 'group', metavar='', nargs='?', help=_("List all rules in this security group (name or ID)") ) return parser def update_parser_network(self, parser): # Accept but hide the argument for consistency with compute. # Network will always return all projects for an admin. parser.add_argument( '--all-projects', action='store_true', default=False, help=argparse.SUPPRESS ) parser.add_argument( '--protocol', metavar='', type=_convert_to_lowercase, help=_("List rules by the IP protocol (" "ah, dhcp, egp, esp, gre, icmp, igmp, " "ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, " "ipv6-opts, ipv6-route, ospf, pgm, rsvp, sctp, tcp, " "udp, udplite, vrrp and integer representations [0-255])." ) ) direction_group = parser.add_mutually_exclusive_group() direction_group.add_argument( '--ingress', action='store_true', help=_("List rules applied to incoming network traffic") ) direction_group.add_argument( '--egress', action='store_true', help=_("List rules applied to outgoing network traffic") ) parser.add_argument( '--long', action='store_true', default=False, help=_("List additional fields in output") ) return parser def update_parser_compute(self, parser): parser.add_argument( '--all-projects', action='store_true', default=False, help=_("Display information from all projects (admin only)") ) # Accept but hide the argument for consistency with network. # There are no additional fields to display at this time. parser.add_argument( '--long', action='store_false', default=False, help=argparse.SUPPRESS ) return parser def _get_column_headers(self, parsed_args): column_headers = ( 'ID', 'IP Protocol', 'IP Range', 'Port Range', ) if parsed_args.long: column_headers = column_headers + ('Direction', 'Ethertype',) column_headers = column_headers + ('Remote Security Group',) if parsed_args.group is None: column_headers = column_headers + ('Security Group',) return column_headers def take_action_network(self, client, parsed_args): column_headers = self._get_column_headers(parsed_args) columns = ( 'id', 'protocol', 'remote_ip_prefix', 'port_range', ) if parsed_args.long: columns = columns + ('direction', 'ether_type',) columns = columns + ('remote_group_id',) # Get the security group rules using the requested query. query = {} if parsed_args.group is not None: # NOTE(rtheis): Unfortunately, the security group resource # does not contain security group rules resources. So use # the security group ID in a query to get the resources. security_group_id = client.find_security_group( parsed_args.group, ignore_missing=False ).id query = {'security_group_id': security_group_id} else: columns = columns + ('security_group_id',) if parsed_args.ingress: query['direction'] = 'ingress' if parsed_args.egress: query['direction'] = 'egress' if parsed_args.protocol is not None: query['protocol'] = parsed_args.protocol rules = [ self._format_network_security_group_rule(r) for r in client.security_group_rules(**query) ] return (column_headers, (utils.get_dict_properties( s, columns, ) for s in rules)) def take_action_compute(self, client, parsed_args): column_headers = self._get_column_headers(parsed_args) columns = ( "ID", "IP Protocol", "IP Range", "Port Range", "Remote Security Group", ) rules_to_list = [] if parsed_args.group is not None: group = client.api.security_group_find( parsed_args.group, ) rules_to_list = group['rules'] else: columns = columns + ('parent_group_id',) search = {'all_tenants': parsed_args.all_projects} for group in client.api.security_group_list(search_opts=search): rules_to_list.extend(group['rules']) # NOTE(rtheis): Turn the raw rules into resources. rules = [] for rule in rules_to_list: rules.append( network_utils.transform_compute_security_group_rule(rule), ) # rules.append(compute_secgroup_rules.SecurityGroupRule( # client.security_group_rules, # network_utils.transform_compute_security_group_rule(rule), # )) return (column_headers, (utils.get_dict_properties( s, columns, ) for s in rules)) class ShowSecurityGroupRule(common.NetworkAndComputeShowOne): _description = _("Display security group rule details") def update_parser_common(self, parser): parser.add_argument( 'rule', metavar="", help=_("Security group rule to display (ID only)") ) return parser def take_action_network(self, client, parsed_args): obj = client.find_security_group_rule(parsed_args.rule, ignore_missing=False) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return (display_columns, data) def take_action_compute(self, client, parsed_args): # NOTE(rtheis): Unfortunately, compute does not have an API # to get or list security group rules so parse through the # security groups to find all accessible rules in search of # the requested rule. obj = None security_group_rules = [] for security_group in client.api.security_group_list(): security_group_rules.extend(security_group['rules']) for security_group_rule in security_group_rules: if parsed_args.rule == str(security_group_rule.get('id')): obj = security_group_rule break if obj is None: msg = _("Could not find security group rule " "with ID '%s'") % parsed_args.rule raise exceptions.CommandError(msg) # NOTE(rtheis): Format security group rule return _format_security_group_rule_show(obj) python-openstackclient-3.14.0/openstackclient/network/v2/address_scope.py0000666000175100017510000002263013232364361026736 0ustar zuulzuul00000000000000# 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. # """Address scope action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils LOG = logging.getLogger(__name__) def _get_columns(item): column_map = { 'is_shared': 'shared', 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) def _get_attrs(client_manager, parsed_args): attrs = {} attrs['name'] = parsed_args.name attrs['ip_version'] = parsed_args.ip_version if parsed_args.share: attrs['shared'] = True if parsed_args.no_share: attrs['shared'] = False if 'project' in parsed_args and parsed_args.project is not None: identity_client = client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id return attrs # TODO(rtheis): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateAddressScope(command.ShowOne): _description = _("Create a new Address Scope") def get_parser(self, prog_name): parser = super(CreateAddressScope, self).get_parser(prog_name) parser.add_argument( 'name', metavar="", help=_("New address scope name") ) parser.add_argument( '--ip-version', type=int, default=4, choices=[4, 6], help=_("IP version (default is 4)") ) parser.add_argument( '--project', metavar="", help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) share_group = parser.add_mutually_exclusive_group() share_group.add_argument( '--share', action='store_true', help=_('Share the address scope between projects') ) share_group.add_argument( '--no-share', action='store_true', help=_('Do not share the address scope between projects (default)') ) 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_address_scope(**attrs) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters={}) return (display_columns, data) class DeleteAddressScope(command.Command): _description = _("Delete address scope(s)") def get_parser(self, prog_name): parser = super(DeleteAddressScope, self).get_parser(prog_name) parser.add_argument( 'address_scope', metavar="", nargs='+', help=_("Address scope(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for scope in parsed_args.address_scope: try: obj = client.find_address_scope(scope, ignore_missing=False) client.delete_address_scope(obj) except Exception as e: result += 1 LOG.error(_("Failed to delete address scope with " "name or ID '%(scope)s': %(e)s"), {'scope': scope, 'e': e}) if result > 0: total = len(parsed_args.address_scope) msg = (_("%(result)s of %(total)s address scopes failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) # TODO(yanxing'an): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class ListAddressScope(command.Lister): _description = _("List address scopes") def get_parser(self, prog_name): parser = super(ListAddressScope, self).get_parser(prog_name) parser.add_argument( '--name', metavar='', help=_("List only address scopes of given name in output") ) parser.add_argument( '--ip-version', type=int, choices=[4, 6], metavar='', dest='ip_version', help=_("List address scopes of given IP version networks (4 or 6)") ) parser.add_argument( '--project', metavar="", help=_("List address scopes according to their project " "(name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) shared_group = parser.add_mutually_exclusive_group() shared_group.add_argument( '--share', action='store_true', help=_("List address scopes shared between projects") ) shared_group.add_argument( '--no-share', action='store_true', help=_("List address scopes not shared between projects") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network columns = ( 'id', 'name', 'ip_version', 'is_shared', 'project_id', ) column_headers = ( 'ID', 'Name', 'IP Version', 'Shared', 'Project', ) attrs = {} if parsed_args.name: attrs['name'] = parsed_args.name if parsed_args.ip_version: attrs['ip_version'] = parsed_args.ip_version if parsed_args.share: attrs['is_shared'] = True if parsed_args.no_share: attrs['is_shared'] = False if 'project' in parsed_args and parsed_args.project is not None: identity_client = self.app.client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id attrs['project_id'] = project_id data = client.address_scopes(**attrs) return (column_headers, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) # TODO(rtheis): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class SetAddressScope(command.Command): _description = _("Set address scope properties") def get_parser(self, prog_name): parser = super(SetAddressScope, self).get_parser(prog_name) parser.add_argument( 'address_scope', metavar="", help=_("Address scope to modify (name or ID)") ) parser.add_argument( '--name', metavar="", help=_('Set address scope name') ) share_group = parser.add_mutually_exclusive_group() share_group.add_argument( '--share', action='store_true', help=_('Share the address scope between projects') ) share_group.add_argument( '--no-share', action='store_true', help=_('Do not share the address scope between projects') ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_address_scope( parsed_args.address_scope, ignore_missing=False) attrs = {} if parsed_args.name is not None: attrs['name'] = parsed_args.name if parsed_args.share: attrs['shared'] = True if parsed_args.no_share: attrs['shared'] = False client.update_address_scope(obj, **attrs) class ShowAddressScope(command.ShowOne): _description = _("Display address scope details") def get_parser(self, prog_name): parser = super(ShowAddressScope, self).get_parser(prog_name) parser.add_argument( 'address_scope', metavar="", help=_("Address scope to display (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_address_scope( parsed_args.address_scope, ignore_missing=False) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters={}) return (display_columns, data) python-openstackclient-3.14.0/openstackclient/network/v2/network_qos_rule_type.py0000666000175100017510000000426413232364361030566 0ustar zuulzuul00000000000000# 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 osc_lib.command import command from osc_lib import utils from openstackclient.i18n import _ from openstackclient.network import sdk_utils def _get_columns(item): column_map = { "type": "rule_type_name", "drivers": "drivers", } invisible_columns = ["id", "name"] return sdk_utils.get_osc_show_columns_for_sdk_resource( item, column_map, invisible_columns) class ListNetworkQosRuleType(command.Lister): _description = _("List QoS rule types") def take_action(self, parsed_args): client = self.app.client_manager.network columns = ( 'type', ) column_headers = ( 'Type', ) data = client.qos_rule_types() return (column_headers, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class ShowNetworkQosRuleType(command.ShowOne): _description = _("Show details about supported QoS rule type") def get_parser(self, prog_name): parser = super(ShowNetworkQosRuleType, self).get_parser(prog_name) parser.add_argument( 'rule_type', metavar="", help=_("Name of QoS rule type") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.get_qos_rule_type(parsed_args.rule_type) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return display_columns, data python-openstackclient-3.14.0/openstackclient/network/v2/ip_availability.py0000666000175100017510000000756413232364361027273 0ustar zuulzuul00000000000000# 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. # """IP Availability Info implementations""" from osc_lib.command import command from osc_lib import utils from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils _formatters = { 'subnet_ip_availability': utils.format_list_of_dicts, } def _get_columns(item): column_map = { 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) # TODO(ankur-gupta-f): Use the SDK resource mapped attribute names once # the OSC minimum requirements include SDK 1.0. class ListIPAvailability(command.Lister): _description = _("List IP availability for network") def get_parser(self, prog_name): parser = super(ListIPAvailability, self).get_parser(prog_name) parser.add_argument( '--ip-version', type=int, default=4, choices=[4, 6], metavar='', dest='ip_version', help=_("List IP availability of given IP version " "networks (default is 4)"), ) parser.add_argument( '--project', metavar='', help=_("List IP availability of given project (name or ID)"), ) identity_common.add_project_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.network columns = ( 'network_id', 'network_name', 'total_ips', 'used_ips', ) column_headers = ( 'Network ID', 'Network Name', 'Total IPs', 'Used IPs', ) filters = {} if parsed_args.ip_version: filters['ip_version'] = parsed_args.ip_version if parsed_args.project: identity_client = self.app.client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id filters['tenant_id'] = project_id filters['project_id'] = project_id data = client.network_ip_availabilities(**filters) return (column_headers, (utils.get_item_properties( s, columns, ) for s in data)) class ShowIPAvailability(command.ShowOne): _description = _("Show network IP availability details") def get_parser(self, prog_name): parser = super(ShowIPAvailability, self).get_parser(prog_name) parser.add_argument( 'network', metavar="", help=_("Show IP availability for a specific network (name or ID)"), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network network_id = client.find_network(parsed_args.network, ignore_missing=False).id obj = client.find_network_ip_availability(network_id, ignore_missing=False) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters=_formatters) return (display_columns, data) python-openstackclient-3.14.0/openstackclient/network/v2/network_meter.py0000666000175100017510000001346613232364361027014 0ustar zuulzuul00000000000000# 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. # """Metering Label Implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils LOG = logging.getLogger(__name__) def _get_columns(item): column_map = { 'is_shared': 'shared', 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) def _get_attrs(client_manager, parsed_args): attrs = {} if parsed_args.description is not None: attrs['description'] = parsed_args.description if parsed_args.project is not None and 'project' in parsed_args: identity_client = client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id if parsed_args.share: attrs['shared'] = True if parsed_args.no_share: attrs['shared'] = False if parsed_args.name is not None: attrs['name'] = parsed_args.name return attrs # TODO(ankur-gupta-f): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateMeter(command.ShowOne): _description = _("Create network meter") def get_parser(self, prog_name): parser = super(CreateMeter, self).get_parser(prog_name) parser.add_argument( '--description', metavar='', help=_("Create description for meter") ) parser.add_argument( '--project', metavar='', help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) share_group = parser.add_mutually_exclusive_group() share_group.add_argument( '--share', action='store_true', default=None, help=_("Share meter between projects") ) share_group.add_argument( '--no-share', action='store_true', help=_("Do not share meter between projects") ) parser.add_argument( 'name', metavar='', help=_('Name of meter'), ) 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_metering_label(**attrs) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters={}) return (display_columns, data) # TODO(ankur-gupta-f): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class DeleteMeter(command.Command): _description = _("Delete network meter") def get_parser(self, prog_name): parser = super(DeleteMeter, self).get_parser(prog_name) parser.add_argument( 'meter', metavar='', nargs='+', help=_('Meter to delete (name or ID)') ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for meter in parsed_args.meter: try: obj = client.find_metering_label(meter, ignore_missing=False) client.delete_metering_label(obj) except Exception as e: result += 1 LOG.error(_("Failed to delete meter with " "ID '%(meter)s': %(e)s"), {"meter": meter, "e": e}) if result > 0: total = len(parsed_args.meter) msg = (_("%(result)s of %(total)s meters failed " "to delete.") % {"result": result, "total": total}) raise exceptions.CommandError(msg) class ListMeter(command.Lister): _description = _("List network meters") def take_action(self, parsed_args): client = self.app.client_manager.network columns = ( 'id', 'name', 'description', 'shared', ) column_headers = ( 'ID', 'Name', 'Description', 'Shared', ) data = client.metering_labels() return (column_headers, (utils.get_item_properties( s, columns, ) for s in data)) class ShowMeter(command.ShowOne): _description = _("Show network meter") def get_parser(self, prog_name): parser = super(ShowMeter, self).get_parser(prog_name) parser.add_argument( 'meter', metavar='', help=_('Meter to display (name or ID)') ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_metering_label(parsed_args.meter, ignore_missing=False) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return display_columns, data python-openstackclient-3.14.0/openstackclient/network/v2/subnet.py0000666000175100017510000006540513232364361025427 0ustar zuulzuul00000000000000# 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 action implementations""" import copy 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 openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils from openstackclient.network.v2 import _tag LOG = logging.getLogger(__name__) def _update_arguments(obj_list, parsed_args_list, option): for item in parsed_args_list: try: obj_list.remove(item) except ValueError: msg = (_("Subnet does not contain %(option)s %(value)s") % {'option': option, 'value': item}) raise exceptions.CommandError(msg) def _format_allocation_pools(data): pool_formatted = ['%s-%s' % (pool.get('start', ''), pool.get('end', '')) for pool in data] return ','.join(pool_formatted) def _format_host_routes(data): # Map the host route keys to match --host-route option. return utils.format_list_of_dicts(convert_entries_to_gateway(data)) _formatters = { 'allocation_pools': _format_allocation_pools, 'dns_nameservers': utils.format_list, 'host_routes': _format_host_routes, 'service_types': utils.format_list, 'tags': utils.format_list, } def _get_common_parse_arguments(parser, is_create=True): parser.add_argument( '--allocation-pool', metavar='start=,end=', dest='allocation_pools', action=parseractions.MultiKeyValueAction, required_keys=['start', 'end'], help=_("Allocation pool IP addresses for this subnet " "e.g.: start=192.168.199.2,end=192.168.199.254 " "(repeat option to add multiple IP addresses)") ) if not is_create: parser.add_argument( '--no-allocation-pool', action='store_true', help=_("Clear associated allocation-pools from the subnet. " "Specify both --allocation-pool and --no-allocation-pool " "to overwrite the current allocation pool information.") ) parser.add_argument( '--dns-nameserver', metavar='', action='append', dest='dns_nameservers', help=_("DNS server for this subnet " "(repeat option to set multiple DNS servers)") ) if not is_create: parser.add_argument( '--no-dns-nameservers', action='store_true', help=_("Clear existing information of DNS Nameservers. " "Specify both --dns-nameserver and --no-dns-nameserver " "to overwrite the current DNS Nameserver information.") ) parser.add_argument( '--host-route', metavar='destination=,gateway=', dest='host_routes', action=parseractions.MultiKeyValueAction, required_keys=['destination', 'gateway'], help=_("Additional route for this subnet " "e.g.: destination=10.10.0.0/16,gateway=192.168.71.254 " "destination: destination subnet (in CIDR notation) " "gateway: nexthop IP address " "(repeat option to add multiple routes)") ) if not is_create: parser.add_argument( '--no-host-route', action='store_true', help=_("Clear associated host-routes from the subnet. " "Specify both --host-route and --no-host-route " "to overwrite the current host route information.") ) parser.add_argument( '--service-type', metavar='', action='append', dest='service_types', help=_("Service type for this subnet " "e.g.: network:floatingip_agent_gateway. " "Must be a valid device owner value for a network port " "(repeat option to set multiple service types)") ) def _get_columns(item): column_map = { 'is_dhcp_enabled': 'enable_dhcp', 'subnet_pool_id': 'subnetpool_id', 'tenant_id': 'project_id', } # Do not show this column when displaying a subnet invisible_columns = ['use_default_subnet_pool'] return sdk_utils.get_osc_show_columns_for_sdk_resource( item, column_map, invisible_columns=invisible_columns ) def convert_entries_to_nexthop(entries): # Change 'gateway' entry to 'nexthop' changed_entries = copy.deepcopy(entries) for entry in changed_entries: if 'gateway' in entry: entry['nexthop'] = entry['gateway'] del entry['gateway'] return changed_entries def convert_entries_to_gateway(entries): # Change 'nexthop' entry to 'gateway' changed_entries = copy.deepcopy(entries) for entry in changed_entries: if 'nexthop' in entry: entry['gateway'] = entry['nexthop'] del entry['nexthop'] return changed_entries def _get_attrs(client_manager, parsed_args, is_create=True): attrs = {} if 'name' in parsed_args and parsed_args.name is not None: attrs['name'] = str(parsed_args.name) if is_create: if 'project' in parsed_args and parsed_args.project is not None: identity_client = client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id client = client_manager.network attrs['network_id'] = client.find_network(parsed_args.network, ignore_missing=False).id if parsed_args.subnet_pool is not None: subnet_pool = client.find_subnet_pool(parsed_args.subnet_pool, ignore_missing=False) attrs['subnetpool_id'] = subnet_pool.id if parsed_args.use_prefix_delegation: attrs['subnetpool_id'] = "prefix_delegation" if parsed_args.use_default_subnet_pool: attrs['use_default_subnet_pool'] = True if parsed_args.prefix_length is not None: attrs['prefixlen'] = parsed_args.prefix_length if parsed_args.subnet_range is not None: attrs['cidr'] = parsed_args.subnet_range if parsed_args.ip_version is not None: attrs['ip_version'] = parsed_args.ip_version if parsed_args.ipv6_ra_mode is not None: attrs['ipv6_ra_mode'] = parsed_args.ipv6_ra_mode if parsed_args.ipv6_address_mode is not None: attrs['ipv6_address_mode'] = parsed_args.ipv6_address_mode if parsed_args.network_segment is not None: attrs['segment_id'] = client.find_segment( parsed_args.network_segment, ignore_missing=False).id if 'gateway' in parsed_args and parsed_args.gateway is not None: gateway = parsed_args.gateway.lower() if not is_create and gateway == 'auto': msg = _("Auto option is not available for Subnet Set. " "Valid options are or none") raise exceptions.CommandError(msg) elif gateway != 'auto': if gateway == 'none': attrs['gateway_ip'] = None else: attrs['gateway_ip'] = gateway if ('allocation_pools' in parsed_args and parsed_args.allocation_pools is not None): attrs['allocation_pools'] = parsed_args.allocation_pools if parsed_args.dhcp: attrs['enable_dhcp'] = True if parsed_args.no_dhcp: attrs['enable_dhcp'] = False if ('dns_nameservers' in parsed_args and parsed_args.dns_nameservers is not None): attrs['dns_nameservers'] = parsed_args.dns_nameservers if 'host_routes' in parsed_args and parsed_args.host_routes is not None: # Change 'gateway' entry to 'nexthop' to match the API attrs['host_routes'] = convert_entries_to_nexthop( parsed_args.host_routes) if ('service_types' in parsed_args and parsed_args.service_types is not None): attrs['service_types'] = parsed_args.service_types if parsed_args.description is not None: attrs['description'] = parsed_args.description return attrs # TODO(abhiraut): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateSubnet(command.ShowOne): _description = _("Create a subnet") def get_parser(self, prog_name): parser = super(CreateSubnet, self).get_parser(prog_name) parser.add_argument( 'name', help=_("New subnet name") ) parser.add_argument( '--project', metavar='', help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) subnet_pool_group = parser.add_mutually_exclusive_group() subnet_pool_group.add_argument( '--subnet-pool', metavar='', help=_("Subnet pool from which this subnet will obtain a CIDR " "(Name or ID)") ) subnet_pool_group.add_argument( '--use-prefix-delegation', help=_("Use 'prefix-delegation' if IP is IPv6 format " "and IP would be delegated externally") ) subnet_pool_group.add_argument( '--use-default-subnet-pool', action='store_true', help=_("Use default subnet pool for --ip-version") ) parser.add_argument( '--prefix-length', metavar='', help=_("Prefix length for subnet allocation from subnet pool") ) parser.add_argument( '--subnet-range', metavar='', help=_("Subnet range in CIDR notation " "(required if --subnet-pool is not specified, " "optional otherwise)") ) dhcp_enable_group = parser.add_mutually_exclusive_group() dhcp_enable_group.add_argument( '--dhcp', action='store_true', help=_("Enable DHCP (default)") ) dhcp_enable_group.add_argument( '--no-dhcp', action='store_true', help=_("Disable DHCP") ) parser.add_argument( '--gateway', metavar='', default='auto', help=_("Specify a gateway for the subnet. The three options are: " ": Specific IP address to use as the gateway, " "'auto': Gateway address should automatically be chosen " "from within the subnet itself, 'none': This subnet will " "not use a gateway, e.g.: --gateway 192.168.9.1, " "--gateway auto, --gateway none (default is 'auto').") ) parser.add_argument( '--ip-version', type=int, default=4, choices=[4, 6], help=_("IP version (default is 4). Note that when subnet pool is " "specified, IP version is determined from the subnet pool " "and this option is ignored.") ) parser.add_argument( '--ipv6-ra-mode', choices=['dhcpv6-stateful', 'dhcpv6-stateless', 'slaac'], help=_("IPv6 RA (Router Advertisement) mode, " "valid modes: [dhcpv6-stateful, dhcpv6-stateless, slaac]") ) parser.add_argument( '--ipv6-address-mode', choices=['dhcpv6-stateful', 'dhcpv6-stateless', 'slaac'], help=_("IPv6 address mode, " "valid modes: [dhcpv6-stateful, dhcpv6-stateless, slaac]") ) parser.add_argument( '--network-segment', metavar='', help=_("Network segment to associate with this subnet " "(name or ID)") ) parser.add_argument( '--network', required=True, metavar='', help=_("Network this subnet belongs to (name or ID)") ) parser.add_argument( '--description', metavar='', help=_("Set subnet description") ) _get_common_parse_arguments(parser) _tag.add_tag_option_to_parser_for_create(parser, _('subnet')) 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_subnet(**attrs) # tags cannot be set when created, so tags need to be set later. _tag.update_tags_for_set(client, obj, parsed_args) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters=_formatters) return (display_columns, data) class DeleteSubnet(command.Command): _description = _("Delete subnet(s)") def get_parser(self, prog_name): parser = super(DeleteSubnet, self).get_parser(prog_name) parser.add_argument( 'subnet', metavar="", nargs='+', help=_("Subnet(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for subnet in parsed_args.subnet: try: obj = client.find_subnet(subnet, ignore_missing=False) client.delete_subnet(obj) except Exception as e: result += 1 LOG.error(_("Failed to delete subnet with " "name or ID '%(subnet)s': %(e)s"), {'subnet': subnet, 'e': e}) if result > 0: total = len(parsed_args.subnet) msg = (_("%(result)s of %(total)s subnets failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) # TODO(abhiraut): Use only the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class ListSubnet(command.Lister): _description = _("List subnets") def get_parser(self, prog_name): parser = super(ListSubnet, self).get_parser(prog_name) parser.add_argument( '--long', action='store_true', default=False, help=_("List additional fields in output") ) parser.add_argument( '--ip-version', type=int, choices=[4, 6], metavar='', dest='ip_version', help=_("List only subnets of given IP version in output." "Allowed values for IP version are 4 and 6."), ) dhcp_enable_group = parser.add_mutually_exclusive_group() dhcp_enable_group.add_argument( '--dhcp', action='store_true', help=_("List subnets which have DHCP enabled") ) dhcp_enable_group.add_argument( '--no-dhcp', action='store_true', help=_("List subnets which have DHCP disabled") ) parser.add_argument( '--service-type', metavar='', action='append', dest='service_types', help=_("List only subnets of a given service type in output " "e.g.: network:floatingip_agent_gateway. " "Must be a valid device owner value for a network port " "(repeat option to list multiple service types)") ) parser.add_argument( '--project', metavar='', help=_("List only subnets which belong to a given project " "in output (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--network', metavar='', help=_("List only subnets which belong to a given network " "in output (name or ID)") ) parser.add_argument( '--gateway', metavar='', help=_("List only subnets of given gateway IP in output") ) parser.add_argument( '--name', metavar='', help=_("List only subnets of given name in output") ) parser.add_argument( '--subnet-range', metavar='', help=_("List only subnets of given subnet range " "(in CIDR notation) in output " "e.g.: --subnet-range 10.10.0.0/16") ) _tag.add_tag_filtering_option_to_parser(parser, _('subnets')) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity network_client = self.app.client_manager.network filters = {} if parsed_args.ip_version: filters['ip_version'] = parsed_args.ip_version if parsed_args.dhcp: filters['enable_dhcp'] = True filters['is_dhcp_enabled'] = True elif parsed_args.no_dhcp: filters['enable_dhcp'] = False filters['is_dhcp_enabled'] = False if parsed_args.service_types: filters['service_types'] = parsed_args.service_types if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id filters['tenant_id'] = project_id filters['project_id'] = project_id if parsed_args.network: network_id = network_client.find_network(parsed_args.network, ignore_missing=False).id filters['network_id'] = network_id if parsed_args.gateway: filters['gateway_ip'] = parsed_args.gateway if parsed_args.name: filters['name'] = parsed_args.name if parsed_args.subnet_range: filters['cidr'] = parsed_args.subnet_range _tag.get_tag_filtering_args(parsed_args, filters) data = network_client.subnets(**filters) headers = ('ID', 'Name', 'Network', 'Subnet') columns = ('id', 'name', 'network_id', 'cidr') if parsed_args.long: headers += ('Project', 'DHCP', 'Name Servers', 'Allocation Pools', 'Host Routes', 'IP Version', 'Gateway', 'Service Types', 'Tags') columns += ('project_id', 'is_dhcp_enabled', 'dns_nameservers', 'allocation_pools', 'host_routes', 'ip_version', 'gateway_ip', 'service_types', 'tags') return (headers, (utils.get_item_properties( s, columns, formatters=_formatters, ) for s in data)) # TODO(abhiraut): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class SetSubnet(command.Command): _description = _("Set subnet properties") def get_parser(self, prog_name): parser = super(SetSubnet, self).get_parser(prog_name) parser.add_argument( 'subnet', metavar="", help=_("Subnet to modify (name or ID)") ) parser.add_argument( '--name', metavar='', help=_("Updated name of the subnet") ) dhcp_enable_group = parser.add_mutually_exclusive_group() dhcp_enable_group.add_argument( '--dhcp', action='store_true', default=None, help=_("Enable DHCP") ) dhcp_enable_group.add_argument( '--no-dhcp', action='store_true', help=_("Disable DHCP") ) parser.add_argument( '--gateway', metavar='', help=_("Specify a gateway for the subnet. The options are: " ": Specific IP address to use as the gateway, " "'none': This subnet will not use a gateway, " "e.g.: --gateway 192.168.9.1, --gateway none.") ) parser.add_argument( '--description', metavar='', help=_("Set subnet description") ) _tag.add_tag_option_to_parser_for_set(parser, _('subnet')) _get_common_parse_arguments(parser, is_create=False) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_subnet(parsed_args.subnet, ignore_missing=False) attrs = _get_attrs(self.app.client_manager, parsed_args, is_create=False) if 'dns_nameservers' in attrs: if not parsed_args.no_dns_nameservers: attrs['dns_nameservers'] += obj.dns_nameservers elif parsed_args.no_dns_nameservers: attrs['dns_nameservers'] = [] if 'host_routes' in attrs: if not parsed_args.no_host_route: attrs['host_routes'] += obj.host_routes elif parsed_args.no_host_route: attrs['host_routes'] = '' if 'allocation_pools' in attrs: if not parsed_args.no_allocation_pool: attrs['allocation_pools'] += obj.allocation_pools elif parsed_args.no_allocation_pool: attrs['allocation_pools'] = [] if 'service_types' in attrs: attrs['service_types'] += obj.service_types if attrs: client.update_subnet(obj, **attrs) # tags is a subresource and it needs to be updated separately. _tag.update_tags_for_set(client, obj, parsed_args) return class ShowSubnet(command.ShowOne): _description = _("Display subnet details") def get_parser(self, prog_name): parser = super(ShowSubnet, self).get_parser(prog_name) parser.add_argument( 'subnet', metavar="", help=_("Subnet to display (name or ID)") ) return parser def take_action(self, parsed_args): obj = self.app.client_manager.network.find_subnet(parsed_args.subnet, ignore_missing=False) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters=_formatters) return (display_columns, data) class UnsetSubnet(command.Command): _description = _("Unset subnet properties") def get_parser(self, prog_name): parser = super(UnsetSubnet, self).get_parser(prog_name) parser.add_argument( '--allocation-pool', metavar='start=,end=', dest='allocation_pools', action=parseractions.MultiKeyValueAction, required_keys=['start', 'end'], help=_('Allocation pool IP addresses to be removed from this ' 'subnet e.g.: start=192.168.199.2,end=192.168.199.254 ' '(repeat option to unset multiple allocation pools)') ) parser.add_argument( '--dns-nameserver', metavar='', action='append', dest='dns_nameservers', help=_('DNS server to be removed from this subnet ' '(repeat option to unset multiple DNS servers)') ) parser.add_argument( '--host-route', metavar='destination=,gateway=', dest='host_routes', action=parseractions.MultiKeyValueAction, required_keys=['destination', 'gateway'], help=_('Route to be removed from this subnet ' 'e.g.: destination=10.10.0.0/16,gateway=192.168.71.254 ' 'destination: destination subnet (in CIDR notation) ' 'gateway: nexthop IP address ' '(repeat option to unset multiple host routes)') ) parser.add_argument( '--service-type', metavar='', action='append', dest='service_types', help=_('Service type to be removed from this subnet ' 'e.g.: network:floatingip_agent_gateway. ' 'Must be a valid device owner value for a network port ' '(repeat option to unset multiple service types)') ) _tag.add_tag_option_to_parser_for_unset(parser, _('subnet')) parser.add_argument( 'subnet', metavar="", help=_("Subnet to modify (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_subnet(parsed_args.subnet, ignore_missing=False) tmp_obj = copy.deepcopy(obj) attrs = {} if parsed_args.dns_nameservers: _update_arguments(tmp_obj.dns_nameservers, parsed_args.dns_nameservers, 'dns-nameserver') attrs['dns_nameservers'] = tmp_obj.dns_nameservers if parsed_args.host_routes: _update_arguments( tmp_obj.host_routes, convert_entries_to_nexthop(parsed_args.host_routes), 'host-route') attrs['host_routes'] = tmp_obj.host_routes if parsed_args.allocation_pools: _update_arguments(tmp_obj.allocation_pools, parsed_args.allocation_pools, 'allocation-pool') attrs['allocation_pools'] = tmp_obj.allocation_pools if parsed_args.service_types: _update_arguments(tmp_obj.service_types, parsed_args.service_types, 'service-type') attrs['service_types'] = tmp_obj.service_types if attrs: client.update_subnet(obj, **attrs) # tags is a subresource and it needs to be updated separately. _tag.update_tags_for_unset(client, obj, parsed_args) python-openstackclient-3.14.0/openstackclient/network/v2/router.py0000666000175100017510000006276513232364361025455 0ustar zuulzuul00000000000000# 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. # """Router action implementations""" import argparse import copy import json 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 openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils from openstackclient.network.v2 import _tag LOG = logging.getLogger(__name__) def _format_admin_state(state): return 'UP' if state else 'DOWN' def _format_router_info(info): try: return json.dumps(info) except (TypeError, KeyError): return '' def _format_routes(routes): # Map the route keys to match --route option. for route in routes: if 'nexthop' in route: route['gateway'] = route.pop('nexthop') return utils.format_list_of_dicts(routes) _formatters = { 'admin_state_up': _format_admin_state, 'is_admin_state_up': _format_admin_state, 'external_gateway_info': _format_router_info, 'availability_zones': utils.format_list, 'availability_zone_hints': utils.format_list, 'routes': _format_routes, 'tags': utils.format_list, } def _get_columns(item): column_map = { 'tenant_id': 'project_id', 'is_ha': 'ha', 'is_distributed': 'distributed', 'is_admin_state_up': 'admin_state_up', } if hasattr(item, 'interfaces_info'): column_map['interfaces_info'] = 'interfaces_info' return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) def _get_attrs(client_manager, parsed_args): attrs = {} if parsed_args.name is not None: attrs['name'] = str(parsed_args.name) if parsed_args.enable: attrs['admin_state_up'] = True if parsed_args.disable: attrs['admin_state_up'] = False if parsed_args.centralized: attrs['distributed'] = False if parsed_args.distributed: attrs['distributed'] = True if ('availability_zone_hints' in parsed_args and parsed_args.availability_zone_hints is not None): attrs['availability_zone_hints'] = parsed_args.availability_zone_hints if parsed_args.description is not None: attrs['description'] = parsed_args.description # "router set" command doesn't support setting project. if 'project' in parsed_args and parsed_args.project is not None: identity_client = client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id return attrs class AddPortToRouter(command.Command): _description = _("Add a port to a router") def get_parser(self, prog_name): parser = super(AddPortToRouter, self).get_parser(prog_name) parser.add_argument( 'router', metavar='', help=_("Router to which port will be added (name or ID)") ) parser.add_argument( 'port', metavar='', help=_("Port to be added (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network port = client.find_port(parsed_args.port, ignore_missing=False) client.add_interface_to_router(client.find_router( parsed_args.router, ignore_missing=False), port_id=port.id) class AddSubnetToRouter(command.Command): _description = _("Add a subnet to a router") def get_parser(self, prog_name): parser = super(AddSubnetToRouter, self).get_parser(prog_name) parser.add_argument( 'router', metavar='', help=_("Router to which subnet will be added (name or ID)") ) parser.add_argument( 'subnet', metavar='', help=_("Subnet to be added (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network subnet = client.find_subnet(parsed_args.subnet, ignore_missing=False) client.add_interface_to_router( client.find_router(parsed_args.router, ignore_missing=False), subnet_id=subnet.id) # TODO(yanxing'an): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateRouter(command.ShowOne): _description = _("Create a new router") def get_parser(self, prog_name): parser = super(CreateRouter, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_("New router name") ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=True, help=_("Enable router (default)") ) admin_group.add_argument( '--disable', action='store_true', help=_("Disable router") ) distribute_group = parser.add_mutually_exclusive_group() distribute_group.add_argument( '--distributed', action='store_true', help=_("Create a distributed router") ) distribute_group.add_argument( '--centralized', action='store_true', help=_("Create a centralized router") ) ha_group = parser.add_mutually_exclusive_group() ha_group.add_argument( '--ha', action='store_true', help=_("Create a highly available router") ) ha_group.add_argument( '--no-ha', action='store_true', help=_("Create a legacy router") ) parser.add_argument( '--description', metavar='', help=_("Set router description") ) parser.add_argument( '--project', metavar='', help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--availability-zone-hint', metavar='', action='append', dest='availability_zone_hints', help=_("Availability Zone in which to create this router " "(Router Availability Zone extension required, " "repeat option to set multiple availability zones)") ) _tag.add_tag_option_to_parser_for_create(parser, _('router')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_attrs(self.app.client_manager, parsed_args) if parsed_args.ha: attrs['ha'] = True if parsed_args.no_ha: attrs['ha'] = False obj = client.create_router(**attrs) # tags cannot be set when created, so tags need to be set later. _tag.update_tags_for_set(client, obj, parsed_args) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters=_formatters) return (display_columns, data) class DeleteRouter(command.Command): _description = _("Delete router(s)") def get_parser(self, prog_name): parser = super(DeleteRouter, self).get_parser(prog_name) parser.add_argument( 'router', metavar="", nargs="+", help=_("Router(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for router in parsed_args.router: try: obj = client.find_router(router, ignore_missing=False) client.delete_router(obj) except Exception as e: result += 1 LOG.error(_("Failed to delete router with " "name or ID '%(router)s': %(e)s"), {'router': router, 'e': e}) if result > 0: total = len(parsed_args.router) msg = (_("%(result)s of %(total)s routers failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) # TODO(yanxing'an): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class ListRouter(command.Lister): _description = _("List routers") def get_parser(self, prog_name): parser = super(ListRouter, self).get_parser(prog_name) parser.add_argument( '--name', metavar='', help=_("List routers according to their name") ) admin_state_group = parser.add_mutually_exclusive_group() admin_state_group.add_argument( '--enable', action='store_true', help=_("List enabled routers") ) admin_state_group.add_argument( '--disable', action='store_true', help=_("List disabled routers") ) parser.add_argument( '--long', action='store_true', default=False, help=_("List additional fields in output") ) parser.add_argument( '--project', metavar='', help=_("List routers according to their project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--agent', metavar='', help=_("List routers hosted by an agent (ID only)") ) _tag.add_tag_filtering_option_to_parser(parser, _('routers')) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity client = self.app.client_manager.network columns = ( 'id', 'name', 'status', 'is_admin_state_up', 'is_distributed', 'is_ha', 'project_id', ) column_headers = ( 'ID', 'Name', 'Status', 'State', 'Distributed', 'HA', 'Project', ) args = {} if parsed_args.name is not None: args['name'] = parsed_args.name if parsed_args.enable: args['admin_state_up'] = True args['is_admin_state_up'] = True elif parsed_args.disable: args['admin_state_up'] = False args['is_admin_state_up'] = False if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id args['tenant_id'] = project_id args['project_id'] = project_id _tag.get_tag_filtering_args(parsed_args, args) if parsed_args.agent is not None: agent = client.get_agent(parsed_args.agent) data = client.agent_hosted_routers(agent) # NOTE: Networking API does not support filtering by parameters, # so we need filtering in the client side. data = [d for d in data if self._filter_match(d, args)] else: data = client.routers(**args) if parsed_args.long: columns = columns + ( 'routes', 'external_gateway_info', ) column_headers = column_headers + ( 'Routes', 'External gateway info', ) # availability zone will be available only when # router_availability_zone extension is enabled if client.find_extension("router_availability_zone"): columns = columns + ( 'availability_zones', ) column_headers = column_headers + ( 'Availability zones', ) columns = columns + ('tags',) column_headers = column_headers + ('Tags',) return (column_headers, (utils.get_item_properties( s, columns, formatters=_formatters, ) for s in data)) @staticmethod def _filter_match(data, conditions): for key, value in conditions.items(): try: if getattr(data, key) != value: return False except AttributeError: # Some filter attributes like tenant_id or admin_state_up # are backward compatibility in older OpenStack SDK support. # They does not exist in the latest release. # In this case we just skip checking such filter condition. continue return True class RemovePortFromRouter(command.Command): _description = _("Remove a port from a router") def get_parser(self, prog_name): parser = super(RemovePortFromRouter, self).get_parser(prog_name) parser.add_argument( 'router', metavar='', help=_("Router from which port will be removed (name or ID)") ) parser.add_argument( 'port', metavar='', help=_("Port to be removed and deleted (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network port = client.find_port(parsed_args.port, ignore_missing=False) client.remove_interface_from_router(client.find_router( parsed_args.router, ignore_missing=False), port_id=port.id) class RemoveSubnetFromRouter(command.Command): _description = _("Remove a subnet from a router") def get_parser(self, prog_name): parser = super(RemoveSubnetFromRouter, self).get_parser(prog_name) parser.add_argument( 'router', metavar='', help=_("Router from which the subnet will be removed (name or ID)") ) parser.add_argument( 'subnet', metavar='', help=_("Subnet to be removed (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network subnet = client.find_subnet(parsed_args.subnet, ignore_missing=False) client.remove_interface_from_router( client.find_router(parsed_args.router, ignore_missing=False), subnet_id=subnet.id) # TODO(yanxing'an): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class SetRouter(command.Command): _description = _("Set router properties") def get_parser(self, prog_name): parser = super(SetRouter, self).get_parser(prog_name) parser.add_argument( 'router', metavar="", help=_("Router to modify (name or ID)") ) parser.add_argument( '--name', metavar='', help=_("Set router name") ) parser.add_argument( '--description', metavar='', help=_('Set router description') ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help=_("Enable router") ) admin_group.add_argument( '--disable', action='store_true', help=_("Disable router") ) distribute_group = parser.add_mutually_exclusive_group() distribute_group.add_argument( '--distributed', action='store_true', help=_("Set router to distributed mode (disabled router only)") ) distribute_group.add_argument( '--centralized', action='store_true', help=_("Set router to centralized mode (disabled router only)") ) routes_group = parser.add_mutually_exclusive_group() # ToDo(Reedip):Remove mutual exclusiveness once clear-routes is removed parser.add_argument( '--route', metavar='destination=,gateway=', action=parseractions.MultiKeyValueAction, dest='routes', default=None, required_keys=['destination', 'gateway'], help=_("Routes associated with the router " "destination: destination subnet (in CIDR notation) " "gateway: nexthop IP address " "(repeat option to set multiple routes)") ) routes_group.add_argument( '--no-route', action='store_true', help=_("Clear routes associated with the router. " "Specify both --route and --no-route to overwrite " "current value of route.") ) routes_group.add_argument( '--clear-routes', action='store_true', help=argparse.SUPPRESS, ) routes_ha = parser.add_mutually_exclusive_group() routes_ha.add_argument( '--ha', action='store_true', help=_("Set the router as highly available " "(disabled router only)") ) routes_ha.add_argument( '--no-ha', action='store_true', help=_("Clear high availability attribute of the router " "(disabled router only)") ) parser.add_argument( '--external-gateway', metavar="", help=_("External Network used as router's gateway (name or ID)") ) parser.add_argument( '--fixed-ip', metavar='subnet=,ip-address=', action=parseractions.MultiKeyValueAction, optional_keys=['subnet', 'ip-address'], help=_("Desired IP and/or subnet (name or ID)" "on external gateway: " "subnet=,ip-address= " "(repeat option to set multiple fixed IP addresses)") ) snat_group = parser.add_mutually_exclusive_group() snat_group.add_argument( '--enable-snat', action='store_true', help=_("Enable Source NAT on external gateway") ) snat_group.add_argument( '--disable-snat', action='store_true', help=_("Disable Source NAT on external gateway") ) _tag.add_tag_option_to_parser_for_set(parser, _('router')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_router(parsed_args.router, ignore_missing=False) # Get the common attributes. attrs = _get_attrs(self.app.client_manager, parsed_args) # Get the route attributes. if parsed_args.ha: attrs['ha'] = True elif parsed_args.no_ha: attrs['ha'] = False if parsed_args.clear_routes: LOG.warning(_( 'The --clear-routes option is deprecated, ' 'please use --no-route instead.' )) if parsed_args.routes is not None: for route in parsed_args.routes: route['nexthop'] = route.pop('gateway') attrs['routes'] = parsed_args.routes if not (parsed_args.no_route or parsed_args.clear_routes): # Map the route keys and append to the current routes. # The REST API will handle route validation and duplicates. attrs['routes'] += obj.routes elif parsed_args.no_route or parsed_args.clear_routes: attrs['routes'] = [] if (parsed_args.disable_snat or parsed_args.enable_snat or parsed_args.fixed_ip) and not parsed_args.external_gateway: msg = (_("You must specify '--external-gateway' in order" "to update the SNAT or fixed-ip values")) raise exceptions.CommandError(msg) if parsed_args.external_gateway: gateway_info = {} network = client.find_network( parsed_args.external_gateway, ignore_missing=False) gateway_info['network_id'] = network.id if parsed_args.disable_snat: gateway_info['enable_snat'] = False if parsed_args.enable_snat: gateway_info['enable_snat'] = True if parsed_args.fixed_ip: ips = [] for ip_spec in parsed_args.fixed_ip: if ip_spec.get('subnet', False): subnet_name_id = ip_spec.pop('subnet') if subnet_name_id: subnet = client.find_subnet(subnet_name_id, ignore_missing=False) ip_spec['subnet_id'] = subnet.id if ip_spec.get('ip-address', False): ip_spec['ip_address'] = ip_spec.pop('ip-address') ips.append(ip_spec) gateway_info['external_fixed_ips'] = ips attrs['external_gateway_info'] = gateway_info if attrs: client.update_router(obj, **attrs) # tags is a subresource and it needs to be updated separately. _tag.update_tags_for_set(client, obj, parsed_args) class ShowRouter(command.ShowOne): _description = _("Display router details") def get_parser(self, prog_name): parser = super(ShowRouter, self).get_parser(prog_name) parser.add_argument( 'router', metavar="", help=_("Router to display (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_router(parsed_args.router, ignore_missing=False) interfaces_info = [] filters = {} filters['device_id'] = obj.id for port in client.ports(**filters): if port.device_owner != "network:router_gateway": for ip_spec in port.fixed_ips: int_info = { 'port_id': port.id, 'ip_address': ip_spec.get('ip_address'), 'subnet_id': ip_spec.get('subnet_id') } interfaces_info.append(int_info) setattr(obj, 'interfaces_info', interfaces_info) display_columns, columns = _get_columns(obj) _formatters['interfaces_info'] = _format_router_info data = utils.get_item_properties(obj, columns, formatters=_formatters) return (display_columns, data) class UnsetRouter(command.Command): _description = _("Unset router properties") def get_parser(self, prog_name): parser = super(UnsetRouter, self).get_parser(prog_name) parser.add_argument( '--route', metavar='destination=,gateway=', action=parseractions.MultiKeyValueAction, dest='routes', default=None, required_keys=['destination', 'gateway'], help=_("Routes to be removed from the router " "destination: destination subnet (in CIDR notation) " "gateway: nexthop IP address " "(repeat option to unset multiple routes)")) parser.add_argument( '--external-gateway', action='store_true', default=False, help=_("Remove external gateway information from the router")) parser.add_argument( 'router', metavar="", help=_("Router to modify (name or ID)") ) _tag.add_tag_option_to_parser_for_unset(parser, _('router')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_router(parsed_args.router, ignore_missing=False) tmp_routes = copy.deepcopy(obj.routes) attrs = {} if parsed_args.routes: try: for route in parsed_args.routes: route['nexthop'] = route.pop('gateway') tmp_routes.remove(route) except ValueError: msg = (_("Router does not contain route %s") % route) raise exceptions.CommandError(msg) attrs['routes'] = tmp_routes if parsed_args.external_gateway: attrs['external_gateway_info'] = {} if attrs: client.update_router(obj, **attrs) # tags is a subresource and it needs to be updated separately. _tag.update_tags_for_unset(client, obj, parsed_args) python-openstackclient-3.14.0/openstackclient/network/v2/network_flavor.py0000666000175100017510000002313013232364361027156 0ustar zuulzuul00000000000000# 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. # """Flavor action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils LOG = logging.getLogger(__name__) def _get_columns(item): column_map = { 'is_enabled': 'enabled', 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) def _get_attrs(client_manager, parsed_args): attrs = {} attrs['name'] = parsed_args.name attrs['service_type'] = parsed_args.service_type if parsed_args.description is not None: attrs['description'] = parsed_args.description if parsed_args.enable: attrs['enabled'] = True if parsed_args.disable: attrs['enabled'] = False if 'project' in parsed_args and parsed_args.project is not None: identity_client = client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id return attrs class AddNetworkFlavorToProfile(command.Command): _description = _("Add a service profile to a network flavor") def get_parser(self, prog_name): parser = super( AddNetworkFlavorToProfile, self).get_parser(prog_name) parser.add_argument( 'flavor', metavar="", help=_("Network flavor (name or ID)") ) parser.add_argument( 'service_profile', metavar="", help=_("Service profile (ID only)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj_flavor = client.find_flavor( parsed_args.flavor, ignore_missing=False) obj_service_profile = client.find_service_profile( parsed_args.service_profile, ignore_missing=False) client.associate_flavor_with_service_profile( obj_flavor, obj_service_profile) # TODO(dasanind): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateNetworkFlavor(command.ShowOne): _description = _("Create new network flavor") def get_parser(self, prog_name): parser = super(CreateNetworkFlavor, self).get_parser(prog_name) parser.add_argument( 'name', metavar="", help=_("Name for the flavor") ) parser.add_argument( '--service-type', metavar="", required=True, help=_('Service type to which the flavor applies to: e.g. VPN ' '(See openstack network service provider list for loaded ' 'examples.)') ) parser.add_argument( '--description', help=_('Description for the flavor') ) parser.add_argument( '--project', metavar="", help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_("Enable the flavor (default)") ) enable_group.add_argument( '--disable', action='store_true', help=_("Disable the flavor") ) 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_flavor(**attrs) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters={}) return (display_columns, data) class DeleteNetworkFlavor(command.Command): _description = _("Delete network flavors") def get_parser(self, prog_name): parser = super(DeleteNetworkFlavor, self).get_parser(prog_name) parser.add_argument( 'flavor', metavar='', nargs='+', help=_('Flavor(s) to delete (name or ID)') ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for flavor in parsed_args.flavor: try: obj = client.find_flavor(flavor, ignore_missing=False) client.delete_flavor(obj) except Exception as e: result += 1 LOG.error(_("Failed to delete flavor with " "name or ID '%(flavor)s': %(e)s"), {"flavor": flavor, "e": e}) if result > 0: total = len(parsed_args.flavor) msg = (_("%(result)s of %(total)s flavors failed " "to delete.") % {"result": result, "total": total}) raise exceptions.CommandError(msg) class ListNetworkFlavor(command.Lister): _description = _("List network flavors") def take_action(self, parsed_args): client = self.app.client_manager.network columns = ( 'id', 'name', 'is_enabled', 'service_type', 'description' ) column_headers = ( 'ID', 'Name', 'Enabled', 'Service Type', 'Description' ) data = client.flavors() return (column_headers, (utils.get_item_properties( s, columns, ) for s in data)) class RemoveNetworkFlavorFromProfile(command.Command): _description = _( "Remove service profile from network flavor") def get_parser(self, prog_name): parser = super( RemoveNetworkFlavorFromProfile, self).get_parser(prog_name) parser.add_argument( 'flavor', metavar="", help=_("Network flavor (name or ID)") ) parser.add_argument( 'service_profile', metavar="", help=_("Service profile (ID only)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj_flavor = client.find_flavor( parsed_args.flavor, ignore_missing=False) obj_service_profile = client.find_service_profile( parsed_args.service_profile, ignore_missing=False) client.disassociate_flavor_from_service_profile( obj_flavor, obj_service_profile) # TODO(dasanind): Use only the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class SetNetworkFlavor(command.Command): _description = _("Set network flavor properties") def get_parser(self, prog_name): parser = super(SetNetworkFlavor, self).get_parser(prog_name) parser.add_argument( 'flavor', metavar="", help=_("Flavor to update (name or ID)") ) parser.add_argument( '--description', help=_('Set network flavor description') ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--disable', action='store_true', help=_("Disable network flavor") ) enable_group.add_argument( '--enable', action='store_true', help=_("Enable network flavor") ) parser.add_argument( '--name', metavar="", help=_('Set flavor name') ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_flavor( parsed_args.flavor, ignore_missing=False) 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.enable: attrs['enabled'] = True if parsed_args.disable: attrs['enabled'] = False client.update_flavor(obj, **attrs) class ShowNetworkFlavor(command.ShowOne): _description = _("Display network flavor details") def get_parser(self, prog_name): parser = super(ShowNetworkFlavor, self).get_parser(prog_name) parser.add_argument( 'flavor', metavar='', help=_('Flavor to display (name or ID)') ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_flavor(parsed_args.flavor, ignore_missing=False) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return display_columns, data python-openstackclient-3.14.0/openstackclient/network/v2/security_group.py0000666000175100017510000002621113232364361027202 0ustar zuulzuul00000000000000# 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. # """Security Group action implementations""" import argparse from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import common from openstackclient.network import sdk_utils from openstackclient.network import utils as network_utils def _format_network_security_group_rules(sg_rules): # For readability and to align with formatting compute security group # rules, trim keys with caller known (e.g. security group and tenant ID) # or empty values. for sg_rule in sg_rules: empty_keys = [k for k, v in six.iteritems(sg_rule) if not v] for key in empty_keys: sg_rule.pop(key) sg_rule.pop('security_group_id', None) sg_rule.pop('tenant_id', None) sg_rule.pop('project_id', None) return utils.format_list_of_dicts(sg_rules) def _format_compute_security_group_rule(sg_rule): info = network_utils.transform_compute_security_group_rule(sg_rule) # Trim parent security group ID since caller has this information. info.pop('parent_group_id', None) # Trim keys with empty string values. keys_to_trim = [ 'ip_protocol', 'ip_range', 'port_range', 'remote_security_group', ] for key in keys_to_trim: if key in info and not info[key]: info.pop(key) return utils.format_dict(info) def _format_compute_security_group_rules(sg_rules): rules = [] for sg_rule in sg_rules: rules.append(_format_compute_security_group_rule(sg_rule)) return utils.format_list(rules, separator='\n') _formatters_network = { 'security_group_rules': _format_network_security_group_rules, } _formatters_compute = { 'rules': _format_compute_security_group_rules, } def _get_columns(item): column_map = { 'security_group_rules': 'rules', 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) # TODO(abhiraut): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateSecurityGroup(common.NetworkAndComputeShowOne): _description = _("Create a new security group") def update_parser_common(self, parser): parser.add_argument( "name", metavar="", help=_("New security group name") ) parser.add_argument( "--description", metavar="", help=_("Security group description") ) return parser def update_parser_network(self, parser): parser.add_argument( '--project', metavar='', help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) return parser def _get_description(self, parsed_args): if parsed_args.description is not None: return parsed_args.description else: return parsed_args.name def take_action_network(self, client, parsed_args): # Build the create attributes. attrs = {} attrs['name'] = parsed_args.name attrs['description'] = self._get_description(parsed_args) if parsed_args.project is not None: identity_client = self.app.client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id # Create the security group and display the results. obj = client.create_security_group(**attrs) display_columns, property_columns = _get_columns(obj) data = utils.get_item_properties( obj, property_columns, formatters=_formatters_network ) return (display_columns, data) def take_action_compute(self, client, parsed_args): description = self._get_description(parsed_args) obj = client.api.security_group_create( parsed_args.name, description, ) display_columns, property_columns = _get_columns(obj) data = utils.get_dict_properties( obj, property_columns, formatters=_formatters_compute ) return (display_columns, data) class DeleteSecurityGroup(common.NetworkAndComputeDelete): _description = _("Delete security group(s)") # Used by base class to find resources in parsed_args. resource = 'group' r = None def update_parser_common(self, parser): parser.add_argument( 'group', metavar='', nargs="+", help=_("Security group(s) to delete (name or ID)"), ) return parser def take_action_network(self, client, parsed_args): obj = client.find_security_group(self.r, ignore_missing=False) client.delete_security_group(obj) def take_action_compute(self, client, parsed_args): client.api.security_group_delete(self.r) # TODO(rauta): Use the SDK resource mapped attribute names once # the OSC minimum requirements include SDK 1.0. class ListSecurityGroup(common.NetworkAndComputeLister): _description = _("List security groups") def update_parser_network(self, parser): # Maintain and hide the argument for backwards compatibility. # Network will always return all projects for an admin. parser.add_argument( '--all-projects', action='store_true', default=False, help=argparse.SUPPRESS, ) parser.add_argument( '--project', metavar='', help=_("List security groups according to the project " "(name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) return parser def update_parser_compute(self, parser): parser.add_argument( '--all-projects', action='store_true', default=False, help=_("Display information from all projects (admin only)") ) return parser def take_action_network(self, client, parsed_args): filters = {} if parsed_args.project: identity_client = self.app.client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id filters['tenant_id'] = project_id filters['project_id'] = project_id data = client.security_groups(**filters) columns = ( "ID", "Name", "Description", "Project ID" ) column_headers = ( "ID", "Name", "Description", "Project" ) return (column_headers, (utils.get_item_properties( s, columns, ) for s in data)) def take_action_compute(self, client, parsed_args): search = {'all_tenants': parsed_args.all_projects} data = client.api.security_group_list( # TODO(dtroyer): add limit, marker search_opts=search, ) columns = ( "ID", "Name", "Description", ) column_headers = columns if parsed_args.all_projects: columns = columns + ('Tenant ID',) column_headers = column_headers + ('Project',) return (column_headers, (utils.get_dict_properties( s, columns, ) for s in data)) class SetSecurityGroup(common.NetworkAndComputeCommand): _description = _("Set security group properties") def update_parser_common(self, parser): parser.add_argument( 'group', metavar='', help=_("Security group to modify (name or ID)") ) parser.add_argument( '--name', metavar='', help=_("New security group name") ) parser.add_argument( "--description", metavar="", help=_("New security group description") ) return parser def take_action_network(self, client, parsed_args): obj = client.find_security_group(parsed_args.group, ignore_missing=False) 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 # NOTE(rtheis): Previous behavior did not raise a CommandError # if there were no updates. Maintain this behavior and issue # the update. client.update_security_group(obj, **attrs) def take_action_compute(self, client, parsed_args): data = client.api.security_group_find(parsed_args.group) if parsed_args.name is not None: data['name'] = parsed_args.name if parsed_args.description is not None: data['description'] = parsed_args.description # NOTE(rtheis): Previous behavior did not raise a CommandError # if there were no updates. Maintain this behavior and issue # the update. client.api.security_group_set( data, data['name'], data['description'], ) class ShowSecurityGroup(common.NetworkAndComputeShowOne): _description = _("Display security group details") def update_parser_common(self, parser): parser.add_argument( 'group', metavar='', help=_("Security group to display (name or ID)") ) return parser def take_action_network(self, client, parsed_args): obj = client.find_security_group(parsed_args.group, ignore_missing=False) display_columns, property_columns = _get_columns(obj) data = utils.get_item_properties( obj, property_columns, formatters=_formatters_network ) return (display_columns, data) def take_action_compute(self, client, parsed_args): obj = client.api.security_group_find(parsed_args.group) display_columns, property_columns = _get_columns(obj) data = utils.get_dict_properties( obj, property_columns, formatters=_formatters_compute ) return (display_columns, data) python-openstackclient-3.14.0/openstackclient/network/v2/network_segment.py0000666000175100017510000002020713232364361027331 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # """Network segment action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ from openstackclient.network import sdk_utils LOG = logging.getLogger(__name__) def _get_columns(item): return sdk_utils.get_osc_show_columns_for_sdk_resource(item, {}) class CreateNetworkSegment(command.ShowOne): _description = _("Create new network segment") def get_parser(self, prog_name): parser = super(CreateNetworkSegment, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('New network segment name') ) parser.add_argument( '--description', metavar='', help=_('Network segment description'), ) parser.add_argument( '--physical-network', metavar='', help=_('Physical network name of this network segment'), ) parser.add_argument( '--segment', metavar='', type=int, help=_('Segment identifier for this network segment which is ' 'based on the network type, VLAN ID for vlan network ' 'type and tunnel ID for geneve, gre and vxlan network ' 'types'), ) parser.add_argument( '--network', metavar='', required=True, help=_('Network this network segment belongs to (name or ID)'), ) parser.add_argument( '--network-type', metavar='', choices=['flat', 'geneve', 'gre', 'local', 'vlan', 'vxlan'], required=True, help=_('Network type of this network segment ' '(flat, geneve, gre, local, vlan or vxlan)'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network attrs = {} attrs['name'] = parsed_args.name attrs['network_id'] = client.find_network(parsed_args.network, ignore_missing=False).id attrs['network_type'] = parsed_args.network_type if parsed_args.description is not None: attrs['description'] = parsed_args.description if parsed_args.physical_network is not None: attrs['physical_network'] = parsed_args.physical_network if parsed_args.segment is not None: attrs['segmentation_id'] = parsed_args.segment obj = client.create_segment(**attrs) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return (display_columns, data) class DeleteNetworkSegment(command.Command): _description = _("Delete network segment(s)") def get_parser(self, prog_name): parser = super(DeleteNetworkSegment, self).get_parser(prog_name) parser.add_argument( 'network_segment', metavar='', nargs='+', help=_('Network segment(s) to delete (name or ID)'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for network_segment in parsed_args.network_segment: try: obj = client.find_segment(network_segment, ignore_missing=False) client.delete_segment(obj) except Exception as e: result += 1 LOG.error(_("Failed to delete network segment with " "ID '%(network_segment)s': %(e)s"), {'network_segment': network_segment, 'e': e}) if result > 0: total = len(parsed_args.network_segment) msg = (_("%(result)s of %(total)s network segments failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListNetworkSegment(command.Lister): _description = _("List network segments") def get_parser(self, prog_name): parser = super(ListNetworkSegment, self).get_parser(prog_name) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( '--network', metavar='', help=_('List network segments that belong to this ' 'network (name or ID)'), ) return parser def take_action(self, parsed_args): network_client = self.app.client_manager.network filters = {} if parsed_args.network: _network = network_client.find_network( parsed_args.network, ignore_missing=False ) filters = {'network_id': _network.id} data = network_client.segments(**filters) headers = ( 'ID', 'Name', 'Network', 'Network Type', 'Segment', ) columns = ( 'id', 'name', 'network_id', 'network_type', 'segmentation_id', ) if parsed_args.long: headers = headers + ( 'Physical Network', ) columns = columns + ( 'physical_network', ) return (headers, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class SetNetworkSegment(command.Command): _description = _("Set network segment properties") def get_parser(self, prog_name): parser = super(SetNetworkSegment, self).get_parser(prog_name) parser.add_argument( 'network_segment', metavar='', help=_('Network segment to modify (name or ID)'), ) parser.add_argument( '--description', metavar='', help=_('Set network segment description'), ) parser.add_argument( '--name', metavar='', help=_('Set network segment name'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_segment(parsed_args.network_segment, ignore_missing=False) attrs = {} if parsed_args.description is not None: attrs['description'] = parsed_args.description if parsed_args.name is not None: attrs['name'] = parsed_args.name client.update_segment(obj, **attrs) class ShowNetworkSegment(command.ShowOne): _description = _("Display network segment details") def get_parser(self, prog_name): parser = super(ShowNetworkSegment, self).get_parser(prog_name) parser.add_argument( 'network_segment', metavar='', help=_('Network segment to display (name or ID)'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_segment( parsed_args.network_segment, ignore_missing=False ) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return (display_columns, data) python-openstackclient-3.14.0/openstackclient/network/v2/network_agent.py0000666000175100017510000003115613232364361026772 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # """Network agent action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ from openstackclient.network import sdk_utils LOG = logging.getLogger(__name__) def _format_alive(alive): return ":-)" if alive else "XXX" def _format_admin_state(state): return 'UP' if state else 'DOWN' _formatters = { 'is_alive': _format_alive, 'alive': _format_alive, 'admin_state_up': _format_admin_state, 'is_admin_state_up': _format_admin_state, 'configurations': utils.format_dict, } def _get_network_columns(item): column_map = { 'is_admin_state_up': 'admin_state_up', 'is_alive': 'alive', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) class AddNetworkToAgent(command.Command): _description = _("Add network to an agent") def get_parser(self, prog_name): parser = super(AddNetworkToAgent, self).get_parser(prog_name) parser.add_argument( '--dhcp', action='store_true', help=_('Add network to a DHCP agent')) parser.add_argument( 'agent_id', metavar='', help=_('Agent to which a network is added (ID only)')) parser.add_argument( 'network', metavar='', help=_('Network to be added to an agent (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network agent = client.get_agent(parsed_args.agent_id) network = client.find_network( parsed_args.network, ignore_missing=False) if parsed_args.dhcp: try: client.add_dhcp_agent_to_network(agent, network) except Exception: msg = 'Failed to add {} to {}'.format( network.name, agent.agent_type) exceptions.CommandError(msg) class AddRouterToAgent(command.Command): _description = _("Add router to an agent") def get_parser(self, prog_name): parser = super(AddRouterToAgent, self).get_parser(prog_name) parser.add_argument( '--l3', action='store_true', help=_('Add router to an L3 agent') ) parser.add_argument( 'agent_id', metavar='', help=_("Agent to which a router is added (ID only)") ) parser.add_argument( 'router', metavar='', help=_("Router to be added to an agent (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network agent = client.get_agent(parsed_args.agent_id) router = client.find_router(parsed_args.router, ignore_missing=False) if parsed_args.l3: client.add_router_to_agent(agent, router) class DeleteNetworkAgent(command.Command): _description = _("Delete network agent(s)") def get_parser(self, prog_name): parser = super(DeleteNetworkAgent, self).get_parser(prog_name) parser.add_argument( 'network_agent', metavar="", nargs='+', help=(_("Network agent(s) to delete (ID only)")) ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for agent in parsed_args.network_agent: try: client.delete_agent(agent, ignore_missing=False) except Exception as e: result += 1 LOG.error(_("Failed to delete network agent with " "ID '%(agent)s': %(e)s"), {'agent': agent, 'e': e}) if result > 0: total = len(parsed_args.network_agent) msg = (_("%(result)s of %(total)s network agents failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) # TODO(huanxuan): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class ListNetworkAgent(command.Lister): _description = _("List network agents") def get_parser(self, prog_name): parser = super(ListNetworkAgent, self).get_parser(prog_name) parser.add_argument( '--agent-type', metavar='', choices=["bgp", "dhcp", "open-vswitch", "linux-bridge", "ofa", "l3", "loadbalancer", "metering", "metadata", "macvtap", "nic"], help=_("List only agents with the specified agent type. " "The supported agent types are: bgp, dhcp, open-vswitch, " "linux-bridge, ofa, l3, loadbalancer, metering, " "metadata, macvtap, nic.") ) parser.add_argument( '--host', metavar='', help=_("List only agents running on the specified host") ) agent_type_group = parser.add_mutually_exclusive_group() agent_type_group.add_argument( '--network', metavar='', help=_('List agents hosting a network (name or ID)') ) agent_type_group.add_argument( '--router', metavar='', help=_('List agents hosting this router (name or ID)') ) 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 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' ) key_value = { 'bgp': 'BGP dynamic routing agent', 'dhcp': 'DHCP agent', 'open-vswitch': 'Open vSwitch agent', 'linux-bridge': 'Linux bridge agent', 'ofa': 'OFA driver agent', 'l3': 'L3 agent', 'loadbalancer': 'Loadbalancer agent', 'metering': 'Metering agent', 'metadata': 'Metadata agent', 'macvtap': 'Macvtap agent', 'nic': 'NIC Switch agent' } filters = {} if parsed_args.network is not None: network = client.find_network( parsed_args.network, ignore_missing=False) data = client.network_hosting_dhcp_agents(network) elif parsed_args.router is not None: if parsed_args.long: columns += ('ha_state',) column_headers += ('HA State',) router = client.find_router(parsed_args.router, ignore_missing=False) data = client.routers_hosting_l3_agents(router) else: if parsed_args.agent_type is not None: filters['agent_type'] = key_value[parsed_args.agent_type] if parsed_args.host is not None: filters['host'] = parsed_args.host data = client.agents(**filters) return (column_headers, (utils.get_item_properties( s, columns, formatters=_formatters, ) for s in data)) class RemoveNetworkFromAgent(command.Command): _description = _("Remove network from an agent.") def get_parser(self, prog_name): parser = super(RemoveNetworkFromAgent, self).get_parser(prog_name) parser.add_argument( '--dhcp', action='store_true', help=_('Remove network from DHCP agent')) parser.add_argument( 'agent_id', metavar='', help=_('Agent to which a network is removed (ID only)')) parser.add_argument( 'network', metavar='', help=_('Network to be removed from an agent (name or ID)')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network agent = client.get_agent(parsed_args.agent_id) network = client.find_network( parsed_args.network, ignore_missing=False) if parsed_args.dhcp: try: client.remove_dhcp_agent_from_network(agent, network) except Exception: msg = 'Failed to remove {} to {}'.format( network.name, agent.agent_type) exceptions.CommandError(msg) class RemoveRouterFromAgent(command.Command): _description = _("Remove router from an agent") def get_parser(self, prog_name): parser = super(RemoveRouterFromAgent, self).get_parser(prog_name) parser.add_argument( '--l3', action='store_true', help=_('Remove router from an L3 agent') ) parser.add_argument( 'agent_id', metavar='', help=_("Agent from which router will be removed (ID only)") ) parser.add_argument( 'router', metavar='', help=_("Router to be removed from an agent (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network agent = client.get_agent(parsed_args.agent_id) router = client.find_router(parsed_args.router, ignore_missing=False) if parsed_args.l3: client.remove_router_from_agent(agent, router) # TODO(huanxuan): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class SetNetworkAgent(command.Command): _description = _("Set network agent properties") def get_parser(self, prog_name): parser = super(SetNetworkAgent, self).get_parser(prog_name) parser.add_argument( 'network_agent', metavar="", help=(_("Network agent to modify (ID only)")) ) parser.add_argument( '--description', metavar='', help=_("Set network agent description") ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', help=_("Enable network agent") ) admin_group.add_argument( '--disable', action='store_true', help=_("Disable network agent") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.get_agent(parsed_args.network_agent) attrs = {} if parsed_args.description is not None: attrs['description'] = str(parsed_args.description) if parsed_args.enable: attrs['is_admin_state_up'] = True attrs['admin_state_up'] = True if parsed_args.disable: attrs['is_admin_state_up'] = False attrs['admin_state_up'] = False client.update_agent(obj, **attrs) class ShowNetworkAgent(command.ShowOne): _description = _("Display network agent details") def get_parser(self, prog_name): parser = super(ShowNetworkAgent, self).get_parser(prog_name) parser.add_argument( 'network_agent', metavar="", help=(_("Network agent to display (ID only)")) ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.get_agent(parsed_args.network_agent) display_columns, columns = _get_network_columns(obj) data = utils.get_item_properties(obj, columns, formatters=_formatters,) return display_columns, data python-openstackclient-3.14.0/openstackclient/network/v2/network_qos_policy.py0000666000175100017510000002326313232364361030055 0ustar zuulzuul00000000000000# 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. import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils LOG = logging.getLogger(__name__) def _get_columns(item): column_map = { 'is_shared': 'shared', 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) def _get_attrs(client_manager, parsed_args): attrs = {} if 'name' in parsed_args and parsed_args.name is not None: attrs['name'] = str(parsed_args.name) if 'description' in parsed_args and parsed_args.description is not None: attrs['description'] = parsed_args.description if parsed_args.share: attrs['shared'] = True if parsed_args.no_share: attrs['shared'] = False # NOTE(ralonsoh): 'default' and 'no_default' parameters are defined only in # create and set commands context only. if 'default' in parsed_args and parsed_args.default: attrs['is_default'] = True if 'no_default' in parsed_args and parsed_args.no_default: attrs['is_default'] = False # NOTE(ralonsoh): 'project' parameter is defined only in create and list # commands context only. if 'project' in parsed_args and parsed_args.project is not None: identity_client = client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id return attrs # TODO(abhiraut): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateNetworkQosPolicy(command.ShowOne): _description = _("Create a QoS policy") def get_parser(self, prog_name): parser = super(CreateNetworkQosPolicy, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_("Name of QoS policy to create") ) parser.add_argument( '--description', metavar='', help=_("Description of the QoS policy") ) share_group = parser.add_mutually_exclusive_group() share_group.add_argument( '--share', action='store_true', default=None, help=_("Make the QoS policy accessible by other projects") ) share_group.add_argument( '--no-share', action='store_true', help=_("Make the QoS policy not accessible by other projects " "(default)") ) parser.add_argument( '--project', metavar='', help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) default_group = parser.add_mutually_exclusive_group() default_group.add_argument( '--default', action='store_true', help=_("Set this as a default network QoS policy"), ) default_group.add_argument( '--no-default', action='store_true', help=_("Set this as a non-default network QoS policy"), ) 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_qos_policy(**attrs) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters={}) return (display_columns, data) class DeleteNetworkQosPolicy(command.Command): _description = _("Delete Qos Policy(s)") def get_parser(self, prog_name): parser = super(DeleteNetworkQosPolicy, self).get_parser(prog_name) parser.add_argument( 'policy', metavar="", nargs="+", help=_("QoS policy(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for policy in parsed_args.policy: try: obj = client.find_qos_policy(policy, ignore_missing=False) client.delete_qos_policy(obj) except Exception as e: result += 1 LOG.error(_("Failed to delete QoS policy " "name or ID '%(qos_policy)s': %(e)s"), {'qos_policy': policy, 'e': e}) if result > 0: total = len(parsed_args.policy) msg = (_("%(result)s of %(total)s QoS policies failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) # TODO(abhiraut): Use only the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class ListNetworkQosPolicy(command.Lister): _description = _("List QoS policies") def get_parser(self, prog_name): parser = super(ListNetworkQosPolicy, self).get_parser(prog_name) parser.add_argument( '--project', metavar='', help=_("List qos policies according to their project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) shared_group = parser.add_mutually_exclusive_group() shared_group.add_argument( '--share', action='store_true', help=_("List qos policies shared between projects") ) shared_group.add_argument( '--no-share', action='store_true', help=_("List qos policies not shared between projects") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network columns = ( 'id', 'name', 'is_shared', 'is_default', 'project_id', ) column_headers = ( 'ID', 'Name', 'Shared', 'Default', 'Project', ) attrs = _get_attrs(self.app.client_manager, parsed_args) data = client.qos_policies(**attrs) return (column_headers, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) # TODO(abhiraut): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class SetNetworkQosPolicy(command.Command): _description = _("Set QoS policy properties") def get_parser(self, prog_name): parser = super(SetNetworkQosPolicy, self).get_parser(prog_name) parser.add_argument( 'policy', metavar="", help=_("QoS policy to modify (name or ID)") ) parser.add_argument( '--name', metavar="", help=_('Set QoS policy name') ) parser.add_argument( '--description', metavar='', help=_("Description of the QoS policy") ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--share', action='store_true', help=_('Make the QoS policy accessible by other projects'), ) enable_group.add_argument( '--no-share', action='store_true', help=_('Make the QoS policy not accessible by other projects'), ) default_group = parser.add_mutually_exclusive_group() default_group.add_argument( '--default', action='store_true', help=_("Set this as a default network QoS policy"), ) default_group.add_argument( '--no-default', action='store_true', help=_("Set this as a non-default network QoS policy"), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_qos_policy( parsed_args.policy, ignore_missing=False) attrs = _get_attrs(self.app.client_manager, parsed_args) client.update_qos_policy(obj, **attrs) class ShowNetworkQosPolicy(command.ShowOne): _description = _("Display QoS policy details") def get_parser(self, prog_name): parser = super(ShowNetworkQosPolicy, self).get_parser(prog_name) parser.add_argument( 'policy', metavar="", help=_("QoS policy to display (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_qos_policy(parsed_args.policy, ignore_missing=False) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return (display_columns, data) python-openstackclient-3.14.0/openstackclient/network/v2/floating_ip_pool.py0000666000175100017510000000445413232364361027450 0ustar zuulzuul00000000000000# 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. # """Floating IP Pool action implementations""" import logging from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ from openstackclient.network import common class ListFloatingIPPool(common.NetworkAndComputeLister): _description = _("List pools of floating IP addresses") def take_action_network(self, client, parsed_args): msg = _("Floating ip pool operations are only available for " "Compute v2 network.") raise exceptions.CommandError(msg) def take_action_compute(self, client, parsed_args): columns = ( 'Name', ) data = client.api.floating_ip_pool_list() return (columns, (utils.get_dict_properties( s, columns, ) for s in data)) class ListIPFloatingPool(ListFloatingIPPool): _description = _("List pools of floating IP addresses") # TODO(tangchen): Remove this class and ``ip floating pool list`` command # two cycles after Mitaka. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action_network(self, client, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "floating ip pool list" instead.')) return super(ListIPFloatingPool, self).take_action_network( client, parsed_args) def take_action_compute(self, client, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "floating ip pool list" instead.')) return super(ListIPFloatingPool, self).take_action_compute( client, parsed_args) python-openstackclient-3.14.0/openstackclient/network/v2/port.py0000666000175100017510000010502113232364361025100 0ustar zuulzuul00000000000000# 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. # """Port action implementations""" import argparse import copy import json 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 openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils from openstackclient.network.v2 import _tag LOG = logging.getLogger(__name__) def _format_admin_state(state): return 'UP' if state else 'DOWN' _formatters = { 'admin_state_up': _format_admin_state, 'is_admin_state_up': _format_admin_state, 'allowed_address_pairs': utils.format_list_of_dicts, 'binding_profile': utils.format_dict, 'binding_vif_details': utils.format_dict, 'binding:profile': utils.format_dict, 'binding:vif_details': utils.format_dict, 'dns_assignment': utils.format_list_of_dicts, 'extra_dhcp_opts': utils.format_list_of_dicts, 'fixed_ips': utils.format_list_of_dicts, 'security_group_ids': utils.format_list, 'tags': utils.format_list, } def _get_columns(item): column_map = { 'binding:host_id': 'binding_host_id', 'binding:profile': 'binding_profile', 'binding:vif_details': 'binding_vif_details', 'binding:vif_type': 'binding_vif_type', 'binding:vnic_type': 'binding_vnic_type', 'is_admin_state_up': 'admin_state_up', 'is_port_security_enabled': 'port_security_enabled', 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) class JSONKeyValueAction(argparse.Action): """A custom action to parse arguments as JSON or key=value pairs Ensures that ``dest`` is a dict """ def __call__(self, parser, namespace, values, option_string=None): # Make sure we have an empty dict rather than None if getattr(namespace, self.dest, None) is None: setattr(namespace, self.dest, {}) # Try to load JSON first before falling back to =. current_dest = getattr(namespace, self.dest) try: current_dest.update(json.loads(values)) except ValueError as e: if '=' in values: current_dest.update([values.split('=', 1)]) else: msg = _("Expected '=' or JSON data for option " "%(option)s, but encountered JSON parsing error: " "%(error)s") % {"option": option_string, "error": e} raise argparse.ArgumentTypeError(msg) def _get_attrs(client_manager, parsed_args): attrs = {} # Handle deprecated options # NOTE(dtroyer): --device-id and --host-id were deprecated in Mar 2016. # Do not remove before 3.x release or Mar 2017. if parsed_args.device_id: attrs['device_id'] = parsed_args.device_id LOG.warning(_( 'The --device-id option is deprecated, ' 'please use --device instead.' )) if parsed_args.host_id: attrs['binding:host_id'] = parsed_args.host_id LOG.warning(_( 'The --host-id option is deprecated, ' 'please use --host instead.' )) if parsed_args.description is not None: attrs['description'] = parsed_args.description if parsed_args.device: attrs['device_id'] = parsed_args.device if parsed_args.device_owner is not None: attrs['device_owner'] = parsed_args.device_owner if parsed_args.enable: attrs['admin_state_up'] = True if parsed_args.disable: attrs['admin_state_up'] = False if parsed_args.vnic_type is not None: attrs['binding:vnic_type'] = parsed_args.vnic_type if parsed_args.host: attrs['binding:host_id'] = parsed_args.host if parsed_args.mac_address is not None: attrs['mac_address'] = parsed_args.mac_address if parsed_args.dns_name is not None: attrs['dns_name'] = parsed_args.dns_name # It is possible that name is not updated during 'port set' if parsed_args.name is not None: attrs['name'] = str(parsed_args.name) # The remaining options do not support 'port set' command, so they require # additional check if 'network' in parsed_args and parsed_args.network is not None: attrs['network_id'] = parsed_args.network if 'project' in parsed_args and parsed_args.project is not None: # TODO(singhj): since 'project' logic is common among # router, network, port etc., maybe move it to a common file. identity_client = client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id attrs['tenant_id'] = project_id if parsed_args.disable_port_security: attrs['port_security_enabled'] = False if parsed_args.enable_port_security: attrs['port_security_enabled'] = True if 'no_qos_policy' in parsed_args and parsed_args.no_qos_policy: attrs['qos_policy_id'] = None if parsed_args.qos_policy: attrs['qos_policy_id'] = client_manager.network.find_qos_policy( parsed_args.qos_policy, ignore_missing=False).id return attrs def _prepare_fixed_ips(client_manager, parsed_args): """Fix and properly format fixed_ip option. Appropriately convert any subnet names to their respective ids. Convert fixed_ips in parsed args to be in valid dictionary format: {'subnet': 'foo'}. """ client = client_manager.network ips = [] if parsed_args.fixed_ip: for ip_spec in parsed_args.fixed_ip: if 'subnet' in ip_spec: subnet_name_id = ip_spec['subnet'] if subnet_name_id: _subnet = client.find_subnet(subnet_name_id, ignore_missing=False) ip_spec['subnet_id'] = _subnet.id del ip_spec['subnet'] if 'ip-address' in ip_spec: ip_spec['ip_address'] = ip_spec['ip-address'] del ip_spec['ip-address'] ips.append(ip_spec) if ips: parsed_args.fixed_ip = ips def _prepare_filter_fixed_ips(client_manager, parsed_args): """Fix and properly format fixed_ip option for filtering. Appropriately convert any subnet names to their respective ids. Convert fixed_ips in parsed args to be in valid list format for filter: ['subnet_id=foo']. """ client = client_manager.network ips = [] for ip_spec in parsed_args.fixed_ip: if 'subnet' in ip_spec: subnet_name_id = ip_spec['subnet'] if subnet_name_id: _subnet = client.find_subnet(subnet_name_id, ignore_missing=False) ips.append('subnet_id=%s' % _subnet.id) if 'ip-address' in ip_spec: ips.append('ip_address=%s' % ip_spec['ip-address']) return ips def _add_updatable_args(parser): parser.add_argument( '--description', metavar='', help=_("Description of this port") ) # NOTE(dtroyer): --device-id is deprecated in Mar 2016. Do not # remove before 3.x release or Mar 2017. device_group = parser.add_mutually_exclusive_group() device_group.add_argument( '--device', metavar='', help=_("Port device ID") ) device_group.add_argument( '--device-id', metavar='', help=argparse.SUPPRESS, ) parser.add_argument( '--mac-address', metavar='', help=_("MAC address of this port (admin only)") ) parser.add_argument( '--device-owner', metavar='', help=_("Device owner of this port. This is the entity that uses " "the port (for example, network:dhcp).") ) parser.add_argument( '--vnic-type', metavar='', choices=['direct', 'direct-physical', 'macvtap', 'normal', 'baremetal', 'virtio-forwarder'], help=_("VNIC type for this port (direct | direct-physical | " "macvtap | normal | baremetal | virtio-forwarder, " " default: normal)") ) # NOTE(dtroyer): --host-id is deprecated in Mar 2016. Do not # remove before 3.x release or Mar 2017. host_group = parser.add_mutually_exclusive_group() host_group.add_argument( '--host', metavar='', help=_("Allocate port on host (ID only)") ) host_group.add_argument( '--host-id', metavar='', help=argparse.SUPPRESS, ) parser.add_argument( '--dns-name', metavar='dns-name', help=_("Set DNS name to this port " "(requires DNS integration extension)") ) # TODO(abhiraut): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. def _convert_address_pairs(parsed_args): ops = [] for opt in parsed_args.allowed_address_pairs: addr = {} addr['ip_address'] = opt['ip-address'] if 'mac-address' in opt: addr['mac_address'] = opt['mac-address'] ops.append(addr) return ops class CreatePort(command.ShowOne): _description = _("Create a new port") def get_parser(self, prog_name): parser = super(CreatePort, self).get_parser(prog_name) parser.add_argument( '--network', metavar='', required=True, help=_("Network this port belongs to (name or ID)") ) _add_updatable_args(parser) fixed_ip = parser.add_mutually_exclusive_group() fixed_ip.add_argument( '--fixed-ip', metavar='subnet=,ip-address=', action=parseractions.MultiKeyValueAction, optional_keys=['subnet', 'ip-address'], help=_("Desired IP and/or subnet for this port (name or ID): " "subnet=,ip-address= " "(repeat option to set multiple fixed IP addresses)") ) fixed_ip.add_argument( '--no-fixed-ip', action='store_true', help=_("No IP or subnet for this port.") ) parser.add_argument( '--binding-profile', metavar='', action=JSONKeyValueAction, help=_("Custom data to be passed as binding:profile. Data may " "be passed as = or JSON. " "(repeat option to set multiple binding:profile data)") ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=True, help=_("Enable port (default)") ) admin_group.add_argument( '--disable', action='store_true', help=_("Disable port") ) parser.add_argument( '--project', metavar='', help=_("Owner's project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( 'name', metavar='', help=_("Name of this port") ) # TODO(singhj): Add support for extended options: # dhcp secgroups = parser.add_mutually_exclusive_group() secgroups.add_argument( '--security-group', metavar='', action='append', dest='security_group', help=_("Security group to associate with this port (name or ID) " "(repeat option to set multiple security groups)") ) secgroups.add_argument( '--no-security-group', dest='no_security_group', action='store_true', help=_("Associate no security groups with this port") ) parser.add_argument( '--qos-policy', metavar='', help=_("Attach QoS policy to this port (name or ID)") ) port_security = parser.add_mutually_exclusive_group() port_security.add_argument( '--enable-port-security', action='store_true', help=_("Enable port security for this port (Default)") ) port_security.add_argument( '--disable-port-security', action='store_true', help=_("Disable port security for this port") ) parser.add_argument( '--allowed-address', metavar='ip-address=[,mac-address=]', action=parseractions.MultiKeyValueAction, dest='allowed_address_pairs', required_keys=['ip-address'], optional_keys=['mac-address'], help=_("Add allowed-address pair associated with this port: " "ip-address=[,mac-address=] " "(repeat option to set multiple allowed-address pairs)") ) _tag.add_tag_option_to_parser_for_create(parser, _('port')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network _network = client.find_network(parsed_args.network, ignore_missing=False) parsed_args.network = _network.id _prepare_fixed_ips(self.app.client_manager, parsed_args) attrs = _get_attrs(self.app.client_manager, parsed_args) if parsed_args.binding_profile is not None: attrs['binding:profile'] = parsed_args.binding_profile if parsed_args.fixed_ip: attrs['fixed_ips'] = parsed_args.fixed_ip elif parsed_args.no_fixed_ip: attrs['fixed_ips'] = [] if parsed_args.security_group: attrs['security_group_ids'] = [client.find_security_group( sg, ignore_missing=False).id for sg in parsed_args.security_group] elif parsed_args.no_security_group: attrs['security_group_ids'] = [] if parsed_args.allowed_address_pairs: attrs['allowed_address_pairs'] = ( _convert_address_pairs(parsed_args)) if parsed_args.qos_policy: attrs['qos_policy_id'] = client.find_qos_policy( parsed_args.qos_policy, ignore_missing=False).id obj = client.create_port(**attrs) # tags cannot be set when created, so tags need to be set later. _tag.update_tags_for_set(client, obj, parsed_args) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters=_formatters) return (display_columns, data) class DeletePort(command.Command): _description = _("Delete port(s)") def get_parser(self, prog_name): parser = super(DeletePort, self).get_parser(prog_name) parser.add_argument( 'port', metavar="", nargs="+", help=_("Port(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network result = 0 for port in parsed_args.port: try: obj = client.find_port(port, ignore_missing=False) client.delete_port(obj) except Exception as e: result += 1 LOG.error(_("Failed to delete port with " "name or ID '%(port)s': %(e)s"), {'port': port, 'e': e}) if result > 0: total = len(parsed_args.port) msg = (_("%(result)s of %(total)s ports failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) # TODO(abhiraut): Use only the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class ListPort(command.Lister): _description = _("List ports") def get_parser(self, prog_name): parser = super(ListPort, self).get_parser(prog_name) parser.add_argument( '--device-owner', metavar='', help=_("List only ports with the specified device owner. " "This is the entity that uses the port (for example, " "network:dhcp).") ) parser.add_argument( '--network', metavar='', help=_("List only ports connected to this network (name or ID)")) device_group = parser.add_mutually_exclusive_group() device_group.add_argument( '--router', metavar='', dest='router', help=_("List only ports attached to this router (name or ID)") ) device_group.add_argument( '--server', metavar='', help=_("List only ports attached to this server (name or ID)"), ) device_group.add_argument( '--device-id', metavar='', help=_("List only ports with the specified device ID") ) parser.add_argument( '--mac-address', metavar='', help=_("List only ports with this MAC address") ) parser.add_argument( '--long', action='store_true', default=False, help=_("List additional fields in output") ) parser.add_argument( '--project', metavar='', help=_("List ports according to their project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--fixed-ip', metavar='subnet=,ip-address=', action=parseractions.MultiKeyValueAction, optional_keys=['subnet', 'ip-address'], help=_("Desired IP and/or subnet for filtering ports " "(name or ID): subnet=,ip-address= " "(repeat option to set multiple fixed IP addresses)"), ) _tag.add_tag_filtering_option_to_parser(parser, _('ports')) return parser def take_action(self, parsed_args): network_client = self.app.client_manager.network identity_client = self.app.client_manager.identity columns = ( 'id', 'name', 'mac_address', 'fixed_ips', 'status', ) column_headers = ( 'ID', 'Name', 'MAC Address', 'Fixed IP Addresses', 'Status', ) filters = {} if parsed_args.long: columns += ('security_group_ids', 'device_owner', 'tags') column_headers += ('Security Groups', 'Device Owner', 'Tags') if parsed_args.device_owner is not None: filters['device_owner'] = parsed_args.device_owner if parsed_args.device_id is not None: filters['device_id'] = parsed_args.device_id if parsed_args.router: _router = network_client.find_router(parsed_args.router, ignore_missing=False) filters['device_id'] = _router.id if parsed_args.server: compute_client = self.app.client_manager.compute server = utils.find_resource(compute_client.servers, parsed_args.server) filters['device_id'] = server.id if parsed_args.network: network = network_client.find_network(parsed_args.network, ignore_missing=False) filters['network_id'] = network.id if parsed_args.mac_address: filters['mac_address'] = parsed_args.mac_address if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id filters['tenant_id'] = project_id filters['project_id'] = project_id if parsed_args.fixed_ip: filters['fixed_ips'] = _prepare_filter_fixed_ips( self.app.client_manager, parsed_args) _tag.get_tag_filtering_args(parsed_args, filters) data = network_client.ports(**filters) headers, attrs = utils.calculate_header_and_attrs( column_headers, columns, parsed_args) return (headers, (utils.get_item_properties( s, attrs, formatters=_formatters, ) for s in data)) # TODO(abhiraut): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class SetPort(command.Command): _description = _("Set port properties") def get_parser(self, prog_name): parser = super(SetPort, self).get_parser(prog_name) _add_updatable_args(parser) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help=_("Enable port") ) admin_group.add_argument( '--disable', action='store_true', help=_("Disable port") ) parser.add_argument( '--name', metavar="", help=_("Set port name") ) parser.add_argument( '--fixed-ip', metavar='subnet=,ip-address=', action=parseractions.MultiKeyValueAction, optional_keys=['subnet', 'ip-address'], help=_("Desired IP and/or subnet for this port (name or ID): " "subnet=,ip-address= " "(repeat option to set multiple fixed IP addresses)") ) parser.add_argument( '--no-fixed-ip', action='store_true', help=_("Clear existing information of fixed IP addresses." "Specify both --fixed-ip and --no-fixed-ip " "to overwrite the current fixed IP addresses.") ) parser.add_argument( '--binding-profile', metavar='', action=JSONKeyValueAction, help=_("Custom data to be passed as binding:profile. Data may " "be passed as = or JSON. " "(repeat option to set multiple binding:profile data)") ) parser.add_argument( '--no-binding-profile', action='store_true', help=_("Clear existing information of binding:profile." "Specify both --binding-profile and --no-binding-profile " "to overwrite the current binding:profile information.") ) parser.add_argument( '--qos-policy', metavar='', help=_("Attach QoS policy to this port (name or ID)") ) parser.add_argument( 'port', metavar="", help=_("Port to modify (name or ID)") ) parser.add_argument( '--security-group', metavar='', action='append', dest='security_group', help=_("Security group to associate with this port (name or ID) " "(repeat option to set multiple security groups)") ) parser.add_argument( '--no-security-group', dest='no_security_group', action='store_true', help=_("Clear existing security groups associated with this port") ) port_security = parser.add_mutually_exclusive_group() port_security.add_argument( '--enable-port-security', action='store_true', help=_("Enable port security for this port") ) port_security.add_argument( '--disable-port-security', action='store_true', help=_("Disable port security for this port") ) parser.add_argument( '--allowed-address', metavar='ip-address=[,mac-address=]', action=parseractions.MultiKeyValueAction, dest='allowed_address_pairs', required_keys=['ip-address'], optional_keys=['mac-address'], help=_("Add allowed-address pair associated with this port: " "ip-address=[,mac-address=] " "(repeat option to set multiple allowed-address pairs)") ) parser.add_argument( '--no-allowed-address', dest='no_allowed_address_pair', action='store_true', help=_("Clear existing allowed-address pairs associated" "with this port." "(Specify both --allowed-address and --no-allowed-address" "to overwrite the current allowed-address pairs)") ) parser.add_argument( '--data-plane-status', metavar='', choices=['ACTIVE', 'DOWN'], help=_("Set data plane status of this port (ACTIVE | DOWN). " "Unset it to None with the 'port unset' command " "(requires data plane status extension)") ) _tag.add_tag_option_to_parser_for_set(parser, _('port')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network _prepare_fixed_ips(self.app.client_manager, parsed_args) obj = client.find_port(parsed_args.port, ignore_missing=False) attrs = _get_attrs(self.app.client_manager, parsed_args) if parsed_args.no_binding_profile: attrs['binding:profile'] = {} if parsed_args.binding_profile: if 'binding:profile' not in attrs: attrs['binding:profile'] = copy.deepcopy(obj.binding_profile) attrs['binding:profile'].update(parsed_args.binding_profile) if parsed_args.no_fixed_ip: attrs['fixed_ips'] = [] if parsed_args.fixed_ip: if 'fixed_ips' not in attrs: # obj.fixed_ips = [{}] if no fixed IPs are set. # Only append this to attrs['fixed_ips'] if actual fixed # IPs are present to avoid adding an empty dict. attrs['fixed_ips'] = [ip for ip in obj.fixed_ips if ip] attrs['fixed_ips'].extend(parsed_args.fixed_ip) if parsed_args.no_security_group: attrs['security_group_ids'] = [] if parsed_args.security_group: if 'security_group_ids' not in attrs: # NOTE(dtroyer): Get existing security groups, iterate the # list to force a new list object to be # created and make sure the SDK Resource # marks the attribute 'dirty'. attrs['security_group_ids'] = [ id for id in obj.security_group_ids ] attrs['security_group_ids'].extend( client.find_security_group(sg, ignore_missing=False).id for sg in parsed_args.security_group ) if parsed_args.no_allowed_address_pair: attrs['allowed_address_pairs'] = [] if parsed_args.allowed_address_pairs: if 'allowed_address_pairs' not in attrs: attrs['allowed_address_pairs'] = ( [addr for addr in obj.allowed_address_pairs if addr] ) attrs['allowed_address_pairs'].extend( _convert_address_pairs(parsed_args) ) if parsed_args.data_plane_status: attrs['data_plane_status'] = parsed_args.data_plane_status if attrs: client.update_port(obj, **attrs) # tags is a subresource and it needs to be updated separately. _tag.update_tags_for_set(client, obj, parsed_args) class ShowPort(command.ShowOne): _description = _("Display port details") def get_parser(self, prog_name): parser = super(ShowPort, self).get_parser(prog_name) parser.add_argument( 'port', metavar="", help=_("Port to display (name or ID)") ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_port(parsed_args.port, ignore_missing=False) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns, formatters=_formatters) return (display_columns, data) # TODO(abhiraut): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class UnsetPort(command.Command): _description = _("Unset port properties") def get_parser(self, prog_name): parser = super(UnsetPort, self).get_parser(prog_name) parser.add_argument( '--fixed-ip', metavar='subnet=,ip-address=', action=parseractions.MultiKeyValueAction, optional_keys=['subnet', 'ip-address'], help=_("Desired IP and/or subnet which should be " "removed from this port (name or ID): subnet=," "ip-address= (repeat option to unset multiple " "fixed IP addresses)")) parser.add_argument( '--binding-profile', metavar='', action='append', help=_("Desired key which should be removed from binding:profile" "(repeat option to unset multiple binding:profile data)")) parser.add_argument( '--security-group', metavar='', action='append', dest='security_group_ids', help=_("Security group which should be removed this port (name " "or ID) (repeat option to unset multiple security groups)") ) parser.add_argument( 'port', metavar="", help=_("Port to modify (name or ID)") ) parser.add_argument( '--allowed-address', metavar='ip-address=[,mac-address=]', action=parseractions.MultiKeyValueAction, dest='allowed_address_pairs', required_keys=['ip-address'], optional_keys=['mac-address'], help=_("Desired allowed-address pair which should be removed " "from this port: ip-address= " "[,mac-address=] (repeat option to set " "multiple allowed-address pairs)") ) parser.add_argument( '--qos-policy', action='store_true', default=False, help=_("Remove the QoS policy attached to the port") ) parser.add_argument( '--data-plane-status', action='store_true', help=_("Clear existing information of data plane status") ) _tag.add_tag_option_to_parser_for_unset(parser, _('port')) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_port(parsed_args.port, ignore_missing=False) # SDK ignores update() if it receives a modified obj and attrs # To handle the same tmp_obj is created in all take_action of # Unset* classes tmp_fixed_ips = copy.deepcopy(obj.fixed_ips) tmp_binding_profile = copy.deepcopy(obj.binding_profile) tmp_secgroups = copy.deepcopy(obj.security_group_ids) tmp_addr_pairs = copy.deepcopy(obj.allowed_address_pairs) _prepare_fixed_ips(self.app.client_manager, parsed_args) attrs = {} if parsed_args.fixed_ip: try: for ip in parsed_args.fixed_ip: tmp_fixed_ips.remove(ip) except ValueError: msg = _("Port does not contain fixed-ip %s") % ip raise exceptions.CommandError(msg) attrs['fixed_ips'] = tmp_fixed_ips if parsed_args.binding_profile: try: for key in parsed_args.binding_profile: del tmp_binding_profile[key] except KeyError: msg = _("Port does not contain binding-profile %s") % key raise exceptions.CommandError(msg) attrs['binding:profile'] = tmp_binding_profile if parsed_args.security_group_ids: try: for sg in parsed_args.security_group_ids: sg_id = client.find_security_group( sg, ignore_missing=False).id tmp_secgroups.remove(sg_id) except ValueError: msg = _("Port does not contain security group %s") % sg raise exceptions.CommandError(msg) attrs['security_group_ids'] = tmp_secgroups if parsed_args.allowed_address_pairs: try: for addr in _convert_address_pairs(parsed_args): tmp_addr_pairs.remove(addr) except ValueError: msg = _("Port does not contain allowed-address-pair %s") % addr raise exceptions.CommandError(msg) attrs['allowed_address_pairs'] = tmp_addr_pairs if parsed_args.qos_policy: attrs['qos_policy_id'] = None if parsed_args.data_plane_status: attrs['data_plane_status'] = None if attrs: client.update_port(obj, **attrs) # tags is a subresource and it needs to be updated separately. _tag.update_tags_for_unset(client, obj, parsed_args) python-openstackclient-3.14.0/openstackclient/network/v2/network.py0000666000175100017510000006222713232364361025617 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # """Network action implementations""" from osc_lib.command import command from osc_lib import utils from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import common from openstackclient.network import sdk_utils from openstackclient.network.v2 import _tag def _format_admin_state(item): return 'UP' if item else 'DOWN' def _format_router_external(item): return 'External' if item else 'Internal' _formatters = { 'subnets': utils.format_list, 'subnet_ids': utils.format_list, 'admin_state_up': _format_admin_state, 'is_admin_state_up': _format_admin_state, 'router:external': _format_router_external, 'is_router_external': _format_router_external, 'availability_zones': utils.format_list, 'availability_zone_hints': utils.format_list, 'tags': utils.format_list, } def _get_columns_network(item): column_map = { 'subnet_ids': 'subnets', 'is_admin_state_up': 'admin_state_up', 'is_router_external': 'router:external', 'is_port_security_enabled': 'port_security_enabled', 'provider_network_type': 'provider:network_type', 'provider_physical_network': 'provider:physical_network', 'provider_segmentation_id': 'provider:segmentation_id', 'is_shared': 'shared', 'ipv4_address_scope_id': 'ipv4_address_scope', 'ipv6_address_scope_id': 'ipv6_address_scope', 'tenant_id': 'project_id', 'tags': 'tags', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) def _get_columns_compute(item): column_map = { 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) def _get_attrs_network(client_manager, parsed_args): attrs = {} if parsed_args.name is not None: attrs['name'] = str(parsed_args.name) if parsed_args.enable: attrs['admin_state_up'] = True if parsed_args.disable: attrs['admin_state_up'] = False if parsed_args.share: attrs['shared'] = True if parsed_args.no_share: attrs['shared'] = False if parsed_args.enable_port_security: attrs['port_security_enabled'] = True if parsed_args.disable_port_security: attrs['port_security_enabled'] = False # "network set" command doesn't support setting project. if 'project' in parsed_args and parsed_args.project is not None: identity_client = client_manager.identity project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id # TODO(dtroyer): Remove tenant_id when we clean up the SDK refactor attrs['tenant_id'] = project_id attrs['project_id'] = project_id # "network set" command doesn't support setting availability zone hints. if 'availability_zone_hints' in parsed_args and \ parsed_args.availability_zone_hints is not None: attrs['availability_zone_hints'] = parsed_args.availability_zone_hints # set description if parsed_args.description: attrs['description'] = parsed_args.description # update_external_network_options if parsed_args.internal: attrs['router:external'] = False if parsed_args.external: attrs['router:external'] = True if parsed_args.no_default: attrs['is_default'] = False if parsed_args.default: attrs['is_default'] = True # Update Provider network options if parsed_args.provider_network_type: attrs['provider:network_type'] = parsed_args.provider_network_type if parsed_args.physical_network: attrs['provider:physical_network'] = parsed_args.physical_network if parsed_args.segmentation_id: attrs['provider:segmentation_id'] = parsed_args.segmentation_id if parsed_args.qos_policy is not None: network_client = client_manager.network _qos_policy = network_client.find_qos_policy(parsed_args.qos_policy, ignore_missing=False) attrs['qos_policy_id'] = _qos_policy.id if 'no_qos_policy' in parsed_args and parsed_args.no_qos_policy: attrs['qos_policy_id'] = None return attrs def _get_attrs_compute(client_manager, parsed_args): attrs = {} if parsed_args.name is not None: attrs['name'] = str(parsed_args.name) if parsed_args.share: attrs['share_subnet'] = True if parsed_args.no_share: attrs['share_subnet'] = False if parsed_args.subnet is not None: attrs['subnet'] = parsed_args.subnet return attrs def _add_additional_network_options(parser): # Add additional network options parser.add_argument( '--provider-network-type', metavar='', help=_("The physical mechanism by which the virtual network " "is implemented. For example: " "flat, geneve, gre, local, vlan, vxlan.")) parser.add_argument( '--provider-physical-network', metavar='', dest='physical_network', help=_("Name of the physical network over which the virtual " "network is implemented")) parser.add_argument( '--provider-segment', metavar='', dest='segmentation_id', help=_("VLAN ID for VLAN networks or Tunnel ID for " "GENEVE/GRE/VXLAN networks")) # TODO(sindhu): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class CreateNetwork(common.NetworkAndComputeShowOne): _description = _("Create new network") def update_parser_common(self, parser): parser.add_argument( 'name', metavar='', help=_("New network name") ) share_group = parser.add_mutually_exclusive_group() share_group.add_argument( '--share', action='store_true', default=None, help=_("Share the network between projects") ) share_group.add_argument( '--no-share', action='store_true', help=_("Do not share the network between projects") ) return parser def update_parser_network(self, parser): admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=True, help=_("Enable network (default)") ) admin_group.add_argument( '--disable', action='store_true', help=_("Disable network") ) parser.add_argument( '--project', metavar='', help=_("Owner's project (name or ID)") ) parser.add_argument( '--description', metavar='', help=_("Set network description") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--availability-zone-hint', action='append', dest='availability_zone_hints', metavar='', help=_("Availability Zone in which to create this network " "(Network Availability Zone extension required, " "repeat option to set multiple availability zones)") ) port_security_group = parser.add_mutually_exclusive_group() port_security_group.add_argument( '--enable-port-security', action='store_true', help=_("Enable port security by default for ports created on " "this network (default)") ) port_security_group.add_argument( '--disable-port-security', action='store_true', help=_("Disable port security by default for ports created on " "this network") ) external_router_grp = parser.add_mutually_exclusive_group() external_router_grp.add_argument( '--external', action='store_true', help=_("Set this network as an external network " "(external-net extension required)") ) external_router_grp.add_argument( '--internal', action='store_true', help=_("Set this network as an internal network (default)") ) default_router_grp = parser.add_mutually_exclusive_group() default_router_grp.add_argument( '--default', action='store_true', help=_("Specify if this network should be used as " "the default external network") ) default_router_grp.add_argument( '--no-default', action='store_true', help=_("Do not use the network as the default external network " "(default)") ) parser.add_argument( '--qos-policy', metavar='', help=_("QoS policy to attach to this network (name or ID)") ) vlan_transparent_grp = parser.add_mutually_exclusive_group() vlan_transparent_grp.add_argument( '--transparent-vlan', action='store_true', help=_("Make the network VLAN transparent")) vlan_transparent_grp.add_argument( '--no-transparent-vlan', action='store_true', help=_("Do not make the network VLAN transparent")) _add_additional_network_options(parser) _tag.add_tag_option_to_parser_for_create(parser, _('network')) return parser def update_parser_compute(self, parser): parser.add_argument( '--subnet', metavar='', required=True, help=_("IPv4 subnet for fixed IPs (in CIDR notation)") ) return parser def take_action_network(self, client, parsed_args): attrs = _get_attrs_network(self.app.client_manager, parsed_args) if parsed_args.transparent_vlan: attrs['vlan_transparent'] = True if parsed_args.no_transparent_vlan: attrs['vlan_transparent'] = False obj = client.create_network(**attrs) # tags cannot be set when created, so tags need to be set later. _tag.update_tags_for_set(client, obj, parsed_args) display_columns, columns = _get_columns_network(obj) data = utils.get_item_properties(obj, columns, formatters=_formatters) return (display_columns, data) def take_action_compute(self, client, parsed_args): attrs = _get_attrs_compute(self.app.client_manager, parsed_args) obj = client.api.network_create(**attrs) display_columns, columns = _get_columns_compute(obj) data = utils.get_dict_properties(obj, columns) return (display_columns, data) class DeleteNetwork(common.NetworkAndComputeDelete): _description = _("Delete network(s)") # Used by base class to find resources in parsed_args. resource = 'network' r = None def update_parser_common(self, parser): parser.add_argument( 'network', metavar="", nargs="+", help=_("Network(s) to delete (name or ID)") ) return parser def take_action_network(self, client, parsed_args): obj = client.find_network(self.r, ignore_missing=False) client.delete_network(obj) def take_action_compute(self, client, parsed_args): client.api.network_delete(self.r) # TODO(sindhu): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class ListNetwork(common.NetworkAndComputeLister): _description = _("List networks") def update_parser_network(self, parser): router_ext_group = parser.add_mutually_exclusive_group() router_ext_group.add_argument( '--external', action='store_true', help=_("List external networks") ) router_ext_group.add_argument( '--internal', action='store_true', help=_("List internal networks") ) parser.add_argument( '--long', action='store_true', help=_("List additional fields in output") ) parser.add_argument( '--name', metavar='', help=_("List networks according to their name") ) admin_state_group = parser.add_mutually_exclusive_group() admin_state_group.add_argument( '--enable', action='store_true', help=_("List enabled networks") ) admin_state_group.add_argument( '--disable', action='store_true', help=_("List disabled networks") ) parser.add_argument( '--project', metavar='', help=_("List networks according to their project (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) shared_group = parser.add_mutually_exclusive_group() shared_group.add_argument( '--share', action='store_true', help=_("List networks shared between projects") ) shared_group.add_argument( '--no-share', action='store_true', help=_("List networks not shared between projects") ) parser.add_argument( '--status', metavar='', choices=['ACTIVE', 'BUILD', 'DOWN', 'ERROR'], help=_("List networks according to their status " "('ACTIVE', 'BUILD', 'DOWN', 'ERROR')") ) parser.add_argument( '--provider-network-type', metavar='', choices=['flat', 'geneve', 'gre', 'local', 'vlan', 'vxlan'], help=_("List networks according to their physical mechanisms. " "The supported options are: flat, geneve, gre, local, " "vlan, vxlan.") ) parser.add_argument( '--provider-physical-network', metavar='', dest='physical_network', help=_("List networks according to name of the physical network") ) parser.add_argument( '--provider-segment', metavar='', dest='segmentation_id', help=_("List networks according to VLAN ID for VLAN networks " "or Tunnel ID for GENEVE/GRE/VXLAN networks") ) parser.add_argument( '--agent', metavar='', dest='agent_id', help=_('List networks hosted by agent (ID only)') ) _tag.add_tag_filtering_option_to_parser(parser, _('networks')) return parser def take_action_network(self, client, parsed_args): identity_client = self.app.client_manager.identity if parsed_args.long: columns = ( 'id', 'name', 'status', 'project_id', 'is_admin_state_up', 'is_shared', 'subnet_ids', 'provider_network_type', 'is_router_external', 'availability_zones', 'tags', ) column_headers = ( 'ID', 'Name', 'Status', 'Project', 'State', 'Shared', 'Subnets', 'Network Type', 'Router Type', 'Availability Zones', 'Tags', ) elif parsed_args.agent_id: columns = ( 'id', 'name', 'subnet_ids' ) column_headers = ( 'ID', 'Name', 'Subnets', ) client = self.app.client_manager.network dhcp_agent = client.get_agent(parsed_args.agent_id) data = client.dhcp_agent_hosting_networks(dhcp_agent) return (column_headers, (utils.get_item_properties( s, columns, formatters=_formatters, ) for s in data)) else: columns = ( 'id', 'name', 'subnet_ids' ) column_headers = ( 'ID', 'Name', 'Subnets', ) args = {} if parsed_args.external: args['router:external'] = True args['is_router_external'] = True elif parsed_args.internal: args['router:external'] = False args['is_router_external'] = False if parsed_args.name is not None: args['name'] = parsed_args.name if parsed_args.enable: args['admin_state_up'] = True args['is_admin_state_up'] = True elif parsed_args.disable: args['admin_state_up'] = False args['is_admin_state_up'] = False if parsed_args.project: project = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ) args['tenant_id'] = project.id args['project_id'] = project.id if parsed_args.share: args['shared'] = True args['is_shared'] = True elif parsed_args.no_share: args['shared'] = False args['is_shared'] = False if parsed_args.status: args['status'] = parsed_args.status if parsed_args.provider_network_type: args['provider:network_type'] = parsed_args.provider_network_type args['provider_network_type'] = parsed_args.provider_network_type if parsed_args.physical_network: args['provider:physical_network'] = parsed_args.physical_network args['provider_physical_network'] = parsed_args.physical_network if parsed_args.segmentation_id: args['provider:segmentation_id'] = parsed_args.segmentation_id args['provider_segmentation_id'] = parsed_args.segmentation_id _tag.get_tag_filtering_args(parsed_args, args) data = client.networks(**args) return (column_headers, (utils.get_item_properties( s, columns, formatters=_formatters, ) for s in data)) def take_action_compute(self, client, parsed_args): columns = ( 'id', 'label', 'cidr', ) column_headers = ( 'ID', 'Name', 'Subnet', ) data = client.api.network_list() return (column_headers, (utils.get_dict_properties( s, columns, formatters=_formatters, ) for s in data)) # TODO(sindhu): Use the SDK resource mapped attribute names once the # OSC minimum requirements include SDK 1.0. class SetNetwork(command.Command): _description = _("Set network properties") def get_parser(self, prog_name): parser = super(SetNetwork, self).get_parser(prog_name) parser.add_argument( 'network', metavar="", help=_("Network to modify (name or ID)") ) parser.add_argument( '--name', metavar='', help=_("Set network name") ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', action='store_true', default=None, help=_("Enable network") ) admin_group.add_argument( '--disable', action='store_true', help=_("Disable network") ) share_group = parser.add_mutually_exclusive_group() share_group.add_argument( '--share', action='store_true', default=None, help=_("Share the network between projects") ) share_group.add_argument( '--no-share', action='store_true', help=_("Do not share the network between projects") ) parser.add_argument( '--description', metavar=" 0: total = len(parsed_args.meter_rule_id) msg = (_("%(result)s of %(total)s meter rules failed " "to delete.") % {"result": result, "total": total}) raise exceptions.CommandError(msg) class ListMeterRule(command.Lister): _description = _("List meter rules") def take_action(self, parsed_args): client = self.app.client_manager.network columns = ( 'id', 'excluded', 'direction', 'remote_ip_prefix', ) column_headers = ( 'ID', 'Excluded', 'Direction', 'Remote IP Prefix', ) data = client.metering_label_rules() return (column_headers, (utils.get_item_properties( s, columns, ) for s in data)) class ShowMeterRule(command.ShowOne): _description = _("Display meter rules details") def get_parser(self, prog_name): parser = super(ShowMeterRule, self).get_parser(prog_name) parser.add_argument( 'meter_rule_id', metavar='', help=_('Meter rule (ID only)') ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_metering_label_rule(parsed_args.meter_rule_id, ignore_missing=False) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return display_columns, data python-openstackclient-3.14.0/openstackclient/network/v2/network_service_provider.py0000666000175100017510000000241713232364361031244 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # """Network Service Providers Implementation""" from osc_lib.command import command from osc_lib import utils from openstackclient.i18n import _ class ListNetworkServiceProvider(command.Lister): _description = _("List Service Providers") def take_action(self, parsed_args): client = self.app.client_manager.network columns = ( 'service_type', 'name', 'is_default', ) column_headers = ( 'Service Type', 'Name', 'Default', ) data = client.service_providers() return(column_headers, (utils.get_item_properties( s, columns, ) for s in data)) python-openstackclient-3.14.0/openstackclient/network/v2/network_qos_rule.py0000666000175100017510000003112413232364361027520 0ustar zuulzuul00000000000000# 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. import itertools from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ from openstackclient.network import sdk_utils RULE_TYPE_BANDWIDTH_LIMIT = 'bandwidth-limit' RULE_TYPE_DSCP_MARKING = 'dscp-marking' RULE_TYPE_MINIMUM_BANDWIDTH = 'minimum-bandwidth' MANDATORY_PARAMETERS = { RULE_TYPE_MINIMUM_BANDWIDTH: {'min_kbps', 'direction'}, RULE_TYPE_DSCP_MARKING: {'dscp_mark'}, RULE_TYPE_BANDWIDTH_LIMIT: {'max_kbps', 'max_burst_kbps'}} OPTIONAL_PARAMETERS = { RULE_TYPE_MINIMUM_BANDWIDTH: set(), RULE_TYPE_DSCP_MARKING: set(), RULE_TYPE_BANDWIDTH_LIMIT: {'direction'}} DIRECTION_EGRESS = 'egress' DIRECTION_INGRESS = 'ingress' DSCP_VALID_MARKS = [0, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 46, 48, 56] ACTION_CREATE = 'create' ACTION_DELETE = 'delete' ACTION_FIND = 'find' ACTION_SET = 'update' ACTION_SHOW = 'get' def _get_columns(item): column_map = { 'tenant_id': 'project_id', } return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) def _check_type_parameters(attrs, type, is_create): req_params = MANDATORY_PARAMETERS[type] opt_params = OPTIONAL_PARAMETERS[type] type_params = req_params | opt_params notreq_params = set(itertools.chain( *[v for k, v in MANDATORY_PARAMETERS.items() if k != type])) notreq_params -= type_params if is_create and None in map(attrs.get, req_params): msg = (_('"Create" rule command for type "%(rule_type)s" requires ' 'arguments %(args)s') % {'rule_type': type, 'args': ", ".join(sorted(req_params))}) raise exceptions.CommandError(msg) if set(attrs.keys()) & notreq_params: msg = (_('Rule type "%(rule_type)s" only requires arguments %(args)s') % {'rule_type': type, 'args': ", ".join(sorted(type_params))}) raise exceptions.CommandError(msg) def _get_attrs(network_client, parsed_args, is_create=False): attrs = {} qos = network_client.find_qos_policy(parsed_args.qos_policy, ignore_missing=False) attrs['qos_policy_id'] = qos.id if not is_create: attrs['id'] = parsed_args.id rule_type = _find_rule_type(qos, parsed_args.id) if not rule_type: msg = (_('Rule ID %(rule_id)s not found') % {'rule_id': parsed_args.id}) raise exceptions.CommandError(msg) else: if not parsed_args.type: msg = _('"Create" rule command requires argument "type"') raise exceptions.CommandError(msg) rule_type = parsed_args.type if parsed_args.max_kbps is not None: attrs['max_kbps'] = parsed_args.max_kbps if parsed_args.max_burst_kbits is not None: # NOTE(ralonsoh): this parameter must be changed in SDK and then in # Neutron API, from 'max_burst_kbps' to # 'max_burst_kbits' attrs['max_burst_kbps'] = parsed_args.max_burst_kbits if parsed_args.dscp_mark is not None: attrs['dscp_mark'] = parsed_args.dscp_mark if parsed_args.min_kbps is not None: attrs['min_kbps'] = parsed_args.min_kbps if parsed_args.ingress: attrs['direction'] = 'ingress' if parsed_args.egress: attrs['direction'] = 'egress' _check_type_parameters(attrs, rule_type, is_create) return attrs def _get_item_properties(item, fields): """Return a tuple containing the item properties.""" row = [] for field in fields: row.append(item.get(field, '')) return tuple(row) def _rule_action_call(client, action, rule_type): rule_type = rule_type.replace('-', '_') func_name = '%(action)s_qos_%(rule_type)s_rule' % {'action': action, 'rule_type': rule_type} return getattr(client, func_name) def _find_rule_type(qos, rule_id): for rule in (r for r in qos.rules if r['id'] == rule_id): return rule['type'].replace('_', '-') return None def _add_rule_arguments(parser): parser.add_argument( '--max-kbps', dest='max_kbps', metavar='', type=int, help=_('Maximum bandwidth in kbps') ) parser.add_argument( '--max-burst-kbits', dest='max_burst_kbits', metavar='', type=int, help=_('Maximum burst in kilobits, 0 means automatic') ) parser.add_argument( '--dscp-mark', dest='dscp_mark', metavar='', type=int, help=_('DSCP mark: value can be 0, even numbers from 8-56, ' 'excluding 42, 44, 50, 52, and 54') ) parser.add_argument( '--min-kbps', dest='min_kbps', metavar='', type=int, help=_('Minimum guaranteed bandwidth in kbps') ) direction_group = parser.add_mutually_exclusive_group() direction_group.add_argument( '--ingress', action='store_true', help=_("Ingress traffic direction from the project point of view") ) direction_group.add_argument( '--egress', action='store_true', help=_("Egress traffic direction from the project point of view") ) class CreateNetworkQosRule(command.ShowOne): _description = _("Create new Network QoS rule") def get_parser(self, prog_name): parser = super(CreateNetworkQosRule, self).get_parser( prog_name) parser.add_argument( 'qos_policy', metavar='', help=_('QoS policy that contains the rule (name or ID)') ) parser.add_argument( '--type', metavar='', choices=[RULE_TYPE_MINIMUM_BANDWIDTH, RULE_TYPE_DSCP_MARKING, RULE_TYPE_BANDWIDTH_LIMIT], help=(_('QoS rule type (%s)') % ", ".join(MANDATORY_PARAMETERS.keys())) ) _add_rule_arguments(parser) return parser def take_action(self, parsed_args): network_client = self.app.client_manager.network attrs = _get_attrs(network_client, parsed_args, is_create=True) try: obj = _rule_action_call( network_client, ACTION_CREATE, parsed_args.type)( attrs.pop('qos_policy_id'), **attrs) except Exception as e: msg = (_('Failed to create Network QoS rule: %(e)s') % {'e': e}) raise exceptions.CommandError(msg) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return display_columns, data class DeleteNetworkQosRule(command.Command): _description = _("Delete Network QoS rule") def get_parser(self, prog_name): parser = super(DeleteNetworkQosRule, self).get_parser(prog_name) parser.add_argument( 'qos_policy', metavar='', help=_('QoS policy that contains the rule (name or ID)') ) parser.add_argument( 'id', metavar='', help=_('Network QoS rule to delete (ID)') ) return parser def take_action(self, parsed_args): network_client = self.app.client_manager.network rule_id = parsed_args.id try: qos = network_client.find_qos_policy(parsed_args.qos_policy, ignore_missing=False) rule_type = _find_rule_type(qos, rule_id) if not rule_type: raise Exception('Rule %s not found' % rule_id) _rule_action_call(network_client, ACTION_DELETE, rule_type)( rule_id, qos.id) except Exception as e: msg = (_('Failed to delete Network QoS rule ID "%(rule)s": %(e)s') % {'rule': rule_id, 'e': e}) raise exceptions.CommandError(msg) class ListNetworkQosRule(command.Lister): _description = _("List Network QoS rules") def get_parser(self, prog_name): parser = super(ListNetworkQosRule, self).get_parser(prog_name) parser.add_argument( 'qos_policy', metavar='', help=_('QoS policy that contains the rule (name or ID)') ) return parser def take_action(self, parsed_args): client = self.app.client_manager.network columns = ( 'id', 'qos_policy_id', 'type', 'max_kbps', 'max_burst_kbps', 'min_kbps', 'dscp_mark', 'direction', ) column_headers = ( 'ID', 'QoS Policy ID', 'Type', 'Max Kbps', 'Max Burst Kbits', 'Min Kbps', 'DSCP mark', 'Direction', ) qos = client.find_qos_policy(parsed_args.qos_policy, ignore_missing=False) data = qos.rules return (column_headers, (_get_item_properties(s, columns) for s in data)) class SetNetworkQosRule(command.Command): _description = _("Set Network QoS rule properties") def get_parser(self, prog_name): parser = super(SetNetworkQosRule, self).get_parser(prog_name) parser.add_argument( 'qos_policy', metavar='', help=_('QoS policy that contains the rule (name or ID)') ) parser.add_argument( 'id', metavar='', help=_('Network QoS rule to delete (ID)') ) _add_rule_arguments(parser) return parser def take_action(self, parsed_args): network_client = self.app.client_manager.network try: qos = network_client.find_qos_policy(parsed_args.qos_policy, ignore_missing=False) rule_type = _find_rule_type(qos, parsed_args.id) if not rule_type: raise Exception('Rule not found') attrs = _get_attrs(network_client, parsed_args) qos_id = attrs.pop('qos_policy_id') qos_rule = _rule_action_call(network_client, ACTION_FIND, rule_type)(attrs.pop('id'), qos_id) _rule_action_call(network_client, ACTION_SET, rule_type)( qos_rule, qos_id, **attrs) except Exception as e: msg = (_('Failed to set Network QoS rule ID "%(rule)s": %(e)s') % {'rule': parsed_args.id, 'e': e}) raise exceptions.CommandError(msg) class ShowNetworkQosRule(command.ShowOne): _description = _("Display Network QoS rule details") def get_parser(self, prog_name): parser = super(ShowNetworkQosRule, self).get_parser(prog_name) parser.add_argument( 'qos_policy', metavar='', help=_('QoS policy that contains the rule (name or ID)') ) parser.add_argument( 'id', metavar='', help=_('Network QoS rule to delete (ID)') ) return parser def take_action(self, parsed_args): network_client = self.app.client_manager.network rule_id = parsed_args.id try: qos = network_client.find_qos_policy(parsed_args.qos_policy, ignore_missing=False) rule_type = _find_rule_type(qos, rule_id) if not rule_type: raise Exception('Rule not found') obj = _rule_action_call(network_client, ACTION_SHOW, rule_type)( rule_id, qos.id) except Exception as e: msg = (_('Failed to set Network QoS rule ID "%(rule)s": %(e)s') % {'rule': rule_id, 'e': e}) raise exceptions.CommandError(msg) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) return display_columns, data python-openstackclient-3.14.0/openstackclient/network/v2/__init__.py0000666000175100017510000000000013232364361025642 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/network/__init__.py0000666000175100017510000000000013232364361025313 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/image/0000775000175100017510000000000013232364654022610 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/image/v1/0000775000175100017510000000000013232364654023136 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/image/v1/image.py0000666000175100017510000006251613232364361024601 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Image V1 Action Implementations""" import argparse import io import logging import os import sys if os.name == "nt": import msvcrt else: msvcrt = None from glanceclient.common import utils as gc_utils from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import utils import six from openstackclient.api import utils as api_utils from openstackclient.i18n import _ CONTAINER_CHOICES = ["ami", "ari", "aki", "bare", "docker", "ova", "ovf"] DEFAULT_CONTAINER_FORMAT = 'bare' DEFAULT_DISK_FORMAT = 'raw' DISK_CHOICES = ["ami", "ari", "aki", "vhd", "vmdk", "raw", "qcow2", "vhdx", "vdi", "iso", "ploop"] LOG = logging.getLogger(__name__) def _format_visibility(data): """Return a formatted visibility string :param data: The server's visibility (is_public) status value: True, False :rtype: A string formatted to public/private """ if data: return 'public' else: return 'private' class CreateImage(command.ShowOne): _description = _("Create/upload an image") def get_parser(self, prog_name): parser = super(CreateImage, self).get_parser(prog_name) parser.add_argument( "name", metavar="", help=_("New image name"), ) parser.add_argument( "--id", metavar="", help=_("Image ID to reserve"), ) parser.add_argument( "--store", metavar="", help=_("Upload image to this store"), ) parser.add_argument( "--container-format", default=DEFAULT_CONTAINER_FORMAT, metavar="", choices=CONTAINER_CHOICES, help=(_("Image container format. " "The supported options are: %(option_list)s. " "The default format is: %(default_opt)s") % {'option_list': ', '.join(CONTAINER_CHOICES), 'default_opt': DEFAULT_CONTAINER_FORMAT}) ) parser.add_argument( "--disk-format", default=DEFAULT_DISK_FORMAT, metavar="", choices=DISK_CHOICES, help=_("Image disk format. The supported options are: %s. " "The default format is: raw") % ', '.join(DISK_CHOICES) ) parser.add_argument( "--size", metavar="", help=_("Image size, in bytes (only used with --location and" " --copy-from)"), ) parser.add_argument( "--min-disk", metavar="", type=int, help=_("Minimum disk size needed to boot image, in gigabytes"), ) parser.add_argument( "--min-ram", metavar="", type=int, help=_("Minimum RAM size needed to boot image, in megabytes"), ) parser.add_argument( "--location", metavar="", help=_("Download image from an existing URL"), ) parser.add_argument( "--copy-from", metavar="", help=_("Copy image from the data store (similar to --location)"), ) source_group = parser.add_mutually_exclusive_group() source_group.add_argument( "--file", metavar="", help=_("Upload image from local file"), ) source_group.add_argument( "--volume", metavar="", help=_("Create image from a volume"), ) parser.add_argument( "--force", dest='force', action='store_true', default=False, help=_("Force image creation if volume is in use " "(only meaningful with --volume)"), ) parser.add_argument( "--checksum", metavar="", help=_("Image hash used for verification"), ) protected_group = parser.add_mutually_exclusive_group() protected_group.add_argument( "--protected", action="store_true", help=_("Prevent image from being deleted"), ) protected_group.add_argument( "--unprotected", action="store_true", help=_("Allow image to be deleted (default)"), ) public_group = parser.add_mutually_exclusive_group() public_group.add_argument( "--public", action="store_true", help=_("Image is accessible to the public"), ) public_group.add_argument( "--private", action="store_true", help=_("Image is inaccessible to the public (default)"), ) parser.add_argument( "--property", dest="properties", metavar="", action=parseractions.KeyValueAction, help=_("Set a property on this image " "(repeat option to set multiple properties)"), ) # NOTE(dtroyer): --owner is deprecated in Jan 2016 in an early # 2.x release. Do not remove before Jan 2017 # and a 3.x release. project_group = parser.add_mutually_exclusive_group() project_group.add_argument( "--project", metavar="", help=_("Set an alternate project on this image (name or ID)"), ) project_group.add_argument( "--owner", metavar="", help=argparse.SUPPRESS, ) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image if getattr(parsed_args, 'owner', None) is not None: LOG.warning(_('The --owner option is deprecated, ' 'please use --project instead.')) # Build an attribute dict from the parsed args, only include # attributes that were actually set on the command line kwargs = {} copy_attrs = ('name', 'id', 'store', 'container_format', 'disk_format', 'owner', 'size', 'min_disk', 'min_ram', 'location', 'copy_from', 'volume', 'force', 'checksum', 'properties') for attr in copy_attrs: if attr in parsed_args: val = getattr(parsed_args, attr, None) if val: # Only include a value in kwargs for attributes that are # actually present on the command line kwargs[attr] = val # Special case project option back to API attribute name 'owner' val = getattr(parsed_args, 'project', None) if val: kwargs['owner'] = val # Handle exclusive booleans with care # Avoid including attributes in kwargs if an option is not # present on the command line. These exclusive booleans are not # a single value for the pair of options because the default must be # to do nothing when no options are present as opposed to always # setting a default. if parsed_args.protected: kwargs['protected'] = True if parsed_args.unprotected: kwargs['protected'] = False if parsed_args.public: kwargs['is_public'] = True if parsed_args.private: kwargs['is_public'] = False info = {} if not parsed_args.location and not parsed_args.copy_from: if parsed_args.volume: volume_client = self.app.client_manager.volume source_volume = utils.find_resource( volume_client.volumes, parsed_args.volume, ) response, body = volume_client.volumes.upload_to_image( source_volume.id, parsed_args.force, parsed_args.name, parsed_args.container_format, parsed_args.disk_format, ) info = body['os-volume_upload_image'] elif parsed_args.file: # Send an open file handle to glanceclient so it will # do a chunked transfer kwargs["data"] = io.open(parsed_args.file, "rb") else: # Read file from stdin if sys.stdin.isatty() is not True: if msvcrt: msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) # Send an open file handle to glanceclient so it will # do a chunked transfer kwargs["data"] = sys.stdin if not parsed_args.volume: # Wrap the call to catch exceptions in order to close files try: image = image_client.images.create(**kwargs) finally: # Clean up open files - make sure data isn't a string if ('data' in kwargs and hasattr(kwargs['data'], 'close') and kwargs['data'] != sys.stdin): kwargs['data'].close() info.update(image._info) info['properties'] = utils.format_dict(info.get('properties', {})) return zip(*sorted(six.iteritems(info))) class DeleteImage(command.Command): _description = _("Delete image(s)") def get_parser(self, prog_name): parser = super(DeleteImage, self).get_parser(prog_name) parser.add_argument( "images", metavar="", nargs="+", help=_("Image(s) to delete (name or ID)"), ) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image for image in parsed_args.images: image_obj = utils.find_resource( image_client.images, image, ) image_client.images.delete(image_obj.id) class ListImage(command.Lister): _description = _("List available images") def get_parser(self, prog_name): parser = super(ListImage, self).get_parser(prog_name) public_group = parser.add_mutually_exclusive_group() public_group.add_argument( "--public", dest="public", action="store_true", default=False, help=_("List only public images"), ) public_group.add_argument( "--private", dest="private", action="store_true", default=False, help=_("List only private images"), ) # Included for silent CLI compatibility with v2 public_group.add_argument( "--shared", dest="shared", action="store_true", default=False, help=argparse.SUPPRESS, ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Filter output based on property'), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) # --page-size has never worked, leave here for silent compatibility # We'll implement limit/marker differently later parser.add_argument( "--page-size", metavar="", help=argparse.SUPPRESS, ) parser.add_argument( '--sort', metavar="[:]", default='name:asc', help=_("Sort output by selected keys and directions(asc or desc) " "(default: name:asc), multiple keys and directions can be " "specified separated by comma"), ) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image kwargs = {} if parsed_args.public: kwargs['public'] = True if parsed_args.private: kwargs['private'] = True # Note: We specifically need to do that below to get the 'status' # column. # # Always set kwargs['detailed'] to True, and then filter the columns # according to whether the --long option is specified or not. kwargs['detailed'] = True if parsed_args.long: columns = ( 'ID', 'Name', 'Disk Format', 'Container Format', 'Size', 'Checksum', 'Status', 'is_public', 'protected', 'owner', 'properties', ) column_headers = ( 'ID', 'Name', 'Disk Format', 'Container Format', 'Size', 'Checksum', 'Status', 'Visibility', 'Protected', 'Project', 'Properties', ) else: columns = ("ID", "Name", "Status") column_headers = columns # List of image data received data = [] # No pages received yet, so start the page marker at None. marker = None while True: page = image_client.api.image_list(marker=marker, **kwargs) if not page: break data.extend(page) # Set the marker to the id of the last item we received marker = page[-1]['id'] if parsed_args.property: # NOTE(dtroyer): coerce to a list to subscript it in py3 attr, value = list(parsed_args.property.items())[0] api_utils.simple_filter( data, attr=attr, value=value, property_field='properties', ) data = utils.sort_items(data, parsed_args.sort) return ( column_headers, (utils.get_dict_properties( s, columns, formatters={ 'is_public': _format_visibility, 'properties': utils.format_dict, }, ) for s in data) ) class SaveImage(command.Command): _description = _("Save an image locally") def get_parser(self, prog_name): parser = super(SaveImage, self).get_parser(prog_name) parser.add_argument( "--file", metavar="", help=_("Downloaded image save filename (default: stdout)"), ) parser.add_argument( "image", metavar="", help=_("Image to save (name or ID)"), ) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image image = utils.find_resource( image_client.images, parsed_args.image, ) data = image_client.images.data(image) gc_utils.save_image(data, parsed_args.file) class SetImage(command.Command): _description = _("Set image properties") def get_parser(self, prog_name): parser = super(SetImage, self).get_parser(prog_name) parser.add_argument( "image", metavar="", help=_("Image to modify (name or ID)"), ) parser.add_argument( "--name", metavar="", help=_("New image name"), ) parser.add_argument( "--min-disk", metavar="", type=int, help=_("Minimum disk size needed to boot image, in gigabytes"), ) parser.add_argument( "--min-ram", metavar="", type=int, help=_("Minimum RAM size needed to boot image, in megabytes"), ) parser.add_argument( "--container-format", metavar="", choices=CONTAINER_CHOICES, help=_("Image container format. The supported options are: %s") % ', '.join(CONTAINER_CHOICES) ) parser.add_argument( "--disk-format", metavar="", choices=DISK_CHOICES, help=_("Image disk format. The supported options are: %s.") % ', '.join(DISK_CHOICES) ) parser.add_argument( "--size", metavar="", type=int, help=_("Size of image data (in bytes)") ) protected_group = parser.add_mutually_exclusive_group() protected_group.add_argument( "--protected", action="store_true", help=_("Prevent image from being deleted"), ) protected_group.add_argument( "--unprotected", action="store_true", help=_("Allow image to be deleted (default)"), ) public_group = parser.add_mutually_exclusive_group() public_group.add_argument( "--public", action="store_true", help=_("Image is accessible to the public"), ) public_group.add_argument( "--private", action="store_true", help=_("Image is inaccessible to the public (default)"), ) parser.add_argument( "--property", dest="properties", metavar="", action=parseractions.KeyValueAction, help=_("Set a property on this image " "(repeat option to set multiple properties)"), ) parser.add_argument( "--store", metavar="", help=_("Upload image to this store"), ) parser.add_argument( "--location", metavar="", help=_("Download image from an existing URL"), ) parser.add_argument( "--copy-from", metavar="", help=_("Copy image from the data store (similar to --location)"), ) parser.add_argument( "--file", metavar="", help=_("Upload image from local file"), ) parser.add_argument( "--volume", metavar="", help=_("Create image from a volume"), ) parser.add_argument( "--force", dest='force', action='store_true', default=False, help=_("Force image change if volume is in use " "(only meaningful with --volume)"), ) parser.add_argument( "--stdin", dest='stdin', action='store_true', default=False, help=_("Read image data from standard input"), ) parser.add_argument( "--checksum", metavar="", help=_("Image hash used for verification"), ) # NOTE(dtroyer): --owner is deprecated in Jan 2016 in an early # 2.x release. Do not remove before Jan 2017 # and a 3.x release. project_group = parser.add_mutually_exclusive_group() project_group.add_argument( "--project", metavar="", help=_("Set an alternate project on this image (name or ID)"), ) project_group.add_argument( "--owner", metavar="", help=argparse.SUPPRESS, ) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image if getattr(parsed_args, 'owner', None) is not None: LOG.warning(_('The --owner option is deprecated, ' 'please use --project instead.')) kwargs = {} copy_attrs = ('name', 'owner', 'min_disk', 'min_ram', 'properties', 'container_format', 'disk_format', 'size', 'store', 'location', 'copy_from', 'volume', 'checksum') for attr in copy_attrs: if attr in parsed_args: val = getattr(parsed_args, attr, None) if val is not None: # Only include a value in kwargs for attributes that are # actually present on the command line kwargs[attr] = val # Special case project option back to API attribute name 'owner' val = getattr(parsed_args, 'project', None) if val: kwargs['owner'] = val # Handle exclusive booleans with care # Avoid including attributes in kwargs if an option is not # present on the command line. These exclusive booleans are not # a single value for the pair of options because the default must be # to do nothing when no options are present as opposed to always # setting a default. if parsed_args.protected: kwargs['protected'] = True if parsed_args.unprotected: kwargs['protected'] = False if parsed_args.public: kwargs['is_public'] = True if parsed_args.private: kwargs['is_public'] = False if parsed_args.force: kwargs['force'] = True # Wrap the call to catch exceptions in order to close files try: image = utils.find_resource( image_client.images, parsed_args.image, ) if not parsed_args.location and not parsed_args.copy_from: if parsed_args.volume: volume_client = self.app.client_manager.volume source_volume = utils.find_resource( volume_client.volumes, parsed_args.volume, ) volume_client.volumes.upload_to_image( source_volume.id, parsed_args.force, parsed_args.image, (parsed_args.container_format if parsed_args.container_format else image.container_format), (parsed_args.disk_format if parsed_args.disk_format else image.disk_format), ) elif parsed_args.file: # Send an open file handle to glanceclient so it will # do a chunked transfer kwargs["data"] = io.open(parsed_args.file, "rb") else: # Read file from stdin if sys.stdin.isatty() is not True: if parsed_args.stdin: if msvcrt: msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) # Send an open file handle to glanceclient so it # will do a chunked transfer kwargs["data"] = sys.stdin else: LOG.warning(_('Use --stdin to enable read image ' 'data from standard input')) if image.properties and parsed_args.properties: image.properties.update(kwargs['properties']) kwargs['properties'] = image.properties image = image_client.images.update(image.id, **kwargs) finally: # Clean up open files - make sure data isn't a string if ('data' in kwargs and hasattr(kwargs['data'], 'close') and kwargs['data'] != sys.stdin): kwargs['data'].close() class ShowImage(command.ShowOne): _description = _("Display image details") def get_parser(self, prog_name): parser = super(ShowImage, self).get_parser(prog_name) parser.add_argument( "--human-readable", default=False, action='store_true', help=_("Print image size in a human-friendly format."), ) parser.add_argument( "image", metavar="", help=_("Image to display (name or ID)"), ) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image image = utils.find_resource( image_client.images, parsed_args.image, ) info = {} info.update(image._info) if parsed_args.human_readable: if 'size' in info: info['size'] = utils.format_size(info['size']) info['properties'] = utils.format_dict(info.get('properties', {})) return zip(*sorted(six.iteritems(info))) python-openstackclient-3.14.0/openstackclient/image/v1/__init__.py0000666000175100017510000000000013232364361025232 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/image/client.py0000666000175100017510000000470413232364361024442 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # import logging from osc_lib import utils from openstackclient.i18n import _ LOG = logging.getLogger(__name__) DEFAULT_API_VERSION = '2' API_VERSION_OPTION = 'os_image_api_version' API_NAME = "image" API_VERSIONS = { "1": "glanceclient.v1.client.Client", "2": "glanceclient.v2.client.Client", } IMAGE_API_TYPE = 'image' IMAGE_API_VERSIONS = { '1': 'openstackclient.api.image_v1.APIv1', '2': 'openstackclient.api.image_v2.APIv2', } def make_client(instance): """Returns an image service client""" image_client = utils.get_client_class( API_NAME, instance._api_version[API_NAME], API_VERSIONS) LOG.debug('Instantiating image client: %s', image_client) endpoint = instance.get_endpoint_for_service_type( API_NAME, region_name=instance.region_name, interface=instance.interface, ) client = image_client( endpoint, token=instance.auth.get_token(instance.session), cacert=instance.cacert, insecure=not instance.verify, ) # Create the low-level API image_api = utils.get_client_class( API_NAME, instance._api_version[API_NAME], IMAGE_API_VERSIONS) LOG.debug('Instantiating image api: %s', image_api) client.api = image_api( session=instance.session, endpoint=instance.get_endpoint_for_service_type( IMAGE_API_TYPE, region_name=instance.region_name, interface=instance.interface, ) ) return client def build_option_parser(parser): """Hook to add global options""" parser.add_argument( '--os-image-api-version', metavar='', default=utils.env('OS_IMAGE_API_VERSION'), help=_('Image API version, default=%s (Env: OS_IMAGE_API_VERSION)') % DEFAULT_API_VERSION, ) return parser python-openstackclient-3.14.0/openstackclient/image/v2/0000775000175100017510000000000013232364654023137 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/image/v2/image.py0000666000175100017510000011144413232364361024575 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Image V2 Action Implementations""" import argparse import logging import sys from glanceclient.common import utils as gc_utils from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.api import utils as api_utils from openstackclient.i18n import _ from openstackclient.identity import common CONTAINER_CHOICES = ["ami", "ari", "aki", "bare", "docker", "ova", "ovf"] DEFAULT_CONTAINER_FORMAT = 'bare' DEFAULT_DISK_FORMAT = 'raw' DISK_CHOICES = ["ami", "ari", "aki", "vhd", "vmdk", "raw", "qcow2", "vhdx", "vdi", "iso", "ploop"] LOG = logging.getLogger(__name__) def _format_image(image): """Format an image to make it more consistent with OSC operations.""" info = {} properties = {} # the only fields we're not including is "links", "tags" and the properties fields_to_show = ['status', 'name', 'container_format', 'created_at', 'size', 'disk_format', 'updated_at', 'visibility', 'min_disk', 'protected', 'id', 'file', 'checksum', 'owner', 'virtual_size', 'min_ram', 'schema'] # split out the usual key and the properties which are top-level for key in six.iterkeys(image): if key in fields_to_show: info[key] = image.get(key) elif key == 'tags': continue # handle this later else: properties[key] = image.get(key) # format the tags if they are there info['tags'] = utils.format_list(image.get('tags')) # add properties back into the dictionary as a top-level key if properties: info['properties'] = utils.format_dict(properties) return info class AddProjectToImage(command.ShowOne): _description = _("Associate project with image") def get_parser(self, prog_name): parser = super(AddProjectToImage, self).get_parser(prog_name) parser.add_argument( "image", metavar="", help=_("Image to share (name or ID)"), ) parser.add_argument( "project", metavar="", help=_("Project to associate with image (name or ID)"), ) common.add_project_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image identity_client = self.app.client_manager.identity project_id = common.find_project(identity_client, parsed_args.project, parsed_args.project_domain).id image_id = utils.find_resource( image_client.images, parsed_args.image).id image_member = image_client.image_members.create( image_id, project_id, ) return zip(*sorted(six.iteritems(image_member))) class CreateImage(command.ShowOne): _description = _("Create/upload an image") deadopts = ('size', 'location', 'copy-from', 'checksum', 'store') def get_parser(self, prog_name): parser = super(CreateImage, self).get_parser(prog_name) # TODO(bunting): There are additional arguments that v1 supported # that v2 either doesn't support or supports weirdly. # --checksum - could be faked clientside perhaps? # --location - maybe location add? # --size - passing image size is actually broken in python-glanceclient # --copy-from - does not exist in v2 # --store - does not exits in v2 parser.add_argument( "name", metavar="", help=_("New image name"), ) parser.add_argument( "--id", metavar="", help=_("Image ID to reserve"), ) parser.add_argument( "--container-format", default=DEFAULT_CONTAINER_FORMAT, choices=CONTAINER_CHOICES, metavar="", help=(_("Image container format. " "The supported options are: %(option_list)s. " "The default format is: %(default_opt)s") % {'option_list': ', '.join(CONTAINER_CHOICES), 'default_opt': DEFAULT_CONTAINER_FORMAT}) ) parser.add_argument( "--disk-format", default=DEFAULT_DISK_FORMAT, choices=DISK_CHOICES, metavar="", help=_("Image disk format. The supported options are: %s. " "The default format is: raw") % ', '.join(DISK_CHOICES) ) parser.add_argument( "--min-disk", metavar="", type=int, help=_("Minimum disk size needed to boot image, in gigabytes"), ) parser.add_argument( "--min-ram", metavar="", type=int, help=_("Minimum RAM size needed to boot image, in megabytes"), ) source_group = parser.add_mutually_exclusive_group() source_group.add_argument( "--file", metavar="", help=_("Upload image from local file"), ) source_group.add_argument( "--volume", metavar="", help=_("Create image from a volume"), ) parser.add_argument( "--force", dest='force', action='store_true', default=False, help=_("Force image creation if volume is in use " "(only meaningful with --volume)"), ) protected_group = parser.add_mutually_exclusive_group() protected_group.add_argument( "--protected", action="store_true", help=_("Prevent image from being deleted"), ) protected_group.add_argument( "--unprotected", action="store_true", help=_("Allow image to be deleted (default)"), ) public_group = parser.add_mutually_exclusive_group() public_group.add_argument( "--public", action="store_true", help=_("Image is accessible to the public"), ) public_group.add_argument( "--private", action="store_true", help=_("Image is inaccessible to the public (default)"), ) public_group.add_argument( "--community", action="store_true", help=_("Image is accessible to the community"), ) public_group.add_argument( "--shared", action="store_true", help=_("Image can be shared"), ) parser.add_argument( "--property", dest="properties", metavar="", action=parseractions.KeyValueAction, help=_("Set a property on this image " "(repeat option to set multiple properties)"), ) parser.add_argument( "--tag", dest="tags", metavar="", action='append', help=_("Set a tag on this image " "(repeat option to set multiple tags)"), ) # NOTE(dtroyer): --owner is deprecated in Jan 2016 in an early # 2.x release. Do not remove before Jan 2017 # and a 3.x release. project_group = parser.add_mutually_exclusive_group() project_group.add_argument( "--project", metavar="", help=_("Set an alternate project on this image (name or ID)"), ) project_group.add_argument( "--owner", metavar="", help=argparse.SUPPRESS, ) common.add_project_domain_option_to_parser(parser) for deadopt in self.deadopts: parser.add_argument( "--%s" % deadopt, metavar="<%s>" % deadopt, dest=deadopt.replace('-', '_'), help=argparse.SUPPRESS, ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity image_client = self.app.client_manager.image for deadopt in self.deadopts: if getattr(parsed_args, deadopt.replace('-', '_'), None): raise exceptions.CommandError( _("ERROR: --%s was given, which is an Image v1 option" " that is no longer supported in Image v2") % deadopt) # Build an attribute dict from the parsed args, only include # attributes that were actually set on the command line kwargs = {} copy_attrs = ('name', 'id', 'container_format', 'disk_format', 'min_disk', 'min_ram', 'tags', 'visibility') for attr in copy_attrs: if attr in parsed_args: val = getattr(parsed_args, attr, None) if val: # Only include a value in kwargs for attributes that # are actually present on the command line kwargs[attr] = val # properties should get flattened into the general kwargs if getattr(parsed_args, 'properties', None): for k, v in six.iteritems(parsed_args.properties): kwargs[k] = str(v) # Handle exclusive booleans with care # Avoid including attributes in kwargs if an option is not # present on the command line. These exclusive booleans are not # a single value for the pair of options because the default must be # to do nothing when no options are present as opposed to always # setting a default. if parsed_args.protected: kwargs['protected'] = True if parsed_args.unprotected: kwargs['protected'] = False if parsed_args.public: kwargs['visibility'] = 'public' if parsed_args.private: kwargs['visibility'] = 'private' if parsed_args.community: kwargs['visibility'] = 'community' if parsed_args.shared: kwargs['visibility'] = 'shared' # Handle deprecated --owner option project_arg = parsed_args.project if parsed_args.owner: project_arg = parsed_args.owner LOG.warning(_('The --owner option is deprecated, ' 'please use --project instead.')) if project_arg: kwargs['owner'] = common.find_project( identity_client, project_arg, parsed_args.project_domain, ).id # open the file first to ensure any failures are handled before the # image is created fp = gc_utils.get_data_file(parsed_args) info = {} if fp is not None and parsed_args.volume: raise exceptions.CommandError(_("Uploading data and using " "container are not allowed at " "the same time")) if fp is None and parsed_args.file: LOG.warning(_("Failed to get an image file.")) return {}, {} if parsed_args.owner: kwargs['owner'] = common.find_project( identity_client, parsed_args.owner, parsed_args.project_domain, ).id # If a volume is specified. if parsed_args.volume: volume_client = self.app.client_manager.volume source_volume = utils.find_resource( volume_client.volumes, parsed_args.volume, ) response, body = volume_client.volumes.upload_to_image( source_volume.id, parsed_args.force, parsed_args.name, parsed_args.container_format, parsed_args.disk_format, ) info = body['os-volume_upload_image'] try: info['volume_type'] = info['volume_type']['name'] except TypeError: info['volume_type'] = None else: image = image_client.images.create(**kwargs) if fp is not None: with fp: try: image_client.images.upload(image.id, fp) except Exception: # If the upload fails for some reason attempt to remove the # dangling queued image made by the create() call above but # only if the user did not specify an id which indicates # the Image already exists and should be left alone. try: if 'id' not in kwargs: image_client.images.delete(image.id) except Exception: pass # we don't care about this one raise # now, throw the upload exception again # update the image after the data has been uploaded image = image_client.images.get(image.id) if not info: info = _format_image(image) return zip(*sorted(six.iteritems(info))) class DeleteImage(command.Command): _description = _("Delete image(s)") def get_parser(self, prog_name): parser = super(DeleteImage, self).get_parser(prog_name) parser.add_argument( "images", metavar="", nargs="+", help=_("Image(s) to delete (name or ID)"), ) return parser def take_action(self, parsed_args): del_result = 0 image_client = self.app.client_manager.image for image in parsed_args.images: try: image_obj = utils.find_resource( image_client.images, image, ) image_client.images.delete(image_obj.id) except Exception as e: del_result += 1 LOG.error(_("Failed to delete image with name or " "ID '%(image)s': %(e)s"), {'image': image, 'e': e}) total = len(parsed_args.images) if (del_result > 0): msg = (_("Failed to delete %(dresult)s of %(total)s images.") % {'dresult': del_result, 'total': total}) raise exceptions.CommandError(msg) class ListImage(command.Lister): _description = _("List available images") def get_parser(self, prog_name): parser = super(ListImage, self).get_parser(prog_name) public_group = parser.add_mutually_exclusive_group() public_group.add_argument( "--public", dest="public", action="store_true", default=False, help=_("List only public images"), ) public_group.add_argument( "--private", dest="private", action="store_true", default=False, help=_("List only private images"), ) public_group.add_argument( "--shared", dest="shared", action="store_true", default=False, help=_("List only shared images"), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Filter output based on property'), ) parser.add_argument( '--name', metavar='', default=None, help=_("Filter images based on name.") ) parser.add_argument( '--status', metavar='', default=None, help=_("Filter images based on status.") ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) # --page-size has never worked, leave here for silent compatibility # We'll implement limit/marker differently later parser.add_argument( "--page-size", metavar="", help=argparse.SUPPRESS, ) parser.add_argument( '--sort', metavar="[:]", default='name:asc', help=_("Sort output by selected keys and directions(asc or desc) " "(default: name:asc), multiple keys and directions can be " "specified separated by comma"), ) parser.add_argument( "--limit", metavar="", type=int, help=_("Maximum number of images to display."), ) parser.add_argument( '--marker', metavar='', default=None, help=_("The last image of the previous page. Display " "list of images after marker. Display all images if not " "specified. (name or ID)"), ) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image kwargs = {} if parsed_args.public: kwargs['public'] = True if parsed_args.private: kwargs['private'] = True if parsed_args.shared: kwargs['shared'] = True if parsed_args.limit: kwargs['limit'] = parsed_args.limit if parsed_args.marker: kwargs['marker'] = utils.find_resource(image_client.images, parsed_args.marker).id if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.status: kwargs['status'] = parsed_args.status if parsed_args.long: columns = ( 'ID', 'Name', 'Disk Format', 'Container Format', 'Size', 'Checksum', 'Status', 'visibility', 'protected', 'owner', 'tags', ) column_headers = ( 'ID', 'Name', 'Disk Format', 'Container Format', 'Size', 'Checksum', 'Status', 'Visibility', 'Protected', 'Project', 'Tags', ) else: columns = ("ID", "Name", "Status") column_headers = columns # List of image data received data = [] if 'marker' in kwargs: data = image_client.api.image_list(**kwargs) else: # No pages received yet, so start the page marker at None. marker = None while True: page = image_client.api.image_list(marker=marker, **kwargs) if not page: break data.extend(page) # Set the marker to the id of the last item we received marker = page[-1]['id'] if parsed_args.property: # NOTE(dtroyer): coerce to a list to subscript it in py3 attr, value = list(parsed_args.property.items())[0] api_utils.simple_filter( data, attr=attr, value=value, property_field='properties', ) data = utils.sort_items(data, parsed_args.sort) return ( column_headers, (utils.get_dict_properties( s, columns, formatters={ 'tags': utils.format_list, }, ) for s in data) ) class RemoveProjectImage(command.Command): _description = _("Disassociate project with image") def get_parser(self, prog_name): parser = super(RemoveProjectImage, self).get_parser(prog_name) parser.add_argument( "image", metavar="", help=_("Image to unshare (name or ID)"), ) parser.add_argument( "project", metavar="", help=_("Project to disassociate with image (name or ID)"), ) common.add_project_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image identity_client = self.app.client_manager.identity project_id = common.find_project(identity_client, parsed_args.project, parsed_args.project_domain).id image_id = utils.find_resource( image_client.images, parsed_args.image).id image_client.image_members.delete(image_id, project_id) class SaveImage(command.Command): _description = _("Save an image locally") def get_parser(self, prog_name): parser = super(SaveImage, self).get_parser(prog_name) parser.add_argument( "--file", metavar="", help=_("Downloaded image save filename (default: stdout)"), ) parser.add_argument( "image", metavar="", help=_("Image to save (name or ID)"), ) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image image = utils.find_resource( image_client.images, parsed_args.image, ) data = image_client.images.data(image.id) if data.wrapped is None: msg = _('Image %s has no data.') % image.id LOG.error(msg) sys.stdout.write(msg + '\n') raise SystemExit gc_utils.save_image(data, parsed_args.file) class SetImage(command.Command): _description = _("Set image properties") deadopts = ('visibility',) def get_parser(self, prog_name): parser = super(SetImage, self).get_parser(prog_name) # TODO(bunting): There are additional arguments that v1 supported # --size - does not exist in v2 # --store - does not exist in v2 # --location - maybe location add? # --copy-from - does not exist in v2 # --file - should be able to upload file # --volume - not possible with v2 as can't change id # --force - see `--volume` # --checksum - maybe could be done client side # --stdin - could be implemented parser.add_argument( "image", metavar="", help=_("Image to modify (name or ID)") ) parser.add_argument( "--name", metavar="", help=_("New image name") ) parser.add_argument( "--min-disk", type=int, metavar="", help=_("Minimum disk size needed to boot image, in gigabytes") ) parser.add_argument( "--min-ram", type=int, metavar="", help=_("Minimum RAM size needed to boot image, in megabytes"), ) parser.add_argument( "--container-format", metavar="", choices=CONTAINER_CHOICES, help=_("Image container format. The supported options are: %s") % ', '.join(CONTAINER_CHOICES) ) parser.add_argument( "--disk-format", metavar="", choices=DISK_CHOICES, help=_("Image disk format. The supported options are: %s") % ', '.join(DISK_CHOICES) ) protected_group = parser.add_mutually_exclusive_group() protected_group.add_argument( "--protected", action="store_true", help=_("Prevent image from being deleted"), ) protected_group.add_argument( "--unprotected", action="store_true", help=_("Allow image to be deleted (default)"), ) public_group = parser.add_mutually_exclusive_group() public_group.add_argument( "--public", action="store_true", help=_("Image is accessible to the public"), ) public_group.add_argument( "--private", action="store_true", help=_("Image is inaccessible to the public (default)"), ) public_group.add_argument( "--community", action="store_true", help=_("Image is accessible to the community"), ) public_group.add_argument( "--shared", action="store_true", help=_("Image can be shared"), ) parser.add_argument( "--property", dest="properties", metavar="", action=parseractions.KeyValueAction, help=_("Set a property on this image " "(repeat option to set multiple properties)"), ) parser.add_argument( "--tag", dest="tags", metavar="", default=None, action='append', help=_("Set a tag on this image " "(repeat option to set multiple tags)"), ) parser.add_argument( "--architecture", metavar="", help=_("Operating system architecture"), ) parser.add_argument( "--instance-id", metavar="", help=_("ID of server instance used to create this image"), ) parser.add_argument( "--instance-uuid", metavar="", dest="instance_id", help=argparse.SUPPRESS, ) parser.add_argument( "--kernel-id", metavar="", help=_("ID of kernel image used to boot this disk image"), ) parser.add_argument( "--os-distro", metavar="", help=_("Operating system distribution name"), ) parser.add_argument( "--os-version", metavar="", help=_("Operating system distribution version"), ) parser.add_argument( "--ramdisk-id", metavar="", help=_("ID of ramdisk image used to boot this disk image"), ) deactivate_group = parser.add_mutually_exclusive_group() deactivate_group.add_argument( "--deactivate", action="store_true", help=_("Deactivate the image"), ) deactivate_group.add_argument( "--activate", action="store_true", help=_("Activate the image"), ) # NOTE(dtroyer): --owner is deprecated in Jan 2016 in an early # 2.x release. Do not remove before Jan 2017 # and a 3.x release. project_group = parser.add_mutually_exclusive_group() project_group.add_argument( "--project", metavar="", help=_("Set an alternate project on this image (name or ID)"), ) project_group.add_argument( "--owner", metavar="", help=argparse.SUPPRESS, ) common.add_project_domain_option_to_parser(parser) for deadopt in self.deadopts: parser.add_argument( "--%s" % deadopt, metavar="<%s>" % deadopt, dest=deadopt.replace('-', '_'), help=argparse.SUPPRESS, ) membership_group = parser.add_mutually_exclusive_group() membership_group.add_argument( "--accept", action="store_true", help=_("Accept the image membership"), ) membership_group.add_argument( "--reject", action="store_true", help=_("Reject the image membership"), ) membership_group.add_argument( "--pending", action="store_true", help=_("Reset the image membership to 'pending'"), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity image_client = self.app.client_manager.image for deadopt in self.deadopts: if getattr(parsed_args, deadopt.replace('-', '_'), None): raise exceptions.CommandError( _("ERROR: --%s was given, which is an Image v1 option" " that is no longer supported in Image v2") % deadopt) kwargs = {} copy_attrs = ('architecture', 'container_format', 'disk_format', 'file', 'instance_id', 'kernel_id', 'locations', 'min_disk', 'min_ram', 'name', 'os_distro', 'os_version', 'prefix', 'progress', 'ramdisk_id', 'tags', 'visibility') for attr in copy_attrs: if attr in parsed_args: val = getattr(parsed_args, attr, None) if val is not None: # Only include a value in kwargs for attributes that are # actually present on the command line kwargs[attr] = val # Properties should get flattened into the general kwargs if getattr(parsed_args, 'properties', None): for k, v in six.iteritems(parsed_args.properties): kwargs[k] = str(v) # Handle exclusive booleans with care # Avoid including attributes in kwargs if an option is not # present on the command line. These exclusive booleans are not # a single value for the pair of options because the default must be # to do nothing when no options are present as opposed to always # setting a default. if parsed_args.protected: kwargs['protected'] = True if parsed_args.unprotected: kwargs['protected'] = False if parsed_args.public: kwargs['visibility'] = 'public' if parsed_args.private: kwargs['visibility'] = 'private' if parsed_args.community: kwargs['visibility'] = 'community' if parsed_args.shared: kwargs['visibility'] = 'shared' # Handle deprecated --owner option project_arg = parsed_args.project if parsed_args.owner: project_arg = parsed_args.owner LOG.warning(_('The --owner option is deprecated, ' 'please use --project instead.')) project_id = None if project_arg: project_id = common.find_project( identity_client, project_arg, parsed_args.project_domain, ).id kwargs['owner'] = project_id image = utils.find_resource( image_client.images, parsed_args.image) activation_status = None if parsed_args.deactivate: image_client.images.deactivate(image.id) activation_status = "deactivated" if parsed_args.activate: image_client.images.reactivate(image.id) activation_status = "activated" membership_group_args = ('accept', 'reject', 'pending') membership_status = [status for status in membership_group_args if getattr(parsed_args, status)] if membership_status: # If a specific project is not passed, assume we want to update # our own membership if not project_id: project_id = self.app.client_manager.auth_ref.project_id # The mutually exclusive group of the arg parser ensure we have at # most one item in the membership_status list. if membership_status[0] != 'pending': membership_status[0] += 'ed' # Glance expects the past form image_client.image_members.update( image.id, project_id, membership_status[0]) if parsed_args.tags: # Tags should be extended, but duplicates removed kwargs['tags'] = list(set(image.tags).union(set(parsed_args.tags))) try: image = image_client.images.update(image.id, **kwargs) except Exception: if activation_status is not None: LOG.info(_("Image %(id)s was %(status)s."), {'id': image.id, 'status': activation_status}) raise class ShowImage(command.ShowOne): _description = _("Display image details") def get_parser(self, prog_name): parser = super(ShowImage, self).get_parser(prog_name) parser.add_argument( "--human-readable", default=False, action='store_true', help=_("Print image size in a human-friendly format."), ) parser.add_argument( "image", metavar="", help=_("Image to display (name or ID)"), ) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image image = utils.find_resource( image_client.images, parsed_args.image, ) if parsed_args.human_readable: image['size'] = utils.format_size(image['size']) info = _format_image(image) return zip(*sorted(six.iteritems(info))) class UnsetImage(command.Command): _description = _("Unset image tags and properties") def get_parser(self, prog_name): parser = super(UnsetImage, self).get_parser(prog_name) parser.add_argument( "image", metavar="", help=_("Image to modify (name or ID)"), ) parser.add_argument( "--tag", dest="tags", metavar="", default=[], action='append', help=_("Unset a tag on this image " "(repeat option to unset multiple tags)"), ) parser.add_argument( "--property", dest="properties", metavar="", default=[], action='append', help=_("Unset a property on this image " "(repeat option to unset multiple properties)"), ) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image image = utils.find_resource( image_client.images, parsed_args.image, ) kwargs = {} tagret = 0 propret = 0 if parsed_args.tags: for k in parsed_args.tags: try: image_client.image_tags.delete(image.id, k) except Exception: LOG.error(_("tag unset failed, '%s' is a " "nonexistent tag "), k) tagret += 1 if parsed_args.properties: for k in parsed_args.properties: if k not in image: LOG.error(_("property unset failed, '%s' is a " "nonexistent property "), k) propret += 1 image_client.images.update( image.id, parsed_args.properties, **kwargs) tagtotal = len(parsed_args.tags) proptotal = len(parsed_args.properties) if (tagret > 0 and propret > 0): msg = (_("Failed to unset %(tagret)s of %(tagtotal)s tags," "Failed to unset %(propret)s of %(proptotal)s properties.") % {'tagret': tagret, 'tagtotal': tagtotal, 'propret': propret, 'proptotal': proptotal}) raise exceptions.CommandError(msg) elif tagret > 0: msg = (_("Failed to unset %(tagret)s of %(tagtotal)s tags.") % {'tagret': tagret, 'tagtotal': tagtotal}) raise exceptions.CommandError(msg) elif propret > 0: msg = (_("Failed to unset %(propret)s of %(proptotal)s" " properties.") % {'propret': propret, 'proptotal': proptotal}) raise exceptions.CommandError(msg) python-openstackclient-3.14.0/openstackclient/image/v2/__init__.py0000666000175100017510000000000013232364361025233 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/image/__init__.py0000666000175100017510000000000013232364361024704 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/locale/0000775000175100017510000000000013232364654022765 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/locale/tr_TR/0000775000175100017510000000000013232364654024017 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/locale/tr_TR/LC_MESSAGES/0000775000175100017510000000000013232364654025604 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/locale/tr_TR/LC_MESSAGES/openstackclient.po0000666000175100017510000067105113232364361031341 0ustar zuulzuul00000000000000# Andreas Jaeger , 2017. #zanata # işbaran akçayır , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: python-openstackclient 3.12.1.dev21\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-08-14 16:23+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-08-15 12:09+0000\n" "Last-Translator: Andreas Jaeger \n" "Language-Team: Turkish (Turkey)\n" "Language: tr-TR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Generator: Zanata 3.9.6\n" "X-POOTLE-MTIME: 1502656444.000000\n" #, python-format msgid "" "\"Create\" rule command for type \"%(rule_type)s\" requires arguments " "%(args)s" msgstr "" "\"%(rule_type)s\" türü için \"create\" kural komutu %(args)s argümanlarını " "gerektirir" msgid "\"Create\" rule command requires argument \"type\"" msgstr "\"Create\" kural komutu için \"type\" argümanı zorunludur" #, python-format msgid "%(errors)s of %(total)s groups failed to delete." msgstr "%(total)s gruptan %(errors)s grup silinirken hata oluştu." #, python-format msgid "%(errors)s of %(total)s projects failed to delete." msgstr "%(total)s projeden %(errors)s tanesinin silme işlemi başarısız." #, python-format msgid "%(errors)s of %(total)s roles failed to delete." msgstr "%(total)s rolden %(errors)s tanesinin silme işlemi başarısız." #, python-format msgid "%(errors)s of %(total)s trusts failed to delete." msgstr "%(total)s güvenden %(errors)s tanesi silinirken hata oluştu." #, python-format msgid "%(errors)s of %(total)s users failed to delete." msgstr "%(total)s kullanıcıdan %(errors)s kullanıcıyı silme işlemi başarısız." #, python-format msgid "%(num)s of %(total)s %(resource)ss failed to delete." msgstr "%(total)s %(resource)s'tan %(num)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s %(resource)ss failed to delete." msgstr "%(total)s'ın %(result)s %(resource)s'ların silinmesi başarısız." #, python-format msgid "%(result)s of %(total)s EC2 keys failed to delete." msgstr "" "%(total)s EC2 anahtarlarından %(result)s anahtarın silme işlemi başarısız." #, python-format msgid "%(result)s of %(total)s QoS policies failed to delete." msgstr "" "%(total)s QoS politikalarından %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s QoS specifications failed to delete." msgstr "%(total)s QoS özelliklerinden %(result)s silme işlemi başarısız." #, python-format msgid "%(result)s of %(total)s RBAC policies failed to delete." msgstr "" "%(total)s RBAC politikasından %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s address scopes failed to delete." msgstr "%(total)s adres kapsamından %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s agents failed to delete." msgstr "%(total)s ajandan %(result)s ajanın silinmesi başarısız." #, python-format msgid "%(result)s of %(total)s aggregates failed to delete." msgstr "%(total)s kümeden %(result)s tanesinin silme işlemi başarısız." #, python-format msgid "%(result)s of %(total)s backups failed to delete." msgstr "%(total)s yedeklerden %(result)s silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s compute services failed to delete." msgstr "" "%(total)s hesaplama servislerinin %(result)s tanesinin silme işlemi " "başarısız." #, python-format msgid "%(result)s of %(total)s consistency group snapshots failed to delete." msgstr "" "%(total)s tutarlılık grubu anlık görüntülerinden %(result)s silinme işlemi " "başarısız." #, python-format msgid "%(result)s of %(total)s consistency groups failed to delete." msgstr "%(total)s tutarlılık gruplarından %(result)s silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s consumers failed to delete." msgstr "%(total)s alıcılardan %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s credential failed to delete." msgstr "%(total)s kimlik bilgisinden %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s domains failed to delete." msgstr "%(total)s alandan %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s endpoints failed to delete." msgstr "%(total)s uç noktalarından %(result)s silinmesi başarısız." #, python-format msgid "%(result)s of %(total)s federation protocols failed to delete." msgstr "" "%(total)s federasyon protokolünden %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s flavor_profiles failed to delete." msgstr "%(total)s flavor_profiles'in %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s flavors failed to delete." msgstr "%(total)s flavor'dan %(result)s flavor'ın silme işlemi başarısız." #, python-format msgid "%(result)s of %(total)s identity providers failed to delete." msgstr "" "%(total)s kimlik sağlayıcıdan %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s keys failed to delete." msgstr "%(total)s anahtarlardan %(result)s anahtarın silme işlemi başarısız." #, python-format msgid "%(result)s of %(total)s mappings failed to delete." msgstr "%(total)s eşleştirmeden %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s meter rules failed to delete." msgstr "" "%(total)s ölçek kurallarından %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s meters failed to delete." msgstr "%(total)s ölçekten %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s network agents failed to delete." msgstr "%(total)s ağ ajanından %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s network segments failed to delete." msgstr "%(total)s ağ dilimlerinin %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s policys failed to delete." msgstr "%(total)s politikadan %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s ports failed to delete." msgstr "" "%(total)s bağlantı noktasından %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s regions failed to delete." msgstr "%(total)s bölgeden %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s routers failed to delete." msgstr "%(total)s yönlendiricilerden %(result)s silme işlemi başarısız." #, python-format msgid "%(result)s of %(total)s server groups failed to delete." msgstr "%(total)s sunucu grubundan %(result)s silinmesi başarısız." #, python-format msgid "%(result)s of %(total)s service providers failed to delete." msgstr "" "%(total)s servis sağlayıcıdan %(result)s tanesinin silme işlemi başarısız." #, python-format msgid "%(result)s of %(total)s services failed to delete." msgstr "%(total)s servisten %(result)s tanesini silme başarısız." #, python-format msgid "%(result)s of %(total)s snapshots failed to delete." msgstr "%(total)s anlık görüntülerden %(result)s silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s subnet pools failed to delete." msgstr "" "%(total)s alt ağ havuzlarından %(result)s sonucunu silme işlemi başarısız." #, python-format msgid "%(result)s of %(total)s subnets failed to delete." msgstr "%(total)s altağlardan %(result)s silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s users not added to group %(group)s." msgstr "" "%(group)s grubuna %(total)s kullanıcıdan %(result)s kullanıcı eklenmedi." #, python-format msgid "%(result)s of %(total)s users not removed from group %(group)s." msgstr "" "%(total)s kullanıcıdan %(result)s tanesi %(group)s grubundan silinmedi." #, python-format msgid "%(result)s of %(total)s volume transfer requests failed to delete" msgstr "" "%(total)s disk bölümü aktarım isteklerinden %(result)s silinirken hata oluştu" #, python-format msgid "%(result)s of %(total)s volume types failed to delete." msgstr "%(total)s disk bölümü türlerinden %(result)s silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s volumes failed to add." msgstr "%(total)s disk bölümlerinden %(result)s eklenirken hata." #, python-format msgid "%(result)s of %(total)s volumes failed to delete." msgstr "%(total)s disk bölümlerinden %(result)s tanesi silinirken hata oluştu." #, python-format msgid "%(result)s of %(total)s volumes failed to remove." msgstr "%(total)s disk bölümünden %(result)s silinirken hata oluştu." #, python-format msgid "%(user)s in group %(group)s\n" msgstr "%(group)s grubundaki %(user)s\n" #, python-format msgid "%(user)s not added to group %(group)s: %(e)s" msgstr "%(user)s %(group)s grubuna eklenmedi: %(e)s" #, python-format msgid "%(user)s not in group %(group)s\n" msgstr "%(group)s grubunda olmayan %(user)s\n" #, python-format msgid "%(user)s not removed from group %(group)s: %(e)s" msgstr "%(group)s'dan %(user)s kaldırılmadı: %(e)s" #, python-format msgid "%s not found" msgstr "%s bulunamadı" msgid "" "'--availability-zone' option will not work if creating consistency group " "from source" msgstr "" "'--availability-zone' seçeneği tutarlılık grubu kaynaktan oluşturulursa " "çalışmaz." msgid "" "'--encryption-provider' should be specified while creating a new encryption " "type" msgstr "" "Yeni bir şifreleme türü oluştururken '--encryption-provider' belirtilmelidir" msgid "" "'--force' option will not work when you create new volume snapshot from an " "existing remote volume snapshot" msgstr "" "Varolan uzak disk bölümünden yeni görüntüsünden yeni disk bölümü anlık " "görüntüsü oluştururken 'force' seçeneği çalışmaz" msgid "'--retype-policy' option will not work without '--type' option" msgstr "'--retype-policy' seçeneği '--type' seçeneği olmadan çalışmaz" msgid "--project is only allowed with --private" msgstr "--project sadece --private ile kullanılabilir" msgid "" "--size is a required option if snapshot or source volume is not specified." msgstr "" "Anlık görüntü veya kaynak disk bölümü belirtilmezse --size gerekli bir " "seçenektir." msgid "A service URL where SAML assertions are being sent (required)" msgstr "SAML bildirimlerinin gönderildiği bir hizmet URL'i (gerekli)" msgid "Accept the image membership" msgstr "İmaj üyeliğini kabul et" msgid "Accept volume transfer request." msgstr "Disk bölümü aktarım isteğini kabul et." msgid "" "Action for the RBAC policy (\"access_as_external\" or \"access_as_shared\")" msgstr "" "RBAC politika için eylem (\"access_as_external\" veya \"access_as_shared\")" msgid "Activate the image" msgstr "İmajı aktifleştir" msgid "" "Add a policy to ('affinity' or 'anti-affinity', default to 'affinity')" msgstr "" "'e bir politika ekle ('affinity' veya 'anti-affinity', varsayılan " "'affinity' için)" msgid "Add a port to a router" msgstr "Yönlendiriciye bir bağlantı noktası ekle" msgid "Add a property to (repeat option to set multiple properties)" msgstr "" "'e bir özellik ekle (birden fazla özellik eklemek için seçeneği " "tekrarla)" msgid "Add a service profile to a network flavor" msgstr "Ağ flavor'ına bir servis profili ekle" msgid "Add a subnet to a router" msgstr "Bir yönlendiriciye bir alt ağ ekle" msgid "" "Add allowed-address pair associated with this port: ip-address=[," "mac-address=] (repeat option to set multiple allowed-address " "pairs)" msgstr "" "Bu bağlantı noktası ile ilişkili izin verilen adres çiftini ekle: ip-" "address=[,mac-address=] (birden fazla izin verilen " "adres çifti ayarlamak için seçeneği tekrarlayın)" msgid "Add fixed IP address to server" msgstr "Sunucuya sabit IP adresi ekle" msgid "Add floating IP address to server" msgstr "Sunucuya kayan IP adresi ekle" msgid "Add host to aggregate" msgstr "Kümeye sunucu ekle" msgid "Add network to a DHCP agent" msgstr "Bir DHCP ajanına ağ ekle" msgid "Add network to an agent" msgstr "Bir ajana ağ ekle" msgid "Add port to server" msgstr "Sunucuya bağlantı noktası ekle" msgid "Add role to project:user" msgstr "Proje:kullanıcıya rol ekle" msgid "Add router to an L3 agent" msgstr "L3 aracısına yönlendirici ekleyin" msgid "Add router to an agent" msgstr "Bir ajana yönlendirici ekle" msgid "Add security group to server" msgstr "Sunucuya güvenlik grubu ekle" msgid "Add user to group" msgstr "Gruba kullanıcı ekle" msgid "Add volume to server" msgstr "Disk bölümünü sunucuya ekle" msgid "Add volume(s) to consistency group" msgstr "Uyum grubuna disk bölümleri ekle" msgid "" "Additional route for this subnet e.g.: destination=10.10.0.0/16," "gateway=192.168.71.254 destination: destination subnet (in CIDR notation) " "gateway: nexthop IP address (repeat option to add multiple routes)" msgstr "" "Bu alt ağ için ek yönlendirici örn: hedef=10.10.0.0/16,geçit=192.168.71.254 " "hedef: hedef alt ağ (CIDR gösteriminde) geçit: bir sonraki durak IP adresi " "(birden fazla yölendirici eklemek için tekrarlanacak seçenek)" msgid "Address scope to display (name or ID)" msgstr "Gösterilecek adres kapsamı (isim veya ID)" msgid "Address scope to modify (name or ID)" msgstr "Değiştirilecek adres kapsamı (ad veya kimlik)" msgid "Address scope(s) to delete (name or ID)" msgstr "Silinecek adres kapsam(lar)ı (isim veya ID)" msgid "Adds a role assignment to a user or group on a domain or project" msgstr "Bir alandaki veya projedeki bir kullanıcıya veya gruba rol atama ekler" msgid "Agent from which router will be removed (ID only)" msgstr "Yönlendiricinin kaldırılacağı ajan (yalnızca ID)" msgid "Agent to which a network is added (ID only)" msgstr "Bir ağ eklenecek ajan (sadece ID)" msgid "Agent to which a network is removed (ID only)" msgstr "Ağın kaldırılacağı ajan (sadece ID)" msgid "Agent to which a router is added (ID only)" msgstr "Yönlendiricinin eklendiği ajan (yalnızca ID)" msgid "Aggregate (name or ID)" msgstr "Küme (isim veya ID)" msgid "Aggregate to display (name or ID)" msgstr "Gösterilecek küme (isim veya ID)" msgid "Aggregate to modify (name or ID)" msgstr "Düzenlenecek küme (isim veya ID)" msgid "Aggregate(s) to delete (name or ID)" msgstr "Silinecek küme(ler) (isim veya ID)" msgid "Allocate port on host (ID only)" msgstr " ana bilgisayarında bağlantı noktası ayır (sadece ID)" msgid "" "Allocation pool IP addresses for this subnet e.g.: start=192.168.199.2," "end=192.168.199.254 (repeat option to add multiple IP addresses)" msgstr "" "Bu alt ağ için ayırma havuzu IP adresleri örn: başlangıç=192.168.199.2," "bitiş=192.168.199.254 (birden fazla IP adresi eklemek için seçeneği tekrarla)" msgid "" "Allocation pool IP addresses to be removed from this subnet e.g.: " "start=192.168.199.2,end=192.168.199.254 (repeat option to unset multiple " "allocation pools)" msgstr "" "Bu altağdan silinecek IP adres tahsis havuzu örn: başlangıç=192.168.199.2," "bitiş=192.168.199.254 (birden fazla tahsis havuzu ayarını kaldırmak için " "seçeneği tekrarla)" msgid "" "Allow to access private flavor (name or ID) (Must be used with --" "private option)" msgstr "" "'nin özel flavor'a erişmesine izin verin (isim veya ID) (--private " "seçeneği ile beraber kullanılmalı)" msgid "" "Allow to access private type (name or ID) (Must be used with --" "private option)" msgstr "" "Özel türe erişimek için 'ye izin ver (isim veya ID) (--private " "seçeneği ile kullanılması zorunludur)" msgid "Allow delete in state other than error or available" msgstr "Hata veya kullanılabilirden başka durumda silinmesine izin ver" msgid "Allow disk over-commit on the destination host" msgstr "Hedef ana bilgisayarda disk aşırı-işlemeye izin ver" msgid "Allow image to be deleted (default)" msgstr "İmajın silinmesine izin ver (varsayılan)" msgid "Allow to back up an in-use volume" msgstr "Kullanımdaki birimi yedeklemeye izin ver" msgid "Allow to delete in-use QoS specification(s)" msgstr "Kullanımdaki QoS özelliklerini silmeye izin ver" msgid "Allow volume to be attached more than once (default to False)" msgstr "Diskin birden fazla eklenmesine izin ver (varsayılan olarak False)" #, python-format msgid "An error occurred when reading rules from file %(path)s: %(error)s" msgstr "%(path)s dosaysından kurallar okunurken hata oluştu: %(error)s" msgid "Anchor for paging" msgstr "Sayfalama için sabitleyici" msgid "Apply rule to incoming network traffic (default)" msgstr "Kuralı gelen trafiğe uygula (varsayılan)" msgid "Apply rule to outgoing network traffic" msgstr "Giden ağ trafiğine kural uygula" msgid "" "Arbitrary scheduler hint key-value pairs to help boot an instance (repeat " "option to set multiple hints)" msgstr "" "İsteğe bağlı bir önyüklemeye yardımcı olmak için keyfi zamanlayıcı ipucu " "anahtar-değer çiftleri (birden fazla ipucu ayarlamak için seçeneği tekrarla)" msgid "" "Argument --dst-port not allowed with arguments --icmp-type and --icmp-code" msgstr "" "--dst-port argümanı --icmp-type ve --icmp-code argümanları ile kullanılamaz" msgid "Argument --icmp-type required with argument --icmp-code" msgstr "--icmp-type argümanı --icmp-code ile kullanılması zorunlu" msgid "Assocaite the floating IP with port (name or ID)" msgstr "Yüzen IP'yi bağlantı noktasıyla ilişkilendirin (ad veya kimlik)" msgid "Associate a QoS specification to a volume type" msgstr "Bir disk bölümü türüyle QoS özelliklerini ilişkilendir" msgid "Associate no security groups with this port" msgstr "Bu bağlantı noktası ile hiç bir güvenlik grubunu ilişkilendirme" msgid "Associate project with image" msgstr "Projeyi imaj ile ilişkilendirin" msgid "Attach QoS policy to this port (name or ID)" msgstr "Bu bağlantı noktasına QoS politikası ekle (isim veya ID)" msgid "" "Attempt forced removal of snapshot(s), regardless of state (defaults to " "False)" msgstr "" "Durumdan bağımsız olarak, anlık görüntüleri zorla kaldırma girişimi " "(varsayılan olarak False)." msgid "" "Attempt forced removal of volume(s), regardless of state (defaults to False)" msgstr "" "Durumdan bağımsız olarak hacim(ler)in zorla kaldırılması girişimi " "(varsayılan olarak False)" msgid "Attempt to mask passwords (default)" msgstr "Parolaları maskelemeye çalış (varsayılan)" msgid "Attempting to upload multiple objects and using --name is not permitted" msgstr "" "Birden çok nesne yüklemeye çalışılıyor ve --name kullanmaya izin verilmiyor" msgid "Authentication URL of remote federated service provider (required)" msgstr "Uzak federe servis sağlayıcının kimlik doğrulama URL'si (gerekli)" msgid "Authentication token to use" msgstr "Kullanılacak yetkilendirme jetonu" msgid "Authorize a request token" msgstr "Bir istek jetonu yetkilendir" msgid "" "Auto option is not available for Subnet Set. Valid options are " "or none" msgstr "" "Otomatik seçeneği Alt ağ Kümesi için kullanılabilir değildir. Geçerli " "değerler veya none'dır" msgid "" "Availability Zone in which to create this network (Network Availability Zone " "extension required, repeat option to set multiple availability zones)" msgstr "" "Bu ağın oluşturulacağı kullanılabilirlik bölgesi (Ağ Kullanılabilirlik Alanı " "uzantısı gerekli, birden çok kullanılabilirlik bölgesi ayarlamak için " "seçeneği tekrarla)" msgid "" "Availability Zone in which to create this router (Router Availability Zone " "extension required, repeat option to set multiple availability zones)" msgstr "" "Bu yönlendiricinin oluşturulacağı Kullanılabilirlik Bölgesi (Yönlendirici " "Kullanılabilirlik Bölge uzantısı gerekiyor, birden fazla kullanılabilirlik " "bölgesi ayarlamak için seçeneği tekrarla)" msgid "" "Availability zone for this consistency group (not available if creating " "consistency group from source)" msgstr "" "Bu tutarlılık grubu için kullanılabilirlik bölgesi (kaynaktan tutarlılık " "grubu oluşturursanız kullanılamaz)" msgid "Availability zone name" msgstr "Kullanılabilirlik bölgesi ismi" msgid "Availability zones list not supported by Block Storage API" msgstr "" "Blok Depolama Alanı API'sı tarafından desteklenmeyen kullanılabilirlik " "bölgeleri listesi" msgid "Availability zones list not supported by Network API" msgstr "" "Ağ API'sı tarafından desteklenmeyen kullanılabilirlik bölgeleri listesi" msgid "Backup to display (name or ID)" msgstr "Gösterilecek yedek (isim veya ID)" msgid "Backup to modify (name or ID)" msgstr "Düzenlenecek yedek (isim veya ID)" msgid "Backup to restore (name or ID)" msgstr "Geri yüklenecek yedek (isim veya ID)" msgid "Backup(s) to delete (name or ID)" msgstr "Silinecek yedek(ler) (isim veya ID)" #, python-format msgid "Can't open '%(data)s': %(exception)s" msgstr "'%(data)s' açılamadı: %(exception)s" #, python-format msgid "Can't open '%(source)s': %(exception)s" msgstr "'%(source)s' açılamadı: %(exception)s" msgid "Cannot remove access for a public flavor" msgstr "Herkese açık flavor'dan erişimin kaldırılması işlemi başarısız" msgid "Cannot set access for a public flavor" msgstr "Ortak flavor için erişim ayarlanamaz" msgid "Cannot specify option --disable-reason without --disable specified." msgstr "--disable-reason seçeneği --disable olmadan belirtilemez." msgid "Change current user password" msgstr "Mevcut kullanıcının parolasını değiştir" msgid "Check user membership in group" msgstr "Kullanıcının grup üyeliğini kontrol et" msgid "Clean project resources, but don't delete the project" msgstr "Projenin kaynaklarını temizle ama projeyi silme" msgid "Clean resources associated with a project" msgstr "Bir proje ile alakalı kaynakları temizle" #, python-format msgid "Clear all tags associated with the %s" msgstr "%s ile ilişkili tüm etiketleri sil" msgid "" "Clear associated allocation-pools from the subnet. Specify both --allocation-" "pool and --no-allocation-pool to overwrite the current allocation pool " "information." msgstr "" "Alt ağdan ilgili paylaştırma havuzunu temizle. Mevcut paylaştırma havuzu " "bilgisinin üzerine yazmak için --allocation-pool ve --no-allocation-pool " "seçeneklerinin her ikisini de belirle." msgid "" "Clear associated host-routes from the subnet. Specify both --host-route and " "--no-host-route to overwrite the current host route information." msgstr "" "Alt ağdaki ilişkili ana makine yollarını temizleyin. Mevcut ana bilgisayar " "yönlendirme bilgisinin üzerine yazmak için --host-route ve --no-host-route " "seçeneklerinin her ikisini de belirtin." msgid "" "Clear existing allowed-address pairs associatedwith this port.(Specify both " "--allowed-address and --no-allowed-addressto overwrite the current allowed-" "address pairs)" msgstr "" "Bu bağlantı noktasıyla ilişkili mevcut izinli adres çiftlerini temizleyin." "(Mevcut izinli adres çiftinin üzerinde yazmak için --allowed-address ve --" "no-allowed-addressto seçeneklerinin her ikisini de belirtiniz)" msgid "" "Clear existing information of DNS Nameservers. Specify both --dns-nameserver " "and --no-dns-nameserver to overwrite the current DNS Nameserver information." msgstr "" "DNS isim sunucularının mevcut bilgilerini temizle. Mevcut DNS isim sunucusu " "bilgisinin üzerine yazmak için --dns-nameserver ve --no-dns-nameserver " "özelliklerini belirle." msgid "" "Clear existing information of binding:profile.Specify both --binding-profile " "and --no-binding-profile to overwrite the current binding:profile " "information." msgstr "" "binding:profile'in mevcut bilgilerini temizle. Mevcut binding:profile " "bilgisinin üzerine yazmak için --binding-profile ve --no-binding-profile her " "ikisini de belirtin." msgid "Clear existing information of data plane status" msgstr "Mevcut veri düzlemi durumu bilgilerini temizle" msgid "" "Clear existing information of fixed IP addresses.Specify both --fixed-ip and " "--no-fixed-ip to overwrite the current fixed IP addresses." msgstr "" "Sabit IP adresleri için mevcut bilgileri silin. Geçerli sabit IP " "adreslerinin üzerine yazmak için hem --fixed-ip hem de --no-fixed-ip " "belirtin." msgid "Clear existing security groups associated with this port" msgstr "Bu bağlantı noktasıyla ilişkili mevcut güvenlik gruplarını temizle" msgid "Clear high availability attribute of the router (disabled router only)" msgstr "" "Yönlendiricinin yüksek kullanılabilirlik özelliğini temizle (sadece devre " "dışı bırakılmış yönlendirici)" msgid "" "Clear routes associated with the router. Specify both --route and --no-route " "to overwrite current value of route." msgstr "" "Yönlendirici ile ilişkili yönleri temizle. Mevcut yön değerinin üzerine " "yazmak için hem --route hem de --no-route seçeneklerini belirtin." #, python-format msgid "" "Clear tags associated with the %s. Specify both --tag and --no-tag to " "overwrite current tags" msgstr "" "%s ile ilgili etiketleri temizle. Mevcut etiketlerin üzerine yazmak için hem " "--tag hem de --no-tag seçeneğini belirtin" msgid "Command Failed: One or more of the operations failed" msgstr "Komut başarısız: Bir veya birden fazla işlem başarısız" msgid "Complete\n" msgstr "Tamamla\n" #, python-format msgid "Compute API version, default=%s (Env: OS_COMPUTE_API_VERSION)" msgstr "Hesaplama API sürümü, varsayılan=%s (Env: OS_COMPUTE_API_VERSION)" #, python-format msgid "Compute service %(service)s of host %(host)s failed to set." msgstr "Ana bilgisayar %(host)s'ın hesap hizmeti %(service)s ayarlanamadı." msgid "Compute service(s) to delete (ID only)" msgstr "Hesaplama servis(ler)ini sil" msgid "Confirm server resize is complete" msgstr "Sunucu yeniden boyutlandırmasının tamamlandığını doğrula" msgid "Consistency group containing (name or ID)" msgstr "'ü içeren tutarlılık grubu (isim veya ID)" msgid "Consistency group snapshot to display (name or ID)" msgstr "Tutarlılık grupunun gösterilecek anlık görüntüsü (isim veya ID)" msgid "Consistency group snapshot(s) to delete (name or ID)" msgstr "Silinecek tutarlılık grubu anlık görüntüleri (isim veya ID)" msgid "Consistency group to contain (name or ID)" msgstr " disk bölümünü içerecek tutarlılık grubu (isim veya ID)" msgid "Consistency group to display (name or ID)" msgstr "Gösterilecek tutarlılık grubu (isim veya ID)" msgid "Consistency group to modify (name or ID)" msgstr "Düzenlenecek tutarlılık grubu (isim veya ID)" msgid "" "Consistency group to snapshot (name or ID) (default to be the same as " ")" msgstr "" "Anlık görüntüsü alınacak tutarlılık grubu (isim veya ID) (varsayılan olarak " " ile aynı)" msgid "Consistency group where the new volume belongs to" msgstr "Yeni disk bölümünün ait olduğu tutarlılık grubu" msgid "Consistency group(s) to delete (name or ID)" msgstr "Silinecek tutarlılık grupları (isim veya ID)" msgid "Consumer key (required)" msgstr "Alıcı anahtarı (gerekli)" #, python-format msgid "Consumer of the QoS. Valid consumers: %s (defaults to 'both')" msgstr "QoS tüketici. Geçerli tüketiciler: %s (varsayılan olarak 'her ikisi')" msgid "Consumer secret (required)" msgstr "Alıcı gizli anahtarı (gerekli)" msgid "Consumer to display" msgstr "Gösterilecek alıcı" msgid "Consumer to modify" msgstr "Düzenlenecek alıcı" msgid "Consumer(s) to delete" msgstr "Silinecek alıcı(lar)" msgid "Container for new object" msgstr "Yeni nesne için kap" #, python-format msgid "Container name is %s characters long, the default limit is 256" msgstr "Kap ismi %s karakter uzunluğunda, varsayılan sınır 256'dır" msgid "Container to display" msgstr "Gösterilecek kap" msgid "Container to list" msgstr "Listelenecek kap" msgid "Container to modify" msgstr "Düzenlenecek kap" msgid "Container to save" msgstr "Kaydedilecek kap" msgid "Container(s) to delete" msgstr "Silinecek kap(lar)" msgid "Copy image from the data store (similar to --location)" msgstr "Veri deposundan imajı kopyala (--location'a benzer)" #, python-format msgid "Could not find security group rule with ID '%s'" msgstr "'%s' ID'li güvenlik grubu kuralı bulunamadı" msgid "Create EC2 credentials" msgstr "EC2 kimlik bilgilerini oluştur" msgid "" "Create a NIC on the server and connect it to network. Specify option " "multiple times to create multiple NICs. This is a wrapper for the '--nic net-" "id=' parameter that provides simple syntax for the standard use " "case of connecting a new server to a given network. For more advanced use " "cases, refer to the '--nic' parameter." msgstr "" "Sunucuda bir NIC oluşturun ve ağa bağlayın. Birden çok NIC oluşturmak için " "seçeneği birden çok kez belirtin. Bu, belirli bir ağa yeni bir sunucu " "bağlamak için standart kullanım örneği için basit sözdizimi sağlayan '--nic " "net-id=' parametresi için bir sarmalayıcıdır. Daha gelişmiş " "kullanım durumları için, '--nic' parametresine bakın." msgid "" "Create a NIC on the server and connect it to port. Specify option multiple " "times to create multiple NICs. This is a wrapper for the '--nic port-" "id=' parameter that provides simple syntax for the standard use case " "of connecting a new server to a given port. For more advanced use cases, " "refer to the '--nic' parameter." msgstr "" "Sunucuda bir NIC oluşturun ve bağlantı noktasına bağlayın. Birden çok NIC " "oluşturmak için seçeneği birden çok kez belirtin. Bu, belirli bir bağlantı " "noktasına yeni bir sunucu bağlamak için standart kullanım örneği için basit " "sözdizimi sağlayan '--nic port-id=' parametresi için bir " "sarmalayıcıdır. Daha gelişmiş kullanım durumları için, '--nic' parametresine " "bakın." msgid "" "Create a NIC on the server. Specify option multiple times to create multiple " "NICs. Either net-id or port-id must be provided, but not both. net-id: " "attach NIC to network with this UUID, port-id: attach NIC to port with this " "UUID, v4-fixed-ip: IPv4 fixed address for NIC (optional), v6-fixed-ip: IPv6 " "fixed address for NIC (optional), none: (v2.37+) no network is attached, " "auto: (v2.37+) the compute service will automatically allocate a network. " "Specifying a --nic of auto or none cannot be used with any other --nic value." msgstr "" "Sunucuda bir NIC oluştur. Birden fazla NIC oluşturmak için seçeneği birden " "fazla kere belirtin. Ya net-id ya da port-id sağlanmalı, ikisi bir arada " "değil. net-id: NIC'nin ağa ekleneceği UUID, port-id: NIC'nin bağlantı " "noktasına takılacağı UUID, v4-fixed-ip: NIC için sabit IPv4 adresi " "(seçimli), v6-fixed-ip: NIC için sabit IPv6 adresi (seçimli), none: (v2.37+) " "hiç ağ takılmaz, auto: (v2.37+) hesaplama servisi otomatik olarak bir ağ " "ayırır. Auto veya none'ı bir --nic ile belirtmek başka bir --nic değeri ile " "kullanılamaz." msgid "Create a QoS policy" msgstr "QoS politikası oluştur" msgid "" "Create a block device on the server.\n" "Block device mapping in the format\n" "=:::\n" ": block device name, like: vdb, xvdc (required)\n" ": UUID of the volume or snapshot (required)\n" ": volume or snapshot; default: volume (optional)\n" ": volume size if create from snapshot (optional)\n" ": true or false; default: false (optional)\n" "(optional extension)" msgstr "" "Sunucu üzerinde blok aygıtı oluştur.\n" "Blok aygıtı eşleşme formatı\n" "=:::\n" ": blok aygıt ismi, örn: vdb, xvdc (gerekli)\n" ": disk bölümünün veya anlık görüntünün UUID'si (gerekli)\n" ": disk bölümü veya anlık görüntü; varsayılan: disk bölümü (seçimli)\n" ": eğer anlık görüntüden oluşturulduysa disk bölümü boyutu " "(seçimli)\n" ": true veya false; varsayılan: false (seçimli)\n" "(seçimli uzantı)" msgid "Create a centralized router" msgstr "Merkezi bir yönlendirici oluştur" msgid "Create a distributed router" msgstr "Dağıtık bir yönlendirici oluştur" msgid "Create a highly available router" msgstr "Yüksek kullanılabilirlikli bir yönlendirici oluştur" msgid "Create a legacy router" msgstr "Miraz yönlendirici oluştur" msgid "Create a new Address Scope" msgstr "Yeni bir Adres Kapsamı oluştur" msgid "Create a new aggregate" msgstr "Yeni bir küme oluştur" msgid "Create a new meter rule" msgstr "Yeni bir ölçek kuralı oluştur" msgid "Create a new port" msgstr "Yeni bir bağlantı noktası oluştur" msgid "Create a new router" msgstr "Yeni bir yönlendirici oluştur" msgid "Create a new security group" msgstr "Yeni bir grup oluştur" msgid "Create a new security group rule" msgstr "Yeni bir güvenlik grubu kuralı oluştur" msgid "Create a new server" msgstr "Yeni bir sunucu oluştur" msgid "Create a new server disk image from an existing server" msgstr "Varolan bir sunucudan yeni bir disk imajı oluştur" msgid "Create a new server group." msgstr "Yeni bir sunucu grubu oluştur." msgid "Create a request token" msgstr "Bir istek jetonu oluştur" msgid "Create a server backup image" msgstr "Bir sunucu yedek imajı oluştur" msgid "Create a snapshot attached to an instance. Default is False" msgstr "Sunucuya bağlanacak bir anlık görüntü oluştur. Varsayılan Fals" msgid "Create a subnet" msgstr "Bir altağ oluşturun" msgid "Create an access token" msgstr "Erişim jetonu oluştur" msgid "Create compute agent" msgstr "Hesaplama ajanı oluştur" msgid "" "Create credentials for user (name or ID; default: current authenticated user)" msgstr "" "Kullanıcı için kimlik bilgileri oluştur (isim veya ID; varsayılan: mevcut " "yetkilendirilmiş kullanıcı)" msgid "" "Create credentials in project (name or ID; default: current authenticated " "project)" msgstr "" "Projede kimlik bilgileri oluştur (isim veya ID; varsayılan: mevcut kimlik " "doğrulama yapılmış proje)" msgid "Create description for meter" msgstr "Sayaç için açıklama oluştur" msgid "Create floating IP" msgstr "Yüzen IP oluştur" msgid "Create image from a volume" msgstr "Bir disk bölümünden imaj oluştur" msgid "Create network RBAC policy" msgstr "Ağ RBAC politikası oluştur" msgid "Create network meter" msgstr "Ağ sayacı oluştur" msgid "Create new Network QoS rule" msgstr "Yeni Ağ QoS kuralı oluştur" msgid "Create new QoS specification" msgstr "Yeni QoS özelliği oluştur" msgid "Create new backup" msgstr "Yeni yedek oluştur" msgid "Create new consistency group snapshot." msgstr "Yeni tutarlılık grubu anlık görüntüsü oluştur." msgid "Create new consistency group." msgstr "Yeni tutarlılık grubu oluştur." msgid "Create new consumer" msgstr "Yeni tüketici oluştur" msgid "Create new container" msgstr "Yeni kap oluştur" msgid "Create new credential" msgstr "Yeni kimlik bilgileri oluştur" msgid "Create new domain" msgstr "Yeni alan oluştur" msgid "Create new endpoint" msgstr "Yeni bir uç nokta oluştur" msgid "Create new federation protocol" msgstr "Yeni federasyon protokolü oluştur" msgid "Create new flavor" msgstr "Yeni flavor oluştur" msgid "Create new group" msgstr "Yeni grup oluştur" msgid "Create new identity provider" msgstr "Yeni kimlik sağlayıcı oluştur" msgid "Create new mapping" msgstr "Yeni eşleştirme oluştur" msgid "Create new network" msgstr "Yeni ağ oluştur" msgid "Create new network flavor" msgstr "Yeni ağ falvor'ı oluştur" msgid "Create new network flavor profile" msgstr "Yeni ağ flavor profili oluştur" msgid "Create new network segment" msgstr "Yeni ağ dilimi oluştur" msgid "Create new policy" msgstr "Yeni politika oluştur" msgid "Create new project" msgstr "Yeni proje oluştur" msgid "Create new public or private key for server ssh access" msgstr "Sunucunun ssh erişimi için yeni açık ve kapalı anahtarları oluştur" msgid "Create new region" msgstr "Yeni bölge oluştur" msgid "Create new role" msgstr "Yeni rol oluştur" msgid "Create new service" msgstr "Yeni servis oluştur" msgid "Create new service provider" msgstr "Yeni servis sağlayıcı oluştur" msgid "Create new snapshot" msgstr "Yeni anlık görüntü oluştur" msgid "Create new trust" msgstr "Yeni güven oluştur" msgid "Create new user" msgstr "Yeni kullanıcı oluştur" msgid "Create new volume" msgstr "Yeni disk bölümü oluştur" msgid "Create new volume backup" msgstr "Yeni disk bölümü yedeği oluştur" msgid "Create new volume snapshot" msgstr "Yeni bir disk bölümü anlık görüntüsü oluştur" msgid "Create new volume type" msgstr "Yeni disk bölümü türü oluşturun" msgid "Create rule in this security group (name or ID)" msgstr "Bu güvenlik grubunda kural oluştur (isim veya ID)" msgid "Create server boot disk from this image (name or ID)" msgstr "Bu imajdan sunucu ön yükleme diski oluştur (isim veya ID)" msgid "" "Create server using this volume as the boot disk (name or ID).\n" "This option automatically creates a block device mapping with a boot index " "of 0. On many hypervisors (libvirt/kvm for example) this will be device vda. " "Do not create a duplicate mapping using --block-device-mapping for this " "volume." msgstr "" "Bu disk bölümünü ön yüklenebilir disk olarak kullanarak sunucu oluştur (isim " "veya ID).\n" "Bu seçenek otomatik olarak 0 ön yükleme diziniyle bir blok aygıt eşleşmesi " "oluşturur. Bir çok yönetici arakatman (örneğin libvirt/kvm) üzerinde bu " "aygıt vda'dir. Bu disk bölümü için --block-device-mapping kullanarak birden " "fazla eşleşme oluşturmayın." msgid "Create server with this flavor (name or ID)" msgstr "Bu flavor ile sunucu oluştur (isim veya ID)" msgid "Create subnet pool" msgstr "Altağ havuzu oluştur" msgid "Create the auto allocated topology for project" msgstr "Proje için otomatik ayrılmış topoloji oluştur" msgid "Create volume in " msgstr " içerisinde disk bölümü oluştur" msgid "Create volume transfer request." msgstr "Disk bölümü aktarım isteği oluştur." msgid "Create/upload an image" msgstr "Bir imaj oluştur/yükle" msgid "Credentials access key" msgstr "Kimlik bilgilerine erişim anahtarı" msgid "Credentials access key(s)" msgstr "Kimlik bilgilerine erişim anahtar(lar)ı" msgid "" "Custom data to be passed as binding:profile. Data may be passed as " "= or JSON. (repeat option to set multiple binding:profile data)" msgstr "" "binding:profile olarak verilecek özel veri. Veri = şeklinde veya " "JSON olarak verilebilir. (birden fazla binding:profile verisi ayarlamak için " "seçeneği tekrarlayın)" msgid "DNS server for this subnet (repeat option to set multiple DNS servers)" msgstr "" "Bu alt ağ için DNS sunucu (birden fazla DNS sunucusu ayarlamak için seçeneği " "tekrarlayın)" msgid "" "DNS server to be removed from this subnet (repeat option to unset multiple " "DNS servers)" msgstr "" "Bu altağdan silinecek DNS sunucu (Birden fazla DNS sunucusunun ayarını " "kaldırmak için seçeneği tekrarla)" msgid "" "DSCP mark: value can be 0, even numbers from 8-56, excluding 42, 44, 50, 52, " "and 54" msgstr "" "DSCP işareti: değer 0 olabilir, 8-56 arasındaki çift sayılar, 42, 44, 50, " "52, ve 54 hariç" msgid "Deactivate the image" msgstr "İmajın aktivasyonunu kaldır" msgid "Default domain (name or ID)" msgstr "Varsayılan alan (isim veya ID)" msgid "Default project (name or ID)" msgstr "Varsayılan proje (isim veya ID)" msgid "Delete EC2 credentials" msgstr "EC2 kimlik bilgilerini sil" msgid "Delete Network QoS rule" msgstr "Ağ QoS kuralını sil" msgid "Delete QoS specification" msgstr "QoS özelliklerini sil" msgid "Delete Qos Policy(s)" msgstr "Qos Politika(lar/s)ını sil" msgid "Delete address scope(s)" msgstr "Adres kapsam(lar)ını sil" msgid "" "Delete auto allocated topology for a given project. Default is the current " "project" msgstr "" "Belirli bir proje için otomatik ayrılan topolojiyi silin. Varsayılan geçerli " "projedir" msgid "Delete auto allocated topology for project" msgstr "Projeye otomatik ayrılan topolojiyi sil" msgid "Delete backup(s)" msgstr "Yedek(ler)i sil" msgid "Delete compute agent(s)" msgstr "Hesaplama ajan(lar)ını sil" msgid "Delete compute service(s)" msgstr "Hesaplama servis(ler)ini sil" msgid "Delete consistency group snapshot(s)." msgstr "Tutarlılık grubu anlık görüntüsünü sil." msgid "Delete consistency group(s)." msgstr "Tutarlılık grubunu sil." msgid "Delete consumer(s)" msgstr "Alıcıları sil" msgid "Delete container" msgstr "Kabı sil" msgid "Delete credential(s)" msgstr "Kimlik bilgilerini sil" msgid "Delete credentials for user (name or ID)" msgstr "Kullanıcı için kimlik bilgilerini sil (isim veya ID)" msgid "Delete domain(s)" msgstr "Alan(lar)ı sil" msgid "Delete endpoint(s)" msgstr "Uç nokta(yı/ları) sil" msgid "Delete existing aggregate(s)" msgstr "Var olan küme(ler/y)i sil" msgid "Delete existing server group(s)." msgstr "Mevcut sunucu gruplarını sil." msgid "Delete federation protocol(s)" msgstr "Federasyon protokol(ünü/lerini) sil" msgid "Delete flavor(s)" msgstr "Flavor(lar)ı sil" msgid "Delete floating IP(s)" msgstr "Yüzen IP(ler)i sil" msgid "Delete group(s)" msgstr "Grup(ları/u) sil" msgid "Delete identity provider(s)" msgstr "Kimlik sağlayıcı(ları/yı) sil" msgid "Delete image(s)" msgstr "İmaj(lar)ı sil" msgid "Delete mapping(s)" msgstr "Eşleştirme(yi/leri) sil" msgid "Delete meter rule(s)" msgstr "Ölçüm kural(lar)ını sil" msgid "Delete network RBAC policy(s)" msgstr "Ağ RBAC politikalarını sil" msgid "Delete network agent(s)" msgstr "Ağ ajanlarını sil" msgid "Delete network flavor profile" msgstr "Ağ flavor profilini sil" msgid "Delete network flavors" msgstr "Ağ flavor'larını sil" msgid "Delete network meter" msgstr "Ağ ölçeğini sil" msgid "Delete network segment(s)" msgstr "Ağ segmentlerini sil" msgid "Delete network(s)" msgstr "Ağı sil" msgid "Delete object from container" msgstr "Kaptan nesne sil" msgid "Delete object(s) from " msgstr "'den nesneleri sil" msgid "Delete policy(s)" msgstr "Politika(ları/yı) sil" msgid "Delete port(s)" msgstr "Bağlantı noktalarını sil" msgid "Delete project(s)" msgstr "Proje(yi/leri) sil" msgid "Delete public or private key(s)" msgstr "Genel veya özel anahtarları sil" msgid "Delete region(s)" msgstr "Bölge(yi/leri) sil" msgid "Delete resources of the project used to authenticate" msgstr "Kimlik kanıtlama için kullanılan proje kaynaklarını sil" msgid "Delete role(s)" msgstr "Rol(leri/ü) sil" msgid "Delete router(s)" msgstr "Yönlendirici(ler/y)i sil" msgid "Delete security group rule(s)" msgstr "Güvenlik grubu kurallarını sil" msgid "Delete security group(s)" msgstr "Güvenlik grubunu sil" msgid "Delete server(s)" msgstr "Sunucu(ları/yu) sil" msgid "Delete service provider(s)" msgstr "Servis sağlayıcı(ları/yı) sil" msgid "Delete service(s)" msgstr "Servis(ler)i sil" msgid "Delete snapshot(s)" msgstr "Anlık görüntü(yü/leri) sil" msgid "Delete subnet pool(s)" msgstr "Altağ havuzunu sil" msgid "Delete subnet(s)" msgstr "Altağ(lar)ı sil" msgid "Delete trust(s)" msgstr "Güveni sil" msgid "Delete user(s)" msgstr "Kullanıcı(yı/ları) sil" msgid "Delete volume backup(s)" msgstr "Disk bölümü yedeklerini sil" msgid "Delete volume snapshot(s)" msgstr "Disk bölümü anlık görüntülerini sil" msgid "Delete volume transfer request(s)." msgstr "Disk bölümü aktarım isteğini sil." msgid "Delete volume type(s)" msgstr "Disk bölümü türlerini sil" msgid "Delete volume(s)" msgstr "Disk bölümlerini sil" #, python-format msgid "Deleting %(resource)s : %(id)s" msgstr "%(resource)s siliniyor: %(id)s" #, python-format msgid "Deleting project: %s" msgstr "Proje siliniyor: %s" msgid "Description for the flavor" msgstr "Flavor için açıklama" msgid "Description for the flavor profile" msgstr "Flavor profili için açıklama" msgid "Description of the QoS policy" msgstr "QoS politikasının tanımı" msgid "Description of the backup" msgstr "Yedeğin açıklaması" msgid "Description of the snapshot" msgstr "Anlık görüntü tanımı" msgid "Description of this consistency group" msgstr "Bu tutarlılık grubunun açıklaması" msgid "Description of this consistency group snapshot" msgstr "Bu tutarlılık grubu anlık görüntüsünün açıklaması" msgid "Description of this port" msgstr "Bu bağlantı noktasının açıklaması" msgid "" "Desired IP and/or subnet (name or ID)on external gateway: subnet=,ip-" "address= (repeat option to set multiple fixed IP addresses)" msgstr "" "Harici geçit üzerinde istenen IP ve/veya altağ: subnet=,ip-" "address= (birden fazla sabit IP adres ayarlamak için seçeneği " "tekrarla)" msgid "" "Desired IP and/or subnet for filtering ports (name or ID): subnet=," "ip-address= (repeat option to set multiple fixed IP addresses)" msgstr "" "Bağlantı noktalarını filtrelemek için tasarlanan IP ve/veya alt ağ (isim " "veya ID): subnet=,ip-address= (birden fazla sabit IP " "adresi ayarlamak için seçeneği tekrarlayın)" msgid "" "Desired IP and/or subnet for this port (name or ID): subnet=,ip-" "address= (repeat option to set multiple fixed IP addresses)" msgstr "" "Bu bağlantı noktası için istenen IP ve / veya alt ağ (ad veya kimlik): " "subnet=, ip-address= (birden fazla sabit IP adresi " "ayarlamak için seçeneği tekrarlayın)" msgid "" "Desired IP and/or subnet which should be removed from this port (name or " "ID): subnet=,ip-address= (repeat option to unset " "multiple fixed IP addresses)" msgstr "" "Bu bağlantı noktasından kaldırılması gereken istenen IP ve/veya alt ağ (isim " "veya ID): subnet=,ip-address= (birden fazla sabit IP " "adresini kaldırmak için seçeneği tekrarlayın)" msgid "" "Desired allowed-address pair which should be removed from this port: ip-" "address= [,mac-address=] (repeat option to set " "multiple allowed-address pairs)" msgstr "" "Bu bağlantıdan kaldırılması gereken tasarlanan erişilebilir adres çifti: ip-" "address= [,mac-address=] (birden fazla izin verilen " "adres çifti ayarlamak için seçeneği tekrarlayın)" msgid "" "Desired key which should be removed from binding:profile(repeat option to " "unset multiple binding:profile data)" msgstr "" "binding:profile'den çıkarılması gereken istenen anahtar (çoklu binding:" "profile verisinin ayarını kaldırmak için seçeneği tekrarlayın)" msgid "" "Destination filename (defaults to object name); using '-' as the filename " "will print the file to stdout" msgstr "" "Hedef dosya ismi (nesne ismine varsayılan); '-' karakterini dosya adı olarak " "kullanmak dosyayı stdout'a yazar" msgid "Destination host (takes the form: host@backend-name#pool)" msgstr "Hedef ana bilgisayar (biçemi: anabilgisayar@artalanismi#havuz)" msgid "Destination port (ssh -p option)" msgstr "Hedef bağlantı noktası (ssh -p seçeneği)" msgid "" "Destination port, may be a single port or a starting and ending port range: " "137:139. Required for IP protocols TCP and UDP. Ignored for ICMP IP " "protocols." msgstr "" "Hedef bağlantı noktası, tek bir bağlantı noktası veya başlangıç ve bitiş " "bağlantı noktası: 137:139 olabilir. TCP ve UDP IP protokolleri için " "zorunludur. ICMP IP protokolleri için gözardı edilir." msgid "" "Device owner of this port. This is the entity that uses the port (for " "example, network:dhcp)." msgstr "" "Bu portun cihaz sahibi. Bu, bağlantı noktasını kullanan varlıktır (örneğin, " "ağ: dhcp)." msgid "Disable DHCP" msgstr "DHCP'yi devre dışı bırak" msgid "Disable Source NAT on external gateway" msgstr "Harici geçit üzerinde Kaynak NAT'ı devre dışı bırak" msgid "Disable domain" msgstr "Alanı devre dışı bırak" msgid "Disable endpoint" msgstr "Uç noktayı devre dışı bırak" msgid "Disable maintenance mode for the host" msgstr "Sunucu için bakım kipini devre dışı bırak" msgid "Disable network" msgstr "Ağı devre dışı bırak" msgid "Disable network agent" msgstr "Ağ ajanını devre dışı bırak" msgid "Disable network flavor" msgstr "Ağ flavor'ını devre dışı bırak" msgid "Disable port" msgstr "Bağlantı noktasını devre dışı bırak" msgid "Disable port security by default for ports created on this network" msgstr "" "Bu ağda oluşturulan bağlantı noktaları için varsayılan olarak bağlantı " "noktası güvenlik işlevini devre dışı bırak" msgid "Disable port security for this port" msgstr "Bu bağlantı noktası için bağlantı noktası güvenliğini devre dışı bırak" msgid "Disable project" msgstr "Projeyi devredışı bırak" msgid "Disable router" msgstr "Yönlendiriciyi devre dışı bırak" msgid "Disable service" msgstr "Servisi devre dışı bırak" msgid "Disable the flavor" msgstr "Flavor'ı etkisiz hale getir (varsayılan)" msgid "Disable the flavor profile" msgstr "Flavor profilini etkisiz hale getir" msgid "Disable the host" msgstr "Sunucuyu devredışı bırak" msgid "Disable the identity provider" msgstr "Kimlik sağlayıcıyı devre dışı bırak" msgid "Disable the service provider" msgstr "Servis sağlayıcıyı devre dışı bırak" msgid "Disable user" msgstr "Kullanıcıyı devre dışı bırak" msgid "Disable volume service" msgstr "Disk bölümü servisini devre dışı bırak" msgid "Disassociate a QoS specification from a volume type" msgstr "Bir QoS özelliğini bir disk bölümü türünden ayırın" msgid "Disassociate any port associated with the floating IP" msgstr "Kayan IP ile ilişkili herhangi bir bağlantıyı ayırın" msgid "Disassociate project with image" msgstr "Projeyi imajla ayır" msgid "Disassociate the QoS from every volume type" msgstr "Her disk bölümü türünden QoS'i ayır" msgid "Disk size in GB (default 0G)" msgstr "GB cinsinden disk boyutu (varsayılan 0G)" msgid "Display from " msgstr "dan göster" msgid "Display EC2 credentials details" msgstr "EC2 kimlik bilgileri detaylarını göster" msgid "Display Network QoS rule details" msgstr "Ağ QoS kural detaylarını göster" msgid "Display QoS policy details" msgstr "QoS politikası ayrıntılarını görüntüle" msgid "Display QoS specification details" msgstr "QoS belirtimi detaylarını göster" msgid "Display account details" msgstr "Hesap detaylarını göster" msgid "Display address scope details" msgstr "Adres kapsam detaylarını göster" msgid "Display aggregate details" msgstr "Küme detaylarını göster" msgid "Display backup details" msgstr "Yedek detaylarını göster" msgid "Display configuration details" msgstr "Yapılandırma detaylarını göster" msgid "Display consistency group details." msgstr "Tutarlılık grubu detaylarını göster." msgid "Display consistency group snapshot details" msgstr "Tutarlılık grubunun anlık görüntüsünü görüntüleme" msgid "Display consumer details" msgstr "Alıcı detaylarını göster" msgid "Display container details" msgstr "Kap detaylarını göster" msgid "Display credential details" msgstr "Kimlik bilgileri detaylarını göster" msgid "Display domain details" msgstr "Alan detaylarını göster" msgid "Display encryption information for each volume type (admin only)" msgstr "Her disk bölümü türü için şifreleme bilgisini göster (sadece yönetici)" msgid "Display encryption information of this volume type (admin only)" msgstr "Bu disk bölümü türünün şifreleme bilgisini göster (sadece yönetici)" msgid "Display endpoint details" msgstr "Uç nokta detaylarını göster" msgid "Display federation protocol details" msgstr "Federasyon protokolü detaylarını göster" msgid "Display flavor details" msgstr "Flavor detaylarını göster" msgid "Display floating IP details" msgstr "Yüzen IP ayrıntılarını görüntüle" msgid "Display group details" msgstr "Grup detaylarını göster" msgid "Display host details" msgstr "Sunucu detaylarını göster" msgid "Display hypervisor details" msgstr "Yönetici ara katman detaylarını göster" msgid "Display hypervisor stats details" msgstr "Yönetici arakatman istatistik detaylarını göster" msgid "Display identity provider details" msgstr "Kimlik sağlayıcı detaylarını göster" msgid "Display image details" msgstr "İmaj detaylarını göster" msgid "Display information from all projects (admin only)" msgstr "Tüm projelerden bilgileri göster (sadece yönetici)" msgid "Display key details" msgstr "Anahtar detaylarını göster" msgid "Display mapping details" msgstr "Eşleşme detaylarını göster" msgid "Display meter rules details" msgstr "Ölçek kuralı detaylarını göster" msgid "Display names instead of IDs" msgstr "ID yerine isimleri göster" msgid "Display network RBAC policy details" msgstr "Ağ RBAC politikası detaylarını göster" msgid "Display network agent details" msgstr "Ağ ajanının ayrıntılarını görüntüle" msgid "Display network flavor details" msgstr "Ağ flavor detaylarını göster" msgid "Display network flavor profile details" msgstr "Ağ flavor profil detaylarını göster" msgid "Display network segment details" msgstr "Ağ dilim detaylarını göster" msgid "Display object details" msgstr "Nesne detaylarını göster" msgid "Display policy details" msgstr "Politika detaylarını göster" msgid "Display port details" msgstr "Bağlantı noktası detaylarını gösterin" msgid "Display project details" msgstr "Proje detaylarını göster" msgid "Display region details" msgstr "Bölge detaylarını göster" msgid "Display role details" msgstr "Rol detaylarını göster" msgid "Display router details" msgstr "Yönlendirici detaylarını göster" msgid "Display security group details" msgstr "Güvenlik grubu detaylarını göster" msgid "Display security group rule details" msgstr "Güvenlik grubu kural detaylarını göster" msgid "Display server diagnostics information" msgstr "Sunucu tanılama bilgilerini göster" msgid "Display server group details." msgstr "Sunucu grup detaylarını göster." msgid "Display service catalog details" msgstr "Servis katalog detaylarını göster" msgid "Display service details" msgstr "Servis detaylarını göster" msgid "Display service provider details" msgstr "Servis sağlayıcı detaylarını göster" msgid "Display snapshot details" msgstr "Anlık görüntü detaylarını göster" msgid "Display subnet details" msgstr "Altağ detaylarını göster" msgid "Display subnet pool details" msgstr "Alt ağ havuz detaylarını göster" msgid "Display trust details" msgstr "Güven detaylarını göster" msgid "Display user details" msgstr "Kullanıcı detaylarını göster" msgid "Display volume backup details" msgstr "Yedek disk bölümü detaylarını göster" msgid "Display volume details" msgstr "Disk bölümü detaylarını göster" msgid "Display volume snapshot details" msgstr "Disk bölümü anlık görüntü detaylarını göster" msgid "Display volume type details" msgstr "Disk bölümü türü detaylarını göster" msgid "Do not make the network VLAN transparent" msgstr "Ağ VLAN'ını transparan yapma" msgid "Do not over-commit disk on the destination host (default)" msgstr "Hedef ana bilgisayarda disk aşırı işleme yapma (varsayılan)" msgid "Do not share meter between projects" msgstr "Ölçümleri projeler arasında paylaşma" msgid "Do not share the address scope between projects" msgstr "Adres kapsamını projeler arasında paylaşmayın" msgid "Do not share the address scope between projects (default)" msgstr "Projeler arasında adres kapsamını paylaşma (varsayılan)" msgid "Do not share the network between projects" msgstr "Ağı projeler arasında paylaşmayın" msgid "Do not use the network as the default external network" msgstr "Ağı varsayılan dış ağ olarak kullanmayın" msgid "Do not use the network as the default external network (default)" msgstr "Ağı varsayılan harici ağ olarak kullanma (varsayılan)" msgid "Domain containing (name or ID)" msgstr "'u içeren alan (isim veya ID)" msgid "Domain containing group(s) (name or ID)" msgstr "Grub(u/ları) içeren alan (isim veya ID)" msgid "Domain owning (name or ID)" msgstr "'ye sahip olan alan (isim veya ID)" msgid "Domain owning (name or ID)" msgstr " kullanıcının ait olduğu alan (isim veya ID)" msgid "Domain owning the project (name or ID)" msgstr "Projenin ait olduğu alan (isim veya ID)" msgid "Domain that contains (name or ID)" msgstr "'yi içeren alan (isim veya ID)" msgid "Domain that contains (name or ID)" msgstr " içeren alan (isim veya ID)" msgid "" "Domain the group belongs to (name or ID). This can be used in case " "collisions between group names exist." msgstr "" "Grubun ait olduğu alan (isim veya ID). Grup isimlerinde bir çatışma olması " "durumunda kullanılabilir." msgid "Domain the project belongs to (name or ID) [only valid with --absolute]" msgstr "" "Projenin ait olduğu alan (isim veya ID) [sadece --absolute ile geçerli]" msgid "" "Domain the project belongs to (name or ID). This can be used in case " "collisions between project names exist." msgstr "" "Projenin ait olduğu domain (isim veya ID). Proje isimlerinde çakışma olması " "durumunda kullanılabilir." msgid "Domain the role belongs to (name or ID)" msgstr "Rolün ait olduğu alan (isim veya ID)" msgid "" "Domain the role belongs to (name or ID). This must be specified when the " "name of a domain specific role is used." msgstr "" "Rolün ait olduğu alan (isim veya ID). Alana özel rol ismi kullanıldığında " "belirtilmek zorundadır." msgid "" "Domain the target project belongs to (name or ID). This can be used in case " "collisions between project names exist." msgstr "" "Hedef projenin ait olduğu alan (isim veya ID) Bu, proje isimleri arasındaki " "çakışmaların olması durumunda kullanılabilir." msgid "" "Domain the user belongs to (name or ID). This can be used in case collisions " "between user names exist." msgstr "" "Kullanıcının ait olduğu alan (isim veya ID). Kullanıcı adlarında bir çatışma " "oluşması durumunda kullanılabilir." msgid "" "Domain to associate with the identity provider. If not specified, a domain " "will be created automatically. (Name or ID)" msgstr "" "Kimlik sağlayıcısı ile ilişkilendirilecek alan adı. Belirtilmemişse, " "otomatik olarak bir alan oluşturulur. (İsim veya kimlik)" msgid "Domain to contain new group (name or ID)" msgstr "Yeni grup içeren alan (isim veya ID)" msgid "Domain to display (name or ID)" msgstr "Gösterilecek alan (isim veya ID)" msgid "Domain to filter (name or ID)" msgstr "Filtrelenecek alan (isim veya ID)" msgid "Domain to modify (name or ID)" msgstr "Düzenlenecek alan (isim veya ID)" msgid "Domain(s) to delete (name or ID)" msgstr "Silinecek alan(lar) (isim veya ID)" msgid "Download from " msgstr " nesneyi 'dan indir" msgid "Download image from an existing URL" msgstr "Mevcut bir URL'den imajı indir" msgid "Downloaded image save filename (default: stdout)" msgstr "İndirilen imajın kaydedileceği dosya adı (varsayılan: stdout)" #, python-format msgid "" "ERROR: --%s was given, which is an Image v1 option that is no longer " "supported in Image v2" msgstr "HATA: --%s, ancak bu İmaj v1 seçeneğidir ve İmaj v2'de desteklenmiyor" #, python-format msgid "ERROR: No %(type)s IP version %(family)s address found" msgstr "HATA: Hiç %(type)s IP sürüm %(family)s adresi bulunamadı" msgid "Egress traffic direction from the project point of view" msgstr "Proje açısından trafik akış yönü" msgid "Either --driver or --metainfo or both are required" msgstr "Ya --driver ya da --metainfo veya her ikisi de gereklidir" msgid "Enable DHCP" msgstr "DHCP'yi etkinleştir" msgid "Enable DHCP (default)" msgstr "DHCP etkinleştir (varsayılan)" msgid "Enable Source NAT on external gateway" msgstr "Harici geçit üzerinde Kaynak NAT'ı etkinleştir" msgid "Enable domain" msgstr "Alanı etkinleştir" msgid "Enable domain (default)" msgstr "Alanı etkinleştir (varsayılan)" msgid "Enable endpoint" msgstr "Uç noktayı etkinleştir" msgid "Enable endpoint (default)" msgstr "Uç noktayı etkinleştir (varsayılan)" msgid "" "Enable generic host-based force-migration, which bypasses driver " "optimizations" msgstr "" "Genel anabilgisayar tabanlı sürücü optimizasyonunu atlayan güç göçünü " "etkinleştir" msgid "Enable identity provider (default)" msgstr "Kimlik sağlayıcıyı etkinleştir (varsayılan)" msgid "Enable maintenance mode for the host" msgstr "Sunucu için bakım kipini etkinleştir" msgid "Enable network" msgstr "Ağı etkinleştir" msgid "Enable network (default)" msgstr "Ağı etkinleştir (varsayılan)" msgid "Enable network agent" msgstr "Ağ ajanını etkinleştir" msgid "Enable network flavor" msgstr "Ağ flavor'ını etkin hale getir" msgid "Enable port" msgstr "Bağlantı noktasını etkinleştir" msgid "Enable port (default)" msgstr "Bağlantı noktasının etkinleştir (varsayılan)" msgid "Enable port security by default for ports created on this network" msgstr "" "Bu ağda oluşturulan bağlantı noktaları için varsayılan olarak bağlantı " "noktası güvenlik özelliğini etkinleştir" msgid "" "Enable port security by default for ports created on this network (default)" msgstr "" "Bu ağda oluşturulan bağlantı noktaları için varsayılan olarak bağlantı " "noktası güvenlik özelliğini etkinleştir (varsayılan)" msgid "Enable port security for this port" msgstr "Bu bağlantı noktası için bağlantı noktası güvenliğini etkinleştir" msgid "Enable port security for this port (Default)" msgstr "" "Bu bağlantı noktası için bağlantı noktası güvenliğini etkinleştir " "(Varsayılan)" msgid "Enable project" msgstr "Projeyi etkinleştir" msgid "Enable project (default)" msgstr "Projeyi etkinleştir (varsayılan)" msgid "Enable router" msgstr "Yönlendiriciyi etkinleştir" msgid "Enable router (default)" msgstr "Yönlendiriciyi etkinleştir (varsayılan)" msgid "Enable service" msgstr "Servisi etkinleştir" msgid "Enable service (default)" msgstr "Servisi etkinleştir (varsayılan)" msgid "Enable the flavor (default)" msgstr "Flavor'ı etkinleştir (varsayılan)" msgid "Enable the flavor profile" msgstr "Flavor profilini etkinleştir" msgid "Enable the host" msgstr "Sunucuyu etkinleştir" msgid "Enable the identity provider" msgstr "Kimlik sağlayıcıyı etkinleştir" msgid "Enable the service provider" msgstr "Servis sağlayıcıyı etkinleştir" msgid "Enable the service provider (default)" msgstr "Servis sağlayıcıyı etkinleştir (varsayılan)" msgid "Enable user (default)" msgstr "Kullanıcıyı etkinleştir (varsayılan)" msgid "Enable volume service" msgstr "Disk bölümü servisini etkinleştir" msgid "End anchor for paging" msgstr "Sayfalama için sabitleyiciyi sonlandır" msgid "" "Endpoint to display (endpoint ID, service ID, service name, service type)" msgstr "" "Gösterilecek uç noktalar (uç nokta ID, servis ID, servis ismi, servis türü)" msgid "Endpoint to modify (ID only)" msgstr "Düzenlenecek uç nokta (sadece ID)" msgid "Endpoint(s) to delete (ID only)" msgstr "Silinecek uç nokta(lar) (sadece ID)" msgid "Ephemeral disk size in GB (default 0G)" msgstr "GB cinsinden geçici disk boyutu (varsayılan 0G)" msgid "Error creating server\n" msgstr "Sunucu oluşturulurken hata\n" #, python-format msgid "Error creating server backup: %s" msgstr "Sunucu yedeği oluşturulurken hata: %s" #, python-format msgid "Error creating server image: %s" msgstr "Sunucu imajı oluşturma hatası: %s" #, python-format msgid "Error creating server: %s" msgstr "Sunucu oluşturma başarısız: %s" msgid "Error deleting server\n" msgstr "Sunucu silinirken hata\n" #, python-format msgid "Error deleting server: %s" msgstr "Sunucu silinirken hata: %s" msgid "Error migrating server\n" msgstr "Sunucu göçü sırasında hata\n" #, python-format msgid "Error migrating server: %s" msgstr "Sunucu göçü sırasında hata: %s" msgid "Error rebooting server\n" msgstr "Sunucu yeniden başlatma hatası\n" #, python-format msgid "Error rebooting server: %s" msgstr "Sunucu yeniden başlatma hatası: %s" msgid "Error rebuilding server\n" msgstr "Sunucu yeniden yapılandırması sırasında hata\n" #, python-format msgid "Error rebuilding server: %s" msgstr "Sunucu yeniden yapılandırması sırasında hata: %s" msgid "Error resizing server\n" msgstr "Sunucunun yeniden boyutlandırması sırasında hata\n" #, python-format msgid "Error resizing server: %s" msgstr "Sunucu yeniden boyutlandırma hatası: %s" msgid "Error retrieving diagnostics data\n" msgstr "Teşhis verisi alınırken hata oluştu\n" #, python-format msgid "Error while executing command: %s" msgstr "Komut çalıştırılırken hata oluştu: %s" msgid "" "Error: If a user or group is specified, either --domain or --project must " "also be specified to list role grants." msgstr "" "Hata: Bir kullanıcı veya grup belirtilmişse, rol izinlerini listelemek için " "--domain veya --project de belirtilmelidir." msgid "" "Ethertype of network traffic (IPv4, IPv6; default: based on IP protocol)" msgstr "" "Ağ trafiğinin ethertype'ı (IPv4, IPv6; varsayılan: IP protokolüne bağlı)" #, python-format msgid "Exclude %s which have all given tag(s) (Comma-separated list of tags)" msgstr "" "Verilen tüm etiketlere sahip %s'i hariç tut (Etiketlerin virgül ile ayrılmış " "listesi)" #, python-format msgid "Exclude %s which have any given tag(s) (Comma-separated list of tags)" msgstr "" "Verilen etiketlerden herhangi birine sahip %s'i hariç tut (Etiketlerin " "virgül ile ayrılmış listesi)" msgid "Exclude remote IP prefix from traffic count" msgstr "Uzak IP önekini trafik sayımından hariç tut" msgid "Existing consistency group (name or ID)" msgstr "Mevcut tutarlılık grubu (isim veya ID)" msgid "Existing consistency group snapshot (name or ID)" msgstr "Varolan tutarlılık grubu anlık görüntüsü (isim veya ID)" #, python-format msgid "" "Expected '=' or JSON data for option %(option)s, but encountered " "JSON parsing error: %(error)s" msgstr "" "%(option)s seçeneği için '=' veya JSON verisi beklenirken JSON " "yorumlama hatası oluştu: %(error)s" msgid "Extend volume size in GB" msgstr "GB cinsinden genişletilmiş disk bölümü boyutu" msgid "" "Extension to display. Currently, only network extensions are supported. " "(Name or Alias)" msgstr "" "Gösterilecek uzantı. Şu an sadece ağ uzantıları destekleniyor. (İsim veya " "Takma ad)" msgid "Extensions list not supported by Block Storage API" msgstr "Blok Depolama API'ı uzantıları listelemeyi desteklemiyor" msgid "Extensions list not supported by Compute API" msgstr "Hesaplama API'ı uzantıların listelemeyi desteklemiyor" msgid "Extensions list not supported by Identity API" msgstr "Kimlik API için uzantıların listlenmesi desteklenmiyor" msgid "External Network used as router's gateway (name or ID)" msgstr "Yönlendirici geçidi olarak kullanılan Harici Ağ (isim veya ID)" #, python-format msgid "Failed to add project %(project)s access to flavor: %(e)s" msgstr "%(project)s projesinin flavor'a erişimi başarısız: %(e)s" #, python-format msgid "Failed to add project %(project)s access to type: %(e)s" msgstr "%(project)s projesinin erişiminin şu türe eklenmesi başarısız: %(e)s" #, python-format msgid "Failed to clean snapshot properties: %s" msgstr "Anlık görüntü özellikleri silinirken hata oluştu: %s" #, python-format msgid "Failed to clean volume properties: %s" msgstr "Disk bölümü özelliklerini silme başarısız: %s" #, python-format msgid "Failed to clear flavor property: %s" msgstr "Flavor özelliğinin silinmesi başarısız: %s" #, python-format msgid "Failed to create Network QoS rule: %(e)s" msgstr "Ağ QoS kuralı oluşturulurken hata oluştu: %(e)s" #, python-format msgid "Failed to delete %(dresult)s of %(total)s images." msgstr "%(total)s imajdan %(dresult)s tanesi silinirken hata oluştu." #, python-format msgid "Failed to delete %(resource)s with ID '%(id)s': %(e)s" msgstr "'%(id)s' ID'li %(resource)s silinemedi: %(e)s" #, python-format msgid "Failed to delete %(resource)s with name or ID '%(name_or_id)s': %(e)s" msgstr "" "'%(name_or_id)s' isimli veya ID'li %(resource)s silinirken hata oluştu: %(e)s" #, python-format msgid "" "Failed to delete EC2 credentials with access key '%(access_key)s': %(e)s" msgstr "" "'%(access_key)s' erişim anahtarlı EC2 kullanıcı bilgileri silinemedi: %(e)s" #, python-format msgid "Failed to delete Network QoS rule ID \"%(rule)s\": %(e)s" msgstr "\"%(rule)s\" Ağ QoS kural ID'si silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete QoS policy name or ID '%(qos_policy)s': %(e)s" msgstr "" "'%(qos_policy)s' isim veya ID'li QoS politikası silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete QoS specification with name or ID '%(qos)s': %(e)s" msgstr "" "'%(qos)s' isimli veya ID'li QoS özelliklerini silme işlemi başarısız: %(e)s" #, python-format msgid "Failed to delete RBAC policy with ID '%(rbac)s': %(e)s" msgstr "'%(rbac)s' ID'li RBAC politikası silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete address scope with name or ID '%(scope)s': %(e)s" msgstr "" "'%(scope)s' isimli veya ID'li adres kapsamı silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete agent with ID '%(id)s': %(e)s" msgstr "'%(id)s' ID'li ajanın silinemedi: %(e)s" #, python-format msgid "Failed to delete aggregate with name or ID '%(aggregate)s': %(e)s" msgstr "'%(aggregate)s' isimli veya ID'li küme silinemedi: %(e)s" #, python-format msgid "Failed to delete backup with name or ID '%(backup)s': %(e)s" msgstr "'%(backup)s' isimli veya ID'li yedek silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete compute service with ID '%(service)s': %(e)s" msgstr "'%(service)s' ID'li hesaplama servisini silme işlemi başarısız: %(e)s" #, python-format msgid "" "Failed to delete consistency group snapshot with name or ID '%(snapshot)s': " "%(e)s" msgstr "" "'%(snapshot)s' isim veya ID'li tutarlılık grubu anlık görüntülerini silme " "işlemi başarısız: %(e)s" #, python-format msgid "" "Failed to delete consistency group with name or ID '%(consistency_group)s':" "%(e)s" msgstr "" "'%(consistency_group)s' isim veya ID'li tutarlılık grubunu silerken hata " "oluştu:%(e)s" #, python-format msgid "Failed to delete consumer with name or ID '%(consumer)s': %(e)s" msgstr "'%(consumer)s' ismi ve ID'si ile alıcılar silinirken hata: %(e)s" #, python-format msgid "Failed to delete consumer with type, name or ID '%(service)s': %(e)s" msgstr "" "'%(service)s' türlü, isimli veya ID'li alıcı silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete credentials with ID '%(credential)s': %(e)s" msgstr "'%(credential)s' ID'li kimlik bilgileri silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete domain with name or ID '%(domain)s': %(e)s" msgstr "'%(domain)s' isimli veya ID'li alan silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete endpoint with ID '%(endpoint)s': %(e)s" msgstr "'%(endpoint)s' ID'li uç noktanın silinmesi başarısız: %(e)s" #, python-format msgid "" "Failed to delete federation protocol with name or ID '%(protocol)s': %(e)s" msgstr "" "'%(protocol)s' isimli veya ID'li federasyon protokolü silinirken hata " "oluştu: %(e)s" #, python-format msgid "Failed to delete flavor profile with ID '%(flavor_profile)s': %(e)s" msgstr "" "'%(flavor_profile)s' ID'li flavor profili silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete flavor with name or ID '%(flavor)s': %(e)s" msgstr "'%(flavor)s' isimli veya ID'li flavor'ı silme işlemi başarısız: %(e)s" #, python-format msgid "Failed to delete group with name or ID '%(group)s': %(e)s" msgstr "'%(group)s' isimli veya ID'li grup silinirken hata oluştu: %(e)s" #, python-format msgid "" "Failed to delete identity providers with name or ID '%(provider)s': %(e)s" msgstr "" "'%(provider)s' isim veya ID'li kimlik sağlayıcılar silinirken hata oluştur: " "%(e)s" #, python-format msgid "Failed to delete image with name or ID '%(image)s': %(e)s" msgstr "'%(image)s' isimli veya ID'li imaj silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete key with name '%(name)s': %(e)s" msgstr "'%(name)s' isimli anahtarın silinmesi başarısız: %(e)s" #, python-format msgid "Failed to delete mapping with name or ID '%(mapping)s': %(e)s" msgstr "" "%(mapping)s' isimli veya ID'li eşleştirme silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete meter rule with ID '%(id)s': %(e)s" msgstr "'%(id)s' ID'li ölçüm kuralını silme işlemi başarısız: %(e)s" #, python-format msgid "Failed to delete meter with ID '%(meter)s': %(e)s" msgstr "'%(meter)s' ID'li ölçek silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete network agent with ID '%(agent)s': %(e)s" msgstr "'%(agent)s' ID'li ağ ajanının silinmesi başarısız: %(e)s" #, python-format msgid "Failed to delete network segment with ID '%(network_segment)s': %(e)s" msgstr "'%(network_segment)s' ID'li ağ dilimleri silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete policy with name or ID '%(policy)s': %(e)s" msgstr "'%(policy)s' isimli veya ID'li politika silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete port with name or ID '%(port)s': %(e)s" msgstr "" "'%(port)s' isimli veya ID'li bağlantı noktası silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete project with name or ID '%(project)s': %(e)s" msgstr "'%(project)s' isimli veya ID'li projeyi silme işlemi başarısız: %(e)s" #, python-format msgid "Failed to delete region with ID '%(region)s': %(e)s" msgstr "'%(region)s' ID'li bölge silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete role with name or ID '%(role)s': %(e)s" msgstr "'%(role)s' isim veya ID'li rolün silme işlemi başarısız: %(e)s" #, python-format msgid "Failed to delete router with name or ID '%(router)s': %(e)s" msgstr "" "'%(router)s' isimli veya ID'li yönlendiriciyi silme işlemi başarısız: %(e)s" #, python-format msgid "Failed to delete service provider with name or ID '%(provider)s': %(e)s" msgstr "" "'%(provider)s' isimli veya ID'li servis sağlayıcıyı silme işlemi başarısız: " "%(e)s" #, python-format msgid "Failed to delete service with name or ID '%(service)s': %(e)s" msgstr "'%(service)s' isimli veya ID'li servisi silme başarısız: %(e)s" #, python-format msgid "Failed to delete snapshot with name or ID '%(snapshot)s': %(e)s" msgstr "" "'%(snapshot)s' isimli veya ID'li anlık görüntüyü silme başarısız: %(e)s" #, python-format msgid "Failed to delete subnet pool with name or ID '%(pool)s': %(e)s" msgstr "" "'%(pool)s' isimli veya ID'li altağ havuzu silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to delete subnet with name or ID '%(subnet)s': %(e)s" msgstr "'%(subnet)s' isim veya ID'li altağı silerken hata oluştu: %(e)s" #, python-format msgid "Failed to delete trust with name or ID '%(trust)s': %(e)s" msgstr "" "'%(trust)s' ismine veya ID'sine sahip güvenin silinmesi başarısız: %(e)s" #, python-format msgid "Failed to delete user with name or ID '%(user)s': %(e)s" msgstr "'%(user)s' isimli veya ID'li kullanıcının silinmesi başarısız: %(e)s" #, python-format msgid "" "Failed to delete volume transfer request with name or ID '%(transfer)s': " "%(e)s" msgstr "" "'%(transfer)s' isimli veya ID'li disk bölümü aktarım isteği silinirken hata " "oluştu: %(e)s" #, python-format msgid "Failed to delete volume type with name or ID '%(volume_type)s': %(e)s" msgstr "" "'%(volume_type)s' isimli veya ID'li disk bölümü türünü silerken hata oluştu: " "%(e)s" #, python-format msgid "Failed to delete volume with name or ID '%(volume)s': %(e)s" msgstr "" "'%(volume)s' isimli veya ID'li disk bölümü silinirken hata oluştu: %(e)s" #, python-format msgid "Failed to display the encryption information of this volume type: %s" msgstr "Bu disk bölümü türü için şifreleme bilgisini gösterme başarısız: %s" #, python-format msgid "Failed to find volume with name or ID '%(volume)s':%(e)s" msgstr "'%(volume)s' isimli veya ID'li disk bölümü bulunamadı: %(e)s" #, python-format msgid "Failed to get access project list for volume type %(type)s: %(e)s" msgstr "" "%(type)s disk bölümü türür için proje listesine erişim sağlama başarısız: " "%(e)s" #, python-format msgid "Failed to get access projects list for flavor '%(flavor)s': %(e)s" msgstr "" "'%(flavor)s' flavor için erişen projelerin listesinin alınma işlemi " "başarısız: %(e)s" msgid "Failed to get an image file." msgstr "İmaj dosyası alma başarısız." #, python-format msgid "Failed to remove flavor access from project: %s" msgstr "Projeden flavor erişiminin kaldırılması başarısız: %s" #, python-format msgid "Failed to remove the encryption type for this volume type: %s" msgstr "Bu disk bölümü türü için şifreleme türünü silme başarısız: %s" #, python-format msgid "Failed to remove volume type access from project: %s" msgstr "Projeden disk bölümü türü erişimi kaldırılırken hata oluştu: %s" msgid "Failed to retrieve extensions list from Network API" msgstr "Ağ API'ından uzantı listesinin alınması başarısız" #, python-format msgid "Failed to set Network QoS rule ID \"%(rule)s\": %(e)s" msgstr "\"%(rule)s\" Ağ QoS kural ID'sini ayarlarken hata oluştu: %(e)s" #, python-format msgid "Failed to set backup state: %s" msgstr "Yedek durumunu ayarlama başarısız: %s" #, python-format msgid "Failed to set encryption information for this volume type: %s" msgstr "Bu disk bölümü türü için şifreleme bilgisini ayarlama başarısız: %s" #, python-format msgid "Failed to set flavor access to project: %s" msgstr "Projeye flavor erişiminin ayarlanması başarısız: %s" #, python-format msgid "Failed to set flavor property: %s" msgstr "Flavor özelliğinin ayarlanması başarısız: %s" #, python-format msgid "Failed to set image property: %s" msgstr "İmaj özelliği ayarlarken hata oluştu: %s" #, python-format msgid "Failed to set snapshot property: %s" msgstr "Anlık görüntü özelliğini ayarlama başarısız: %s" #, python-format msgid "Failed to set snapshot state: %s" msgstr "Anlık görüntü durumunu ayarlama başarısız: %s" #, python-format msgid "Failed to set volume bootable property: %s" msgstr "Disk bölümü ön yükleme özelliği ayarlanırken hata oluştu: %s" #, python-format msgid "Failed to set volume property: %s" msgstr "Disk özelliklerini ayarlama işlemi başarısız: %s" #, python-format msgid "Failed to set volume read-only access mode flag: %s" msgstr "Disk bölümü salt okunur erişim kipi bayrağı ayarlanamadı: %s" #, python-format msgid "Failed to set volume size: %s" msgstr "Disk bölümü boyutunu ayarlama başarısız: %s" #, python-format msgid "Failed to set volume state: %s" msgstr "Disk bölümü durumunu ayarlama başarısız: %s" #, python-format msgid "Failed to set volume type access to project: %s" msgstr "Projeye erişim için disk bölümü türü ayarlama başarısız: %s" #, python-format msgid "Failed to set volume type property: %s" msgstr "Disk bölümü türü özelliğini ayarlarken hata oluştu: %s" #, python-format msgid "Failed to set volume type: %s" msgstr "Disk bölümü türü ayarlanırken hata oluştu: %s" #, python-format msgid "Failed to unset %(propret)s of %(proptotal)s properties." msgstr "" "%(proptotal)s özellikten %(propret)s özelliğin ayarının kaldırılması " "başarısız." #, python-format msgid "" "Failed to unset %(tagret)s of %(tagtotal)s tags,Failed to unset %(propret)s " "of %(proptotal)s properties." msgstr "" "%(tagtotal)s etiketten %(tagret)s tanesinin ayarlarını kaldırmak başarısız, " "%(proptotal)s özellikten %(propret)s özelliğin ayarının kaldırılması " "başarısız." #, python-format msgid "Failed to unset %(tagret)s of %(tagtotal)s tags." msgstr "" "%(tagtotal)s etiketin %(tagret)s tanesinin ayarının kaldırılması başarısız" #, python-format msgid "Failed to unset flavor property: %s" msgstr "Flavor özelliğini kaldırma işlemi başarısız: %s" #, python-format msgid "Failed to unset image property: %s" msgstr "İmaj özelliği ayarını kaldırma başarısız: %s" #, python-format msgid "Failed to unset volume property: %s" msgstr "Disk bölümü özelliği ayarlarını kaldırma başarısız: %s" #, python-format msgid "Failed to unset volume type property: %s" msgstr "Disk bölümü türü özelliğini kaldırma işlemi başarısız: %s" #, python-format msgid "Failed to update backup name or description: %s" msgstr "Yedek ismi ve açıklaması güncellenirken hata oluştu: %s" #, python-format msgid "Failed to update snapshot display name or display description: %s" msgstr "" "Anlık görüntü görünür ismi veya görünür açıklamasını güncelleme işlemi " "başarısız: %s" #, python-format msgid "Failed to update snapshot name or description: %s" msgstr "Anlık görüntü adı veya açıklaması güncellenemedi: %s" #, python-format msgid "Failed to update volume display name or display description: %s" msgstr "" "Disk bölümü gösterim ismi veya gösterim açıklamasını güncelleme başarısız: %s" #, python-format msgid "Failed to update volume type name or description: %s" msgstr "Disk bölümü türü ismi veya açıklaması güncellenirken hata oluştu: %s" msgid "Failover volume host to different backend" msgstr "Disk bölümü anabilgisayarını başka arka yüze devret" msgid "Federation protocol to display (name or ID)" msgstr "Gösterilecek federasyon protokolü (isim veya ID)" msgid "Federation protocol to modify (name or ID)" msgstr "Düzenlenecek federasyon protokolü (isim veya ID)" msgid "Federation protocol(s) to delete (name or ID)" msgstr "Silinecek federasyon protokol(ü/leri) (isim veya ID)" msgid "" "File to inject into image before boot (repeat option to set multiple files)" msgstr "" "Önyüklemeden önce imaja enjekte etmek için dosya (birden çok dosyayı " "ayarlamak için seçeneği tekrar edin)" msgid "" "Filename for private key to save. If not used, print private key in console." msgstr "" "Kapalı anahtarın kaydedileceği dosyanın ismi. Kullanılmazsa, kapalı anahtar " "konsola basılır." msgid "Filename for public key to add. If not used, creates a private key." msgstr "" "Eklenecek açık anahtarın dosya ismi. Kullanılmazsa, bir kapalı anahtar " "oluşturur." msgid "Filename that contains a new set of mapping rules" msgstr "Eşleşme kurallarının yeni bir kümesini içeren dosya adı" msgid "Filename that contains a set of mapping rules (required)" msgstr "Eşleştirme kuralları kümesi içeren dosya adı (gerekli)" msgid "Filter by interface type (admin, public or internal)" msgstr "Arayüz türüne göre filtrele (yönetici, genele açık veya dahili)" msgid "Filter by parent region ID" msgstr "Üst bölge ID'sine göre filtrele" msgid "Filter by region ID" msgstr "Bölge ID'sine göre filtrele" msgid "Filter by service (type, name or ID)" msgstr "Servise göre filtrele (tür, isim veya ID)" msgid "Filter credentials by (name or ID)" msgstr "Kimlik bilgilerini 'ya göre filtrele (isim veya ID)" msgid "Filter credentials by type: cert, ec2" msgstr "Kimlik bilgilerinin türe göre filtrele: cert, ec2" msgid "Filter group list by (name or ID)" msgstr "Grup listesini 'e göre filtrele (isim veya ID)" msgid "Filter group list by (name or ID)" msgstr "'ya göre grup listesini filtrele (isim veya ID)" msgid "Filter hypervisors using substring" msgstr "" " alt karakter dizisini kullanarak yönetici arakatmanları filtrele" msgid "Filter images based on name." msgstr "İmajları isme göre filtrele." msgid "Filter images based on status." msgstr "İmajları duruma göre filtrele." msgid "Filter list by user (name or ID)" msgstr "Listeyi kullanıcıya göre filtrele (isim veya ID)" msgid "Filter list using " msgstr " kullanarak listeyi filtrele" msgid "Filter output based on property" msgstr "Çıktıyı özelliğe göre filtrele" msgid "Filter projects by (name or ID)" msgstr "Projeleri 'e göre filtrele (isim veya ID)" msgid "Filter projects by (name or ID)" msgstr "Projeleri 'ya göre filtrele (isim veya ID)" msgid "Filter results by project (name or ID) (admin only)" msgstr "Sonuçları projeye göre filtrele (isim veya ID) (sadece yönetici)" msgid "Filter results by status" msgstr "Sunuçları duruma göre filtrele" msgid "Filter results by user (name or ID) (admin only)" msgstr "Sonuçları kullanıcıya göre filtrele (isim veya ID) (sadece yönetici)" msgid "Filter results by volume name" msgstr "Sonuçları disk bölümü ismine göre filtrele" msgid "Filter roles by (name or ID)" msgstr "Rolleri 'ye göre filtrele (isim veya ID)" msgid "Filter roles by (name or ID)" msgstr "Rolleri 'ya göre filtrele (isim veya ID)" msgid "Filter users by (name or ID)" msgstr "Kullanıcıları 'e göre filtrele (isim veya ID)" msgid "Filter users by membership (name or ID)" msgstr " üyeliğine göre kullanıcıları filtrele (isim veya ID)" msgid "Filter users by (name or ID)" msgstr "Kullanıcıları 'ye göre filtrele (isim veya ID)" msgid "Filter users by project (name or ID)" msgstr "Kullanıcıları projeye göre filtrele (isim veya ID)" msgid "Filters results by a consistency group (name or ID)" msgstr "Bir tutarlılık grubuna göre sonuçları filtrele (isim veya ID)" msgid "Filters results by a name." msgstr "Bir isme göre sonuçları filtrele." msgid "" "Filters results by a status (\"available\", \"error\", \"creating\", " "\"deleting\" or \"error_deleting\")" msgstr "" "Sonuçları bir duruma göre filtrele (\"available\", \"error\", \"creating\", " "\"deleting\" veya \"error_deleting\")" msgid "" "Filters results by a status. ('available', 'error', 'creating', 'deleting' " "or 'error-deleting')" msgstr "" "Bir duruma göre sonuçları filtrele. ('kullanılabilir', 'hata', " "'oluşturuluyor', 'siliniyor' veya 'silinirken hata')" msgid "Filters results by a volume (name or ID)." msgstr "Bir disk bölümüne göre sonuçları filtrele (isim veya ID)." msgid "Filters results by the backup name" msgstr "Yedek ismine göre sonuçları listele" msgid "" "Filters results by the backup status ('creating', 'available', 'deleting', " "'error', 'restoring' or 'error_restoring')" msgstr "" "Yedek durumuna göre sonuçları filtrele ('oluşturuluyor', 'kullanılabilir', " "'siliniyor', 'hata' veya 'geri yüklenirken hata')" msgid "Filters results by the volume which they backup (name or ID)" msgstr "Yedeklenen disk bölümüne göre sonuçları filtrele (isim veya ID)" msgid "Fixed IP address mapped to the floating IP" msgstr "Sabit IP adres yüzen IP adresi ile eşleşti" msgid "Fixed IP address to associate with this floating IP address" msgstr "Bu kayan IP adresi ile ilişkili sabit IP adresi" msgid "Fixed IP address to remove from the server (IP only)" msgstr "Sunucudan kaldırılacak sabit IP adresi (sadece IP)" msgid "Fixed IP of the port (required only if port has multiple IPs)" msgstr "" "Bağlantı noktasının sabit IP'si (yalnızca bağlantı noktası birden fazla IP " "bulunduğunda gereklidir)" msgid "Flavor is available to other projects (default)" msgstr "Flavor diğer projeler için kullanılabilirdir (varsayılan)" msgid "Flavor is not available to other projects" msgstr "Flavor diğer projelerde kullanılabilir değildir" msgid "Flavor profile to display (ID only)" msgstr "Gösterilecek flavor profili (sadece ID)" msgid "Flavor profile to update (ID only)" msgstr "Güncellenecek flavor profili (sadece ID)" msgid "Flavor profile(s) to delete (ID only)" msgstr "Silinecek flavor profilleri (sadece ID)" msgid "Flavor to display (name or ID)" msgstr "Gösterilecek flavor (isim veya ID)" msgid "Flavor to modify (name or ID)" msgstr "Düzenlenecek flavor (isim veya ID)" msgid "Flavor to update (name or ID)" msgstr "Güncellenecek flavor (isim veya ID)" msgid "Flavor(s) to delete (name or ID)" msgstr "Silinecek flavor(lar) (isim veya ID)" msgid "Floating IP address" msgstr "Yüzen IP adresi" msgid "Floating IP address to assign to server (IP only)" msgstr "Sunucuya atanacak kayan IP adresi (sadece IP)" msgid "Floating IP address to remove from server (IP only)" msgstr "Sunucudan kaldırılacak kayan IP adresi (sadece IP)" msgid "Floating IP to associate (IP address or ID)" msgstr "İlişkilendirilecek yüzen IP adresi (IP adres veya ID)" msgid "Floating IP to disassociate (IP address or ID)" msgstr "Bağlantıyı kesmek için kayan IP (IP adresi veya kimliği)" msgid "Floating IP to display (IP address or ID)" msgstr "Görüntülenecek kayan IP (IP adresi veya kimliği)" msgid "Floating IP(s) to delete (IP address or ID)" msgstr "Silinecek yüzen IP(ler) (IP adres veya ID)" msgid "Floating ip pool operations are only available for Compute v2 network." msgstr "" "Yüzen IP havuz işlemleri sadece Hesaplama v2 ağı için kullanılabilirdir." msgid "Force down service" msgstr "Servisi durmaya zorla" msgid "Force image change if volume is in use (only meaningful with --volume)" msgstr "" "Disk bölümü kullanımda ise imajı değişmeye zorla (sadece --volume ile " "anlamlıdır)" msgid "" "Force image creation if volume is in use (only meaningful with --volume)" msgstr "" "Disk bölümü kullanımda ise imaj oluşturmaya zorla (sadece --volume ile " "anlamlıdır)" msgid "Force up service" msgstr "Servisi açılmaya zorla" msgid "Freeze and disable the specified volume host" msgstr "Belirtilen disk bölümü sunucusunu dondur ve devre dışı bırak" msgid "Group containing (name or ID)" msgstr "'ı içeren grup (isim veya ID)" msgid "Group to check (name or ID)" msgstr "Kontrol edilecek grup (isim veya ID)" msgid "Group to contain (name or ID)" msgstr "'ı içeren grup (isim veya ID)" msgid "Group to display (name or ID)" msgstr "Gösterilecek grup (isim veya ID)" msgid "Group to filter (name or ID)" msgstr "Filtrelenecek grup (isim veya ID)" msgid "Group to modify (name or ID)" msgstr "Düzenlenecek grup (isim veya ID)" msgid "Group(s) to delete (name or ID)" msgstr "Silinecek grup(lar) (isim veya ID)" msgid "Helper class capable of reading rules from files" msgstr "Yardımcı sınıf kuralları dosyadan okuyabilir" msgid "Hints for the scheduler (optional extension)" msgstr "Zamanlayıcı için ipuçları (isteğe bağlı eklenti)" msgid "Host to add to " msgstr " için eklenecek sunucu" msgid "Host to modify (name only)" msgstr "Düzenlenecek sunucu (isim sadece)" msgid "Host to remove from " msgstr "'den kaldırılacak sunucu" msgid "Hypervisor to display (name or ID)" msgstr "Gösterilecek yönetici arakatman (isim veya ID)" msgid "ICMP IP protocol required with arguments --icmp-type and --icmp-code" msgstr "" "ICMP IP protokolü --icmp-type ve --icmp-code argümanları ile zorunludur" msgid "ICMP code for ICMP IP protocols" msgstr "ICMP IP protokolleri için ICMP kodu" msgid "ICMP type for ICMP IP protocols" msgstr "ICMP IP protokolü için ICMP türü" msgid "ID of agent(s) to delete" msgstr "Silinecek ajanların ID'si" msgid "ID of credential to change" msgstr "Değiştirilecek kimlik bilgilerinin ID'si" msgid "ID of credential to display" msgstr "Gösterilecek kimlik bilgilerinin ID'si" msgid "ID of credential(s) to delete" msgstr "Silinecek kimlik bilgilerinin ID'si" msgid "ID of kernel image used to boot this disk image" msgstr "Bu disk imajını ön yüklemek için kullanılan çekirdek imajının kimliği" msgid "ID of ramdisk image used to boot this disk image" msgstr "Bu disk imajını önyüklemek için kullanılan ramdisk imajının kimliği" msgid "ID of server instance used to create this image" msgstr "Bu imajı oluşturmak için kullanılan sunucu örneği kimliği" msgid "ID of the agent" msgstr "Ajanın ID'si" msgid "IP address to add to server (name only)" msgstr "Sunucuya eklenecek IP adresi (sadece isim)" msgid "IP address to remove from server (name only)" msgstr "Sunucudan kaldırılacak IP adresi (sadece isim)" msgid "" "IP protocol (ah, dccp, egp, esp, gre, icmp, igmp, ipv6-encap, ipv6-frag, " "ipv6-icmp, ipv6-nonxt, ipv6-opts, ipv6-route, ospf, pgm, rsvp, sctp, tcp, " "udp, udplite, vrrp and integer representations [0-255]; default: tcp)" msgstr "" "IP protokolü (ah, dccp, egp, esp, gre, icmp, igmp, ipv6-encap, ipv6-frag, " "ipv6-icmp, ipv6-nonxt, ipv6-opts, ipv6-route, ospf, pgm, rsvp, sctp, tcp, " "udp, udplite, vrrp ve tam sayı gösterimi [0-255]; varsayılan: tcp)" msgid "IP protocol (icmp, tcp, udp; default: tcp)" msgstr "IP protokolü (icmp, tcp, udp; varsayılan: tcp)" msgid "IP version (default is 4)" msgstr "IP sürümü (varsayılan 4)" msgid "" "IP version (default is 4). Note that when subnet pool is specified, IP " "version is determined from the subnet pool and this option is ignored." msgstr "" "IP sürümü (varsayılan 4). Alt ağ havuzu belirtildiğinde, IP sürümü alt ağ " "havuzundan belirlenir ve bu seçenek göz ardı edilir." msgid "IPv4 subnet for fixed IPs (in CIDR notation)" msgstr "Sabit IP'ler için IPv4 alt ağı (CIDR gösteriminde)" msgid "" "IPv6 RA (Router Advertisement) mode, valid modes: [dhcpv6-stateful, dhcpv6-" "stateless, slaac]" msgstr "" "IPv6 (Yönlendirici İlanı) kipi, geçerli kipler: [dhcpv6-stateful, dhcpv6-" "stateless, slaac]" msgid "" "IPv6 address mode, valid modes: [dhcpv6-stateful, dhcpv6-stateless, slaac]" msgstr "" "IPv6 adres kipi, geçerli kipler: [dhcpv6-stateful, dhcpv6-stateless, slaac]" #, python-format msgid "Identity API version, default=%s (Env: OS_IDENTITY_API_VERSION)" msgstr "Kimlik API sürümü, varsayılan=%s (Env: OS_IDENTITY_API_VERSION)" msgid "" "Identity provider that supports (name or ID) (required)" msgstr "" "'ü destekleyen kimlik sağlayıcı (isim veya ID) (gerekli)" msgid "" "Identity provider that will support the new federation protocol (name or " "ID) (required)" msgstr "" "Yeni federasyon protokolünü destekleyecek kimlik sağlayıcı (isim veya ID) " "(gerekli)" msgid "Identity provider to display" msgstr "Gösterilecek kimlik sağlayıcı" msgid "Identity provider to list (name or ID) (required)" msgstr "Listelenecek kimlik sağlayıcı (isim veya ID) (gerekli)" msgid "Identity provider to modify" msgstr "Düzenlenecek kimlik sağlayıcıları" msgid "Identity provider(s) to delete" msgstr "Silinecek kimlik sağlayıcı(lar)" msgid "" "If specified, the volume state will be locked and will not allow a migration " "to be aborted (possibly by another operation)" msgstr "" "Belirtilirse, disk bölümü durumu kilitlenir ve geçiş işleminin iptal " "edilmesine izin vermeyecektir (muhtemelen başka bir işlemle)" msgid "" "If specified, the volume state will not be locked and the a migration can be " "aborted (default) (possibly by another operation)" msgstr "" "Belirtilirse, disk bölümü durumu kilitlenmez ve bir taşıma işlemi iptal " "edilebilir (varsayılan) (muhtemelen başka bir işlemle)" msgid "If topology exists returns the topology's information (Default)" msgstr "Topoloji var ise, topolojinin bilgisini döndürür (Varsayılan)" #, python-format msgid "Image %(id)s was %(status)s." msgstr "%(id)s imaj %(status)s idi." #, python-format msgid "Image API version, default=%s (Env: OS_IMAGE_API_VERSION)" msgstr "İmaj API sürümü, öntanımlı=%s (Env: OS_IMAGE_API_VERSION)" msgid "Image ID to reserve" msgstr "Ayrılacak imaj ID'si" msgid "Image can be shared" msgstr "İmaj paylaşılabilir" #, python-format msgid "" "Image container format. The supported options are: %(option_list)s. The " "default format is: %(default_opt)s" msgstr "" "İmaj kap biçemi. Desteklenen seçenekler: %(option_list)s. Varsayılan biçem: " "%(default_opt)s" #, python-format msgid "Image container format. The supported options are: %s" msgstr "İmaj kap biçimi. Desteklenen seçenekler: %s" #, python-format msgid "Image disk format. The supported options are: %s" msgstr "İmaj disk biçimi. Desteklenen seçenekler: %s" #, python-format msgid "Image disk format. The supported options are: %s." msgstr "İmaj disk biçemi. Desteklenen seçenekler: %s." #, python-format msgid "" "Image disk format. The supported options are: %s. The default format is: raw" msgstr "" "İmaj disk biçemi. Desteklenen seçenekler: %s. Varsayılan biçem: işlem " "görmemiş" msgid "Image hash used for verification" msgstr "Doğrulama için kullanılan imaj özeti" msgid "Image is accessible to the community" msgstr "İmaj topluluk tarafından erişilebilir" msgid "Image is accessible to the public" msgstr "İmaj genele açıktır" msgid "Image is inaccessible to the public (default)" msgstr "İmaj genele açık değildir (varsayılan)" msgid "Image size, in bytes (only used with --location and --copy-from)" msgstr "" "İmaj boyutu, bayt cinsinden (sadece --location ve --copy-from ile kullanılır)" msgid "Image to display (name or ID)" msgstr "Görüntülenecek imaj (ad veya kimlik)" msgid "Image to modify (name or ID)" msgstr "Düzenlenecek imaj (isim veya ID)" msgid "Image to save (name or ID)" msgstr "Kaydedilecek imaj (isim veya ID)" msgid "Image to share (name or ID)" msgstr "Paylaşılacak imaj (isim veya ID)" msgid "Image to unshare (name or ID)" msgstr "Paylaşımdan kaldırılacak imaj (isim veya ID)" msgid "Image(s) to delete (name or ID)" msgstr "Silinecek imaj(lar) (isim veya ID)" msgid "Include (name or ID)" msgstr "'i içer (isim veya ID)" msgid "Include (name or ID)" msgstr "'u içer (isim veya ID)" msgid "Include (name or ID)" msgstr " dahil et (isim veya ID)" msgid "Include (name or ID)" msgstr " dahil et (isim veya ID)" msgid "Include all projects (admin only)" msgstr "Tüm projeleri dahil et (sadece yönetici)" msgid "Include remote IP prefix from traffic count (default)" msgstr "Trafik sayımından uzak IP önekini ekle (varsayılan)" msgid "Include reservations count [only valid with --absolute]" msgstr "Rezervasyon sayısını ekle [sadece --absolute ile geçerlidir]" msgid "" "Incorrect set of arguments provided. See openstack --help for more details" msgstr "" "Yanlış argüman kümesi girildi. Daha fazla detay için openstack --help " "komutunun çıktısına bakınız" msgid "Ingress traffic direction from the project point of view" msgstr "Projenin bakış açısından gelen trafik yönü" #, python-format msgid "Invalid argument %s, characters ',' and '=' are not allowed" msgstr "%s geçersiz değişken, ',' ve '=' karakterlerine izin verilmiyor" #, python-format msgid "Invalid changes-since value: %s" msgstr "Geçersiz değişiklikler-şu değerden beri:%s" #, python-format msgid "" "Invalid nic argument '%s'. Nic arguments must be of the form --nic ." msgstr "" "Geçersiz '%s' nic argümanı, Nic argümanları --nic biçiminde olmalıdır." msgid "Issue new token" msgstr "Yeni jeton yayınla" #, python-format msgid "Key file %(private_key)s can not be saved: %(exception)s" msgstr "%(private_key)s anahtar dosyası kaydedilemedi: %(exception)s" #, python-format msgid "Key file %(public_key)s not found: %(exception)s" msgstr "%(public_key)s anahtar dosyası bulunamadı: %(exception)s" msgid "Keypair to inject into this server (optional extension)" msgstr "Bu sunucuya enjekte etmek için anahtarlık (isteğe bağlı uzantı)" msgid "Label to associate with this metering rule (name or ID)" msgstr "Bu ölçüm kuralı ile ilişkili etiket (isim veya ID)" msgid "Limit the number of containers returned" msgstr "İade edilen kap sayısını sınırla" msgid "Limit the number of objects returned" msgstr "Döndürülen nesnelerin sayısını sınırla" #, python-format msgid "List %s which have all given tag(s) (Comma-separated list of tags)" msgstr "" "Verilen tüm etiketlere sahip olan %s'i listele (Virgül ile ayrılmış etiket " "listesi)" #, python-format msgid "List %s which have any given tag(s) (Comma-separated list of tags)" msgstr "" "Verilen tüm etiketlere sahip olan %s'i listele (Virgül ile ayrılmış etiket " "listesi)" msgid "List API extensions" msgstr "API uzantılarını listele" msgid "List EC2 credentials" msgstr "EC2 kimlik bilgilerini listele" msgid "List IP availability for network" msgstr "Ağ için IP kullanılabilirliğini listele" msgid "List IP availability of given IP version networks (default is 4)" msgstr "" "Verilen IP sürüm ağlarının IP kullanılabilirliğini listele (varsayılan sürüm " "4)" msgid "List IP availability of given project (name or ID)" msgstr "Verilen projenin IP kullanılabilirliğini listeleyin (isim veya ID)" msgid "List Network QoS rules" msgstr "Ağ QoS kurallarını listele" msgid "List QoS policies" msgstr "QoS politikaları listesi" msgid "List QoS rule types" msgstr "QoS kural türlerini listele" msgid "List QoS specifications" msgstr "QoS özelliklerini listele" msgid "List Service Providers" msgstr "Servis Sağlayıcıları listele" msgid "List a project's resources" msgstr "Bir projenin kaynaklarını listele" msgid "List accessible domains" msgstr "Erişilebilir alanları listele" msgid "List accessible projects" msgstr "Erişilebilir projeleri listele" msgid "List additional fields in output" msgstr "Çıktıdaki ek alanları listele" msgid "List address scopes" msgstr "Adres kapsamlarını listele" msgid "List address scopes according to their project (name or ID)" msgstr "Adres kapsamlarını projelerine göre listele (ad veya kimlik)" msgid "List address scopes not shared between projects" msgstr "Projeler arasında paylaşılmayan adres kapsamlarını listele" msgid "List address scopes of given IP version networks (4 or 6)" msgstr "Verilen IP sürüm ağlarının adres kapsamlarını listele (4 veya 6)" msgid "List address scopes shared between projects" msgstr "Projeler arasında paylaşılan adres kapsamlarını listele" msgid "List agents hosting a network (name or ID)" msgstr "Bir ağa ev sahipliği yapan ajanları listele (isim veya ID)" msgid "List agents hosting this router (name or ID)" msgstr "Bu yönlendiriciyi barındıran ajanları listele (isim veya ID)" msgid "List all aggregates" msgstr "Tüm kümeleri listele" msgid "List all containers (default is 10000)" msgstr "Tüm kapları listlele (varsayılan 10000)" msgid "List all flavors, whether public or private" msgstr "Herkese açık veya gizli bütün flavorları listele" msgid "List all objects in container (default is 10000)" msgstr "Kaptaki tüm nesneleri listele (varsayılan 1000)" msgid "List all rules in this security group (name or ID)" msgstr "Bu güvenlik grubundaki tüm kuralları listele (isim veya ID)" msgid "List all server groups." msgstr "Bütün sunucu gruplarını listele." msgid "List availability zones and their status" msgstr "Kullanılabilirlik alanlarını ve durumlarını listele" msgid "List available images" msgstr "Kullanılabilir imajlar listesi" msgid "List backups" msgstr "Yedekleri listele" msgid "List compute agents" msgstr "Hesaplama ajanlarını listele" msgid "List compute availability zones" msgstr "Hesaplama kullanılabilirlik alanlarını listele" msgid "List compute quota" msgstr "Hesaplama kotasını listele" msgid "List compute services" msgstr "Hesaplama servislerini listele" msgid "List consistency group snapshots." msgstr "Tutarlılık grubu anlık görüntülerini listele." msgid "List consistency groups." msgstr "Tutarlılık gruplarını listele." msgid "List consumers" msgstr "Alıcıları listele" msgid "List containers" msgstr "Kapları listele" msgid "List credentials" msgstr "Kimlik bilgilerini listele" msgid "List disabled networks" msgstr "Devre dışı bırakılan ağları listele" msgid "List disabled routers" msgstr "Devre dışı bırakılmış yönlendiricileri listele" msgid "List domains" msgstr "Alanları listele" msgid "List enabled networks" msgstr "Aktif ağları listele" msgid "List enabled routers" msgstr "Etkinleştirilmiş yönlendiricileri listele" msgid "List endpoints" msgstr "Uç noktaları listele" msgid "List extensions for the Block Storage API" msgstr "Blok Depolama API için uzantıları listele" msgid "List extensions for the Compute API" msgstr "Hesaplama API için uzantıları listele" msgid "List extensions for the Identity API" msgstr "Kimlik API için uzantıları listele" msgid "List extensions for the Network API" msgstr "Ağ API için uzantıları listele" msgid "List external networks" msgstr "Harici ağları listele" msgid "List federation protocols" msgstr "Federasyon protokollerinin listele" msgid "List flavors" msgstr "Flavorları listele" msgid "List floating IP(s)" msgstr "Yüzen IP(ler) listesi" msgid "List floating IP(s) according to given fixed IP address" msgstr "Verilen sabit IP adresine göre yüzen IP(ler) listesi" msgid "List floating IP(s) according to given network (name or ID)" msgstr "Verilen ağdaki yüzen IP(ler) listesi (isim veya ID)" msgid "List floating IP(s) according to given port (name or ID)" msgstr "Verilen bağlantı noktasına göre yüzen IP(ler) listesi (isim veya ID)" msgid "List floating IP(s) according to given project (name or ID)" msgstr "Verilen projeye göre yüzen IP(ler)i listele (isim veya ID)" msgid "List floating IP(s) according to given router (name or ID)" msgstr "Verilen yönlendiriciye göre yüzen IP(ler)i listele (isim veya ID)" msgid "List floating IP(s) according to given status ('ACTIVE', 'DOWN')" msgstr "Verilen duruma göre yüzen IP(ler) listesi ('AKTİF', 'KAPALI')" msgid "List groups" msgstr "Grupları listele" msgid "List hosts" msgstr "Sunucuları listele" msgid "List hypervisors" msgstr "Yönetici arakatman listesi" msgid "List identity providers" msgstr "Kimlik sağlayıcılarını listele" msgid "List internal networks" msgstr "Dahili ağları listele" msgid "List key fingerprints" msgstr "Anahtar parmak izlerini listele" msgid "List mappings" msgstr "Eşleşme listesi" msgid "List meter rules" msgstr "Ölçek kurallarını listele" msgid "List module versions" msgstr "Modül sürümlerini listele" msgid "List network RBAC policies" msgstr "Ağ RBAC politikalarının listesi" msgid "" "List network RBAC policies according to given action (\"access_as_external\" " "or \"access_as_shared\")" msgstr "" "Verilen eyleme göre ağ RBAC ilkelerini listele (\"access_as_external\" veya " "\"access_as_shared\")" msgid "" "List network RBAC policies according to given object type (\"qos_policy\" or " "\"network\")" msgstr "" "Verilen nesne türüne göre Ağ RBAC politikalarının listesi (\"qos_policy\" " "veya \"network\")" msgid "List network agents" msgstr "Ağ ajanlarını listele" msgid "List network availability zones" msgstr "Ağ kullanılabilirlik alanlarını listele" msgid "List network flavor profile(s)" msgstr "Ağ flavor profil(ler)ini listele" msgid "List network flavors" msgstr "Ağ flavor'larını listele" msgid "List network meters" msgstr "Ağ ölçeklerini listele" msgid "List network quota" msgstr "Ağ kotasını listele" msgid "List network segments" msgstr "Ağ bölümlerini listele" msgid "List network segments that belong to this network (name or ID)" msgstr "Bu ağa ait ağ kesimlerini listeleyin (ad veya kimlik)" msgid "List networks" msgstr "Ağları listele" msgid "" "List networks according to VLAN ID for VLAN networks or Tunnel ID for GENEVE/" "GRE/VXLAN networks" msgstr "" "VLAN ağları için VLAN ID'ye veya GENEVA/GRE/VXLAN ağları için Tünel ID'ye " "göre ağları listele" msgid "List networks according to name of the physical network" msgstr "Ağları fiziksel ağın adına göre listeleme" msgid "List networks according to their name" msgstr "Ağları isimlerine göre listele" msgid "" "List networks according to their physical mechanisms. The supported options " "are: flat, geneve, gre, local, vlan, vxlan." msgstr "" "Ağları fiziksel mekanizmalarına göre listeleyin. Desteklenen seçenekler " "şunlardır: flat, geneve, gre, local, vlan, vxlan." msgid "List networks according to their project (name or ID)" msgstr "Projelerine göre ağları listele (isim veya ID)" msgid "" "List networks according to their status ('ACTIVE', 'BUILD', 'DOWN', 'ERROR')" msgstr "" "Ağları durumlarına göre listeleyin ('AKTİF', 'KURMA', 'KAPALI', 'HATA')" msgid "List networks hosted by agent (ID only)" msgstr "Aracı tarafından barındırılan ağları listele (yalnızca ID)" msgid "List networks not shared between projects" msgstr "Projeler arasında paylaşılmayan ağları listele" msgid "List networks shared between projects" msgstr "Projeler arasında paylaşılan ağları listele" msgid "List objects" msgstr "Nesneleri listele" msgid "List only address scopes of given name in output" msgstr "Çıktıda verilen adın sadece adres kapsamlarını listeleyin" msgid "List only agents running on the specified host" msgstr "Yalnızca belirtilen ana bilgisayarda çalışan ajanları listele" msgid "" "List only agents with the specified agent type. The supported agent types " "are: bgp, dhcp, open-vswitch, linux-bridge, ofa, l3, loadbalancer, metering, " "metadata, macvtap, nic." msgstr "" "Yalnızca belirtilen aracı türü olan aracıları listeleyin. Desteklenen aracı " "türleri şunlardır: bgp, dhcp, open-vswitch, linux-bridge, ofa, l3, " "loadbalancer, metering, metadata, macvtap, nic." msgid "List only ports attached to this router (name or ID)" msgstr "" "Yalnızca bu yönlendiriciye bağlı bağlantı noktalarını listeleyin (adı veya " "ID'si)" msgid "List only ports attached to this server (name or ID)" msgstr "Sadece bu sunucuya takılan bağlantı noktalarını listele (isim veya ID)" msgid "List only ports connected to this network (name or ID)" msgstr "" "Yalnızca bu ağa bağlı bağlantı noktalarını (isim veya kimliğini) listeleyin" msgid "" "List only ports with the specified device owner. This is the entity that " "uses the port (for example, network:dhcp)." msgstr "" "Yalnızca belirtilen aygıt sahibi olan bağlantı noktalarını listeleyin. Bu, " "bağlantı noktasını kullanan varlıktır (örneğin, ağ: dhcp)." msgid "List only ports with this MAC address" msgstr "Sadece bu MAC adresine sahip bağlantı noktalarını listele" msgid "List only private flavors" msgstr "Sadece gizli flavorları listele" msgid "List only private images" msgstr "Sadece gizli imajları listele" msgid "List only private types (admin only)" msgstr "Sadece özel türleri listele (sadece yönetici)" msgid "List only public flavors (default)" msgstr "Sadece herkese açık flavor'ları listele (varsayılan)" msgid "List only public images" msgstr "Sadece genele açık imajları listele" msgid "List only public types" msgstr "Sadece genele açık türleri listele" msgid "" "List only servers changed after a certain point of time. The provided time " "should be an ISO 8061 formatted time. ex 2016-03-04T06:27:59Z ." msgstr "" "Yalnızca belirli bir zaman noktasından sonra sunucuları listeleyin. Verilen " "süre bir ISO 8061 biçiminde olmalıdır. Örn 2016-03-04T06: 27: 59Z ." msgid "List only shared images" msgstr "Sadece paylaşılan imajları listele" msgid "List only specified service (name only)" msgstr "Sadece belirtilen servisleri listele (sadece isim)" msgid "List only subnet pools of given address scope in output (name or ID)" msgstr "" "Verilen adres kapsamındaki sadece altağ havuzlarını çıktıda listele (isim " "veya ID)" msgid "List only subnet pools of given name in output" msgstr "Verilen isimdeki sadece altağ havuzlarını çıktıda listele" msgid "" "List only subnets of a given service type in output e.g.: network:" "floatingip_agent_gateway. Must be a valid device owner value for a network " "port (repeat option to list multiple service types)" msgstr "" "Çıktıda verilen servisin sadece altağlarını listele örn: network:" "floatingip_agent_gateway. Bir ağ bağlantı noktası için geçerli bir aygıt " "sahibi değeri olmalıdır (birden fazla servis türü listelemek için seçeneği " "tekrarla)" msgid "" "List only subnets of given IP version in output.Allowed values for IP " "version are 4 and 6." msgstr "" "Verilen IP sürümünün sadece altağlarını çıktıda listele. IP sürümü için izin " "verilen sürümler 4 ve 6." msgid "List only subnets of given gateway IP in output" msgstr "Verilen geçit IP'sinin sadece alt ağlarını çıktıda listele" msgid "List only subnets of given name in output" msgstr "Verilen isimdeki sadece altağları çıktıda listele" msgid "" "List only subnets of given subnet range (in CIDR notation) in output e.g.: --" "subnet-range 10.10.0.0/16" msgstr "" "Verilen alt ağ aralığında (CIDR notasyonu ile) sadece altağları çıktıda " "listele örn: --subnet-range 10.10.0.0/16" msgid "" "List only subnets which belong to a given network in output (name or ID)" msgstr "Verilen bir ağa ait sadece altağları çıktıda listele (isim veya ID)" msgid "" "List only subnets which belong to a given project in output (name or ID)" msgstr "" "Verilen bir projeye ait sadece altağları çıktıda listele (isim veya ID)" msgid "List policies" msgstr "Politikaları listele" msgid "List pools of floating IP addresses" msgstr "Yüzer IP adresleri havuzlarını listele" msgid "List ports" msgstr "Bağlantı noktalarını listele" msgid "List ports according to their project (name or ID)" msgstr "Projeye bağlı olarak bağlantı noktalarını listele (isim veya ID)" msgid "List projects" msgstr "Projeleri listele" msgid "List projects for the authenticated user. Supersedes other filters." msgstr "" "Yetkilendirilmiş kullanıcı için projeleri listele. Diğer filtrelerin yerini " "alır." msgid "List qos policies according to their project (name or ID)" msgstr "Projelerine göre QoS politikalarını listele (isim veya ID)" msgid "List qos policies not shared between projects" msgstr "Projeler arasında paylaştırılmayan qos ilkelerini listele" msgid "List qos policies shared between projects" msgstr "Projeler arasında paylaşılan qos politikalarını listele" msgid "List quotas for all projects with non-default quota values" msgstr "" "Varsayılan olmayan kota değerlerine sahip tüm projelerin kotalarını listeleme" msgid "List recent events of a server" msgstr "Bir sunucunun son olaylarını listele" msgid "List recognized commands by group" msgstr "Grup tarafından tanınan komutları listele" msgid "List regions" msgstr "Bölgeleri listele" msgid "List resource usage per project" msgstr "Her proje için kaynak kullanımını listele" msgid "List role assignments" msgstr "Rol atamalarını listele" msgid "List roles" msgstr "Rolleri listele" msgid "List routers" msgstr "Yönlendiricilerin listesi" msgid "List routers according to their name" msgstr "Yönlendiricileri isimlerine göre listele" msgid "List routers according to their project (name or ID)" msgstr "Yönlendiricileri projelerine göre listele (isim veya ID)" msgid "List routers hosted by an agent (ID only)" msgstr "Bir ajan tarafından sunulan yönlendiricileri listele (sadece ID)" msgid "List rules applied to incoming network traffic" msgstr "Gelen ağ trafiğine uygulanan kurallar listesi" msgid "List rules applied to outgoing network traffic" msgstr "Giden ağ trafiğine uygulanan kuralları listele" msgid "" "List rules by the IP protocol (ah, dhcp, egp, esp, gre, icmp, igmp, ipv6-" "encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, ipv6-opts, ipv6-route, ospf, pgm, " "rsvp, sctp, tcp, udp, udplite, vrrp and integer representations [0-255])." msgstr "" "Kuralları IP protokolüne göre listele (ah, dhcp, egp, esp, gre, icmp, igmp, " "ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, ipv6-opts, ipv6-route, ospf, " "pgm, rsvp, sctp, tcp, udp, udplite, vrrp ve tam sayı gösterimleri [0-255])" msgid "List security group rules" msgstr "Güvenlik grubu kurallarını listele" msgid "List security groups" msgstr "Güvenlik gruplarını listele" msgid "List security groups according to the project (name or ID)" msgstr "Projeye göre güvenlik grubunu listele (isim veya ID)" msgid "List servers" msgstr "Sunucuları listele" msgid "List service command" msgstr "Servis komutunu listele" msgid "List service providers" msgstr "Servis sağlayıcıları listele" msgid "List services" msgstr "Servisleri listele" msgid "List services in the service catalog" msgstr "Servis katalogundaki servisleri listele" msgid "List services on specified host (name only)" msgstr "Belirtilen sunucu üzerindeki servisleri listele (sadece isim)" msgid "List snapshots" msgstr "Anlık görüntüleri listele" msgid "List subnet pools" msgstr "Altağ havuzlarını listele" msgid "List subnet pools according to their project (name or ID)" msgstr "Alt ağ havuzlarını projelerine göre listele (isim veya ID)" msgid "List subnet pools not shared between projects" msgstr "Projeler arasında paylaşılmayan altağ havularını listele" msgid "List subnet pools not used as the default external subnet pool" msgstr "" "Varsayılan harici altağ havuzu olarak kullanılmayan altağ havuzlarını listele" msgid "List subnet pools shared between projects" msgstr "Projeler arasında paylaşılan altağ havuzlarını listele" msgid "List subnet pools used as the default external subnet pool" msgstr "" "Varsayılan harici altağ havuzu olarak kullanılan altağ havuzlarını listele" msgid "List subnets" msgstr "Alt ağları listele" msgid "List subnets which have DHCP disabled" msgstr "DHCP'nin devre dışı olduğu altağları listele" msgid "List subnets which have DHCP enabled" msgstr "DHCP'nin etkin olduğu altağları listele" msgid "List the default volume type" msgstr "Varsayılan disk bölümü türünü listele" msgid "List trusts" msgstr "Güvenleri listele" msgid "List user-role assignments" msgstr "Kullanıcı rol atamalarını listele" msgid "List users" msgstr "Kullanıcıları listele" msgid "List volume availability zones" msgstr "Disk bölümü kullanılabilirlik alanlarını listele" msgid "List volume backups" msgstr "Disk bölümü yedeklerini listele" msgid "List volume quota" msgstr "Disk bölümü kotasını listele" msgid "List volume snapshots" msgstr "Disk bölümü anlık görüntülerini listele" msgid "List volume types" msgstr "Disk bölümü türlerini listele" msgid "List volumes" msgstr "Disk bölümlerini listele" msgid "" "Listing assignments using role list is deprecated as of the Newton release. " "Use role assignment list --user --project --names " "instead." msgstr "" "Rol listesi kullanarak liste atamaları, Newton sürümünden itibaren " "kullanımdan kaldırılmıştır. Onun yerine rol atama listesi --user " "--project --names komutunu kullanın." msgid "" "Listing assignments using role list is deprecated. Use role assignment list " "--group --domain --names instead." msgstr "" "Rol listesini kullanarak liste atamaları kullanımdan kaldırıldı. Onun yerine " "role assignment list --group --domain --names " "kullanın." msgid "" "Listing assignments using role list is deprecated. Use role assignment list " "--group --project --names instead." msgstr "" "Rol listesini kullanarak liste atamaları kullanımdan kaldırıldı. Onun yerine " "role assignment list --group --project --names " "kullanın." msgid "" "Listing assignments using role list is deprecated. Use role assignment list " "--user --domain --names instead." msgstr "" "Rol listesini kullanarak liste atamaları kullanımdan kaldırıldı. Bunun " "yerine role assignment list --user --domain --" "names kullanın." msgid "" "Listing assignments using role list is deprecated. Use role assignment list " "--user --domain default --names instead." msgstr "" "Rol listesini kullanarak liste atamaları kullanımdan kaldırıldı. Onun yerine " "role assignment list --user --domain default --names kullanın." msgid "" "Listing assignments using role list is deprecated. Use role assignment list " "--user --project --names instead." msgstr "" "Rol listesini kullanarak liste atamaları kullanımdan kaldırıldı. Bunun " "yerine, role assignment list --user --project --" "names kullanın." msgid "" "Listing assignments using user role list is deprecated as of the Newton " "release. Use role assignment list --user --project --names instead." msgstr "" "Atamaları kullanıcı rol listesi kullanarak listelemek Newton sürümünden " "itibaren kullanımdan kaldırılmıştır. Onun yerine role assignment list --user " " --project --names komutunu kullanın." msgid "Lists all volume transfer requests." msgstr "Tüm disk bölümü aktarım isteklerini listele." msgid "Local filename(s) to upload" msgstr "Yüklenecek yerel dosya ad(lar)ı" msgid "Lock server(s). A non-admin user will not be able to execute actions" msgstr "" "Sunucu(ları/yu) kilitle. Yönetici olmayan kullanıcılar işlem yapamayacaktır." msgid "Login name (ssh -l option)" msgstr "Giriş adı (ssh -l seçeneği)" msgid "MAC address of this port (admin only)" msgstr "Bu bağlantı noktasının MAC adresi (yalnızca yönetici)" msgid "MD5 hash" msgstr "MD5 özeti" msgid "MD5 hash of the agent" msgstr "Ajanın MD5 özeti" msgid "Make the QoS policy accessible by other projects" msgstr "QoS ilkesini diğer projeler tarafından erişilebilir hale getirin" msgid "Make the QoS policy not accessible by other projects" msgstr "QoS ilkesine diğer projeler tarafından erişilemez yap" msgid "Make the QoS policy not accessible by other projects (default)" msgstr "" "QoS ilkesine diğer projeler tarafından erişilebilir olmamasını sağlayın " "(varsayılan)" msgid "Make the network VLAN transparent" msgstr "Ağ VLAN'ını transparan yap" msgid "Mapping that is to be used (name or ID)" msgstr "Kullanılacak eşleşme (isim veya ID)" msgid "Mapping that is to be used (name or ID) (required)" msgstr "Kullanılacak eşleştirme (isim veya ID) (gerekli)" msgid "Mapping to display" msgstr "Gösterilecek eşleşme" msgid "Mapping to modify" msgstr "Düzenlenecek eşleşme" msgid "Mapping(s) to delete" msgstr "Silinecek eşletirme(ler)" msgid "Mark volume as bootable" msgstr "Disk bölümünü ön yüklenebilir olarak işaretle" msgid "Mark volume as non-bootable" msgstr "Disk bölümünü ön yüklenebilir olarak işaretle" msgid "Mark volume as non-bootable (default)" msgstr "Disk bölümünü ön yüklemesiz olarak işaretle (varsayılan)" msgid "Maximum bandwidth in kbps" msgstr "En büyük bant genişliği kbps cinsinden" msgid "Maximum burst in kilobits, 0 means automatic" msgstr "Kilo bit cinsinden en büyük atış, 0 otomatik anlamına gelir" msgid "Maximum number of backups to display" msgstr "En fazla gösterilecek yedek sayısı " msgid "Maximum number of flavors to display" msgstr "Gösterilecek en fazla flavor sayısı" msgid "Maximum number of images to display." msgstr "Gösterilecek en fazla imaj sayısı." msgid "" "Maximum number of servers to display. If limit equals -1, all servers will " "be displayed. If limit is greater than 'osapi_max_limit' option of Nova API, " "'osapi_max_limit' will be used instead." msgstr "" "Gösterilecek en fazla sunucu sayısı. Eğer sınır -1'e eşitse, tüm sunucular " "gösterilir. Eğer limit Nova API'nın 'osapi_max_limit' seçeneğinden daha " "büyükse, onun yerine 'osapi_max_limit' kullanılacaktır." msgid "Maximum number of servers to launch (default=1)" msgstr "Başlatılması gereken en fazla sunucu sayısı (varsayılan=1)" msgid "Maximum number of snapshots to display" msgstr "Gösterilecek en büyük anlık görüntü sayısı" msgid "Maximum number of volumes to display" msgstr "Gösterilecek en çok disk bölümü sayısı" msgid "Memory size in MB (default 256M)" msgstr "MB cinsinden bellek boyutu (varsayılan 256M)" msgid "" "Metainfo for the flavor profile. This becomes required if --driver is " "missing and vice versa" msgstr "" "Flavor profili için Metainfo. --driver eksikse bu gereklidir ya da tam tersi" msgid "Meter rule (ID only)" msgstr "Ölçek kuralı (sadece ID)" msgid "Meter rule to delete (ID only)" msgstr "Silinecek ölçüm kuralı (sadece ID)" msgid "Meter to delete (name or ID)" msgstr "Silinecek ölçek (isim veya ID)" msgid "Meter to display (name or ID)" msgstr "Gösterilecek ölçek (isim veya ID)" msgid "Migrate server to different host" msgstr "Farklı konakçıya sunucuyu göç ettir" msgid "Migrate volume to a new host" msgstr "Disk bölümünü yeni bir sunucuya göç ettir" msgid "" "Migration policy while re-typing volume (\"never\" or \"on-demand\", default " "is \"never\" ) (available only when --type option is specified)" msgstr "" "Disk bölümü yeniden yazarken geçiş politikası (\"hiçbir zaman\" veya \"talep " "üzerine\", varsayılan \"hiçbir zaman\") (yalnızca --type seçeneği " "belirtildiğinde kullanılabilir)" msgid "Minimum RAM size needed to boot image, in megabytes" msgstr "" "İmajı ön yüklemek için kullanılacak en küçük RAM boyutu, megabayt cinsinden" msgid "Minimum disk size needed to boot image, in gigabytes" msgstr "" "İmajı ön yüklemek için gerekli en küçük disk boyutu, gigabayt cinsinden" msgid "Minimum guaranteed bandwidth in kbps" msgstr "En az garanti edilen kbps cinsinden bant genişliği" msgid "Minimum number of servers to launch (default=1)" msgstr "Başlatılması gereken minimum sunucu sayısı (varsayılan=1)" msgid "Modify from " msgstr "dan düzenle" #, python-format msgid "Multiple %(resource)s exist with %(attr)s='%(value)s'" msgstr "Çoklu %(resource)s %(attr)s='%(value)s' ile mevcut" #, python-format msgid "Multiple service matches found for '%s', use an ID to be more specific." msgstr "" "'%s' için birden fazla servis eşleşmesi bulundu, daha belirgin olması için " "ID kullanın." msgid "Name for the flavor" msgstr "Flavor için isim" msgid "Name of QoS policy to create" msgstr "Oluşturulacak QoS politikasının ismi" msgid "" "Name of a file that contains many remote IDs to associate with the identity " "provider, one per line" msgstr "" "Her satır başına bir tane olmak üzere, kimlik sağlayıcısı ile " "ilişkilendirilecek çok sayıda uzak kimliği içeren bir dosyanın adı" msgid "Name of host" msgstr "Sunucu ismi" msgid "Name of key(s) to delete (name only)" msgstr "Silinecek anahtar(lar)ın ismi (sadece isim)" msgid "Name of meter" msgstr "Ölçeğin adı" msgid "Name of new consistency group (default to None)" msgstr "Yeni tutarlılık grubunun adı (varsayılan olarak None)" msgid "Name of new consistency group snapshot (default to None)" msgstr "" "Yeni tutarlılık grubunun anlık görüntüsünün adı (varsayılan olarak None)" msgid "Name of new disk image (default: server name)" msgstr "Yeni disk imajlarının ismi (varsayılan: sunucu adı)" msgid "Name of service (Binary name)" msgstr "Servis ismi (İkili isim)" msgid "Name of the backup" msgstr "Yedek ismi" msgid "Name of the backup image (default: server name)" msgstr "Yedek imajın ismi (varsayılan: sunucu adı)" msgid "Name of the new snapshot" msgstr "Yeni anlık görüntünün ismi" msgid "Name of the new subnet pool" msgstr "Yeni altağ havuzunun ismi" msgid "" "Name of the physical network over which the virtual network is implemented" msgstr "Sanal ağın üzerinde uygulandığı fiziksel ağın adı" msgid "Name of the snapshot" msgstr "Anlık görüntü ismi" msgid "Name of this port" msgstr "Bu bağlantı noktasının ismi" msgid "Name of volume host" msgstr "Disk bölümü anabilgisayarının ismi" msgid "Name or ID of project to show usage for" msgstr "Kullanımı gösterilecek projenin isim veya ID'si" msgid "Name or ID of security group to remove from server" msgstr "Sunucudan kaldırılacak güvenlik grubunun isim veya ID'si" msgid "Name or ID of server to use" msgstr "Kullanılacak sunucunun isim veya ID'si" #, python-format msgid "Network API version, default=%s (Env: OS_NETWORK_API_VERSION)" msgstr "Ağ API sürümü, varsayılan=%s (Env: OS_NETWORK_API_VERSION)" msgid "Network QoS rule to delete (ID)" msgstr "Silinecek Ağ QoS kuralı (ID)" msgid "Network agent to display (ID only)" msgstr "Görüntülenecek ağ ajanı (yalnızca kimlik kartı)" msgid "Network agent to modify (ID only)" msgstr "Değiştirilecek ağ ajanı (yalnızca ID)" msgid "Network agent(s) to delete (ID only)" msgstr "Silinecek ağ ajanları (sadece ID)" msgid "Network flavor (name or ID)" msgstr "Ağ flavor'ı (isim veya ID)" msgid "Network segment description" msgstr "Ağ dilimi açıklaması" msgid "Network segment to associate with this subnet (name or ID)" msgstr "Bu ağ ile ilişkili ağ dilimi (isim veya ID)" msgid "Network segment to display (name or ID)" msgstr "Gösterilecek ağ dilimi (isim veya ID)" msgid "Network segment to modify (name or ID)" msgstr "Değiştirilecek ağ segmenti (ad veya kimlik)" msgid "Network segment(s) to delete (name or ID)" msgstr "Silinecek ağ segmentleri (ad veya kimlik)" msgid "Network this network segment belongs to (name or ID)" msgstr "Bu ağ bölümünün ait olduğu ağ (isim veya ID)" msgid "Network this port belongs to (name or ID)" msgstr "Bu portun ait olduğu ağ (isim veya kimlik numarası)" msgid "Network this subnet belongs to (name or ID)" msgstr "Bu alt ağın ait olduğu ağ (isim veya ID)" msgid "Network to allocate floating IP from (name or ID)" msgstr "Yüzen IP'nin ayrılacağı ağ (isim veya ID)" msgid "Network to allocate the fixed IP address from (name or ID)" msgstr "Sabit IP adresi ayrılacak ağ (isim veya ID)" msgid "Network to be added to an agent (name or ID)" msgstr "Bir ajana eklenecek ağ (isim veya ID)" msgid "Network to be removed from an agent (name or ID)" msgstr "Bir ajandan kaldırılacak ağ (isim veya ID)" msgid "Network to display (name or ID)" msgstr "Gösterilecek ağ (isim veya ID)" msgid "Network to fetch an IP address from (name or ID)" msgstr "IP adresi çekilecek ağ (isim veya ID)" msgid "Network to modify (name or ID)" msgstr "Düzenlenecek ağ (isim veya ID)" msgid "" "Network type of this network segment (flat, geneve, gre, local, vlan or " "vxlan)" msgstr "Bu ağ diliminin ağ türü (flat, geneve, gre, local, vlan veya vxlan)" msgid "Network(s) to delete (name or ID)" msgstr "Silinecek ağ(lar) (isim veya ID)" msgid "New Authentication URL of remote federated service provider" msgstr "Uzak federe servis sağlayıcının yeni Kimlik Doğrulama URL'si" msgid "New MIME type of the policy rules file" msgstr "Politika kuralları dosyasının yeni MIME türü" msgid "New MIME type of the policy rules file (defaults to application/json)" msgstr "" "Politika kuralları dosyasının yeni MIME türü (varsayılan application/json)" msgid "New QoS specification name" msgstr "Yeni QoS özellik ismi" msgid "New address scope name" msgstr "Yeni adres kapsam ismi" msgid "New aggregate name" msgstr "Yeni küme ismi" msgid "New backup description" msgstr "Yeni yedek açıklaması" msgid "New backup name" msgstr "Yeni yedek ismi" msgid "" "New backup state (\"available\" or \"error\") (admin only) (This option " "simply changes the state of the backup in the database with no regard to " "actual status, exercise caution when using)" msgstr "" "Yeni yedek durumu (\"kullanılabilir\" veya \"hata\") (sadece yönetici) (Bu " "seçenek, veritabanındaki yedeklemenin durumunu gerçek durumu dikkate almadan " "değiştirir, kullanırken dikkatli olun.)" msgid "New consistency group description" msgstr "Yeni tutarlılık grubu açıklaması" msgid "New consistency group name" msgstr "Yeni tutarlılık grubu ismi" msgid "New consumer description" msgstr "Yeni tüketici tanımı" msgid "New container name(s)" msgstr "Yeni kap ismi" msgid "New credential data" msgstr "Yeni kimlik bilgileri verisi" msgid "New credential type: cert, ec2" msgstr "Yeni kimlik bilgisi türü: cert, ec2" msgid "New domain description" msgstr "Yeni alan tanımı" msgid "New domain name" msgstr "Yeni alan adı" msgid "New endpoint URL" msgstr "Yeni uç nokta URL'i" msgid "New endpoint admin URL" msgstr "Yeni uç nokta yönetici URL'i" msgid "New endpoint interface type (admin, public or internal)" msgstr "Yeni uç nokta arayüz türü (yönetici, genele açık veya dahili)" msgid "New endpoint internal URL" msgstr "Yeni uç nokta dahili URL'i" msgid "New endpoint public URL (required)" msgstr "Yeni uç nokta herkese açık URL (gerekli)" msgid "New endpoint region ID" msgstr "Yeni uç nokta bölge ID'si" msgid "New endpoint service (name or ID)" msgstr "Yeni uç nokta servisi (isim veya ID)" msgid "New federation protocol name (must be unique per identity provider)" msgstr "" "Yeni federasyon protokolü ismi (her kimlik sağlayıcı için benzersiz " "olmalıdır)" msgid "New flavor name" msgstr "Yeni flavor adı" msgid "New group description" msgstr "Yeni grup açıklaması" msgid "New group name" msgstr "Yeni grup ismi" msgid "New identity provider description" msgstr "Yeni kimlik sağlayıcı açıklaması" msgid "New identity provider name (must be unique)" msgstr "Yeni kimlik sağlayıcı ismi (benzersiz olmalıdır)" msgid "New image name" msgstr "Yeni imaj ismi" msgid "New mapping name (must be unique)" msgstr "Yeni eşleştirme ismi (benzersiz olmalı)" msgid "New network name" msgstr "Yeni ağ adı" msgid "New network segment name" msgstr "Yeni ağ dilim adı" msgid "New parent region ID" msgstr "Yeni üst bölge ID'si" msgid "New password: " msgstr "Yeni parola: " msgid "New project name" msgstr "Yeni proje adı" msgid "New public or private key name" msgstr "Yeni açık ve kapalı anahtar ismi" msgid "New region ID" msgstr "Yeni bölge ID'si" msgid "New region description" msgstr "Yeni bölge tanımı" msgid "New role name" msgstr "Yeni rol adı" msgid "New router name" msgstr "Yeni yönlendirici ismi " msgid "New security group description" msgstr "Yeni güvenlik grubu açıklaması" msgid "New security group name" msgstr "Yeni güvenlik grubu ismi" msgid "New serialized policy rules file" msgstr "Yeni dizileştirilmiş politika kuralları dosyası" msgid "New server group name" msgstr "Yeni sunucu grup ismi" msgid "New server name" msgstr "Yeni sunucu ismi" msgid "New server state (valid value: active, error)" msgstr "Yeni sunucu durumu (geçerli değer: aktif, hata)" msgid "New service description" msgstr "Yeni servis tanımı" msgid "New service name" msgstr "Yeni servis ismi" msgid "New service provider URL, where SAML assertions are sent" msgstr "SAML bildirimlerinin gönderildiği yeni hizmet sağlayıcı URL'si" msgid "New service provider description" msgstr "Yeni servis sağlayıcı tanımı" msgid "New service provider name (must be unique)" msgstr "Yeni servis sağlayıcı ismi (benzersiz olmak zorunda)" msgid "New service type (compute, image, identity, volume, etc)" msgstr "Yeni servis türü (hesaplama, imaj, kimlik, disk bölümü, vs.)" #, python-format msgid "New size must be greater than %s GB" msgstr "Yeni boyut %s GB'den büyük olmak zorunda" msgid "New snapshot description" msgstr "Yeni anlık görüntü tanımı" msgid "New snapshot name" msgstr "Yeni anlık görüntü ismi" msgid "" "New snapshot state. (\"available\", \"error\", \"creating\", \"deleting\", " "or \"error_deleting\") (admin only) (This option simply changes the state of " "the snapshot in the database with no regard to actual status, exercise " "caution when using)" msgstr "" "Yeni anlık görüntü durumu. (\"kullanılabilir\", \"hata\", \"oluşturuluyor\", " "\"siliniyor\", veya \"silerken hata\") (sadece yönetici) (Bu seçenek, gerçek " "duruma bakılmaksızın veritabanındaki anlık görüntüsünün durumunu değiştirir, " "kullanırken dikkatli olun)" msgid "New subnet name" msgstr "Yeni altağ ismi" msgid "New transfer request name (default to None)" msgstr "Yeni aktarım isteği ismi (varsayılan olarak None)" msgid "New user name" msgstr "Yeni kullanıcı ismi" msgid "New user password" msgstr "Yeni kullanıcı parolası" #, python-format msgid "New value for the %s quota" msgstr "%s kotası için yeni değer" msgid "New volume description" msgstr "Yeni disk bölümü açıklaması" msgid "New volume name" msgstr "Yeni disk bölümü ismi" msgid "" "New volume state (\"available\", \"error\", \"creating\", \"deleting\", \"in-" "use\", \"attaching\", \"detaching\", \"error_deleting\" or \"maintenance\") " "(admin only) (This option simply changes the state of the volume in the " "database with no regard to actual status, exercise caution when using)" msgstr "" "Yeni disk bölümü durumu (\"kullanılabilir\", \"hata\", \"oluşturuluyor\", " "\"siliniyor\", \"kullanımda\", \"ekleniyor\", \"çıkarılıyor\", \"silinirken " "hata\" veya \"bakım\") (sadece yönetici) (Bu seçenek, veritabanındaki " "birimin durumunu gerçek durumu dikkate almadan değiştirir, kullanırken " "dikkatli olun.)" msgid "New volume type (name or ID)" msgstr "Yeni disk bölümü türü (isim veya ID)" #, python-format msgid "No %(resource)s with a %(attr)s or ID of '%(value)s' found" msgstr "%(attr)s veya '%(value)s' ID'li bir %(resource)s bulunamadı" #, python-format msgid "No agent with a ID of '%(id)s' exists." msgstr "'%(id)s'nin bir ID'si ile bir ajan yok." msgid "" "No existing encryption type found, creating new encryption type for this " "volume type ..." msgstr "" "Mevcut şifreleme türü bulunamadı, bu disk bölümü türü için yeni şifreleme " "türü oluşturuluyor ..." msgid "" "No password was supplied, authentication will fail when a user does not have " "a password." msgstr "" "Parola girilmedi, bir kullanıcının parolası olmadığında kimlik doğrulama " "başarısız olur." #, python-format msgid "No service catalog with a type, name or ID of '%s' exists." msgstr "'%s' türünde, isminde veya ID'si ile bir servis kataloğu yok." #, python-format msgid "No service with a type, name or ID of '%s' exists." msgstr "'%s' türünde, isminde veya ID'si ile bir servis bulunamadı." #, python-format msgid "No tags associated with the %s" msgstr "%s ile ilişkilendirilmiş hiç etiket yok" msgid "Number of backups to keep (default: 1)" msgstr "Tutulacak yedekleme sayısı (varsayılan: 1)" msgid "Number of lines to display from the end of the log (default=all)" msgstr "Günlüğün sonundan gösterilecek satır sayısı (varsayılan=tümü)" msgid "Number of vcpus (default 1)" msgstr "vcpus sayısı (varsayılan 1)" #, python-format msgid "Object name is %s characters long, default limit is 1024" msgstr "Nesne ismi %s karakter uzunluğunda, varsayılan sınır 1024" msgid "Object to display" msgstr "Gösterilecek nesne" msgid "Object to modify" msgstr "Düzenlenecek nesne" msgid "Object to save" msgstr "Kaydedilecek nesne" msgid "Object(s) to delete" msgstr "Silinecek nesne(ler)" msgid "One or more of the set operations failed" msgstr "Bir veya birden fazla ayar işlemleri başarısız" msgid "One or more of the unset operations failed" msgstr "Bir veya birden fazla ayar kaldırma işlemi başarısız" msgid "Only an authorized user may issue a new token." msgstr "Yalnızca yetkili bir kullanıcı yeni bir jeton verebilir." msgid "Only display deleted servers (Admin only)." msgstr "Sadece silinen sunucuları göster (sadece admin)." msgid "Only return hosts in the availability zone" msgstr "Sadece kullanılabilirlik bölgesindeki sunucuları döndürür" msgid "Only return instances that match the reservation" msgstr "Sadece rezervasyonla eşleşen sunucuları döndürür" msgid "Operating system architecture" msgstr "İşletim sistemi mimarisi" msgid "Operating system distribution name" msgstr "İşletim sistemi dağıtım adı" msgid "Operating system distribution version" msgstr "Işletim sistemi dağıtım sürümü" msgid "Optional backup container name" msgstr "Seçimli yedek kap ismi" msgid "Options in ssh_config(5) format (ssh -o option)" msgstr "ssh_config(5) biçemi içerisindeki seçenekler (ssh -o seçeneği)" msgid "Original user password" msgstr "Orijinal kullanıcı parolası" msgid "Owner's project (name or ID)" msgstr "Sahibin projesi (isim veya ID)" msgid "Parent of the project (name or ID)" msgstr "Projenin üst projesi (isim veya ID)" msgid "Parent region ID" msgstr "Üst bölge ID'si" msgid "Passwords do not match, password unchanged" msgstr "Parolalar eşleşmedi, parola değiştirilmedi" msgid "Pause server(s)" msgstr "Sunucu(ları/yu) durdur" msgid "Perform a block live migration" msgstr "Bir blok gerçek göç gerçekleştir" msgid "Perform a hard or soft server reboot" msgstr "Sert veya yumuşak sunucu yeniden başlatmayı gerçekleştir" msgid "Perform a hard reboot" msgstr "Sert yeniden başlatmayı gerçekleştir" msgid "Perform a shared live migration (default)" msgstr "Paylaşımlı canlı göç gerçekleştir (varsayılan)" msgid "Perform a soft reboot" msgstr "Yumuşak yeniden başlatmayı gerçekleştir" msgid "Perform an incremental backup" msgstr "Artımlı bir yedekleme gerçekleştir" msgid "Physical network name of this network segment" msgstr "Bu ağ kesiminin fiziksel ağ adı" msgid "Policy to display" msgstr "Gösterilecek politika" msgid "Policy to modify" msgstr "Düzenlenecek politika" msgid "Policy(s) to delete" msgstr "Silinecek politika(lar)" msgid "Port device ID" msgstr "Bağlantı noktası aygıtı ID'si" #, python-format msgid "Port does not contain allowed-address-pair %s" msgstr "%s izin verilen adres çiftlerini içermeyen bağlantı noktası" #, python-format msgid "Port does not contain binding-profile %s" msgstr "Bağlantı noktası %s bağlantı-profilini içermiyor" #, python-format msgid "Port does not contain fixed-ip %s" msgstr "Bağlantı noktası %s sabit ip'sini içermiyor" #, python-format msgid "Port does not contain security group %s" msgstr "Bağlantı noktası %s güvenlik grubunu içermiyor" msgid "Port to add to the server (name or ID)" msgstr "Sunucuya eklenecek bağlantı noktası (isim veya ID)" msgid "Port to be added (name or ID)" msgstr "Eklenecek bağlantı noktası (isim veya ID)" msgid "Port to be associated with the floating IP (name or ID)" msgstr "Yüzen IP ile ilişkilendirilecek bağlantı noktası (isim veya ID)" msgid "Port to be removed and deleted (name or ID)" msgstr "Kaldırılacak ve silinecek bağlantı noktası (isim veya ID)" msgid "Port to display (name or ID)" msgstr "Gösterilecek bağlantı noktası (isim veya ID)" msgid "Port to modify (name or ID)" msgstr "Düzenlenecek bağlantı noktası (isim veya ID)" msgid "Port to remove from the server (name or ID)" msgstr "Sunucudan kaldırılacak bağlantı noktası (isim veya ID)" msgid "Port(s) to delete (name or ID)" msgstr "Silinecek bağlantı noktaları (isim veya ID)" msgid "Prefix length for subnet allocation from subnet pool" msgstr "Altağ havuzundan altağ tahsisi için ön ek uzunluğu" msgid "Prevent image from being deleted" msgstr "İmajı silinmekten koru" msgid "Print image size in a human-friendly format." msgstr "İmaj boyutunu insan dostu bir biçimde bastırın." msgid "Private key file (ssh -i option)" msgstr "Gizli anahtar dosyası (ssh -i seçeneği)" msgid "Project and User must be specified" msgstr "Proje ve kullanıcı belirtilmeli" msgid "Project being delegated (name or ID) (required)" msgstr "Devredilen proje (isim veya ID) (gerekli)" msgid "Project description" msgstr "Proje açıklaması" msgid "Project must be specified" msgstr "Proje belirtilmek zorunda" msgid "Project that consumer wants to access (name or ID) (required)" msgstr "Alıcının erişmek istediği proje (isim veya ID) (gerekli)" msgid "Project to associate with image (name or ID)" msgstr "İmaj ile ilişkili proje (isim veya ID)" msgid "Project to clean (name or ID)" msgstr "Temizlenecek proje (isim veya ID)" msgid "Project to disassociate with image (name or ID)" msgstr "İmaj ile ilişkişi kesilecek proje (isim veya ID)" msgid "Project to display (name or ID)" msgstr "Gösterilecek proje (isim veya ID)" msgid "Project to filter (name or ID)" msgstr "Filtrelenecek proje (isim veya ID)" msgid "Project to modify (name or ID)" msgstr "Düzenlenecek projeler (isim veya ID)" msgid "Project which limits the scope of the credential (name or ID)" msgstr "Kimlik bilgilerinin kapsamını sınırlayan proje (isim veya ID)" msgid "Project(s) to delete (name or ID)" msgstr "Silinecek proje(ler) (isim veya ID)" msgid "Prompt interactively for password" msgstr "Parolayı interaktif olarak sor" msgid "" "Property key to remove from server (repeat option to remove multiple values)" msgstr "" "Sunucudan kaldırılacak özellik anahtaru (birden fazla değer silmek için " "seçeneği tekrarla)" msgid "" "Property to add for this flavor (repeat option to set multiple properties)" msgstr "" "Bu flavor'a eklenecek özellik (birden fazla özellik ayarlamak için seçeneği " "tekrarlayın)" msgid "" "Property to add or modify for this QoS specification (repeat option to set " "multiple properties)" msgstr "" "Bu QoS belirtimi için ekleme veya değişiklik yapma özelliği (birden fazla " "özellik ayarlamak için seçeneği tekrarla)" msgid "" "Property to add or modify for this flavor (repeat option to set multiple " "properties)" msgstr "" "Bu flavor için eklenecek veye düzenlenecek özellik (birden fazla özellik " "ayarlamak için seçeneği tekrarla)" msgid "" "Property to add to this aggregate (repeat option to set multiple properties)" msgstr "" "Bu kümeye eklenecek özellik (çoklu özellik ayarlamak için seçeneği tekrarla)" msgid "" "Property to add/change for this server (repeat option to set multiple " "properties)" msgstr "" "Bu sunucu için eklenecek/değiştirilecek özellik (birden falza özellik " "ayarlamak için seçeneği tekrarla)" msgid "" "Property to add/change for this snapshot (repeat option to set multiple " "properties)" msgstr "" "Bu anlık görüntü için eklenecek/değiştirilecek özellik (birden fazla özellik " "ayarlamak için seçeneği tekrarla)" msgid "" "Property to remove from account (repeat option to remove multiple properties)" msgstr "" "Hesaptan silinecek özellik (birden fazla özellik silmek için seçeneği " "tekrarla)" msgid "" "Property to remove from aggregate (repeat option to remove multiple " "properties)" msgstr "" "Kümeden kaldırılacak özellikler (birden fazla özelliği kaldırmak için " "seçeneği tekrarlayın)" msgid "" "Property to remove from container (repeat option to remove multiple " "properties)" msgstr "" "Kaptan kaldırılacak özellik (birden fazla özellik kaldırmak için seçeneği " "tekrarla)" msgid "" "Property to remove from flavor (repeat option to unset multiple properties)" msgstr "" "Flavor'dan kaldırılacak özellik (birden fazla özelliği kaldırmak için " "seçeneği tekrarla)" msgid "" "Property to remove from object (repeat option to remove multiple properties)" msgstr "" "Nesneden kaldırılacak özellik (birden fazla özellik kaldırmak için seçeneği " "tekrarla)" msgid "" "Property to remove from snapshot (repeat option to remove multiple " "properties)" msgstr "" "Anlık görüntüden kaldırılacak özellik (birden fazla özellik kaldırmak için " "seçeneği tekrarlayın)" msgid "" "Property to remove from the QoS specification. (repeat option to unset " "multiple properties)" msgstr "" "QoS belirtiminden kaldırılacak özellik. (birden fazla özelliğin ayarını " "kaldırmak için seçeneği tekrarla)" msgid "" "Property to set on (repeat option to set multiple properties)" msgstr "" " üzerinde ayarlanacak özellik (çoklu özellik ayarlamak için " "seçeneği tekrarla)" msgid "Public or private key to display (name only)" msgstr "Gösterilecek açık veya kapalı anahtar (sadece isim)" msgid "Put server in rescue mode" msgstr "Sunucuyu kurtarma kipine getir" msgid "" "Python module path to driver. This becomes required if --metainfo is missing " "and vice versa" msgstr "" "Python modülünün sürücüye yolu. --metainfo eksikse bu gereklidir ya da tam " "tersi" msgid "QoS policy that contains the rule (name or ID)" msgstr "Kuralı içeren QoS politikası (isim veya ID)" msgid "QoS policy to attach to this network (name or ID)" msgstr "Bu ağa eklenecek QoS politikası (isim veya ID)" msgid "QoS policy to display (name or ID)" msgstr "Görüntülenecek QoS politikası (ad veya kimlik)" msgid "QoS policy to modify (name or ID)" msgstr "Değiştirmek için QoS politikası (ad veya ID)" msgid "QoS policy(s) to delete (name or ID)" msgstr "Silinecek QoS politika(lar/s)ı (isim veya ID)" #, python-format msgid "QoS rule type (%s)" msgstr "QoS kural türü (%s)" msgid "QoS specification to display (name or ID)" msgstr "Gösterilecek QoS belirtimi (isim veya ID)" msgid "QoS specification to modify (name or ID)" msgstr "Düzenlenecek QoS özelliği (isim veya ID)" msgid "QoS specification(s) to delete (name or ID)" msgstr "Silinecek QoS özellikleri (isim veya ID)" msgid "RBAC policy (ID only)" msgstr "RBAC politikası (sadece ID)" msgid "RBAC policy to be modified (ID only)" msgstr "Değiştirilecek RBAC politikası (yalnızca ID)" msgid "RBAC policy(s) to delete (ID only)" msgstr "Silinecek RBAC politikaları (sadece ID)" msgid "RX/TX factor (default 1.0)" msgstr "RX/TX faktörü (varsayılan 1.0)" msgid "Read image data from standard input" msgstr "Standart girdiden imaj verilerini oku" msgid "" "Reason for disabling the service (in quotas). Should be used with --disable " "option." msgstr "" "Servisi devre dışı bırakma sebebi (kota cinsinden). --disable seçeneği ile " "birlikte kullanılmalı." msgid "Reason for disabling the service (should be used with --disable option)" msgstr "" "Servisi devredışı bırakmak için sebep (--disable seçeneği ile kullanılmalı)" msgid "Rebuild server" msgstr "Sunucuyu yeniden yapılandır" msgid "" "Recreate server from the specified image (name or ID). Defaults to the " "currently used one." msgstr "" "Sunucuyu belirtilen imajdan yeniden oluşturun (ad veya ID). Varsayılan " "olarak o anda kullanılana ayarlıdır." msgid "Recursively delete objects and container" msgstr "Nesneleri ve kabı yinelemeli olarak sil" msgid "Region ID(s) to delete" msgstr "Silinecek bölge ID(leri)" msgid "Region to display" msgstr "Gösterilecek bölge" msgid "Region to modify" msgstr "Düzenlenecek bölge" msgid "Regular expression to match IP addresses" msgstr "IP adresleriyle eşleşen düzenli ifadeler" msgid "Regular expression to match IPv6 addresses" msgstr "IPv6 adresleriyle eşleşen düzenli ifadeler" msgid "Regular expression to match instance name (admin only)" msgstr "Sunucu adıyla eşleşen düzenli ifadeler (yalnızca yönetici)" msgid "Regular expression to match names" msgstr "Adları eşleştirmek için düzenli ifadeler" msgid "Reject the image membership" msgstr "İmaj üyeliğini red et" msgid "" "Remote IDs to associate with the Identity Provider (repeat option to provide " "multiple values)" msgstr "" "Kimlik Sağlayıcısı ile ilişkilendirilecek uzak kimlikler (birden fazla değer " "sağlamak için seçeneği tekrarlayın)" msgid "" "Remote IP address block (may use CIDR notation; default for IPv4 rule: " "0.0.0.0/0)" msgstr "" "Uzak IP adres bloğu (CIDR notasyonu kullanılabilir; IPv4 kuralı için " "varsayılan: 0.0.0.0/0)" msgid "Remote security group (name or ID)" msgstr "Uzak güvenlik grubu (isim veya ID)" msgid "Remove a port from a router" msgstr "Bir yönlendiriciden bir bağlantı noktası kaldır" msgid "" "Remove a property from this volume type (repeat option to remove multiple " "properties)" msgstr "" "Bu disk bölümü türünden bir özelliği kaldır (birden fazla özellik silmek " "için seçeneği tekrarla)" msgid "" "Remove a property from volume (repeat option to remove multiple properties)" msgstr "" "Disk bölümünden bir özelliği sil (birden fazla özelliği kaldırmak için " "seçeneği tekrarla)" msgid "Remove a subnet from a router" msgstr "Alt ağı yönlendiriciden kaldır" msgid "Remove address scope associated with the subnet pool" msgstr "Alt ağ havuzuyla ilişkili adres alanını kaldır" msgid "" "Remove all properties from (specify both --property and --no-" "property to overwrite the current properties)" msgstr "" "'den tüm özellikleri kaldır (mevcut üzelliklerin üzerine yazmak " "için hem --property hem de --no-property'yi belirleyin)" msgid "" "Remove all properties from (specify both --no-property and --" "property to remove the current properties before setting new properties.)" msgstr "" "'dan tüm özellikleri kaldır (Yeni özellikleri ayarlamadan önce " "geçerli özellikleri kaldırmak için --no-property ve --property seçeneklerini " "belirtin.)" msgid "" "Remove all properties from (specify both --no-property and --" "property to remove the current properties before setting new properties.)" msgstr "" "'den tüm özellikleri kaldır (yeni özellikleri ayarlamadan önce " "geçerli özellikleri kaldırmak için --no-property ve --property seçeneklerini " "belirtin.)" msgid "" "Remove all properties from this flavor (specify both --no-property and --" "property to remove the current properties before setting new properties.)" msgstr "" "Bu flavor'daki tüm özellikleri kaldır (yeni özellikler tanımlamadan önce " "mevcut özellikleri kaldırmak için --no-property ve --property seçeneklerinin " "her ikisini de belirtin.)" msgid "" "Remove an image property from volume (repeat option to remove multiple image " "properties)" msgstr "" "Disk bölümünden bir imaj özelliğini sil (birden fazla imaj özelliği silmek " "için seçeneği tekrarla)" msgid "Remove any snapshots along with volume(s) (defaults to False)" msgstr "" "Herhangi bir anlık görüntüsünü hacimle birlikte çıkarın (varsayılan olarak " "False)" msgid "Remove external gateway information from the router" msgstr "Yönlendiriciden harici geçit bilgisini sil" msgid "Remove fixed IP address from server" msgstr "Sunucudan sabit IP adresini kaldırın" msgid "Remove flavor access from project (name or ID) (admin only)" msgstr "Flavor erişimini projeden kaldır (isim veya ID) (sadece yönetici)" msgid "Remove floating IP address from server" msgstr "Sunucudan kayan IP adresi kaldırın" msgid "Remove host from aggregate" msgstr "Kümeden sunucuyu kaldır" msgid "Remove network from DHCP agent" msgstr "Ağı DHCP ajanından sil" msgid "Remove network from an agent." msgstr "Bir ajandan ağı kaldırın." msgid "Remove port from server" msgstr "Sunucudan bağlantı noktasını sil" msgid "Remove role from project : user" msgstr "Rolü proje : kullanıcıdan kaldırın" msgid "Remove router from an L3 agent" msgstr "Yönlendiriciyi L3 ajanından kaldır" msgid "Remove router from an agent" msgstr "Yönlendiriciyi bir ajandan kaldır" msgid "Remove security group from server" msgstr "Sunucudan güvenlik grubunu kaldır" msgid "Remove service profile from network flavor" msgstr "Servis profilini ağ flavor'ından kaldır" msgid "" "Remove subnet pool prefixes (in CIDR notation). (repeat option to unset " "multiple prefixes)." msgstr "" "Alt ağ havuzu öneklerini kaldır (CIDR gösteriminde). (Birden fazla önekin " "ayarını kaldırmak için seçeneği tekrarlayın)." msgid "Remove the QoS policy attached to the port" msgstr "Bağlantı noktasına eklenmiş QoS politikasını kaldır" msgid "Remove the QoS policy attached to this network" msgstr "Bu ağa bağlı QoS politikasını kaldırın" msgid "Remove the encryption type for this volume type (admin oly)" msgstr "Bu disk bölümü için şifreleme türünü sil (sadece yönetici)" msgid "Remove the encryption type for this volume type (admin only)" msgstr "Bu disk bölümü türü için şifreleme türü kaldırıldı (sadece yönetici)" msgid "Remove user from group" msgstr "Kullanıcıyı gruptan kaldır" msgid "Remove volume from server" msgstr "Disk bölümünü sunucudan kaldır" msgid "Remove volume(s) from consistency group" msgstr "Tutarlılık grubundan disk bölümlerini sil" msgid "Removes a role assignment from domain/project : user/group" msgstr "Bir rol atamasını alan/proje : kullanıcı/gruptan kaldırır." msgid "Removes volume type access to project (name or ID) (admin only)" msgstr "Projeye disk türü erişimini kaldırır (isim veya ID) (sadece yönetici)" msgid "Replicated volume to clone (name or ID)" msgstr "Klonlanacak yinelenmiş disk bölümü (isim veya ID)" msgid "Request ID of the event to show (ID only)" msgstr "Gösterilecek olayın ID'sini iste (sadece ID)" msgid "Request token to authorize (ID only) (required)" msgstr "Yetkilendirilecek istek jetonu (sadece ID) (gerekli)" msgid "Request token to exchange for access token (required)" msgstr "Erişim anahtarı alışverişi için istek jetonu (gerekli)" msgid "Requested fixed IP address" msgstr "Sabit IP adresi iste" msgid "Reset the image membership to 'pending'" msgstr "İmaj üyeliğini 'beklemede' olarak sıfırlayın" msgid "Resize server to specified flavor" msgstr "Sunucuyu belirtilen flavor'a yeniden boyutlandır" msgid "Restore backup" msgstr "Yedeği yeniden yükle" msgid "Restore server from rescue mode" msgstr "Kurtarma kipinden sunucuyu onar" msgid "Restore server state before resize" msgstr "Sunucu durumunu yeniden boyutlandırmadan önceki haline geri getir" msgid "Restore server(s)" msgstr "Sunucu(ları/yu) onar " msgid "Restore volume backup" msgstr "Disk bölümü yedeğini geri yükle" msgid "Resume server(s)" msgstr "Sunucu(ları/yu) kaldığı yerden devam ettir" msgid "Return existing domain" msgstr "Mevcut alanı döndür" msgid "Return existing group" msgstr "Mevcut grubu döndür" msgid "Return existing project" msgstr "Mevcut projeyi döndür" msgid "Return existing role" msgstr "Mevcut rolü döndür" msgid "Return existing user" msgstr "Mevcut kullanıcıyı döndür" msgid "" "Return the auto allocated topology for a given project. Default is current " "project" msgstr "" "Belirli bir proje için otomatik olarak ayrılan topolojiyi döndürür. " "Varsayılan geçerli projedir" #, python-format msgid "Returning existing domain %s" msgstr "Mevcut alanı döndür %s" #, python-format msgid "Returning existing group %s" msgstr "Mevcut %s grubunu döndürme" #, python-format msgid "Returning existing project %s" msgstr "Mevcut %s projesi döndürülüyor" #, python-format msgid "Returning existing role %s" msgstr "Mevcut %s rol döndürülüyor" #, python-format msgid "Returning existing user %s" msgstr "Mevcut kullanıcıyı döndür %s" msgid "Returns only effective role assignments" msgstr "Sadece verimli rol atamalarını döndür" msgid "Retype new password: " msgstr "Yeni parolayı yeniden yaz: " msgid "Revoke existing token" msgstr "Yeni jeton yayınla" msgid "" "Role not added, incorrect set of arguments provided. See openstack --help " "for more details" msgstr "" "Rol eklenmedi, hatalı argümanlar sağlandı. Daha fazla bilgi için openstack --" "help komutunun çıktısına bakın." msgid "Role to add to : (name or ID)" msgstr ":'a eklenecek rol (isim veya ID)" msgid "Role to add to (name or ID)" msgstr " eklenecek rol (isim veya ID)" msgid "Role to display (name or ID)" msgstr "Gösterilecek roller (isim veya ID)" msgid "Role to filter (name or ID)" msgstr "Filtrelenecek rol (isim veya ID)" msgid "Role to modify (name or ID)" msgstr "Düzenlenecek rol (isim veya ID)" msgid "Role to remove (name or ID)" msgstr "Kaldırılacak rol (isim veya ID)" msgid "Role(s) to delete (name or ID)" msgstr "Silinecek rol(ler) (isim veya ID)" msgid "" "Roles to authorize (name or ID) (repeat option to set multiple values) " "(required)" msgstr "" "Yetkilendirilecek roller (isim veya ID) (birden fazla değer ayarlamak için " "seçeneği tekrarla) (gerekli)" msgid "" "Roles to authorize (name or ID) (repeat option to set multiple values, " "required)" msgstr "" "Yetkilendirilecek roller (isim veya ID) (birden fazla değer ayarlamak için " "seçeneği tekrarlayın, gerekli)" msgid "Roll up items with " msgstr "Elemanları ile toparla" msgid "" "Route to be removed from this subnet e.g.: destination=10.10.0.0/16," "gateway=192.168.71.254 destination: destination subnet (in CIDR notation) " "gateway: nexthop IP address (repeat option to unset multiple host routes)" msgstr "" "Bu altağdan silinecek yön örn: hedef=10.10.0.0/16,geçit=192.168.71.254 hedef:" "hedef altağ (CIDR notasyonunda) geçit: bir sonraki uğranacak IP adresi " "(birden fazla sunucu yönü ayarı kaldırmak için seçeneği tekrar et)" #, python-format msgid "Router does not contain route %s" msgstr "Yönlendirici %s yönünü içermiyor" msgid "Router from which port will be removed (name or ID)" msgstr "Bağlantı noktasının kaldırılacağı yönlendirici (isim veya ID)" msgid "Router from which the subnet will be removed (name or ID)" msgstr "Alt ağdan kaldırılacak yönlendirici (isim veya ID)" msgid "Router to be added to an agent (name or ID)" msgstr "Bir ajana eklenecek yönlendirici (ad veya kimlik)" msgid "Router to be removed from an agent (name or ID)" msgstr "Bir ajandan kaldırılacak yönlendirici (ad veya kimlik)" msgid "Router to display (name or ID)" msgstr "Gösterilecek yönlendirici (isim veya ID)" msgid "Router to modify (name or ID)" msgstr "Düzenlenecek yönlendirici (isim veya ID)" msgid "Router to which port will be added (name or ID)" msgstr "Bağlantı noktası eklenecek yönlendirici (isim veya ID)" msgid "Router to which subnet will be added (name or ID)" msgstr "Alt ağın ekleneceği yönlendirici (isim veya ID)" msgid "Router(s) to delete (name or ID)" msgstr "Silinecek yönlendirici(ler) (isim veya ID)" msgid "" "Routes associated with the router destination: destination subnet (in CIDR " "notation) gateway: nexthop IP address (repeat option to set multiple routes)" msgstr "" "Yönlendirici hedefi ile ilişkili yönlendiriciler: hedef altağ (CIDR " "notasyonunda) geçit: bir sonraki atlanacak IP adresi (birden fazla " "yönlendirici ayarlamak için seçeneği tekrarla)" msgid "" "Routes to be removed from the router destination: destination subnet (in " "CIDR notation) gateway: nexthop IP address (repeat option to unset multiple " "routes)" msgstr "" "Yönlendirici hedefinden kaldırılacak yönlendiriciler: hedef alt ağ (CIDR " "notasyonuyla) geçit: atlanacak sonraki IP adresi (birden fazla " "yönlendiricinin ayarını kaldırmak için seçeneği tekrarla)" #, python-format msgid "Rule ID %(rule_id)s not found" msgstr "%(rule_id)s kural ID'si bulunamadı" msgid "Rule applies to incoming network traffic (default)" msgstr "Gelen ağ trafiğine uygulanacak kural (varsayılan)" msgid "Rule applies to outgoing network traffic" msgstr "Dışarıya doğru ağ trafiğine uygulanacak kural" #, python-format msgid "Rule type \"%(rule_type)s\" only requires arguments %(args)s" msgstr "\"%(rule_type)s\" kural türü sadece %(args)s argümanlarını gerektirir" msgid "SSH to server" msgstr "Sunucuya SSH ile bağlan" msgid "Save an image locally" msgstr "İmajı yerel olarak kaydet" msgid "Save container contents locally" msgstr "Kap içeriğini yerel olarak kaydet" msgid "Save object locally" msgstr "Nesneyi yerel olarak kaydet" msgid "" "Scale server to a new flavor.\n" "\n" "A resize operation is implemented by creating a new server and copying the\n" "contents of the original disk into a new one. It is also a two-step process " "for\n" "the user: the first is to perform the resize, the second is to either " "confirm\n" "(verify) success and release the old server, or to declare a revert to " "release\n" "the new server and restart the old one." msgstr "" "Sunucuyu yeni bir flavor'a ölçekle.\n" "\n" "Bir yeniden boyutlandırma işlemi yeni bir sunucu oluşturma ve orijinal \n" "diskteki içeriğin yeni bir tanesine kopyalanması ile gerçekleştirilir. Bu " "ayrıca\n" "kullanıcı için iki adımlı bir süreçtir: birincisi yeniden boyutlandırmayı " "gerçekleştirmek,\n" "ikincisi ya başarılı olduğunu doğrulamak ve eski sunucuyu silmek, ya da " "yenisini silip\n" "eskisini yeniden başlatma isteğini belirtmek." msgid "Search by flavor (name or ID)" msgstr "Flavor'a göre ara (isim veya ID)" msgid "Search by hostname" msgstr "Sunucu adına göre ara" msgid "Search by image (name or ID)" msgstr "İmaja göre ara (isim veya ID)" msgid "Search by project (admin only) (name or ID)" msgstr "Projeye göre ara (sadece yönetici) (isim veya ID)" msgid "Search by server status" msgstr "Sunucu durumuna göre ara" msgid "Search by user (admin only) (name or ID)" msgstr "Kullanıcıya göre ara (sadece yönetici) (isim veya ID)" msgid "Secret associated with (required)" msgstr " ile ilişkili gizli anahtar (gerekli)" msgid "Security group description" msgstr "Güvenlik grubu açıklaması" msgid "Security group rule to display (ID only)" msgstr "Gösterilecek güvenlik grubu kuralları (sadece ID)" msgid "Security group rule(s) to delete (ID only)" msgstr "Silinecek güvenlik grubu kuralları (sadece ID)" msgid "Security group to add (name or ID)" msgstr "Eklenecek güvenlik grubu (isim veya ID)" msgid "" "Security group to assign to this server (name or ID) (repeat option to set " "multiple groups)" msgstr "" "Bu sunucuya atanan güvenlik grubu (isim veya ID) (birden fazla grup " "ayarlamak için seçeneği tekrar edin)" msgid "" "Security group to associate with this port (name or ID) (repeat option to " "set multiple security groups)" msgstr "" "Bu bağlantı noktası ile ilişkilendirilecek güvenlik grubu (isim veya ID) " "(birden fazla güvenlik grubu ayarlamak için seçeneği tekrarla)" msgid "Security group to display (name or ID)" msgstr "Gösterilecek güvenlik grubu (isim veya ID)" msgid "Security group to modify (name or ID)" msgstr "Düzenlenecek güvenlik grubu (isim veya ID)" msgid "" "Security group which should be removed this port (name or ID) (repeat option " "to unset multiple security groups)" msgstr "" "Bu bağlantı noktasının kaldırılması gereken güvenlik grubu (isim veya ID) " "(birden fazla güvenlik grubunun ayarını kaldırmak için seçeneği tekrarla)" msgid "Security group(s) to delete (name or ID)" msgstr "Silinecek güvenlik grubu (isim veya ID)" msgid "" "Segment identifier for this network segment which is based on the network " "type, VLAN ID for vlan network type and tunnel ID for geneve, gre and vxlan " "network types" msgstr "" "Ağ türüne göre bölüm belirteci, vlan ağ türü için VLAN ID, geneve, gre ve " "vxlan ağ türleri için tünel ID" msgid "Select an availability zone for the server" msgstr "Sunucu için kullanılabilirlik bölgesi seçin" msgid "Server (name or ID)" msgstr "Sunucu (isim veya ID)" msgid "Server internal device name for volume" msgstr "Disk bölümü için sunucu dahili aygıt ismi" msgid "Server to add the port to (name or ID)" msgstr "Bağlantı noktası eklenecek sunucu (isim veya ID)" msgid "Server to back up (name or ID)" msgstr "Yedeklenecek sunucu (isim veya ID)" msgid "Server to create image (name or ID)" msgstr "İmaj oluşturulacak sunucu (isim veya ID)" msgid "Server to list events (name or ID)" msgstr "Olayları listelenecek sunucu (isim veya ID)" msgid "Server to receive the IP address (name or ID)" msgstr "IP adresin alınacağı sunucu (isim veya ID)" msgid "Server to receive the fixed IP address (name or ID)" msgstr "Sabit IP adresleri alınacak sunucu (isim veya ID)" msgid "Server to receive the floating IP address (name or ID)" msgstr "Kayan IP adresi alınacak sunucu (isim veya ID)" msgid "Server to remove the IP address from (name or ID)" msgstr "IP adresin kaldırılacağı sunucu (isim veya ID)" msgid "Server to remove the fixed IP address from (name or ID)" msgstr "Sabit IP adresin silineceği sunucu (isim veya ID)" msgid "Server to remove the floating IP address from (name or ID)" msgstr "Kayan IP adresinin kaldırılacağı sunucu (isim veya ID)" msgid "Server to remove the port from (name or ID)" msgstr "Bağlantı noktasının kaldırılacağı sunucu (isim veya ID)" msgid "Server to show URL (name or ID)" msgstr "URL'i gösterilecek sunucu (isim veya ID)" msgid "Server to show console log (name or ID)" msgstr "Konsol günlüğü gösterilecek sunucu (isim veya ID)" msgid "Server to show event details (name or ID)" msgstr "Olay detayları gösterilecek sunucu (isim veya ID)" msgid "Server(s) to create dump file (name or ID)" msgstr "Çıktı dosyası oluşturulacak sunucu(lar) (isim veya ID)" msgid "Server(s) to delete (name or ID)" msgstr "Silinecek sunucu(lar) (isim veya ID)" msgid "Server(s) to lock (name or ID)" msgstr "Kilitlenecek sunucu(lar) (isim veya ID)" msgid "Server(s) to pause (name or ID)" msgstr "Durdurulacak sunucu(lar) (isim veya ID)" msgid "Server(s) to restore (name or ID)" msgstr "Onarılacak sunucu(lar) (isim veya ID)" msgid "Server(s) to resume (name or ID)" msgstr "Devam ettirilece sunucu(lar) (isim veya ID)" msgid "Server(s) to shelve (name or ID)" msgstr "Rafa kaldırılacak sunucu(lar) (isim veya ID)" msgid "Server(s) to start (name or ID)" msgstr "Başlatılacak sunucu(lar) (isim veya ID)" msgid "Server(s) to stop (name or ID)" msgstr "Durdurulacak sunucu(lar) (isim veya ID)" msgid "Server(s) to suspend (name or ID)" msgstr "Durdurulacak sunucu(lar) (isim veya ID)" msgid "Server(s) to unlock (name or ID)" msgstr "Kilidi kaldırılacak sunucu(lar) (isim veya ID)" msgid "Server(s) to unpause (name or ID)" msgstr "Devam ettirilecek sunucu(lar) (isim veya ID)" msgid "Server(s) to unshelve (name or ID)" msgstr "Alınacak sunucu(lar) (isim veya ID)" msgid "Service profile (ID only)" msgstr "Servis profili (sadece ID)" msgid "Service provider to display" msgstr "Gösterilecek servis sağlayıcı" msgid "Service provider to modify" msgstr "Düzenlenecek servis sağlayıcı" msgid "Service provider(s) to delete" msgstr "Silinecek servis sağlayıcı(lar)" msgid "Service to be associated with new endpoint (name or ID)" msgstr "Yeni uç nokta ile ilişkilendirilecek servis (isim veya ID)" msgid "Service to display (type or name)" msgstr "Gösterilecek servis (tür veya isim)" msgid "Service to display (type, name or ID)" msgstr "Gösterilecek servis (tür, isim veya ID)" msgid "Service to modify (type, name or ID)" msgstr "Düzenlenecek servis (tür, isim veya ID)" msgid "" "Service type for this subnet e.g.: network:floatingip_agent_gateway. Must be " "a valid device owner value for a network port (repeat option to set multiple " "service types)" msgstr "" "Bu alt ağ için servis türü örn: network:floatingip_agent_gateway. Bir ağ " "bağlantı noktası için geçerli bir cihaz sahibi değeri olmalıdır (birden " "fazla servis türü ayarlamak için seçeneği tekrarlayın)" msgid "" "Service type to be removed from this subnet e.g.: network:" "floatingip_agent_gateway. Must be a valid device owner value for a network " "port (repeat option to unset multiple service types)" msgstr "" "Bu altağdan kaldırılacak servis türü örn: network:floatingip_agent_gateway. " "Bir ağ bağlantı noktası için geçerli bir aygıt sahibi değeri olmalıdır " "(birden fazla servis türünün ayarını kaldırmak için seçeneği tekrarlayın)" msgid "" "Service type to which the flavor applies to: e.g. VPN (See openstack network " "service provider list for loaded examples.)" msgstr "" "Flavor'ın uygulanacağı hizmet türü: ör. VPN (Yüklü sunucular için açık devre " "ağ servis sağlayıcısı listesine bakın.)" msgid "Service(s) to delete (type, name or ID)" msgstr "Silinecek servis(ler) (tür, isim veya ID)" msgid "Set DNS name to this port (requires DNS integration extension)" msgstr "" "DNS adını bu bağlantı noktasına ayarlayın (DNS entegrasyon uzantısı " "gerektirir)" msgid "Set Network QoS rule properties" msgstr "Ağ QoS kural özelliklerini ayarla" msgid "Set QoS policy name" msgstr "QoS ilke adı ayarla" msgid "Set QoS policy properties" msgstr "QoS ilke özelliklerini ayarla" msgid "Set QoS specification properties" msgstr "QoS özellik özelliğini ayarla" msgid "" "Set a QoS specification property (repeat option to set multiple properties)" msgstr "" "Bir QoS özellik özelliği ayarla (birden fazla özellik ayarlamak için " "seçeneği tekrarla)" msgid "Set a project property (repeat option to set multiple properties)" msgstr "" "Bir proje özelliği ayarla (birden fazla özellik ayarlamak için seçeneği " "tekrarla)" msgid "Set a property on (repeat option to set multiple properties)" msgstr "" " üzerinde bir özellik ayarla (birden fazla özellik ayarlamak için " "seçeneği tekrarla)" msgid "" "Set a property on this account (repeat option to set multiple properties)" msgstr "" "Bu hesap üzerindeki özelliği ayarla (birden fazla özellik ayarlamak için " "seçeneği tekrarla)" msgid "" "Set a property on this container (repeat option to set multiple properties)" msgstr "" "Bu kap üzerinde bir özellik ayarla (birden fazla özellik ayarlamak için " "seçenekleri tekrarla)" msgid "Set a property on this image (repeat option to set multiple properties)" msgstr "" "Bu imaj üzerindeki bir özelliği ayarla (birden fazla özellik ayarlamak için " "seçeneği tekrarla)" msgid "" "Set a property on this object (repeat option to set multiple properties)" msgstr "" "Bu nesne üzerinde bir özellik ayarla (birden fazla özellik ayarlamak için " "seçeneği tekrarla)" msgid "Set a property on this server (repeat option to set multiple values)" msgstr "" "Bu sunucuda bir özellik ayarlayın (birden fazla değeri ayarlamak için " "seçeneği tekrarlayın)" msgid "" "Set a property on this volume (repeat option to set multiple properties)" msgstr "" "Bu disk bölümü üzerinde bir özellik ayarla (birden fazla özellik ayarlamak " "için seçeneği tekrarla)" msgid "" "Set a property on this volume type (repeat option to set multiple properties)" msgstr "" "Bu disk bölümü türü üzerinde bir özellik ayarla (birden fazla özellik " "ayarlamak için seçeneği tekrarla)" msgid "" "Set a property to this snapshot (repeat option to set multiple properties)" msgstr "" "Bu anlık görüntü için bir özellik ayarla (birden fazla özellikleri ayarlamak " "için seçeneği tekrarla)" msgid "" "Set a property to this volume (repeat option to set multiple properties)" msgstr "" "Bu disk bölümüne bir özellik ayarla (birden fazla özellik ayarlamak için " "seçeneği tekrarlayın)" msgid "Set a tag on this image (repeat option to set multiple tags)" msgstr "" "Bu imaj üzerinde bir etiket oluştur (birden fazla etiket oluşturmak için " "seçeneği tekrarla)" msgid "Set account properties" msgstr "Hesap özelliklerini ayarla" msgid "" "Set address scope associated with the subnet pool (name or ID), prefixes " "must be unique across address scopes" msgstr "" "Alt ağ havuzuyla ilişkili adres kapsamını ayarla (isim veya ID), öneklerin " "adres kapsamları arasında benzersiz olması gerekir" msgid "Set address scope name" msgstr "Adres kapsamı adını ayarla" msgid "Set address scope properties" msgstr "Adres kapsamı özelliklerini ayarlama" msgid "Set aggregate name" msgstr "Küme ismini ayarla" msgid "Set aggregate properties" msgstr "Küme özelliklerini ayarla" msgid "Set an alternate project on this image (name or ID)" msgstr "Bu imaj üzerinde alternatif bir proje ayarla (isim veya ID)" msgid "" "Set an image property on this volume (repeat option to set multiple image " "properties)" msgstr "" "Bu disk bölümü üzerinde imaj özelliği ayarla (birden fazla imaj özelliği " "ayarlamak için seçeneği tekrarla)" msgid "Set availability zone name" msgstr "Kullanılabilirlik bölge adını ayarla" msgid "Set compute agent properties" msgstr "Hesaplama ajanı özelliklerini ayarla" msgid "Set compute service properties" msgstr "Hesaplama servisi özelliklerini ayarla" msgid "Set consistency group properties" msgstr "Tutarlılık grubu özelliklerini ayarla" msgid "Set consumer properties" msgstr "Alıcı özelliklerini ayarla" msgid "Set container properties" msgstr "Kap özelliklerini ayarla" msgid "Set credential properties" msgstr "Kimlik bilgileri özelliklerini ayarla" msgid "" "Set data plane status of this port (ACTIVE | DOWN). Unset it to None with " "the 'port unset' command (requires data plane status extension)" msgstr "" "Bu bağlantı noktasının veri düzlemi durumunu ayarlayın (ACTIVE | DOWN). " "'port unset' komutu ile None'a getirin (veri düzlemi durum uzantısı " "gerektirir)" msgid "Set default project (name or ID)" msgstr "Varsayılan projeyi ayarla (isim veya ID)" msgid "" "Set default quota for subnet pool as the number ofIP addresses allowed in a " "subnet" msgstr "" "Bir alt ağda izin verilen IP adreslerinin sayısı olarak alt ağ havuzu için " "varsayılan kota ayarla" msgid "Set domain properties" msgstr "Alan özelliklerini ayarla" msgid "Set endpoint properties" msgstr "Uç nokta özellikleri ayarla" msgid "Set federation protocol properties" msgstr "Federasyon protokolü özelliklerini ayarla" msgid "Set flavor access to project (name or ID) (admin only)" msgstr "Projeye flavor erişimi ayarla (isim veya ID) (sadece yönetici)" msgid "Set flavor name" msgstr "Flavor ismi tanımla" msgid "Set flavor properties" msgstr "Flavor özelliklerini ayarla" msgid "Set floating IP Properties" msgstr "Yüzen IP özelliklerini ayarla" msgid "Set floating IP description" msgstr "Yüzen IP açıklaması ayarla" msgid "Set group properties" msgstr "Grup özelliklerini ayarla" msgid "Set host properties" msgstr "Sunucu özelliklerini ayarla" msgid "Set identity provider description" msgstr "Kimlik sağlayıcı tanımlarını ayarla" msgid "Set identity provider properties" msgstr "Kimlik sağlayıcı özelliklerini ayarla" msgid "Set image properties" msgstr "İmaj özelliklerini ayarla" msgid "Set mapping properties" msgstr "Eşleşme özelliklerini ayarla" msgid "Set network RBAC policy properties" msgstr "Ağ RBAC ilke özelliklerini ayarlama" msgid "Set network agent description" msgstr "Ağ aracı açıklaması ayarla" msgid "Set network agent properties" msgstr "Ağ ajanı özelliklerini ayarla" msgid "Set network description" msgstr "Ağ açıklamasını ayarla" msgid "Set network flavor description" msgstr "Ağ flavor açıklamasını ayarla" msgid "Set network flavor profile properties" msgstr "Ağ flavor profil özelliklerini ayarla" msgid "Set network flavor properties" msgstr "Ağ flavor'ının özelliklerini ayarla" msgid "Set network name" msgstr "Ağ ismini ayarla" msgid "Set network properties" msgstr "Ağ özelliklerini ayarla" msgid "Set network segment description" msgstr "Ağ kesimi açıklamasını ayarla" msgid "Set network segment name" msgstr "Ağ bölüm ismi ayarla" msgid "Set network segment properties" msgstr "Ağ kesimi özelliklerini ayarla" msgid "Set new root password (interactive only)" msgstr "Yeni root parolası ayarla (sadece interaktif)" msgid "Set object properties" msgstr "Nesne özelliklerini ayarla" msgid "Set policy properties" msgstr "Politika özelliklerini ayarla" msgid "Set port name" msgstr "Bağlantı noktası ismini ayarla" msgid "Set port properties" msgstr "Bağlantı noktaları özelliklerini ayarla" msgid "Set project description" msgstr "Proje açıklamasını ayarla" msgid "Set project name" msgstr "Proje ismini ayarla" msgid "Set project properties" msgstr "Proje özelliklerini ayarla" msgid "Set quotas for " msgstr " için kotaları ayarla" msgid "Set quotas for a specific " msgstr "Belirli bir için kota ayarla" msgid "Set quotas for project or class" msgstr "Proje veya sınıf için kotaları ayarla" msgid "Set quotas for this project or class (name/ID)" msgstr "Bu proje veya sınıf için (isim/ID) kotaları ayarla" msgid "Set region properties" msgstr "Bölgenin özelliklerini ayarla" msgid "Set role name" msgstr "Rol ismini ayarla" msgid "Set role properties" msgstr "Rol özelliklerini ayarla" msgid "Set router description" msgstr "Yönlendirici açıklaması ayarla" msgid "Set router name" msgstr "Yönlendirici isimini ayarla" msgid "Set router properties" msgstr "Yönlendirici özelliklerini ayarla" msgid "Set router to centralized mode (disabled router only)" msgstr "" "Yönlendiriciyi merkezi kipe ayarla (sadece devre dışı bırakılmış " "yönlendiriciler)" msgid "Set router to distributed mode (disabled router only)" msgstr "" "Yönlendiriciyi dağıtık kipte ayarla (sadece devre dışı bırakılmış " "yönlendiriciler)" msgid "Set security group properties" msgstr "Güvenlik grubu özelliklerini ayarla" msgid "Set security group rule description" msgstr "Güvenlik grubu kural tanımını ayarla" msgid "Set server properties" msgstr "Sunucu özelliklerini ayarla" msgid "Set service properties" msgstr "Servis özelliklerini ayarla" msgid "Set service provider properties" msgstr "Servis sağlayıcı özelliklerini ayarlayın" msgid "Set snapshot properties" msgstr "Anlık görüntü özelliklerini ayarlayın" msgid "Set subnet description" msgstr "Alt ağ açıklaması ayarla" msgid "Set subnet pool default prefix length" msgstr "Alt ağ havuzu varsayılan ön ek boyutunu ayarla " msgid "Set subnet pool description" msgstr "Alt ağ havuzu açıklaması ayarla" msgid "Set subnet pool maximum prefix length" msgstr "Alt ağ havuzu en büyük ön ek boyutunu ayarla" msgid "Set subnet pool minimum prefix length" msgstr "Altağ havuzunun en küçün ön ek boyutunu ayarla" msgid "Set subnet pool name" msgstr "Alt ağ havuz ismini ayarla" msgid "" "Set subnet pool prefixes (in CIDR notation) (repeat option to set multiple " "prefixes)" msgstr "" "Alt ağ havuzu öneklerini ayarla (CIDR notasyonunda) (birden fazla ön ek " "ayarlamak için seçeneği tekrarla)" msgid "Set subnet pool properties" msgstr "Alt ağ havuzu özellikleri ayarla" msgid "Set subnet properties" msgstr "Altağ özelliklerini ayarla" msgid "" "Set the class that provides encryption support for this volume type (e.g " "\"LuksEncryptor\") (admin only) (This option is required when setting " "encryption type of a volume for the first time. Consider using other " "encryption options such as: \"--encryption-cipher\", \"--encryption-key-size" "\" and \"--encryption-control-location\")" msgstr "" "Bu birim türü için şifreleme desteği sağlayan sınıfı ayarlayın (örn " "\"LuksEncryptor\") (sadece yönetici) (Bu seçenek, bir disk bölümü şifreleme " "türünü ilk kez ayarlarken gereklidir. Şu diğer şifreleme seçeneklerini " "kullanmayı düşünün: \"--encryption-cipher\", \"--encryption-key-size\" ve " "\"--encryption-control-location\")" msgid "" "Set the class that provides encryption support for this volume type (e.g " "\"LuksEncryptor\") (admin only) (This option is required when setting " "encryption type of a volume. Consider using other encryption options such " "as: \"--encryption-cipher\", \"--encryption-key-size\" and \"--encryption-" "control-location\")" msgstr "" "Bu disk bölümü türü için şifreleme desteği sağlayan sınıfı ayarla (örn " "\"LuksEncryptor\") (sadece yönetici) (Bir disk bölümünün şifreleme türü " "ayarlanırken bu seçenek zorunludur. \"--encryption-cipher\", \"--encryption-" "key-size\" ve \"--encryption-control-location\" gibi diğer şifreleme " "seçeneklerini kullanmayı göz önünde bulundurun)" msgid "" "Set the encryption algorithm or mode for this volume type (e.g \"aes-xts-" "plain64\") (admin only)" msgstr "" "Bu disk bölümü türü için şifreleme algoritmasını veya kipini ayarla (örn " "\"aes-xts-plain64\") (sadece yönetici)" msgid "Set the network as the default external network" msgstr "Ağı varsayılan dış ağ olarak ayarlayın" msgid "" "Set the notional service where the encryption is performed (\"front-end\" or " "\"back-end\") (admin only) (The default value for this option is \"front-end" "\" when setting encryption type of a volume for the first time. Consider " "using other encryption options such as: \"--encryption-cipher\", \"--" "encryption-key-size\" and \"--encryption-provider\")" msgstr "" "Şifrelemenin yapıldığı kavramsal servisi ayarla (\"front-end\" veya \"back-" "end\") (sadece yönetici) (Disk bölümü türü şifrelemesi ilk kez ayarlanırken " "bu seçenek için varsayılan değer \"front-end\"dir. Şu diğer şifreleme " "seçenelerini kullanmayı düşünün: \"--encryption-cipher\", \"--encryption-key-" "size\" ve \"--encryption-provider\")" msgid "" "Set the notional service where the encryption is performed (\"front-end\" or " "\"back-end\") (admin only) (The default value for this option is \"front-end" "\" when setting encryption type of a volume. Consider using other encryption " "options such as: \"--encryption-cipher\", \"--encryption-key-size\" and \"--" "encryption-provider\")" msgstr "" "Şifrelemenin gerçekleştirildiği kavramsal servisi ayarla (\"front-end\" veya " "\"back-end\") (sadece yönetici) (Bir disk bölümünün şifreleme türü " "ayarlanırken bu seçenek için varsayılan değer \"front-end\"'dir. \"--" "encryption-cipher\", \"--encryption-key-size\" ve \"--encryption-provider\" " "gibi diğer şifreleme seçeneklerini kullanmayı göz önünde bulundurun)" msgid "Set the password on the rebuilt instance" msgstr "Yeniden oluşturulmuş sunucudaki parolayı ayarla" msgid "Set the router as highly available (disabled router only)" msgstr "" "Yönlendiriciyi yüksek kullanılabilirlikli olarak ayarla (sadece " "yönlendiriciyi devre dışı bırak)" msgid "" "Set the size of the encryption key of this volume type (e.g \"128\" or " "\"256\") (admin only)" msgstr "" "Bu disk bölümü türünün şifreleem anahtarı boyutunu ayarla (örn \"128\" veya " "\"256\") (sadece yönetici)" msgid "Set the type of volume" msgstr "Disk bölümü türünü ayarla" msgid "Set this as a default network QoS policy" msgstr "Bunu varsayılan bir ağ QoS politikası olarak ayarla" msgid "Set this as a default subnet pool" msgstr "Bunu varsayılan altağ havuzunu ayarla" msgid "Set this as a non-default network QoS policy" msgstr "Bunu varsayılan olmayan bir ağ QoS politikası olarak ayarla" msgid "Set this as a non-default subnet pool" msgstr "Bunu varsayılan olmayan altağ havuzu olarak ayarla" msgid "" "Set this network as an external network (external-net extension required)" msgstr "" "Bu şebekeyi harici bir ağ olarak ayarlayın (harici ağ uzantısı gerekir)" msgid "Set this network as an internal network" msgstr "Bu şebekeyi dahili bir şebeke olarak ayarlayın" msgid "Set this network as an internal network (default)" msgstr "Bu ağı dahili bir ağ olarak ayarlayın (varsayılan)" msgid "Set this subnet pool as not shared" msgstr "Bu alt ağ havuzunu paylaşılmayan olarak ayarlayın" msgid "Set this subnet pool as shared" msgstr "Bu alt ağ havuzunu paylaşılan olarak ayarla" msgid "Set user description" msgstr "Kullanıcı tanımını ayarla" msgid "Set user email address" msgstr "Kullanıcı e-posta adresini ayarla" msgid "Set user name" msgstr "Kullanıcı adını ayarla" msgid "Set user password" msgstr "Kullanıcı parolası ayarla" msgid "Set user properties" msgstr "Kullanıcı özelliklerini ayarla" msgid "Set volume backup properties" msgstr "Disk bölümü yedek özelliklerini ayarla" msgid "Set volume host properties" msgstr "Disk bölümü sunucu özelliklerini ayarla" msgid "Set volume properties" msgstr "Disk bölümü özelliklerini ayarla" msgid "Set volume service properties" msgstr "Disk bölümü servisi özelliklerini ayarla" msgid "Set volume snapshot properties" msgstr "Disk bölümü anlık görüntüsü özelliklerini ayarla" msgid "Set volume to read-only access mode" msgstr "Disk bölümünü salt okunur kipine ayarla" msgid "Set volume to read-write access mode" msgstr "Disk bölümünü okuma yazma erişimi kipine ayarla" msgid "Set volume to read-write access mode (default)" msgstr "Okuma-yazma erişim kipine disk bölümüne ayarla (varsayılan)" msgid "Set volume type access to project (name or ID) (admin only)" msgstr "" "Projeye disk bölümü türü erişimini ayarla (isim veya ID) (sadece yönetici)" msgid "Set volume type description" msgstr "Disk bölümü türü açıklamasını ayarla" msgid "Set volume type name" msgstr "Disk bölüm türü ismini ayarla" msgid "Set volume type properties" msgstr "Disk bölümü türü özelliklerini ayarla" msgid "Sets an expiration date for the trust (format of YYYY-mm-ddTHH:MM:SS)" msgstr "" "Güven için son kullanma tarihi ayarlayın (YYYY-mm-ddTHH:MM:SS biçiminde)" msgid "Share meter between projects" msgstr "Sayacı projeler arasında paylaş" msgid "Share the address scope between projects" msgstr "Projeler arasında adres kapsamını paylaş" msgid "Share the network between projects" msgstr "Ağları projeler arasında paylaşın" msgid "Shelve server(s)" msgstr "Sunucu(yu/ları) raftan çıkart" msgid "Show API extension" msgstr "API uzantısını göster" msgid "Show IP availability for a specific network (name or ID)" msgstr "Belirli bir ağ için IP kullanılabilirliğini göster (isim veya ID)" msgid "Show RDP console URL" msgstr "RDP konsol URL'ini göster" msgid "Show SPICE console URL" msgstr "SPICE konsol URL'ini göster" msgid "Show WebMKS console URL" msgstr "WebMKS konsol URL'ini göster" msgid "Show absolute limits" msgstr "Mutlak sınırları göster" msgid "Show all modules that have version information" msgstr "Sürüm bilgisine sahip tüm modülleri göster" msgid "" "Show commands filtered by a command group, for example: identity, volume, " "compute, image, network and other keywords" msgstr "" "Komutları bir komut grubu tarafından filtrelenmiş halde göster, örneğin: " "kimlik, disk bölümü, hesaplama, imaj, ağ ve diğer anahtar kelimeler" msgid "Show compute and block storage limits" msgstr "Hesaplama ve blok depolama sınırlarını göster" msgid "Show credentials for user (name or ID)" msgstr "Kullanıcılar için kimlik bilgilerini göster (isim veya ID)" msgid "Show default quotas for " msgstr " için varsayılan kotaları göster" msgid "Show detail for all projects (admin only) (defaults to False)" msgstr "" "Tüm projeler için detayları göster (sadece yönetici) (varsayılan olarak " "False)" msgid "Show details for all projects. Admin only. (defaults to False)" msgstr "" "Tüm projeler için detayları göster. Sadece yönetici. (varsayılan olarak " "False)" msgid "" "Show limits for a specific project (name or ID) [only valid with --absolute]" msgstr "" "Belirli bir proje için sınırları göster (isim veya ID) [sadece --absolute " "ile geçerli]" msgid "Show network IP availability details" msgstr "Ağ IP kullanılabilirlik detaylarını göster" msgid "Show network details" msgstr "Ağ detaylarını göster" msgid "Show network meter" msgstr "Ağ ölçeklerini göster" msgid "Show noVNC console URL (default)" msgstr "noVNC konsol URL'ini göster (varsayılan)" msgid "Show only bare public key paired with the generated key" msgstr "" "Yalnızca oluşturulan anahtarla eşleştirilmiş çıplak genel anahtarı göster" msgid "Show password in clear text" msgstr "Parolaları düz metin olarak göster" msgid "Show project's subtree (children) as a list" msgstr "Projenin alt projelerini (çocuklarını) bir liste olarak göster" msgid "Show quotas for " msgstr " için kotaları göster" msgid "Show quotas for project or class" msgstr "Proje veya sınıf için kotaları göster" msgid "Show quotas for this project or class (name or ID)" msgstr "Bu proje veya sınıf (isim veaya ID) için kotaları göster" msgid "Show rate limits" msgstr "Oran sınırları göster" msgid "Show resource usage for a single project" msgstr "Tek bir proje için kaynak kullanımını göster" msgid "Show serial console URL" msgstr "serial konsol URL'ini göster" msgid "Show server details" msgstr "Sunucu detaylarını göster" msgid "Show server event details" msgstr "Sunucu olay detaylarını listele" msgid "Show server's console output" msgstr "Sunucunun konsol çıktısını göster" msgid "Show server's remote console URL" msgstr "Sunucunun uzak konsol URL'ini göster" msgid "Show service catalog information" msgstr "Servis katalog bilgisini göster" msgid "Show the project's parents as a list" msgstr "Projenin üst projelerini bir liste olarak göster" msgid "Show volume details" msgstr "Disk bölümü detaylarını göster" msgid "Show volume transfer request details." msgstr "Disk bölümü aktarım isteği detaylarını göster." msgid "Show xvpvnc console URL" msgstr "xvpvnc konsol URL'ini göster" msgid "Size of image data (in bytes)" msgstr "İmaj verisinin boyutu (bayt cinsinden)" msgid "Skip flavor and image name lookup." msgstr "Flavor veya imaj ismi aramasını atla." msgid "Snapshot to backup (name or ID)" msgstr "Yedeği alınacak anlık görüntü (isim veya ID)" msgid "Snapshot to display (name or ID)" msgstr "Gösterilecek anlık görüntü (isim veya ID)" msgid "Snapshot to modify (name or ID)" msgstr "Düzenlenecek anlık görüntü (isim veya ID)" msgid "Snapshot(s) to delete (name or ID)" msgstr "Silinecek anlık görüntü(ler) (isim veya ID)" msgid "" "Sort output by selected keys and directions (asc or desc) (default: asc), " "repeat this option to specify multiple keys and directions." msgstr "" "Çıktıyı seçilen anahtarlara ve yönlere göre sırala (artan veya azalan) " "(varsayılan: artan), birden çok anahtar ve yön belirlemek için bu seçeneği " "tekrarlayın." msgid "" "Sort output by selected keys and directions(asc or desc) (default: name:" "asc), multiple keys and directions can be specified separated by comma" msgstr "" "Çıktıyı seçilen tuşlara ve yönlere göre sırala (artan veya azalan) " "(varsayılan: ad:artan), virgülle ayrılmış olarak birden çok anahtar ve yön " "belirlenebilir" msgid "Specific service endpoint to use" msgstr "Kullanılacak belirli bir servis uç noktası" msgid "Specifies if the role grant is inheritable to the sub projects" msgstr "" "Rol atamasının alt projelere miras bırakılıp bırakılmayacağını belirler" msgid "" "Specify a gateway for the subnet. The three options are: : " "Specific IP address to use as the gateway, 'auto': Gateway address should " "automatically be chosen from within the subnet itself, 'none': This subnet " "will not use a gateway, e.g.: --gateway 192.168.9.1, --gateway auto, --" "gateway none (default is 'auto')." msgstr "" "Alt ağ için bir geçit belirle. Üç seçenek: : geçit olarak " "kullanılacak belirli bir IP adresi, 'auto': Geçit adresi ağdan otomatik " "olarak seçilmelidir, 'none': Bu alt ağ bir geçit kullanmayacak, örn: --" "gateway 192.168.9.1, --gateway auto, --gateway none (varsayılan 'auto')." msgid "" "Specify a gateway for the subnet. The options are: : Specific IP " "address to use as the gateway, 'none': This subnet will not use a gateway, e." "g.: --gateway 192.168.9.1, --gateway none." msgstr "" "Alt ağ için bir geçit belirle. Seçenekler: : Geçit olarak " "kullanılacak belirli bir IP adresi, 'none': Bu alt ağ geçit olarak " "kullanılmayacak, örn: --gateway 192.168.9.1, --gateway none." msgid "Specify an alternate project (name or ID)" msgstr "Alternatif bir proje belirle (isim veya ID)" msgid "Specify an alternate user (name or ID)" msgstr "Alternatif bir kullanıcı belirle (isim veya ID)" msgid "Specify if this network should be used as the default external network" msgstr "" "Bu ağın varsayılan dış ağ olarak kullanılması gerekip gerekmediğini " "belirleyin" msgid "" "Specifying a --nic of auto or none cannot be used with any other --nic, --" "network or --port value." msgstr "" "auto veya none --nic'i belirtmek başka bir --nic, --network veya --port " "değeriyle kullanılamaz." msgid "" "Specifying the auth-key as a positional argument has been deprecated. " "Please use the --auth-key option in the future." msgstr "" "Yetki anahtarını pozisyonel argüman olarak belirleme kullanımdan " "kaldırıldı. Lütfen gelecekte --auth-key seçeneğini kullanın." msgid "Start server(s)." msgstr "Sunucu(ları/yu) başlat." msgid "Stop server(s)." msgstr "Sunucu(ları/yu) durdur." #, python-format msgid "Subnet does not contain %(option)s %(value)s" msgstr "Ağ %(option)s %(value)s'yü içermiyor" msgid "Subnet on which you want to create the floating IP (name or ID)" msgstr "Yüzen IP'yi oluşturmak istediğiniz alt ağ (isim veya ID)" #, python-format msgid "Subnet pool does not contain prefix %s" msgstr "%s önekini içermeyen altağ havuzu" msgid "Subnet pool from which this subnet will obtain a CIDR (Name or ID)" msgstr "Bu alt ağın bir CIDR alacağı alt ağ havuzu (isim veya ID)" msgid "Subnet pool to display (name or ID)" msgstr "Gösterilecek altağ havuzu (isim veya ID)" msgid "Subnet pool to modify (name or ID)" msgstr "Düzenlenecek altağ havuzu (isim veya ID)" msgid "Subnet pool(s) to delete (name or ID)" msgstr "Silinecek altağ havuzları (isim veya ID)" msgid "" "Subnet range in CIDR notation (required if --subnet-pool is not specified, " "optional otherwise)" msgstr "" "CIDR notasyonunda altağ aralığı (--subnet-pool belirtilmediyse zorunlu, " "diğer türlü seçimlidir)" msgid "Subnet to be added (name or ID)" msgstr "Eklenecek alt ağ (isim veya ID)" msgid "Subnet to be removed (name or ID)" msgstr "Kaldırılacak altağ (isim veya ID)" msgid "Subnet to display (name or ID)" msgstr "Gösterilecek altağ (isim veya ID)" msgid "Subnet to modify (name or ID)" msgstr "Düzenlenecek altağ (isim veya ID)" msgid "Subnet(s) to delete (name or ID)" msgstr "Silinecek altağ(lar) (isim veya ID)" msgid "Suspend server(s)" msgstr "Sunucu(yu/ları) durdur" msgid "Swap space size in MB (default 0M)" msgstr "MB cinsinden takas alanı boyutu (varsayılan 0M)" #, python-format msgid "Tag to be added to the %s (repeat option to set multiple tags)" msgstr "" "%s'e eklenecek etiketler (birden fazla etiket ayarlamak için seçeneği tekrar " "et)" #, python-format msgid "Tag to be removed from the %s (repeat option to remove multiple tags)" msgstr "" "%s'den kaldırılacak etiket (birden fazla etiket silmek için seçenekleri " "tekrarlayın)" msgid "Target hostname" msgstr "Hedef sunucu adı" msgid "Thaw and enable the specified volume host" msgstr "Belirtilen disk bölümü barındırıcısını çöz ve etkinleştir" #, python-format msgid "The %(old)s option is deprecated, please use %(new)s instead." msgstr "" "%(old)s seçeneği kullanımdan kaldırıldı, lütfen onun yerine %(new)s kullanın." msgid "The --clear-routes option is deprecated, please use --no-route instead." msgstr "" "--clear-routes seçeneği kullanımdan kaldırıldı, onun yerine --no-route " "kullanın." msgid "The --device-id option is deprecated, please use --device instead." msgstr "" "--device-id seçeneği kullanımdan kaldırıldı, lütfen onun yerine --device " "komutunu kullanın." msgid "The --host-id option is deprecated, please use --host instead." msgstr "" "--host-id seçeneği kullanımdan kaldırıldı, lütfen onun yerine --host " "komutunu kullanın." msgid "The --owner option is deprecated, please use --project instead." msgstr "" "--owner seçeneği kullanımdan kaldırıldı, onun yerine lütfen --project " "seçeneğini kullanın." msgid "" "The ID of the volume backend replication target where the host will failover " "to (required)" msgstr "" "Ana bilgisayarın üstleneceği disk bölümü arkaplan kopyası ID'si (zorunlu)" msgid "" "The argument --type is deprecated, use service create --name " "type instead." msgstr "" "--type argümanı kullanımdan kaldırılmıştır, onun yerine service create --" "name type komutunu kullanın." msgid "" "The attribute(s) of the exsiting remote volume snapshot (admin required) " "(repeat option to specify multiple attributes) e.g.: '--remote-source source-" "name=test_name --remote-source source-id=test_id'" msgstr "" "Varolan uzak birimin anlık görüntüsünün nitelikleri (yönetici gerekli) " "(birden fazla özellik belirlemek için seçeneği tekrarlayın) örn: '--remote-" "source source-name=test_name --remote-source source-id=test_id'" msgid "The last backup of the previous page (name or ID)" msgstr "Bir önceki sayfanın son yedeği (isim veya ID)" msgid "The last flavor ID of the previous page" msgstr "Bir önceki sayfanın son flavor ID'si" msgid "" "The last image of the previous page. Display list of images after marker. " "Display all images if not specified. (name or ID)" msgstr "" "Bir önceki sayfanın son imajı. İşaretçiden sonraki imajların listesini " "görüntüle. Belirtilmemişse tüm imajları görüntüleyin. (isim veya ID)" msgid "" "The last server of the previous page. Display list of servers after marker. " "Display all servers if not specified. (name or ID)" msgstr "" "Bir önceki sayfanın son sunucusu. İşaretçi sonrasındaki sunucuların " "listesini görüntüle. Belirtilmemişse tüm sunucuları görüntüleyin. (isim veya " "ID)" msgid "The last snapshot ID of the previous page" msgstr "Bir önceki sayfanın son anlık görüntü ID'si" msgid "The last volume ID of the previous page" msgstr "Bir önceki sayfanın son disk bölümü ID'si" msgid "The object to which this RBAC policy affects (name or ID)" msgstr "Bu RBAC politikasının etkilediği nesne (ad veya kimlik)" msgid "The owner project (name or ID)" msgstr "Projenin sahibi (isim veya ID)" msgid "" "The physical mechanism by which the virtual network is implemented. For " "example: flat, geneve, gre, local, vlan, vxlan." msgstr "" "Sanal ağın uygulandığı fiziksel mekanizma. Örneğin: düz, geneve, gre, yerel, " "vlan, vxlan." msgid "The project to which the RBAC policy will be enforced (name or ID)" msgstr "RBAC politikası dayatılacak proje (isim veya ID)" msgid "The remote IP prefix to associate with this rule" msgstr "Bu kural ile ilişkilendirilecek uzak IP ön eki" msgid "" "This command has been deprecated. Please use \"floating ip create\" instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Lütfen onun yerine \"floating ip create\" " "kullanın." msgid "" "This command has been deprecated. Please use \"floating ip delete\" instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Lütfen yerine \"floating ip delete\" " "komutunu kullanın." msgid "" "This command has been deprecated. Please use \"floating ip list\" instead." msgstr "" "Bu komut kullanımdan kalktı. Onun yerine lütfen \"floating ip list\" " "kullanın." msgid "" "This command has been deprecated. Please use \"floating ip pool list\" " "instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Lütfen, onun yerine \"floating ip pool list" "\" komutunu kullanın." msgid "" "This command has been deprecated. Please use \"floating ip show\" instead." msgstr "" "Bu komut önerilmiyor. Lütfen bunun yerine \"floating ip show\"ı kullanın." msgid "" "This command has been deprecated. Please use \"server add fixed ip\" instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Onun yerine lütfen \"server add fixed ip\" " "komutunu kullanın." msgid "" "This command has been deprecated. Please use \"server add floating ip\" " "instead." msgstr "" "Bu komut kullanımdan kaldırılmıştır. Onun yerine lütfen \"server add " "floating ip\" kullanın." msgid "" "This command has been deprecated. Please use \"server remove fixed ip\" " "instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Lütfen onun yerine \"server remove fixed ip" "\" komutunu kullanın." msgid "" "This command has been deprecated. Please use \"server remove floating ip\" " "instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Onun yerine lütfen \"server remove floating " "ip\" komutunu kullanın." msgid "" "This command has been deprecated. Please use \"volume backup create\" " "instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Onun yerine lütfen \"volume backup create\" " "komutunu kullanın." msgid "" "This command has been deprecated. Please use \"volume backup delete\" " "instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Lütfen onun yerine \"volume backup delete\" " "kullanın." msgid "" "This command has been deprecated. Please use \"volume backup list\" instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Lütfen onun yerine \"volume backup list\" " "komutunu kullanın." msgid "" "This command has been deprecated. Please use \"volume backup restore\" " "instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Lütfen onun yerine \"volume backup restore" "\" komutunu kullanın." msgid "" "This command has been deprecated. Please use \"volume backup show\" instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Lütfen onun yerine \"volume backup show\" " "komutunu kullanın." msgid "" "This command has been deprecated. Please use \"volume snapshot create\" " "instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Lütfen onun yerine \"volume snapshot create" "\" komutunu kullanın." msgid "" "This command has been deprecated. Please use \"volume snapshot delete\" " "instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Lütfen onun yerine \"volume snapshot delete" "\" komutunu kullanın." msgid "" "This command has been deprecated. Please use \"volume snapshot list\" " "instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Onun yerine lütfen \"volume snapshot list\" " "komutunu kullanın." msgid "" "This command has been deprecated. Please use \"volume snapshot set\" instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Lütfen bunun yerine \"volume snapshot set\" " "komutunu kullanın." msgid "" "This command has been deprecated. Please use \"volume snapshot show\" " "instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Lütfen onun yerine \"volume snapshot show\" " "komutunu kullan." msgid "" "This command has been deprecated. Please use \"volume snapshot unset\" " "instead." msgstr "" "Bu komut kullanımdan kaldırıldı. Lütfen onun yerine \"volume snapshot unset" "\" komutunu kullanın." msgid "Token to be deleted" msgstr "Silinecek jeton" msgid "" "Tokens generated from the trust will represent (defaults to False)" msgstr "" "Güvenden oluşturulan jeton 'ı temsil edecek (varsayılan False)" msgid "Trust to display" msgstr "Gösterilecek güven" msgid "Trust(s) to delete" msgstr "Silinecek güvenler" msgid "Type of OS" msgstr "OS türü" msgid "Type of architecture" msgstr "Mimari türü" msgid "Type of hypervisor" msgstr "Arakatman türü" msgid "" "Type of the object that RBAC policy affects (\"qos_policy\" or \"network\")" msgstr "" "RBAC politikasını etkileyen nesne türü (\"qos_policy\" veya \"network\")" msgid "URL" msgstr "URL" msgid "URL of the agent" msgstr "Ajanın URL'i" msgid "Unique flavor ID; 'auto' creates a UUID (default: auto)" msgstr "Benzersiz flavor ID'si; 'auto' bir UUID oluşturur (varsayılan: auto)" msgid "Unlock server(s)" msgstr "Sunucu(ların/nun) kilidini kaldır" msgid "Unpause server(s)" msgstr "Sunucu(ları/yu) devam ettir" msgid "Unset QoS specification properties" msgstr "QoS belirtimi özellikleri ayarlarını kaldır" msgid "Unset a project property (repeat option to unset multiple properties)" msgstr "" "Proje özelliğini kaldır (birden fazla özellik kaldırmak için seçeneği " "tekrarla)" msgid "" "Unset a property on this image (repeat option to set multiple properties)" msgstr "" "Bu imajdaki bir özelliği kaldır (birden fazla özelliği ayarlamak için " "seçeneği tekrarla)" msgid "Unset a tag on this image (repeat option to set multiple tags)" msgstr "" "Bu imajdan etiketi kaldır (birden fazla etiket ayarlamak için seçeneği " "tekrarla)" msgid "Unset account properties" msgstr "Hesap özelliklerinin ayarını kaldır" msgid "Unset aggregate properties" msgstr "Küme özelliklerini kaldır" msgid "Unset container properties" msgstr "Kap özelliklerinin ayarını kaldır" msgid "Unset flavor properties" msgstr "Flavor özelliklerini geri al" msgid "Unset floating IP Properties" msgstr "Yüzer IP Özelliklerini Kaldır" msgid "Unset image tags and properties" msgstr "İmaj etiketlerinin ve özelliklerinin ayarını kaldır" msgid "Unset network properties" msgstr "Ağ özelliklerinin ayarını kaldır" msgid "Unset object properties" msgstr "Nesne özelliklerinin ayarını kaldır" msgid "Unset port properties" msgstr "Bağlantı noktası özelliklerinin ayarını kaldır" msgid "Unset project properties" msgstr "Proje özelliklerini kaldır" msgid "Unset router properties" msgstr "Yönlendirici özelliklerini kaldır" msgid "Unset server properties" msgstr "Sunucu özelliklerini kaldır" msgid "Unset snapshot properties" msgstr "Anlık görüntü özelliklerinin ayarını kaldır" msgid "Unset subnet pool properties" msgstr "Altağ havuz özelliklerinin ayarlarını kaldır" msgid "Unset subnet properties" msgstr "Altağ özelliklerinin ayarını kaldır" msgid "Unset volume properties" msgstr "Disk bölümü özellikleri ayarlarını kaldır" msgid "Unset volume snapshot properties" msgstr "Disk bölümü anlık görüntü özelliklerinin ayarını kaldır" msgid "Unset volume type properties" msgstr "Disk bölümü türü özelliklerinin ayarlarını kaldır" msgid "Unshelve server(s)" msgstr "Sunucuları al" msgid "Updated name of the subnet" msgstr "Alt ağın güncellenmiş ismi" msgid "" "Upload a file and rename it. Can only be used when uploading a single object" msgstr "" "Bir dosya yükle ve yeniden adlandır. Yalnızca tek bir nesne yüklerken " "kullanılabilir" msgid "Upload image from local file" msgstr "Yerel dosyadan imajı yükle" msgid "Upload image to this store" msgstr "Bu depoya imaj yükle" msgid "Upload object to container" msgstr "Kabı nesneye yükle" msgid "Uploading data and using container are not allowed at the same time" msgstr "Aynı anda veri yüklemek ve kap kullanmaya izin verilmiyor." #, python-format msgid "Usage from %(start)s to %(end)s on project %(project)s: \n" msgstr "%(start)s'dan %(end)s'e %(project)s projesindeki kullanım:\n" #, python-format msgid "Usage from %(start)s to %(end)s: \n" msgstr "%(start)s'dan %(end)s'e kullanım: \n" msgid "Usage range end date, ex 2012-01-20 (default: tomorrow)" msgstr "Kullanım aralığı bitiş tarihi, ex 2012-01-20 (varsayılan: yarın)" msgid "Usage range start date, ex 2012-01-20 (default: 4 weeks ago)" msgstr "" "Kullanım aralığı başlangıç tarihi, ex 2012-01-20 (varsayılan: 4 hafta önce)" msgid "Use --stdin to enable read image data from standard input" msgstr "Standart girdiden imaj verilerini okuyabilmek için --stdin kullanın" msgid "Use as source of volume (name or ID)" msgstr "Disk bölümünün kaynağı olarak kullan (isim veya ID)" msgid "Use as source of volume (name or ID)" msgstr "" " anlık görüntüsünü disk bölümü kaynağı olarak kullan (isim veya ID)" msgid "Use default subnet pool for --ip-version" msgstr "--ip-version için varsayılan altağ havuzunu kullan" msgid "Use only IPv4 addresses" msgstr "Sadece IPv4 adresleri kullan" msgid "Use only IPv6 addresses" msgstr "Sadece IPv6 adresleri kullan" msgid "Use other IP address (public, private, etc)" msgstr "Diğer IP adresi kullan (genel, gizli, vs.)" msgid "Use private IP address" msgstr "Gizli IP adresi kullan" msgid "Use public IP address" msgstr "Genel IP adresi kullan" msgid "" "Use specified volume as the config drive, or 'True' to use an ephemeral drive" msgstr "" "Belirtilen birimi yapılandırma sürücüsü olarak kullanın veya kısa ömürlü bir " "sürücüyü kullanmak için 'True' kullanın" msgid "" "Used to populate the backup_type property of the backup image (default: " "empty)" msgstr "" "Yedek imajın backup_type özelliğini doldurmak için kullanılır (varsayılan: " "boş)" msgid "User data file to serve from the metadata server" msgstr "Üst veri sunucusundan sunmak için kullanıcı veri dosyası" msgid "User description" msgstr "Kullanıcı tanımı" msgid "User must be specified" msgstr "Kullanıcı belirtilmeli" msgid "User that is assuming authorization (name or ID)" msgstr "Yetki varsayan kullanıcı (adı veya kimliği)" msgid "User that is delegating authorization (name or ID)" msgstr "Yetkilendirme yetkisini devreden kullanıcı (isim veya ID)" msgid "User that owns the credential (name or ID)" msgstr "Kimlik bilgilerine sahip kullanıcı (isim veya ID)" msgid "User to check (name or ID)" msgstr "Kontrol edilecek kullanıcı (isim veya ID)" msgid "User to display (name or ID)" msgstr "Gösterilecek kullanıcı (isim veya ID)" msgid "User to filter (name or ID)" msgstr "Filtrelenecek kullanıcı (isim veya ID)" msgid "User to list (name or ID)" msgstr "Listelenecek kullanıcı (isim veya ID)" msgid "User to modify (name or ID)" msgstr "Düzenlenecek kullanıcı (isim veya ID)" msgid "" "User(s) to add to (name or ID) (repeat option to add multiple users)" msgstr "" "'a eklenecek kullanıcı(lar) (isim veya ID) (birden fazla kullanıcı " "eklemek için seçeneği tekrarlayın)" msgid "User(s) to delete (name or ID)" msgstr "Silinecek kullanıcı(lar) (isim veya ID)" msgid "" "User(s) to remove from (name or ID) (repeat option to remove " "multiple users)" msgstr "" "'dan kaldırılacak kullanıcı(lar) (isim veya ID) (birden fazla " "kullanıcı kaldırmak için seçeneği tekrarlayın)" msgid "VLAN ID for VLAN networks or Tunnel ID for GENEVE/GRE/VXLAN networks" msgstr "VLAN ağları için VLAN ID veya GENEVA/GRE/VXLAN ağları için Tünel ID" msgid "" "VNIC type for this port (direct | direct-physical | macvtap | normal | " "baremetal | virtio-forwarder, default: normal)" msgstr "" "Bu bağlantı noktası için VNIC türü (direct | direct-physical | macvtap | " "normal | baremetal | virtio-forwarder, varsayılan: normal)" msgid "" "Validate the requirements for auto allocated topology. Does not return a " "topology." msgstr "" "Otomatik ayrılan topoloji gereksinimlerini doğrulayın. Bir topoloji " "döndürmez." msgid "Verifier associated with (required)" msgstr " ile ilişkili doğrulayıcı (gerekli)" msgid "Version" msgstr "Sürüm" msgid "Version of the agent" msgstr "Ajanın sürümü" #, python-format msgid "Volume API version, default=%s (Env: OS_VOLUME_API_VERSION)" msgstr "Disk bölümü API sürümü, varsayılan=%s (Env: OS_VOLUME_API_VERSION)" msgid "Volume description" msgstr "Disk bölümü açıklaması" #, python-format msgid "Volume is in %s state, it must be available before size can be extended" msgstr "" "Disk bölümü %s durumunda, boyut genişletilmeden önce kullanılabilir olmak " "zorunda." msgid "Volume name" msgstr "Disk bölümü ismi" msgid "" "Volume or snapshot (name or ID) must be specified if --block-device-mapping " "is specified" msgstr "" "Disk bölümü veya anlık görüntü (isim veya ID), eğer --block-device-mapping " "belirtildiyse, belirtilmek zorundadır." msgid "Volume size in GB (Required unless --snapshot or --source is specified)" msgstr "" "GB cinsinden disk bölümü boyutu (--snapshot veya --source belirtilmezse " "gereklidir)" msgid "" "Volume size in GB (Required unless --snapshot or --source or --source-" "replicated is specified)" msgstr "" "GB cinsinden disk bölümü boyutu (--snapshot veya --source veya --source-" "replicated belirtilmedikçe gereklidir)" msgid "Volume to add (name or ID)" msgstr "Eklenecek disk bölümü (isim veya ID)" msgid "Volume to backup (name or ID)" msgstr "Yedeklenecek disk bölümü (isim veya ID)" msgid "Volume to clone (name or ID)" msgstr "Kopyalanacak disk bölümü (isim veya ID)" msgid "Volume to display (name or ID)" msgstr "Gösterilecek disk bölümü (isim veya ID)" msgid "Volume to migrate (name or ID)" msgstr "Göç ettirilecek disk bölümü (isim veya ID)" msgid "Volume to modify (name or ID)" msgstr "Düzenlenecek disk bölümü (isim veya ID)" msgid "Volume to remove (name or ID)" msgstr "Kaldırılacak disk bölümü (isim veya ID)" msgid "Volume to restore to (name or ID)" msgstr "Geri yüklenecek disk bölümü (isim veya ID)" msgid "Volume to snapshot (name or ID)" msgstr "Anlık görüntüsü oluşturulacak disk bölümü (isim veya ID)" msgid "Volume to snapshot (name or ID) (default is )" msgstr "" "Anlık görüntüsü alınacak disk bölümü (isim veya ID) (varsayılan )" msgid "Volume to transfer (name or ID)" msgstr "Aktarılacak disk bölümü (isim veya ID)" msgid "Volume transfer request authentication key" msgstr "Disk bölümü aktarım isteği yetkilendirme anahtarı" msgid "Volume transfer request to accept (ID only)" msgstr "Kabul edilecek disk bölümü aktarım isteği (sadece ID)" msgid "Volume transfer request to display (name or ID)" msgstr "Gösterilecek disk bölümü aktarım isteği (isim veya ID)" msgid "Volume transfer request(s) to delete (name or ID)" msgstr "Silinecek disk bölümü aktarım isteği (isim veya ID)" msgid "Volume type description" msgstr "Disk bölümü türü açıklaması" msgid "Volume type is accessible to the public" msgstr "Disk bölümü türü genel olarak erişilebilir" msgid "Volume type is not accessible to the public" msgstr "Disk bölümü türü genele açık değil" msgid "Volume type name" msgstr "Disk bölümü tür ismi" msgid "Volume type of this consistency group (name or ID)" msgstr "Bu tutarlılık grubunun disk bölümü türü (isim veya ID)" msgid "Volume type to associate the QoS (name or ID)" msgstr "QoS ile ilişkili disk bölümü türü (isim veya ID)" msgid "Volume type to disassociate the QoS from (name or ID)" msgstr "QoS'in ayrılacağı disk bölümü (isim veya ID)" msgid "Volume type to display (name or ID)" msgstr "Gösterilecek disk bölümü türü (isim veya ID)" msgid "Volume type to modify (name or ID)" msgstr "Düzenlenecek disk bölümü türü (isim veya ID)" msgid "Volume type(s) to delete (name or ID)" msgstr "Disk bölümü türlerini sil" msgid "" "Volume(s) to add to (name or ID) (repeat option to add " "multiple volumes)" msgstr "" "'a eklenecek disk bölümleri (isim veya ID) (birden fazla " "disk bölümü eklemek için seçeneği tekrarlayın)" msgid "Volume(s) to delete (name or ID)" msgstr "Silinecek disk bölümleri (isim veya ID)" msgid "" "Volume(s) to remove from (name or ID) (repeat option to " "remove multiple volumes)" msgstr "" "'dan silinecek disk bölümleri (isim veya ID) (birden " "fazla disk bölümü silmek için seçeneği tekrarlayın)" msgid "Wait for backup image create to complete" msgstr "Yedek imaj oluşturmanın tamamlanması için bekleyin" msgid "Wait for build to complete" msgstr "Yapılandırmanın tamamlanmasını bekle" msgid "Wait for delete to complete" msgstr "Silme işleminin bitmesini bekle" msgid "Wait for migrate to complete" msgstr "Göçün tamamlanması bekleniyor" msgid "Wait for operation to complete" msgstr "İşlemin tamamlanmasını bekleyin" msgid "Wait for reboot to complete" msgstr "Yeniden başlatmanın bitmesini bekleyin" msgid "Wait for rebuild to complete" msgstr "Yeniden yapılandırmanın tamamlanmasını bekle" msgid "Wait for resize to complete" msgstr "Yeniden boyutlandırmanın tamamlanmasını bekleyin" msgid "" "You must specify '--external-gateway' in orderto update the SNAT or fixed-ip " "values" msgstr "" "SNAT veya sabit ip değerlerini güncellemek için '--external-gateway' " "belirtmelisiniz" msgid "argument --auth-key is required" msgstr "--auth-key argümanı zorunludur" msgid "" "can't create server with port specified since network endpoint not enabled" msgstr "" "ağ uç noktası etkin olmadığı için belirtilen bağlantı noktası ile sunucu " "oluşturulamadı" msgid "either network or port should be specified but not both" msgstr "ya ağ ya da bağlantı noktası belirtilmelidir ama ikisi bir arada değil" msgid "many found" msgstr "çok bulundu" msgid "max instances should be > 0" msgstr "en büyük sunucu sayısı > 0 olmalıdır" msgid "min instances should be <= max instances" msgstr "en küçük sunucu sayısı <= en büyük sunucu sayısı olmalıdır" msgid "min instances should be > 0" msgstr "en küçük sunucu sayısı > 0 olmalıdır" msgid "network" msgstr "ağ" msgid "networks" msgstr "ağlar" msgid "none found" msgstr "hiç bulunamadı" msgid "port" msgstr "bağlantı noktası" msgid "ports" msgstr "bağlantı noktaları" #, python-format msgid "property unset failed, '%s' is a nonexistent property " msgstr "özellik kaldırma başarısız, '%s' diye bir özellik yok " msgid "router" msgstr "yönlendirici" msgid "routers" msgstr "yönlendiriciler" msgid "server group to display (name or ID)" msgstr "gösterilecek sunucu grupları (isim veya ID)" msgid "server group(s) to delete (name or ID)" msgstr "silinecek sunucu grupları (isim veya ID)" #, python-format msgid "service %s not found\n" msgstr "%s servisi bulunamadı\n" msgid "subnet" msgstr "alt ağ" msgid "subnet pool" msgstr "altağ havuzu" msgid "subnet pools" msgstr "altağ havuzları" msgid "subnets" msgstr "altağlar" #, python-format msgid "tag unset failed, '%s' is a nonexistent tag " msgstr "etiket kaldırma başarısız, '%s' diye bir etiket yok " msgid "user that owns the credential (name or ID)" msgstr "Kimlik bilgilerinin sahibi kullanıcı (isim veya ID)" #, python-format msgid "versions supported by client: %(min)s - %(max)s" msgstr "istemci tarafından desteklenen sürümler: %(min)s - %(max)s" python-openstackclient-3.14.0/openstackclient/i18n.py0000666000175100017510000000142713232364361022660 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # import oslo_i18n _translators = oslo_i18n.TranslatorFactory(domain='openstackclient') # The primary translation function using the well-known name "_" _ = _translators.primary python-openstackclient-3.14.0/openstackclient/identity/0000775000175100017510000000000013232364654023357 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/identity/common.py0000666000175100017510000002132713232364361025223 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Common identity code""" from keystoneclient import exceptions as identity_exc from keystoneclient.v3 import domains from keystoneclient.v3 import groups from keystoneclient.v3 import projects from keystoneclient.v3 import users from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ def find_service_in_list(service_list, service_id): """Find a service by id in service list.""" for service in service_list: if service.id == service_id: return service raise exceptions.CommandError( "No service with a type, name or ID of '%s' exists." % service_id) def find_service(identity_client, name_type_or_id): """Find a service by id, name or type.""" try: # search for service id return identity_client.services.get(name_type_or_id) except identity_exc.NotFound: # ignore NotFound exception, raise others pass try: # search for service name return identity_client.services.find(name=name_type_or_id) except identity_exc.NotFound: pass except identity_exc.NoUniqueMatch: msg = _("Multiple service matches found for '%s', " "use an ID to be more specific.") raise exceptions.CommandError(msg % name_type_or_id) try: # search for service type return identity_client.services.find(type=name_type_or_id) except identity_exc.NotFound: msg = _("No service with a type, name or ID of '%s' exists.") raise exceptions.CommandError(msg % name_type_or_id) except identity_exc.NoUniqueMatch: msg = _("Multiple service matches found for '%s', " "use an ID to be more specific.") raise exceptions.CommandError(msg % name_type_or_id) def _get_token_resource(client, resource, parsed_name, parsed_domain=None): """Peek into the user's auth token to get resource IDs Look into a user's token to try and find the ID of a domain, project or user, when given the name. Typically non-admin users will interact with the CLI using names. However, by default, keystone does not allow look up by name since it would involve listing all entities. Instead opt to use the correct ID (from the token) instead. :param client: An identity client :param resource: A resource to look at in the token, this may be `domain`, `project_domain`, `user_domain`, `project`, or `user`. :param parsed_name: This is input from parsed_args that the user is hoping to find in the token. :param parsed_domain: This is domain filter from parsed_args that used to filter the results. :returns: The ID of the resource from the token, or the original value from parsed_args if it does not match. """ try: token = client.auth.client.get_token() token_data = client.tokens.get_token_data(token) token_dict = token_data['token'] # NOTE(stevemar): If domain is passed, just look at the project domain. if resource == 'domain': token_dict = token_dict['project'] obj = token_dict[resource] # user/project under different domain may has a same name if parsed_domain and parsed_domain not in obj['domain'].values(): return parsed_name return obj['id'] if obj['name'] == parsed_name else parsed_name # diaper defense in case parsing the token fails except Exception: # noqa return parsed_name 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_domain(identity_client, name_or_id): return _find_identity_resource(identity_client.domains, name_or_id, domains.Domain) def find_group(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.groups, name_or_id, groups.Group) else: return _find_identity_resource(identity_client.groups, name_or_id, groups.Group, domain_id=domain_id) 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 find_user(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.users, name_or_id, users.User) else: return _find_identity_resource(identity_client.users, name_or_id, users.User, domain_id=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}) def add_user_domain_option_to_parser(parser): parser.add_argument( '--user-domain', metavar='', help=_('Domain the user belongs to (name or ID). ' 'This can be used in case collisions between user names ' 'exist.'), ) def add_group_domain_option_to_parser(parser): parser.add_argument( '--group-domain', metavar='', help=_('Domain the group belongs to (name or ID). ' 'This can be used in case collisions between group names ' 'exist.'), ) def add_project_domain_option_to_parser(parser): 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.'), ) def add_role_domain_option_to_parser(parser): parser.add_argument( '--role-domain', metavar='', help=_('Domain the role belongs to (name or ID). ' 'This must be specified when the name of a domain specific ' 'role is used.'), ) def add_inherited_option_to_parser(parser): parser.add_argument( '--inherited', action='store_true', default=False, help=_('Specifies if the role grant is inheritable to the sub ' 'projects'), ) python-openstackclient-3.14.0/openstackclient/identity/v2_0/0000775000175100017510000000000013232364654024125 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/identity/v2_0/service.py0000666000175100017510000001435413232364361026143 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Service action implementations""" import argparse import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common LOG = logging.getLogger(__name__) class CreateService(command.ShowOne): _description = _("Create new service") def get_parser(self, prog_name): parser = super(CreateService, self).get_parser(prog_name) parser.add_argument( 'type_or_name', metavar='', help=_('New service type (compute, image, identity, volume, etc)'), ) type_or_name_group = parser.add_mutually_exclusive_group() type_or_name_group.add_argument( '--type', metavar='', help=argparse.SUPPRESS, ) type_or_name_group.add_argument( '--name', metavar='', help=_('New service name'), ) parser.add_argument( '--description', metavar='', help=_('New service description'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity type_or_name = parsed_args.type_or_name name = parsed_args.name type = parsed_args.type # If only a single positional is present, it's a . # This is not currently legal so it is considered a new case. if not type and not name: type = type_or_name # If --type option is present then positional is handled as ; # display deprecation message. elif type: name = type_or_name LOG.warning(_('The argument --type is deprecated, use service' ' create --name type instead.')) # If --name option is present the positional is handled as . # Making --type optional is new, but back-compatible elif name: type = type_or_name service = identity_client.services.create( name, type, parsed_args.description) info = {} info.update(service._info) return zip(*sorted(six.iteritems(info))) class DeleteService(command.Command): _description = _("Delete service(s)") def get_parser(self, prog_name): parser = super(DeleteService, self).get_parser(prog_name) parser.add_argument( 'services', metavar='', nargs='+', help=_('Service(s) to delete (type, name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity result = 0 for service in parsed_args.services: try: service = common.find_service(identity_client, service) identity_client.services.delete(service.id) except Exception as e: result += 1 LOG.error(_("Failed to delete service with " "name or ID '%(service)s': %(e)s"), {'service': service, 'e': e}) if result > 0: total = len(parsed_args.services) msg = (_("%(result)s of %(total)s services failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListService(command.Lister): _description = _("List services") def get_parser(self, prog_name): parser = super(ListService, 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): if parsed_args.long: columns = ('ID', 'Name', 'Type', 'Description') else: columns = ('ID', 'Name', 'Type') data = self.app.client_manager.identity.services.list() return ( columns, (utils.get_item_properties(s, columns) for s in data), ) class ShowService(command.ShowOne): _description = _("Display service details") def get_parser(self, prog_name): parser = super(ShowService, self).get_parser(prog_name) parser.add_argument( 'service', metavar='', help=_('Service to display (type, name or ID)'), ) parser.add_argument( '--catalog', action='store_true', default=False, help=_('Show service catalog information'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity auth_ref = self.app.client_manager.auth_ref if parsed_args.catalog: endpoints = auth_ref.service_catalog.get_endpoints( service_type=parsed_args.service) for (service, service_endpoints) in six.iteritems(endpoints): if service_endpoints: info = {"type": service} info.update(service_endpoints[0]) return zip(*sorted(six.iteritems(info))) msg = _("No service catalog with a type, name or ID of '%s' " "exists.") % (parsed_args.service) raise exceptions.CommandError(msg) else: service = common.find_service(identity_client, parsed_args.service) info = {} info.update(service._info) return zip(*sorted(six.iteritems(info))) python-openstackclient-3.14.0/openstackclient/identity/v2_0/user.py0000666000175100017510000003025013232364361025452 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Identity v2.0 User action implementations""" import logging from keystoneauth1 import exceptions as ks_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateUser(command.ShowOne): _description = _("Create new user") def get_parser(self, prog_name): parser = super(CreateUser, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('New user name'), ) parser.add_argument( '--project', metavar='', help=_('Default project (name or ID)'), ) parser.add_argument( '--password', metavar='', help=_('Set user password'), ) parser.add_argument( '--password-prompt', dest="password_prompt", action="store_true", help=_('Prompt interactively for password'), ) parser.add_argument( '--email', metavar='', help=_('Set user email address'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable user (default)'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable user'), ) parser.add_argument( '--or-show', action='store_true', help=_('Return existing user'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity if parsed_args.project: project_id = utils.find_resource( identity_client.tenants, parsed_args.project, ).id else: project_id = None enabled = True if parsed_args.disable: enabled = False if parsed_args.password_prompt: parsed_args.password = utils.get_password(self.app.stdin) if not parsed_args.password: LOG.warning(_("No password was supplied, authentication will fail " "when a user does not have a password.")) try: user = identity_client.users.create( parsed_args.name, parsed_args.password, parsed_args.email, tenant_id=project_id, enabled=enabled, ) except ks_exc.Conflict: if parsed_args.or_show: user = utils.find_resource( identity_client.users, parsed_args.name, ) LOG.info(_('Returning existing user %s'), user.name) else: raise # NOTE(dtroyer): The users.create() method wants 'tenant_id' but # the returned resource has 'tenantId'. Sigh. # We're using project_id now inside OSC so there. if 'tenantId' in user._info: user._info.update( {'project_id': user._info.pop('tenantId')} ) info = {} info.update(user._info) return zip(*sorted(six.iteritems(info))) class DeleteUser(command.Command): _description = _("Delete user(s)") def get_parser(self, prog_name): parser = super(DeleteUser, self).get_parser(prog_name) parser.add_argument( 'users', metavar='', nargs="+", help=_('User(s) to delete (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity errors = 0 for user in parsed_args.users: try: user_obj = utils.find_resource( identity_client.users, user, ) identity_client.users.delete(user_obj.id) except Exception as e: errors += 1 LOG.error(_("Failed to delete user with " "name or ID '%(user)s': %(e)s"), {'user': user, 'e': e}) if errors > 0: total = len(parsed_args.users) msg = (_("%(errors)s of %(total)s users failed " "to delete.") % {'errors': errors, 'total': total}) raise exceptions.CommandError(msg) class ListUser(command.Lister): _description = _("List users") def get_parser(self, prog_name): parser = super(ListUser, self).get_parser(prog_name) parser.add_argument( '--project', metavar='', help=_('Filter users by project (name or ID)'), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity def _format_project(project): if not project: return "" if project in project_cache.keys(): return project_cache[project].name else: return project project = None if parsed_args.project: project = utils.find_resource( identity_client.tenants, parsed_args.project, ) project = project.id if parsed_args.long: columns = ( 'ID', 'Name', 'tenantId', 'Email', 'Enabled', ) column_headers = ( 'ID', 'Name', 'Project', 'Email', 'Enabled', ) # Cache the project list project_cache = {} try: for p in identity_client.tenants.list(): project_cache[p.id] = p except Exception: # Just forget it if there's any trouble pass else: columns = column_headers = ('ID', 'Name') data = identity_client.users.list(tenant_id=project) if parsed_args.project: d = {} for s in data: d[s.id] = s data = d.values() if parsed_args.long: # FIXME(dtroyer): Sometimes user objects have 'tenant_id' instead # of 'tenantId'. Why? Dunno yet, but until that # is fixed we need to handle it; auth_token.py # only looks for 'tenantId'. for d in data: if 'tenant_id' in d._info: d._info['tenantId'] = d._info.pop('tenant_id') d._add_details(d._info) return (column_headers, (utils.get_item_properties( s, columns, mixed_case_fields=('tenantId',), formatters={'tenantId': _format_project}, ) for s in data)) class SetUser(command.Command): _description = _("Set user properties") def get_parser(self, prog_name): parser = super(SetUser, self).get_parser(prog_name) parser.add_argument( 'user', metavar='', help=_('User to modify (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('Set user name'), ) parser.add_argument( '--project', metavar='', help=_('Set default project (name or ID)'), ) parser.add_argument( '--password', metavar='', help=_('Set user password'), ) parser.add_argument( '--password-prompt', dest="password_prompt", action="store_true", help=_('Prompt interactively for password'), ) parser.add_argument( '--email', metavar='', help=_('Set user email address'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable user (default)'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable user'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity if parsed_args.password_prompt: parsed_args.password = utils.get_password(self.app.stdin) if '' == parsed_args.password: LOG.warning(_("No password was supplied, authentication will fail " "when a user does not have a password.")) user = utils.find_resource( identity_client.users, parsed_args.user, ) if parsed_args.password: identity_client.users.update_password( user.id, parsed_args.password, ) if parsed_args.project: project = utils.find_resource( identity_client.tenants, parsed_args.project, ) identity_client.users.update_tenant( user.id, project.id, ) kwargs = {} if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.email: kwargs['email'] = parsed_args.email kwargs['enabled'] = user.enabled if parsed_args.enable: kwargs['enabled'] = True if parsed_args.disable: kwargs['enabled'] = False identity_client.users.update(user.id, **kwargs) class ShowUser(command.ShowOne): _description = _("Display user details") def get_parser(self, prog_name): parser = super(ShowUser, self).get_parser(prog_name) parser.add_argument( 'user', metavar='', help=_('User to display (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity info = {} try: user = utils.find_resource( identity_client.users, parsed_args.user, ) info.update(user._info) except ks_exc.Forbidden: auth_ref = self.app.client_manager.auth_ref if ( parsed_args.user == auth_ref.user_id or parsed_args.user == auth_ref.username ): # Ask for currently auth'ed project so return it info = { 'id': auth_ref.user_id, 'name': auth_ref.username, 'project_id': auth_ref.project_id, # True because we don't get this far if it is disabled 'enabled': True, } else: raise if 'tenantId' in info: info.update( {'project_id': info.pop('tenantId')} ) if 'tenant_id' in info: info.update( {'project_id': info.pop('tenant_id')} ) return zip(*sorted(six.iteritems(info))) python-openstackclient-3.14.0/openstackclient/identity/v2_0/endpoint.py0000666000175100017510000001360713232364361026323 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Endpoint action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common LOG = logging.getLogger(__name__) class CreateEndpoint(command.ShowOne): _description = _("Create new endpoint") def get_parser(self, prog_name): parser = super(CreateEndpoint, self).get_parser(prog_name) parser.add_argument( 'service', metavar='', help=_('Service to be associated with new endpoint (name or ID)'), ) parser.add_argument( '--publicurl', metavar='', required=True, help=_('New endpoint public URL (required)'), ) parser.add_argument( '--adminurl', metavar='', help=_('New endpoint admin URL'), ) parser.add_argument( '--internalurl', metavar='', help=_('New endpoint internal URL'), ) parser.add_argument( '--region', metavar='', help=_('New endpoint region ID'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity service = common.find_service(identity_client, parsed_args.service) endpoint = identity_client.endpoints.create( parsed_args.region, service.id, parsed_args.publicurl, parsed_args.adminurl, parsed_args.internalurl,) info = {} info.update(endpoint._info) info['service_name'] = service.name info['service_type'] = service.type return zip(*sorted(six.iteritems(info))) class DeleteEndpoint(command.Command): _description = _("Delete endpoint(s)") def get_parser(self, prog_name): parser = super(DeleteEndpoint, self).get_parser(prog_name) parser.add_argument( 'endpoints', metavar='', nargs='+', help=_('Endpoint(s) to delete (ID only)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity result = 0 for endpoint in parsed_args.endpoints: try: identity_client.endpoints.delete(endpoint) except Exception as e: result += 1 LOG.error(_("Failed to delete endpoint with " "ID '%(endpoint)s': %(e)s"), {'endpoint': endpoint, 'e': e}) if result > 0: total = len(parsed_args.endpoints) msg = (_("%(result)s of %(total)s endpoints failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListEndpoint(command.Lister): _description = _("List endpoints") def get_parser(self, prog_name): parser = super(ListEndpoint, 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): identity_client = self.app.client_manager.identity if parsed_args.long: columns = ('ID', 'Region', 'Service Name', 'Service Type', 'PublicURL', 'AdminURL', 'InternalURL') else: columns = ('ID', 'Region', 'Service Name', 'Service Type') data = identity_client.endpoints.list() for ep in data: service = common.find_service(identity_client, ep.service_id) ep.service_name = service.name ep.service_type = service.type return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class ShowEndpoint(command.ShowOne): _description = _("Display endpoint details") def get_parser(self, prog_name): parser = super(ShowEndpoint, self).get_parser(prog_name) parser.add_argument( 'endpoint_or_service', metavar='', help=_('Endpoint to display (endpoint ID, service ID,' ' service name, service type)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity data = identity_client.endpoints.list() match = None for ep in data: if ep.id == parsed_args.endpoint_or_service: match = ep service = common.find_service(identity_client, ep.service_id) if match is None: service = common.find_service(identity_client, parsed_args.endpoint_or_service) for ep in data: if ep.service_id == service.id: match = ep if match is None: return None info = {} info.update(match._info) info['service_name'] = service.name info['service_type'] = service.type return zip(*sorted(six.iteritems(info))) python-openstackclient-3.14.0/openstackclient/identity/v2_0/project.py0000666000175100017510000002536713232364361026157 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Identity v2 Project action implementations""" import logging from keystoneauth1 import exceptions as ks_exc from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateProject(command.ShowOne): _description = _("Create new project") def get_parser(self, prog_name): parser = super(CreateProject, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('New project name'), ) parser.add_argument( '--description', metavar='', help=_('Project description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable project (default)'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable project'), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Add a property to ' '(repeat option to set multiple properties)'), ) parser.add_argument( '--or-show', action='store_true', help=_('Return existing project'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity enabled = True if parsed_args.disable: enabled = False kwargs = {} if parsed_args.property: kwargs = parsed_args.property.copy() try: project = identity_client.tenants.create( parsed_args.name, description=parsed_args.description, enabled=enabled, **kwargs ) except ks_exc.Conflict: if parsed_args.or_show: project = utils.find_resource( identity_client.tenants, parsed_args.name, ) LOG.info(_('Returning existing project %s'), project.name) else: raise # TODO(stevemar): Remove the line below when we support multitenancy project._info.pop('parent_id', None) return zip(*sorted(six.iteritems(project._info))) class DeleteProject(command.Command): _description = _("Delete project(s)") def get_parser(self, prog_name): parser = super(DeleteProject, self).get_parser(prog_name) parser.add_argument( 'projects', metavar='', nargs="+", help=_('Project(s) to delete (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity errors = 0 for project in parsed_args.projects: try: project_obj = utils.find_resource( identity_client.tenants, project, ) identity_client.tenants.delete(project_obj.id) except Exception as e: errors += 1 LOG.error(_("Failed to delete project with " "name or ID '%(project)s': %(e)s"), {'project': project, 'e': e}) if errors > 0: total = len(parsed_args.projects) msg = (_("%(errors)s of %(total)s projects failed " "to delete.") % {'errors': errors, 'total': total}) raise exceptions.CommandError(msg) class ListProject(command.Lister): _description = _("List projects") def get_parser(self, prog_name): parser = super(ListProject, self).get_parser(prog_name) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( '--sort', metavar='[:]', help=_('Sort output by selected keys and directions (asc or desc) ' '(default: asc), repeat this option to specify multiple ' 'keys and directions.'), ) return parser def take_action(self, parsed_args): if parsed_args.long: columns = ('ID', 'Name', 'Description', 'Enabled') else: columns = ('ID', 'Name') data = self.app.client_manager.identity.tenants.list() if parsed_args.sort: data = utils.sort_items(data, parsed_args.sort) return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class SetProject(command.Command): _description = _("Set project properties") def get_parser(self, prog_name): parser = super(SetProject, self).get_parser(prog_name) parser.add_argument( 'project', metavar='', help=_('Project to modify (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('Set project name'), ) parser.add_argument( '--description', metavar='', help=_('Set project description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable project'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable project'), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Set a project property ' '(repeat option to set multiple properties)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity project = utils.find_resource( identity_client.tenants, parsed_args.project, ) kwargs = project._info if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.description: kwargs['description'] = parsed_args.description if parsed_args.enable: kwargs['enabled'] = True if parsed_args.disable: kwargs['enabled'] = False if parsed_args.property: kwargs.update(parsed_args.property) if 'id' in kwargs: del kwargs['id'] if 'name' in kwargs: # Hack around broken Identity API arg names kwargs['tenant_name'] = kwargs['name'] del kwargs['name'] identity_client.tenants.update(project.id, **kwargs) class ShowProject(command.ShowOne): _description = _("Display project details") def get_parser(self, prog_name): parser = super(ShowProject, self).get_parser(prog_name) parser.add_argument( 'project', metavar='', help=_('Project to display (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity info = {} try: project = utils.find_resource( identity_client.tenants, parsed_args.project, ) info.update(project._info) except ks_exc.Forbidden: auth_ref = self.app.client_manager.auth_ref if ( parsed_args.project == auth_ref.project_id or parsed_args.project == auth_ref.project_name ): # Ask for currently auth'ed project so return it info = { 'id': auth_ref.project_id, 'name': auth_ref.project_name, # True because we don't get this far if it is disabled 'enabled': True, } else: raise # TODO(stevemar): Remove the line below when we support multitenancy info.pop('parent_id', None) # NOTE(stevemar): Property handling isn't really supported in Keystone # and needs a lot of extra handling. Let's reserve the properties that # the API has and handle the extra top level properties. reserved = ('name', 'id', 'enabled', 'description') properties = {} for k, v in info.items(): if k not in reserved: # If a key is not in `reserved` it's a property, pop it info.pop(k) # If a property has been "unset" it's `None`, so don't show it if v is not None: properties[k] = v info['properties'] = utils.format_dict(properties) return zip(*sorted(six.iteritems(info))) class UnsetProject(command.Command): _description = _("Unset project properties") def get_parser(self, prog_name): parser = super(UnsetProject, self).get_parser(prog_name) parser.add_argument( 'project', metavar='', help=_('Project to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action='append', default=[], help=_('Unset a project property ' '(repeat option to unset multiple properties)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity project = utils.find_resource( identity_client.tenants, parsed_args.project, ) kwargs = project._info for key in parsed_args.property: if key in kwargs: kwargs[key] = None identity_client.tenants.update(project.id, **kwargs) python-openstackclient-3.14.0/openstackclient/identity/v2_0/role_assignment.py0000666000175100017510000000747513232364361027702 0ustar zuulzuul00000000000000# 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. # """Identity v2 Assignment action implementations """ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ # noqa class ListRoleAssignment(command.Lister): _description = _("List role assignments") def get_parser(self, prog_name): parser = super(ListRoleAssignment, self).get_parser(prog_name) parser.add_argument( '--user', metavar='', help='User to filter (name or ID)', ) parser.add_argument( '--project', metavar='', help='Project to filter (name or ID)', ) parser.add_argument( '--names', action="store_true", help='Display names instead of IDs', ) parser.add_argument( '--auth-user', action="store_true", dest='authuser', help='Only list assignments for the authenticated user', ) parser.add_argument( '--auth-project', action="store_true", dest='authproject', help='Only list assignments for the project to which the ' 'authenticated user\'s token is scoped', ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity auth_ref = self.app.client_manager.auth_ref include_names = True if parsed_args.names else False user = None if parsed_args.user: user = utils.find_resource( identity_client.users, parsed_args.user, ) elif parsed_args.authuser: if auth_ref: user = utils.find_resource( identity_client.users, auth_ref.user_id ) project = None if parsed_args.project: project = utils.find_resource( identity_client.projects, parsed_args.project, ) elif parsed_args.authproject: if auth_ref: project = utils.find_resource( identity_client.projects, auth_ref.project_id ) # If user or project is not specified, we would ideally list all # relevant assignments in the system (to be compatible with v3). # However, there is no easy way of doing that in v2. if not user or not project: msg = _("Project and User must be specified") raise exceptions.CommandError(msg) else: data = identity_client.roles.roles_for_user(user.id, project.id) columns = ('Role', 'User', 'Project') for user_role in data: if include_names: setattr(user_role, 'role', user_role.name) user_role.user = user.name user_role.project = project.name else: setattr(user_role, 'role', user_role.id) user_role.user = user.id user_role.project = project.id return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) python-openstackclient-3.14.0/openstackclient/identity/v2_0/token.py0000666000175100017510000000430513232364361025616 0ustar zuulzuul00000000000000# Copyright 2014 eBay 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. # """Identity v2 Token action implementations""" from osc_lib.command import command from osc_lib import exceptions import six from openstackclient.i18n import _ class IssueToken(command.ShowOne): _description = _("Issue new token") # scoped token is optional required_scope = False def get_parser(self, prog_name): parser = super(IssueToken, self).get_parser(prog_name) return parser def take_action(self, parsed_args): auth_ref = self.app.client_manager.auth_ref if not auth_ref: raise exceptions.AuthorizationFailure( "Only an authorized user may issue a new token.") data = {} if auth_ref.auth_token: data['id'] = auth_ref.auth_token if auth_ref.expires: datetime_obj = auth_ref.expires expires_str = datetime_obj.strftime('%Y-%m-%dT%H:%M:%S%z') data['expires'] = expires_str if auth_ref.project_id: data['project_id'] = auth_ref.project_id if auth_ref.user_id: data['user_id'] = auth_ref.user_id return zip(*sorted(six.iteritems(data))) class RevokeToken(command.Command): _description = _("Revoke existing token") def get_parser(self, prog_name): parser = super(RevokeToken, self).get_parser(prog_name) parser.add_argument( 'token', metavar='', help=_('Token to be deleted'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity identity_client.tokens.delete(parsed_args.token) python-openstackclient-3.14.0/openstackclient/identity/v2_0/role.py0000666000175100017510000002746313232364361025451 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Identity v2 Role action implementations""" import logging from keystoneauth1 import exceptions as ks_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class AddRole(command.ShowOne): _description = _("Add role to project:user") def get_parser(self, prog_name): parser = super(AddRole, self).get_parser(prog_name) parser.add_argument( 'role', metavar='', help=_('Role to add to : (name or ID)'), ) parser.add_argument( '--project', metavar='', required=True, help=_('Include (name or ID)'), ) parser.add_argument( '--user', metavar='', required=True, help=_('Include (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity role = utils.find_resource(identity_client.roles, parsed_args.role) project = utils.find_resource( identity_client.tenants, parsed_args.project, ) user = utils.find_resource(identity_client.users, parsed_args.user) role = identity_client.roles.add_user_role( user.id, role.id, project.id, ) info = {} info.update(role._info) return zip(*sorted(six.iteritems(info))) class CreateRole(command.ShowOne): _description = _("Create new role") def get_parser(self, prog_name): parser = super(CreateRole, self).get_parser(prog_name) parser.add_argument( 'role_name', metavar='', help=_('New role name'), ) parser.add_argument( '--or-show', action='store_true', help=_('Return existing role'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity try: role = identity_client.roles.create(parsed_args.role_name) except ks_exc.Conflict: if parsed_args.or_show: role = utils.find_resource( identity_client.roles, parsed_args.role_name, ) LOG.info(_('Returning existing role %s'), role.name) else: raise info = {} info.update(role._info) return zip(*sorted(six.iteritems(info))) class DeleteRole(command.Command): _description = _("Delete role(s)") def get_parser(self, prog_name): parser = super(DeleteRole, self).get_parser(prog_name) parser.add_argument( 'roles', metavar='', nargs="+", help=_('Role(s) to delete (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity errors = 0 for role in parsed_args.roles: try: role_obj = utils.find_resource( identity_client.roles, role, ) identity_client.roles.delete(role_obj.id) except Exception as e: errors += 1 LOG.error(_("Failed to delete role with " "name or ID '%(role)s': %(e)s"), {'role': role, 'e': e}) if errors > 0: total = len(parsed_args.roles) msg = (_("%(errors)s of %(total)s roles failed " "to delete.") % {'errors': errors, 'total': total}) raise exceptions.CommandError(msg) class ListRole(command.Lister): _description = _("List roles") def get_parser(self, prog_name): parser = super(ListRole, self).get_parser(prog_name) parser.add_argument( '--project', metavar='', help=_('Filter roles by (name or ID)'), ) parser.add_argument( '--user', metavar='', help=_('Filter roles by (name or ID)'), ) return parser def take_action(self, parsed_args): def _deprecated(): # NOTE(henry-nash): Deprecated as of Newton, so we should remove # this in the 'P' release. self.log.warning(_('Listing assignments using role list is ' 'deprecated as of the Newton release. Use role ' 'assignment list --user --project ' ' --names instead.')) identity_client = self.app.client_manager.identity auth_ref = self.app.client_manager.auth_ref # No user or project specified, list all roles in the system if not parsed_args.user and not parsed_args.project: columns = ('ID', 'Name') data = identity_client.roles.list() elif parsed_args.user and parsed_args.project: user = utils.find_resource( identity_client.users, parsed_args.user, ) project = utils.find_resource( identity_client.projects, parsed_args.project, ) _deprecated() data = identity_client.roles.roles_for_user(user.id, project.id) elif parsed_args.user: user = utils.find_resource( identity_client.users, parsed_args.user, ) if self.app.client_manager.auth_ref: project = utils.find_resource( identity_client.projects, auth_ref.project_id ) else: msg = _("Project must be specified") raise exceptions.CommandError(msg) _deprecated() data = identity_client.roles.roles_for_user(user.id, project.id) elif parsed_args.project: project = utils.find_resource( identity_client.projects, parsed_args.project, ) if self.app.client_manager.auth_ref: user = utils.find_resource( identity_client.users, auth_ref.user_id ) else: msg = _("User must be specified") raise exceptions.CommandError(msg) _deprecated() data = identity_client.roles.roles_for_user(user.id, project.id) if parsed_args.user or parsed_args.project: columns = ('ID', 'Name', 'Project', 'User') for user_role in data: user_role.user = user.name user_role.project = project.name return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class ListUserRole(command.Lister): _description = _("List user-role assignments") def get_parser(self, prog_name): parser = super(ListUserRole, self).get_parser(prog_name) parser.add_argument( 'user', metavar='', nargs='?', help=_('User to list (name or ID)'), ) parser.add_argument( '--project', metavar='', help=_('Filter users by (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity auth_ref = self.app.client_manager.auth_ref # Project and user are required, if not included in command args # default to the values used for authentication. For token-flow # authentication they must be included on the command line. if (not parsed_args.project and self.app.client_manager.auth_ref.project_id): parsed_args.project = auth_ref.project_id if not parsed_args.project: msg = _("Project must be specified") raise exceptions.CommandError(msg) if (not parsed_args.user and self.app.client_manager.auth_ref.user_id): parsed_args.user = auth_ref.user_id if not parsed_args.user: msg = _("User must be specified") raise exceptions.CommandError(msg) self.log.warning(_('Listing assignments using user role list is ' 'deprecated as of the Newton release. Use role ' 'assignment list --user --project ' ' --names instead.')) project = utils.find_resource( identity_client.tenants, parsed_args.project, ) user = utils.find_resource(identity_client.users, parsed_args.user) data = identity_client.roles.roles_for_user(user.id, project.id) columns = ( 'ID', 'Name', 'Project', 'User', ) # Add the names to the output even though they will be constant for role in data: role.user = user.name role.project = project.name return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class RemoveRole(command.Command): _description = _("Remove role from project : user") def get_parser(self, prog_name): parser = super(RemoveRole, self).get_parser(prog_name) parser.add_argument( 'role', metavar='', help=_('Role to remove (name or ID)'), ) parser.add_argument( '--project', metavar='', required=True, help=_('Include (name or ID)'), ) parser.add_argument( '--user', metavar='', required=True, help=_('Include (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity role = utils.find_resource(identity_client.roles, parsed_args.role) project = utils.find_resource( identity_client.tenants, parsed_args.project, ) user = utils.find_resource(identity_client.users, parsed_args.user) identity_client.roles.remove_user_role( user.id, role.id, project.id) class ShowRole(command.ShowOne): _description = _("Display role details") def get_parser(self, prog_name): parser = super(ShowRole, self).get_parser(prog_name) parser.add_argument( 'role', metavar='', help=_('Role to display (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity role = utils.find_resource(identity_client.roles, parsed_args.role) info = {} info.update(role._info) return zip(*sorted(six.iteritems(info))) python-openstackclient-3.14.0/openstackclient/identity/v2_0/catalog.py0000666000175100017510000000632313232364361026112 0ustar zuulzuul00000000000000# 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. # """Identity v2 Service Catalog action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) def _format_endpoints(eps=None): if not eps: return "" ret = '' for index, ep in enumerate(eps): region = eps[index].get('region') if region is None: region = '' ret += region + '\n' for endpoint_type in ['publicURL', 'internalURL', 'adminURL']: url = eps[index].get(endpoint_type) if url: ret += " %s: %s\n" % (endpoint_type, url) return ret class ListCatalog(command.Lister): _description = _("List services in the service catalog") def take_action(self, parsed_args): # Trigger auth if it has not happened yet auth_ref = self.app.client_manager.auth_ref if not auth_ref: raise exceptions.AuthorizationFailure( "Only an authorized user may issue a new token." ) data = auth_ref.service_catalog.catalog columns = ('Name', 'Type', 'Endpoints') return (columns, (utils.get_dict_properties( s, columns, formatters={ 'Endpoints': _format_endpoints, }, ) for s in data)) class ShowCatalog(command.ShowOne): _description = _("Display service catalog details") def get_parser(self, prog_name): parser = super(ShowCatalog, self).get_parser(prog_name) parser.add_argument( 'service', metavar='', help=_('Service to display (type or name)'), ) return parser def take_action(self, parsed_args): # Trigger auth if it has not happened yet auth_ref = self.app.client_manager.auth_ref if not auth_ref: raise exceptions.AuthorizationFailure( "Only an authorized user may issue a new token." ) data = None for service in auth_ref.service_catalog.catalog: if (service.get('name') == parsed_args.service or service.get('type') == parsed_args.service): data = service data['endpoints'] = _format_endpoints(data['endpoints']) if 'endpoints_links' in data: data.pop('endpoints_links') break if not data: LOG.error(_('service %s not found\n'), parsed_args.service) return ((), ()) return zip(*sorted(six.iteritems(data))) python-openstackclient-3.14.0/openstackclient/identity/v2_0/ec2creds.py0000666000175100017510000001447213232364361026176 0ustar zuulzuul00000000000000# Copyright 2012 OpenStack Foundation # Copyright 2013 Nebula 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. # """Identity v2 EC2 Credentials action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateEC2Creds(command.ShowOne): _description = _("Create EC2 credentials") def get_parser(self, prog_name): parser = super(CreateEC2Creds, self).get_parser(prog_name) parser.add_argument( '--project', metavar='', help=_( 'Create credentials in project ' '(name or ID; default: current authenticated project)' ), ) parser.add_argument( '--user', metavar='', help=_( 'Create credentials for user ' '(name or ID; default: current authenticated user)' ), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity if parsed_args.project: project = utils.find_resource( identity_client.tenants, parsed_args.project, ).id else: # Get the project from the current auth project = self.app.client_manager.auth_ref.project_id if parsed_args.user: user = utils.find_resource( identity_client.users, parsed_args.user, ).id else: # Get the user from the current auth user = self.app.client_manager.auth_ref.user_id creds = identity_client.ec2.create(user, project) info = {} info.update(creds._info) if 'tenant_id' in info: info.update( {'project_id': info.pop('tenant_id')} ) return zip(*sorted(six.iteritems(info))) class DeleteEC2Creds(command.Command): _description = _("Delete EC2 credentials") def get_parser(self, prog_name): parser = super(DeleteEC2Creds, self).get_parser(prog_name) parser.add_argument( 'access_keys', metavar='', nargs='+', help=_('Credentials access key(s)'), ) parser.add_argument( '--user', metavar='', help=_('Delete credentials for user (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity if parsed_args.user: user = utils.find_resource( identity_client.users, parsed_args.user, ).id else: # Get the user from the current auth user = self.app.client_manager.auth_ref.user_id result = 0 for access_key in parsed_args.access_keys: try: identity_client.ec2.delete(user, access_key) except Exception as e: result += 1 LOG.error(_("Failed to delete EC2 credentials with " "access key '%(access_key)s': %(e)s"), {'access_key': access_key, 'e': e}) if result > 0: total = len(parsed_args.access_keys) msg = (_("%(result)s of %(total)s EC2 keys failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListEC2Creds(command.Lister): _description = _("List EC2 credentials") def get_parser(self, prog_name): parser = super(ListEC2Creds, self).get_parser(prog_name) parser.add_argument( '--user', metavar='', help=_('Filter list by user (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity if parsed_args.user: user = utils.find_resource( identity_client.users, parsed_args.user, ).id else: # Get the user from the current auth user = self.app.client_manager.auth_ref.user_id columns = ('access', 'secret', 'tenant_id', 'user_id') column_headers = ('Access', 'Secret', 'Project ID', 'User ID') data = identity_client.ec2.list(user) return (column_headers, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class ShowEC2Creds(command.ShowOne): _description = _("Display EC2 credentials details") def get_parser(self, prog_name): parser = super(ShowEC2Creds, self).get_parser(prog_name) parser.add_argument( 'access_key', metavar='', help=_('Credentials access key'), ) parser.add_argument( '--user', metavar='', help=_('Show credentials for user (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity if parsed_args.user: user = utils.find_resource( identity_client.users, parsed_args.user, ).id else: # Get the user from the current auth user = self.app.client_manager.auth_ref.user_id creds = identity_client.ec2.get(user, parsed_args.access_key) info = {} info.update(creds._info) if 'tenant_id' in info: info.update( {'project_id': info.pop('tenant_id')} ) return zip(*sorted(six.iteritems(info))) python-openstackclient-3.14.0/openstackclient/identity/v2_0/__init__.py0000666000175100017510000000000013232364361026221 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/identity/client.py0000666000175100017510000000460113232364361025205 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # import logging from keystoneclient.v2_0 import client as identity_client_v2 from osc_lib import utils from openstackclient.i18n import _ LOG = logging.getLogger(__name__) DEFAULT_API_VERSION = '3' API_VERSION_OPTION = 'os_identity_api_version' API_NAME = 'identity' API_VERSIONS = { '2.0': 'openstackclient.identity.client.IdentityClientv2', '2': 'openstackclient.identity.client.IdentityClientv2', '3': 'keystoneclient.v3.client.Client', } # Translate our API version to auth plugin version prefix AUTH_VERSIONS = { '2.0': 'v2', '2': 'v2', '3': 'v3', } def make_client(instance): """Returns an identity service client.""" identity_client = utils.get_client_class( API_NAME, instance._api_version[API_NAME], API_VERSIONS) LOG.debug('Instantiating identity client: %s', identity_client) # Remember interface only if interface is set kwargs = utils.build_kwargs_dict('interface', instance.interface) client = identity_client( session=instance.session, region_name=instance.region_name, **kwargs ) return client def build_option_parser(parser): """Hook to add global options""" parser.add_argument( '--os-identity-api-version', metavar='', default=utils.env('OS_IDENTITY_API_VERSION'), help=_('Identity API version, default=%s ' '(Env: OS_IDENTITY_API_VERSION)') % DEFAULT_API_VERSION, ) return parser class IdentityClientv2(identity_client_v2.Client): """Tweak the earlier client class to deal with some changes""" def __getattr__(self, name): # Map v3 'projects' back to v2 'tenants' if name == "projects": return self.tenants else: raise AttributeError(name) python-openstackclient-3.14.0/openstackclient/identity/v3/0000775000175100017510000000000013232364654023707 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/identity/v3/service.py0000666000175100017510000001531413232364361025722 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Identity v3 Service action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common LOG = logging.getLogger(__name__) class CreateService(command.ShowOne): _description = _("Create new service") def get_parser(self, prog_name): parser = super(CreateService, self).get_parser(prog_name) parser.add_argument( 'type', metavar='', help=_('New service type (compute, image, identity, volume, etc)'), ) parser.add_argument( '--name', metavar='', help=_('New service name'), ) parser.add_argument( '--description', metavar='', help=_('New service description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable service (default)'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable service'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity enabled = True if parsed_args.disable: enabled = False service = identity_client.services.create( name=parsed_args.name, type=parsed_args.type, description=parsed_args.description, enabled=enabled, ) service._info.pop('links') return zip(*sorted(six.iteritems(service._info))) class DeleteService(command.Command): _description = _("Delete service(s)") def get_parser(self, prog_name): parser = super(DeleteService, self).get_parser(prog_name) parser.add_argument( 'service', metavar='', nargs='+', help=_('Service(s) to delete (type, name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity result = 0 for i in parsed_args.service: try: service = common.find_service(identity_client, i) identity_client.services.delete(service.id) except Exception as e: result += 1 LOG.error(_("Failed to delete consumer with type, " "name or ID '%(service)s': %(e)s"), {'service': i, 'e': e}) if result > 0: total = len(parsed_args.service) msg = (_("%(result)s of %(total)s services failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListService(command.Lister): _description = _("List services") def get_parser(self, prog_name): parser = super(ListService, 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): if parsed_args.long: columns = ('ID', 'Name', 'Type', 'Description', 'Enabled') else: columns = ('ID', 'Name', 'Type') data = self.app.client_manager.identity.services.list() return ( columns, (utils.get_item_properties(s, columns) for s in data), ) class SetService(command.Command): _description = _("Set service properties") def get_parser(self, prog_name): parser = super(SetService, self).get_parser(prog_name) parser.add_argument( 'service', metavar='', help=_('Service to modify (type, name or ID)'), ) parser.add_argument( '--type', metavar='', help=_('New service type (compute, image, identity, volume, etc)'), ) parser.add_argument( '--name', metavar='', help=_('New service name'), ) parser.add_argument( '--description', metavar='', help=_('New service description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable service'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable service'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity service = common.find_service(identity_client, parsed_args.service) kwargs = {} if parsed_args.type: kwargs['type'] = parsed_args.type if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.description: kwargs['description'] = parsed_args.description if parsed_args.enable: kwargs['enabled'] = True if parsed_args.disable: kwargs['enabled'] = False identity_client.services.update( service.id, **kwargs ) class ShowService(command.ShowOne): _description = _("Display service details") def get_parser(self, prog_name): parser = super(ShowService, self).get_parser(prog_name) parser.add_argument( 'service', metavar='', help=_('Service to display (type, name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity service = common.find_service(identity_client, parsed_args.service) service._info.pop('links') return zip(*sorted(six.iteritems(service._info))) python-openstackclient-3.14.0/openstackclient/identity/v3/user.py0000666000175100017510000004137413232364361025245 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Identity v3 User action implementations""" import copy import logging from keystoneauth1 import exceptions as ks_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common LOG = logging.getLogger(__name__) class CreateUser(command.ShowOne): _description = _("Create new user") def get_parser(self, prog_name): parser = super(CreateUser, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('New user name'), ) parser.add_argument( '--domain', metavar='', help=_('Default domain (name or ID)'), ) parser.add_argument( '--project', metavar='', help=_('Default project (name or ID)'), ) common.add_project_domain_option_to_parser(parser) parser.add_argument( '--password', metavar='', help=_('Set user password'), ) parser.add_argument( '--password-prompt', dest="password_prompt", action="store_true", help=_('Prompt interactively for password'), ) parser.add_argument( '--email', metavar='', help=_('Set user email address'), ) parser.add_argument( '--description', metavar='', help=_('User description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable user (default)'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable user'), ) parser.add_argument( '--or-show', action='store_true', help=_('Return existing user'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity project_id = None if parsed_args.project: project_id = common.find_project(identity_client, parsed_args.project, parsed_args.project_domain).id domain_id = None if parsed_args.domain: domain_id = common.find_domain(identity_client, parsed_args.domain).id enabled = True if parsed_args.disable: enabled = False if parsed_args.password_prompt: parsed_args.password = utils.get_password(self.app.stdin) if not parsed_args.password: LOG.warning(_("No password was supplied, authentication will fail " "when a user does not have a password.")) try: user = identity_client.users.create( name=parsed_args.name, domain=domain_id, default_project=project_id, password=parsed_args.password, email=parsed_args.email, description=parsed_args.description, enabled=enabled ) except ks_exc.Conflict: if parsed_args.or_show: user = utils.find_resource(identity_client.users, parsed_args.name, domain_id=domain_id) LOG.info(_('Returning existing user %s'), user.name) else: raise user._info.pop('links') return zip(*sorted(six.iteritems(user._info))) class DeleteUser(command.Command): _description = _("Delete user(s)") def get_parser(self, prog_name): parser = super(DeleteUser, self).get_parser(prog_name) parser.add_argument( 'users', metavar='', nargs="+", help=_('User(s) to delete (name or ID)'), ) parser.add_argument( '--domain', metavar='', help=_('Domain owning (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity domain = None if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain) errors = 0 for user in parsed_args.users: try: if domain is not None: user_obj = utils.find_resource(identity_client.users, user, domain_id=domain.id) else: user_obj = utils.find_resource(identity_client.users, user) identity_client.users.delete(user_obj.id) except Exception as e: errors += 1 LOG.error(_("Failed to delete user with " "name or ID '%(user)s': %(e)s"), {'user': user, 'e': e}) if errors > 0: total = len(parsed_args.users) msg = (_("%(errors)s of %(total)s users failed " "to delete.") % {'errors': errors, 'total': total}) raise exceptions.CommandError(msg) class ListUser(command.Lister): _description = _("List users") def get_parser(self, prog_name): parser = super(ListUser, self).get_parser(prog_name) parser.add_argument( '--domain', metavar='', help=_('Filter users by (name or ID)'), ) project_or_group = parser.add_mutually_exclusive_group() project_or_group.add_argument( '--group', metavar='', help=_('Filter users by membership (name or ID)'), ) project_or_group.add_argument( '--project', metavar='', help=_('Filter users by (name or ID)'), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity domain = None if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain).id group = None if parsed_args.group: group = common.find_group(identity_client, parsed_args.group, parsed_args.domain).id if parsed_args.project: if domain is not None: project = utils.find_resource( identity_client.projects, parsed_args.project, domain_id=domain ).id else: project = utils.find_resource( identity_client.projects, parsed_args.project, ).id assignments = identity_client.role_assignments.list( project=project) # NOTE(stevemar): If a user has more than one role on a project # then they will have two entries in the returned data. Since we # are looking for any role, let's just track unique user IDs. user_ids = set() for assignment in assignments: if hasattr(assignment, 'user'): user_ids.add(assignment.user['id']) # NOTE(stevemar): Call find_resource once we have unique IDs, so # it's fewer trips to the Identity API, then collect the data. data = [] for user_id in user_ids: user = utils.find_resource(identity_client.users, user_id) data.append(user) else: data = identity_client.users.list( domain=domain, group=group, ) # Column handling if parsed_args.long: columns = ['ID', 'Name', 'Default Project Id', 'Domain Id', 'Description', 'Email', 'Enabled'] column_headers = copy.deepcopy(columns) column_headers[2] = 'Project' column_headers[3] = 'Domain' else: columns = ['ID', 'Name'] column_headers = columns return ( column_headers, (utils.get_item_properties( s, columns, formatters={}, ) for s in data) ) class SetUser(command.Command): _description = _("Set user properties") def get_parser(self, prog_name): parser = super(SetUser, self).get_parser(prog_name) parser.add_argument( 'user', metavar='', help=_('User to modify (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('Set user name'), ) parser.add_argument( '--domain', metavar='', help=_('Domain the user belongs to (name or ID). This can be ' 'used in case collisions between user names exist.'), ) parser.add_argument( '--project', metavar='', help=_('Set default project (name or ID)'), ) common.add_project_domain_option_to_parser(parser) parser.add_argument( '--password', metavar='', help=_('Set user password'), ) parser.add_argument( '--password-prompt', dest="password_prompt", action="store_true", help=_('Prompt interactively for password'), ) parser.add_argument( '--email', metavar='', help=_('Set user email address'), ) parser.add_argument( '--description', metavar='', help=_('Set user description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable user (default)'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable user'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity if parsed_args.password_prompt: parsed_args.password = utils.get_password(self.app.stdin) if '' == parsed_args.password: LOG.warning(_("No password was supplied, authentication will fail " "when a user does not have a password.")) user_str = common._get_token_resource(identity_client, 'user', parsed_args.user, parsed_args.domain) if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain) user = utils.find_resource(identity_client.users, user_str, domain_id=domain.id) else: user = utils.find_resource( identity_client.users, parsed_args.user, ) kwargs = {} if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.email: kwargs['email'] = parsed_args.email if parsed_args.password: kwargs['password'] = parsed_args.password if parsed_args.description: kwargs['description'] = parsed_args.description if parsed_args.project: project_id = common.find_project(identity_client, parsed_args.project, parsed_args.project_domain).id kwargs['default_project'] = project_id kwargs['enabled'] = user.enabled if parsed_args.enable: kwargs['enabled'] = True if parsed_args.disable: kwargs['enabled'] = False identity_client.users.update(user.id, **kwargs) class SetPasswordUser(command.Command): _description = _("Change current user password") required_scope = False def get_parser(self, prog_name): parser = super(SetPasswordUser, self).get_parser(prog_name) parser.add_argument( '--password', metavar='', help=_('New user password'), ) parser.add_argument( '--original-password', metavar='', help=_('Original user password'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity # FIXME(gyee): there are two scenarios: # # 1. user update password for himself # 2. admin update password on behalf of the user. This is an unlikely # scenario because that will require admin knowing the user's # original password which is forbidden under most security # policies. # # Of the two scenarios above, user either authenticate using its # original password or an authentication token. For scenario #1, # if user is authenticating with its original password (i.e. passing # --os-password argument), we can just make use of it instead of using # --original-password or prompting. For scenario #2, admin will need # to specify --original-password option or this won't work because # --os-password is the admin's own password. In the future if we stop # supporting scenario #2 then we can just do this. # # current_password = (parsed_args.original_password or # self.app.cloud.password) # current_password = parsed_args.original_password if current_password is None: current_password = utils.get_password( self.app.stdin, prompt="Current Password:", confirm=False) password = parsed_args.password if password is None: password = utils.get_password( self.app.stdin, prompt="New Password:") if '' == password: LOG.warning(_("No password was supplied, authentication will fail " "when a user does not have a password.")) identity_client.users.update_password(current_password, password) class ShowUser(command.ShowOne): _description = _("Display user details") def get_parser(self, prog_name): parser = super(ShowUser, self).get_parser(prog_name) parser.add_argument( 'user', metavar='', help=_('User to display (name or ID)'), ) parser.add_argument( '--domain', metavar='', help=_('Domain owning (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity user_str = common._get_token_resource(identity_client, 'user', parsed_args.user, parsed_args.domain) if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain) user = utils.find_resource(identity_client.users, user_str, domain_id=domain.id) else: user = utils.find_resource(identity_client.users, user_str) user._info.pop('links') return zip(*sorted(six.iteritems(user._info))) python-openstackclient-3.14.0/openstackclient/identity/v3/region.py0000666000175100017510000001343713232364361025551 0ustar zuulzuul00000000000000# 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. # """Identity v3 Region action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateRegion(command.ShowOne): _description = _("Create new region") def get_parser(self, prog_name): parser = super(CreateRegion, self).get_parser(prog_name) # NOTE(stevemar): The API supports an optional region ID, but that # seems like poor UX, we will only support user-defined IDs. parser.add_argument( 'region', metavar='', help=_('New region ID'), ) parser.add_argument( '--parent-region', metavar='', help=_('Parent region ID'), ) parser.add_argument( '--description', metavar='', help=_('New region description'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity region = identity_client.regions.create( id=parsed_args.region, parent_region=parsed_args.parent_region, description=parsed_args.description, ) region._info['region'] = region._info.pop('id') region._info['parent_region'] = region._info.pop('parent_region_id') region._info.pop('links', None) return zip(*sorted(six.iteritems(region._info))) class DeleteRegion(command.Command): _description = _("Delete region(s)") def get_parser(self, prog_name): parser = super(DeleteRegion, self).get_parser(prog_name) parser.add_argument( 'region', metavar='', nargs='+', help=_('Region ID(s) to delete'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity result = 0 for i in parsed_args.region: try: identity_client.regions.delete(i) except Exception as e: result += 1 LOG.error(_("Failed to delete region with " "ID '%(region)s': %(e)s"), {'region': i, 'e': e}) if result > 0: total = len(parsed_args.region) msg = (_("%(result)s of %(total)s regions failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListRegion(command.Lister): _description = _("List regions") def get_parser(self, prog_name): parser = super(ListRegion, self).get_parser(prog_name) parser.add_argument( '--parent-region', metavar='', help=_('Filter by parent region ID'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity kwargs = {} if parsed_args.parent_region: kwargs['parent_region_id'] = parsed_args.parent_region columns_headers = ('Region', 'Parent Region', 'Description') columns = ('ID', 'Parent Region Id', 'Description') data = identity_client.regions.list(**kwargs) return (columns_headers, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class SetRegion(command.Command): _description = _("Set region properties") def get_parser(self, prog_name): parser = super(SetRegion, self).get_parser(prog_name) parser.add_argument( 'region', metavar='', help=_('Region to modify'), ) parser.add_argument( '--parent-region', metavar='', help=_('New parent region ID'), ) parser.add_argument( '--description', metavar='', help=_('New region description'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity kwargs = {} if parsed_args.description: kwargs['description'] = parsed_args.description if parsed_args.parent_region: kwargs['parent_region'] = parsed_args.parent_region identity_client.regions.update(parsed_args.region, **kwargs) class ShowRegion(command.ShowOne): _description = _("Display region details") def get_parser(self, prog_name): parser = super(ShowRegion, self).get_parser(prog_name) parser.add_argument( 'region', metavar='', help=_('Region to display'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity region = utils.find_resource(identity_client.regions, parsed_args.region) region._info['region'] = region._info.pop('id') region._info['parent_region'] = region._info.pop('parent_region_id') region._info.pop('links', None) return zip(*sorted(six.iteritems(region._info))) python-openstackclient-3.14.0/openstackclient/identity/v3/endpoint.py0000666000175100017510000003146113232364361026103 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Identity v3 Endpoint action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common LOG = logging.getLogger(__name__) def get_service_name(service): if hasattr(service, 'name'): return service.name else: return '' class AddProjectToEndpoint(command.Command): _description = _("Associate a project to an endpoint") def get_parser(self, prog_name): parser = super( AddProjectToEndpoint, self).get_parser(prog_name) parser.add_argument( 'endpoint', metavar='', help=_('Endpoint to associate with ' 'specified project (name or ID)'), ) parser.add_argument( 'project', metavar='', help=_('Project to associate with ' 'specified endpoint name or ID)'), ) common.add_project_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.identity endpoint = utils.find_resource(client.endpoints, parsed_args.endpoint) project = common.find_project(client, parsed_args.project, parsed_args.project_domain) client.endpoint_filter.add_endpoint_to_project( project=project.id, endpoint=endpoint.id) class CreateEndpoint(command.ShowOne): _description = _("Create new endpoint") def get_parser(self, prog_name): parser = super(CreateEndpoint, self).get_parser(prog_name) parser.add_argument( 'service', metavar='', help=_('Service to be associated with new endpoint (name or ID)'), ) parser.add_argument( 'interface', metavar='', choices=['admin', 'public', 'internal'], help=_('New endpoint interface type (admin, public or internal)'), ) parser.add_argument( 'url', metavar='', help=_('New endpoint URL'), ) parser.add_argument( '--region', metavar='', help=_('New endpoint region ID'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', dest='enabled', action='store_true', default=True, help=_('Enable endpoint (default)'), ) enable_group.add_argument( '--disable', dest='enabled', action='store_false', help=_('Disable endpoint'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity service = common.find_service(identity_client, parsed_args.service) endpoint = identity_client.endpoints.create( service=service.id, url=parsed_args.url, interface=parsed_args.interface, region=parsed_args.region, enabled=parsed_args.enabled ) info = {} endpoint._info.pop('links') info.update(endpoint._info) info['service_name'] = get_service_name(service) info['service_type'] = service.type return zip(*sorted(six.iteritems(info))) class DeleteEndpoint(command.Command): _description = _("Delete endpoint(s)") def get_parser(self, prog_name): parser = super(DeleteEndpoint, self).get_parser(prog_name) parser.add_argument( 'endpoint', metavar='', nargs='+', help=_('Endpoint(s) to delete (ID only)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity result = 0 for i in parsed_args.endpoint: try: endpoint_id = utils.find_resource( identity_client.endpoints, i).id identity_client.endpoints.delete(endpoint_id) except Exception as e: result += 1 LOG.error(_("Failed to delete endpoint with " "ID '%(endpoint)s': %(e)s"), {'endpoint': i, 'e': e}) if result > 0: total = len(parsed_args.endpoint) msg = (_("%(result)s of %(total)s endpoints failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListEndpoint(command.Lister): _description = _("List endpoints") def get_parser(self, prog_name): parser = super(ListEndpoint, self).get_parser(prog_name) parser.add_argument( '--service', metavar='', help=_('Filter by service (type, name or ID)'), ) parser.add_argument( '--interface', metavar='', choices=['admin', 'public', 'internal'], help=_('Filter by interface type (admin, public or internal)'), ) parser.add_argument( '--region', metavar='', help=_('Filter by region ID'), ) list_group = parser.add_mutually_exclusive_group() list_group.add_argument( '--endpoint', metavar='', help=_('Endpoint to list filters'), ) list_group.add_argument( '--project', metavar='', help=_('Project to list filters (name or ID)'), ) common.add_project_domain_option_to_parser(list_group) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity endpoint = None if parsed_args.endpoint: endpoint = utils.find_resource(identity_client.endpoints, parsed_args.endpoint) project = None if parsed_args.project: project = common.find_project(identity_client, parsed_args.project, parsed_args.project_domain) if endpoint: columns = ('ID', 'Name') data = ( identity_client.endpoint_filter .list_projects_for_endpoint(endpoint=endpoint.id) ) else: columns = ('ID', 'Region', 'Service Name', 'Service Type', 'Enabled', 'Interface', 'URL') kwargs = {} if parsed_args.service: service = common.find_service(identity_client, parsed_args.service) kwargs['service'] = service.id if parsed_args.interface: kwargs['interface'] = parsed_args.interface if parsed_args.region: kwargs['region'] = parsed_args.region if project: data = ( identity_client.endpoint_filter .list_endpoints_for_project(project=project.id) ) else: data = identity_client.endpoints.list(**kwargs) service_list = identity_client.services.list() for ep in data: service = common.find_service_in_list(service_list, ep.service_id) ep.service_name = get_service_name(service) ep.service_type = service.type return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class RemoveProjectFromEndpoint(command.Command): _description = _("Dissociate a project from an endpoint") def get_parser(self, prog_name): parser = super( RemoveProjectFromEndpoint, self).get_parser(prog_name) parser.add_argument( 'endpoint', metavar='', help=_('Endpoint to dissociate from ' 'specified project (name or ID)'), ) parser.add_argument( 'project', metavar='', help=_('Project to dissociate from ' 'specified endpoint name or ID)'), ) common.add_project_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.identity endpoint = utils.find_resource(client.endpoints, parsed_args.endpoint) project = common.find_project(client, parsed_args.project, parsed_args.project_domain) client.endpoint_filter.delete_endpoint_from_project( project=project.id, endpoint=endpoint.id) class SetEndpoint(command.Command): _description = _("Set endpoint properties") def get_parser(self, prog_name): parser = super(SetEndpoint, self).get_parser(prog_name) parser.add_argument( 'endpoint', metavar='', help=_('Endpoint to modify (ID only)'), ) parser.add_argument( '--region', metavar='', help=_('New endpoint region ID'), ) parser.add_argument( '--interface', metavar='', choices=['admin', 'public', 'internal'], help=_('New endpoint interface type (admin, public or internal)'), ) parser.add_argument( '--url', metavar='', help=_('New endpoint URL'), ) parser.add_argument( '--service', metavar='', help=_('New endpoint service (name or ID)'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', dest='enabled', action='store_true', help=_('Enable endpoint'), ) enable_group.add_argument( '--disable', dest='disabled', action='store_true', help=_('Disable endpoint'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity endpoint = utils.find_resource(identity_client.endpoints, parsed_args.endpoint) service_id = None if parsed_args.service: service = common.find_service(identity_client, parsed_args.service) service_id = service.id enabled = None if parsed_args.enabled: enabled = True if parsed_args.disabled: enabled = False identity_client.endpoints.update( endpoint.id, service=service_id, url=parsed_args.url, interface=parsed_args.interface, region=parsed_args.region, enabled=enabled ) class ShowEndpoint(command.ShowOne): _description = _("Display endpoint details") def get_parser(self, prog_name): parser = super(ShowEndpoint, self).get_parser(prog_name) parser.add_argument( 'endpoint', metavar='', help=_('Endpoint to display (endpoint ID, service ID,' ' service name, service type)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity endpoint = utils.find_resource(identity_client.endpoints, parsed_args.endpoint) service = common.find_service(identity_client, endpoint.service_id) info = {} endpoint._info.pop('links') info.update(endpoint._info) info['service_name'] = get_service_name(service) info['service_type'] = service.type return zip(*sorted(six.iteritems(info))) python-openstackclient-3.14.0/openstackclient/identity/v3/policy.py0000666000175100017510000001273313232364361025563 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Identity v3 Policy action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreatePolicy(command.ShowOne): _description = _("Create new policy") def get_parser(self, prog_name): parser = super(CreatePolicy, self).get_parser(prog_name) parser.add_argument( '--type', metavar='', default="application/json", help=_('New MIME type of the policy rules file ' '(defaults to application/json)'), ) parser.add_argument( 'rules', metavar='', help=_('New serialized policy rules file'), ) return parser def take_action(self, parsed_args): blob = utils.read_blob_file_contents(parsed_args.rules) identity_client = self.app.client_manager.identity policy = identity_client.policies.create( blob=blob, type=parsed_args.type ) policy._info.pop('links') policy._info.update({'rules': policy._info.pop('blob')}) return zip(*sorted(six.iteritems(policy._info))) class DeletePolicy(command.Command): _description = _("Delete policy(s)") def get_parser(self, prog_name): parser = super(DeletePolicy, self).get_parser(prog_name) parser.add_argument( 'policy', metavar='', nargs='+', help=_('Policy(s) to delete'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity result = 0 for i in parsed_args.policy: try: identity_client.policies.delete(i) except Exception as e: result += 1 LOG.error(_("Failed to delete policy with name or " "ID '%(policy)s': %(e)s"), {'policy': i, 'e': e}) if result > 0: total = len(parsed_args.policy) msg = (_("%(result)s of %(total)s policys failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListPolicy(command.Lister): _description = _("List policies") def get_parser(self, prog_name): parser = super(ListPolicy, 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): if parsed_args.long: columns = ('ID', 'Type', 'Blob') column_headers = ('ID', 'Type', 'Rules') else: columns = ('ID', 'Type') column_headers = columns data = self.app.client_manager.identity.policies.list() return (column_headers, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class SetPolicy(command.Command): _description = _("Set policy properties") def get_parser(self, prog_name): parser = super(SetPolicy, self).get_parser(prog_name) parser.add_argument( 'policy', metavar='', help=_('Policy to modify'), ) parser.add_argument( '--type', metavar='', help=_('New MIME type of the policy rules file'), ) parser.add_argument( '--rules', metavar='', help=_('New serialized policy rules file'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity blob = None if parsed_args.rules: blob = utils.read_blob_file_contents(parsed_args.rules) kwargs = {} if blob: kwargs['blob'] = blob if parsed_args.type: kwargs['type'] = parsed_args.type identity_client.policies.update(parsed_args.policy, **kwargs) class ShowPolicy(command.ShowOne): _description = _("Display policy details") def get_parser(self, prog_name): parser = super(ShowPolicy, self).get_parser(prog_name) parser.add_argument( 'policy', metavar='', help=_('Policy to display'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity policy = utils.find_resource(identity_client.policies, parsed_args.policy) policy._info.pop('links') policy._info.update({'rules': policy._info.pop('blob')}) return zip(*sorted(six.iteritems(policy._info))) python-openstackclient-3.14.0/openstackclient/identity/v3/project.py0000666000175100017510000003152113232364361025726 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Project action implementations""" import logging from keystoneauth1 import exceptions as ks_exc from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common LOG = logging.getLogger(__name__) class CreateProject(command.ShowOne): _description = _("Create new project") def get_parser(self, prog_name): parser = super(CreateProject, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('New project name'), ) parser.add_argument( '--domain', metavar='', help=_('Domain owning the project (name or ID)'), ) parser.add_argument( '--parent', metavar='', help=_('Parent of the project (name or ID)'), ) parser.add_argument( '--description', metavar='', help=_('Project description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable project'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable project'), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Add a property to ' '(repeat option to set multiple properties)'), ) parser.add_argument( '--or-show', action='store_true', help=_('Return existing project'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity domain = None if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain).id parent = None if parsed_args.parent: parent = utils.find_resource( identity_client.projects, parsed_args.parent, ).id enabled = True if parsed_args.disable: enabled = False kwargs = {} if parsed_args.property: kwargs = parsed_args.property.copy() try: project = identity_client.projects.create( name=parsed_args.name, domain=domain, parent=parent, description=parsed_args.description, enabled=enabled, **kwargs ) except ks_exc.Conflict: if parsed_args.or_show: project = utils.find_resource(identity_client.projects, parsed_args.name, domain_id=domain) LOG.info(_('Returning existing project %s'), project.name) else: raise project._info.pop('links') return zip(*sorted(six.iteritems(project._info))) class DeleteProject(command.Command): _description = _("Delete project(s)") def get_parser(self, prog_name): parser = super(DeleteProject, self).get_parser(prog_name) parser.add_argument( 'projects', metavar='', nargs="+", help=_('Project(s) to delete (name or ID)'), ) parser.add_argument( '--domain', metavar='', help=_('Domain owning (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity domain = None if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain) errors = 0 for project in parsed_args.projects: try: if domain is not None: project_obj = utils.find_resource(identity_client.projects, project, domain_id=domain.id) else: project_obj = utils.find_resource(identity_client.projects, project) identity_client.projects.delete(project_obj.id) except Exception as e: errors += 1 LOG.error(_("Failed to delete project with " "name or ID '%(project)s': %(e)s"), {'project': project, 'e': e}) if errors > 0: total = len(parsed_args.projects) msg = (_("%(errors)s of %(total)s projects failed " "to delete.") % {'errors': errors, 'total': total}) raise exceptions.CommandError(msg) class ListProject(command.Lister): _description = _("List projects") def get_parser(self, prog_name): parser = super(ListProject, self).get_parser(prog_name) parser.add_argument( '--domain', metavar='', help=_('Filter projects by (name or ID)'), ) parser.add_argument( '--user', metavar='', help=_('Filter projects by (name or ID)'), ) parser.add_argument( '--my-projects', action='store_true', help=_('List projects for the authenticated user. ' 'Supersedes other filters.'), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( '--sort', metavar='[:]', help=_('Sort output by selected keys and directions (asc or desc) ' '(default: asc), repeat this option to specify multiple ' 'keys and directions.'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity if parsed_args.long: columns = ('ID', 'Name', 'Domain ID', 'Description', 'Enabled') else: columns = ('ID', 'Name') kwargs = {} domain_id = None if parsed_args.domain: domain_id = common.find_domain(identity_client, parsed_args.domain).id kwargs['domain'] = domain_id if parsed_args.user: if parsed_args.domain: user_id = utils.find_resource(identity_client.users, parsed_args.user, domain_id=domain_id).id else: user_id = utils.find_resource(identity_client.users, parsed_args.user).id kwargs['user'] = user_id if parsed_args.my_projects: # NOTE(adriant): my-projects supersedes all the other filters. kwargs = {'user': self.app.client_manager.auth_ref.user_id} try: data = identity_client.projects.list(**kwargs) except ks_exc.Forbidden: # NOTE(adriant): if no filters, assume a forbidden is non-admin # wanting their own project list. if not kwargs: user = self.app.client_manager.auth_ref.user_id data = identity_client.projects.list( user=user) else: raise if parsed_args.sort: data = utils.sort_items(data, parsed_args.sort) return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class SetProject(command.Command): _description = _("Set project properties") def get_parser(self, prog_name): parser = super(SetProject, self).get_parser(prog_name) parser.add_argument( 'project', metavar='', help=_('Project to modify (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('Set project name'), ) parser.add_argument( '--domain', metavar='', help=_('Domain owning (name or ID)'), ) parser.add_argument( '--description', metavar='', help=_('Set project description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable project'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable project'), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Set a property on ' '(repeat option to set multiple properties)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity project = common.find_project(identity_client, parsed_args.project, parsed_args.domain) kwargs = {} if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.description: kwargs['description'] = parsed_args.description if parsed_args.enable: kwargs['enabled'] = True if parsed_args.disable: kwargs['enabled'] = False if parsed_args.property: kwargs.update(parsed_args.property) identity_client.projects.update(project.id, **kwargs) class ShowProject(command.ShowOne): _description = _("Display project details") def get_parser(self, prog_name): parser = super(ShowProject, self).get_parser(prog_name) parser.add_argument( 'project', metavar='', help=_('Project to display (name or ID)'), ) parser.add_argument( '--domain', metavar='', help=_('Domain owning (name or ID)'), ) parser.add_argument( '--parents', action='store_true', default=False, help=_('Show the project\'s parents as a list'), ) parser.add_argument( '--children', action='store_true', default=False, help=_('Show project\'s subtree (children) as a list'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity project_str = common._get_token_resource(identity_client, 'project', parsed_args.project, parsed_args.domain) if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain) project = utils.find_resource( identity_client.projects, project_str, domain_id=domain.id) else: project = utils.find_resource( identity_client.projects, project_str) if parsed_args.parents or parsed_args.children: # NOTE(RuiChen): utils.find_resource() can't pass kwargs, # if id query hit the result at first, so call # identity manager.get() with kwargs directly. project = identity_client.projects.get( project.id, parents_as_ids=parsed_args.parents, subtree_as_ids=parsed_args.children) project._info.pop('links') return zip(*sorted(six.iteritems(project._info))) python-openstackclient-3.14.0/openstackclient/identity/v3/group.py0000666000175100017510000003236213232364361025420 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Group action implementations""" import logging import sys from keystoneauth1 import exceptions as ks_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common LOG = logging.getLogger(__name__) class AddUserToGroup(command.Command): _description = _("Add user to group") def get_parser(self, prog_name): parser = super(AddUserToGroup, self).get_parser(prog_name) parser.add_argument( 'group', metavar='', help=_('Group to contain (name or ID)'), ) parser.add_argument( 'user', metavar='', nargs='+', help=_('User(s) to add to (name or ID) ' '(repeat option to add multiple users)'), ) common.add_group_domain_option_to_parser(parser) common.add_user_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity group_id = common.find_group(identity_client, parsed_args.group, parsed_args.group_domain).id result = 0 for i in parsed_args.user: try: user_id = common.find_user(identity_client, i, parsed_args.user_domain).id identity_client.users.add_to_group(user_id, group_id) except Exception as e: result += 1 msg = _("%(user)s not added to group %(group)s: %(e)s") % { 'user': i, 'group': parsed_args.group, 'e': e, } LOG.error(msg) if result > 0: total = len(parsed_args.user) msg = (_("%(result)s of %(total)s users not added to group " "%(group)s.")) % { 'result': result, 'total': total, 'group': parsed_args.group, } raise exceptions.CommandError(msg) class CheckUserInGroup(command.Command): _description = _("Check user membership in group") def get_parser(self, prog_name): parser = super(CheckUserInGroup, self).get_parser(prog_name) parser.add_argument( 'group', metavar='', help=_('Group to check (name or ID)'), ) parser.add_argument( 'user', metavar='', help=_('User to check (name or ID)'), ) common.add_group_domain_option_to_parser(parser) common.add_user_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity user_id = common.find_user(identity_client, parsed_args.user, parsed_args.user_domain).id group_id = common.find_group(identity_client, parsed_args.group, parsed_args.group_domain).id try: identity_client.users.check_in_group(user_id, group_id) except ks_exc.http.HTTPClientError as e: if e.http_status == 403 or e.http_status == 404: msg = _("%(user)s not in group %(group)s\n") % { 'user': parsed_args.user, 'group': parsed_args.group, } sys.stderr.write(msg) else: raise e else: msg = _("%(user)s in group %(group)s\n") % { 'user': parsed_args.user, 'group': parsed_args.group, } sys.stdout.write(msg) class CreateGroup(command.ShowOne): _description = _("Create new group") def get_parser(self, prog_name): parser = super(CreateGroup, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('New group name'), ) parser.add_argument( '--domain', metavar='', help=_('Domain to contain new group (name or ID)'), ) parser.add_argument( '--description', metavar='', help=_('New group description'), ) parser.add_argument( '--or-show', action='store_true', help=_('Return existing group'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity domain = None if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain).id try: group = identity_client.groups.create( name=parsed_args.name, domain=domain, description=parsed_args.description) except ks_exc.Conflict: if parsed_args.or_show: group = utils.find_resource(identity_client.groups, parsed_args.name, domain_id=domain) LOG.info(_('Returning existing group %s'), group.name) else: raise group._info.pop('links') return zip(*sorted(six.iteritems(group._info))) class DeleteGroup(command.Command): _description = _("Delete group(s)") def get_parser(self, prog_name): parser = super(DeleteGroup, self).get_parser(prog_name) parser.add_argument( 'groups', metavar='', nargs="+", help=_('Group(s) to delete (name or ID)'), ) parser.add_argument( '--domain', metavar='', help=_('Domain containing group(s) (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity errors = 0 for group in parsed_args.groups: try: group_obj = common.find_group(identity_client, group, parsed_args.domain) identity_client.groups.delete(group_obj.id) except Exception as e: errors += 1 LOG.error(_("Failed to delete group with " "name or ID '%(group)s': %(e)s"), {'group': group, 'e': e}) if errors > 0: total = len(parsed_args.groups) msg = (_("%(errors)s of %(total)s groups failed " "to delete.") % {'errors': errors, 'total': total}) raise exceptions.CommandError(msg) class ListGroup(command.Lister): _description = _("List groups") def get_parser(self, prog_name): parser = super(ListGroup, self).get_parser(prog_name) parser.add_argument( '--domain', metavar='', help=_('Filter group list by (name or ID)'), ) parser.add_argument( '--user', metavar='', help=_('Filter group list by (name or ID)'), ) common.add_user_domain_option_to_parser(parser) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity domain = None if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain).id if parsed_args.user: user = common.find_user( identity_client, parsed_args.user, parsed_args.user_domain, ).id else: user = None # List groups if parsed_args.long: columns = ('ID', 'Name', 'Domain ID', 'Description') else: columns = ('ID', 'Name') data = identity_client.groups.list( domain=domain, user=user, ) return ( columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data) ) class RemoveUserFromGroup(command.Command): _description = _("Remove user from group") def get_parser(self, prog_name): parser = super(RemoveUserFromGroup, self).get_parser(prog_name) parser.add_argument( 'group', metavar='', help=_('Group containing (name or ID)'), ) parser.add_argument( 'user', metavar='', nargs='+', help=_('User(s) to remove from (name or ID) ' '(repeat option to remove multiple users)'), ) common.add_group_domain_option_to_parser(parser) common.add_user_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity group_id = common.find_group(identity_client, parsed_args.group, parsed_args.group_domain).id result = 0 for i in parsed_args.user: try: user_id = common.find_user(identity_client, i, parsed_args.user_domain).id identity_client.users.remove_from_group(user_id, group_id) except Exception as e: result += 1 msg = _("%(user)s not removed from group %(group)s: %(e)s") % { 'user': i, 'group': parsed_args.group, 'e': e, } LOG.error(msg) if result > 0: total = len(parsed_args.user) msg = (_("%(result)s of %(total)s users not removed from group " "%(group)s.")) % { 'result': result, 'total': total, 'group': parsed_args.group, } raise exceptions.CommandError(msg) class SetGroup(command.Command): _description = _("Set group properties") def get_parser(self, prog_name): parser = super(SetGroup, self).get_parser(prog_name) parser.add_argument( 'group', metavar='', help=_('Group to modify (name or ID)'), ) parser.add_argument( '--domain', metavar='', help=_('Domain containing (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('New group name'), ) parser.add_argument( '--description', metavar='', help=_('New group description'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity group = common.find_group(identity_client, parsed_args.group, parsed_args.domain) kwargs = {} if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.description: kwargs['description'] = parsed_args.description identity_client.groups.update(group.id, **kwargs) class ShowGroup(command.ShowOne): _description = _("Display group details") def get_parser(self, prog_name): parser = super(ShowGroup, self).get_parser(prog_name) parser.add_argument( 'group', metavar='', help=_('Group to display (name or ID)'), ) parser.add_argument( '--domain', metavar='', help=_('Domain containing (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity group = common.find_group(identity_client, parsed_args.group, domain_name_or_id=parsed_args.domain) group._info.pop('links') return zip(*sorted(six.iteritems(group._info))) python-openstackclient-3.14.0/openstackclient/identity/v3/mapping.py0000666000175100017510000001463713232364361025724 0ustar zuulzuul00000000000000# Copyright 2014 CERN # # 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. # """Identity v3 federation mapping action implementations""" import json import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class _RulesReader(object): _description = _("Helper class capable of reading rules from files") def _read_rules(self, path): """Read and parse rules from path Expect the file to contain a valid JSON structure. :param path: path to the file :return: loaded and valid dictionary with rules :raises exception.CommandError: In case the file cannot be accessed or the content is not a valid JSON. Example of the content of the file: [ { "local": [ { "group": { "id": "85a868" } } ], "remote": [ { "type": "orgPersonType", "any_one_of": [ "Employee" ] }, { "type": "sn", "any_one_of": [ "Young" ] } ] } ] """ blob = utils.read_blob_file_contents(path) try: rules = json.loads(blob) except ValueError as e: msg = _("An error occurred when reading rules from file " "%(path)s: %(error)s") % {"path": path, "error": e} raise exceptions.CommandError(msg) else: return rules class CreateMapping(command.ShowOne, _RulesReader): _description = _("Create new mapping") def get_parser(self, prog_name): parser = super(CreateMapping, self).get_parser(prog_name) parser.add_argument( 'mapping', metavar='', help=_('New mapping name (must be unique)'), ) parser.add_argument( '--rules', metavar='', required=True, help=_('Filename that contains a set of mapping rules (required)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity rules = self._read_rules(parsed_args.rules) mapping = identity_client.federation.mappings.create( mapping_id=parsed_args.mapping, rules=rules) mapping._info.pop('links', None) return zip(*sorted(six.iteritems(mapping._info))) class DeleteMapping(command.Command): _description = _("Delete mapping(s)") def get_parser(self, prog_name): parser = super(DeleteMapping, self).get_parser(prog_name) parser.add_argument( 'mapping', metavar='', nargs='+', help=_('Mapping(s) to delete'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity result = 0 for i in parsed_args.mapping: try: identity_client.federation.mappings.delete(i) except Exception as e: result += 1 LOG.error(_("Failed to delete mapping with name or " "ID '%(mapping)s': %(e)s"), {'mapping': i, 'e': e}) if result > 0: total = len(parsed_args.mapping) msg = (_("%(result)s of %(total)s mappings failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListMapping(command.Lister): _description = _("List mappings") def take_action(self, parsed_args): # NOTE(marek-denis): Since rules can be long and tedious I have decided # to only list ids of the mappings. If somebody wants to check the # rules, (s)he should show specific ones. identity_client = self.app.client_manager.identity data = identity_client.federation.mappings.list() columns = ('ID',) items = [utils.get_item_properties(s, columns) for s in data] return (columns, items) class SetMapping(command.Command, _RulesReader): _description = _("Set mapping properties") def get_parser(self, prog_name): parser = super(SetMapping, self).get_parser(prog_name) parser.add_argument( 'mapping', metavar='', help=_('Mapping to modify'), ) parser.add_argument( '--rules', metavar='', help=_('Filename that contains a new set of mapping rules'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity rules = self._read_rules(parsed_args.rules) mapping = identity_client.federation.mappings.update( mapping=parsed_args.mapping, rules=rules) mapping._info.pop('links', None) class ShowMapping(command.ShowOne): _description = _("Display mapping details") def get_parser(self, prog_name): parser = super(ShowMapping, self).get_parser(prog_name) parser.add_argument( 'mapping', metavar='', help=_('Mapping to display'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity mapping = identity_client.federation.mappings.get(parsed_args.mapping) mapping._info.pop('links', None) return zip(*sorted(six.iteritems(mapping._info))) python-openstackclient-3.14.0/openstackclient/identity/v3/trust.py0000666000175100017510000001647313232364361025452 0ustar zuulzuul00000000000000# 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. # """Identity v3 Trust action implementations""" import datetime import logging from keystoneclient import exceptions as identity_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common LOG = logging.getLogger(__name__) class CreateTrust(command.ShowOne): _description = _("Create new trust") def get_parser(self, prog_name): parser = super(CreateTrust, self).get_parser(prog_name) parser.add_argument( 'trustor', metavar='', help=_('User that is delegating authorization (name or ID)'), ) parser.add_argument( 'trustee', metavar='', help=_('User that is assuming authorization (name or ID)'), ) parser.add_argument( '--project', metavar='', required=True, help=_('Project being delegated (name or ID) (required)'), ) parser.add_argument( '--role', metavar='', action='append', default=[], help=_('Roles to authorize (name or ID) ' '(repeat option to set multiple values, required)'), required=True ) parser.add_argument( '--impersonate', dest='impersonate', action='store_true', default=False, help=_('Tokens generated from the trust will represent ' ' (defaults to False)'), ) parser.add_argument( '--expiration', metavar='', help=_('Sets an expiration date for the trust' ' (format of YYYY-mm-ddTHH:MM:SS)'), ) common.add_project_domain_option_to_parser(parser) parser.add_argument( '--trustor-domain', metavar='', help=_('Domain that contains (name or ID)'), ) parser.add_argument( '--trustee-domain', metavar='', help=_('Domain that contains (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity # NOTE(stevemar): Find the two users, project and roles that # are necessary for making a trust usable, the API dictates that # trustee, project and role are optional, but that makes the trust # pointless, and trusts are immutable, so let's enforce it at the # client level. trustor_id = common.find_user(identity_client, parsed_args.trustor, parsed_args.trustor_domain).id trustee_id = common.find_user(identity_client, parsed_args.trustee, parsed_args.trustee_domain).id project_id = common.find_project(identity_client, parsed_args.project, parsed_args.project_domain).id role_ids = [] for role in parsed_args.role: try: role_id = utils.find_resource( identity_client.roles, role, ).id except identity_exc.Forbidden: role_id = role role_ids.append(role_id) expires_at = None if parsed_args.expiration: expires_at = datetime.datetime.strptime(parsed_args.expiration, '%Y-%m-%dT%H:%M:%S') trust = identity_client.trusts.create( trustee_id, trustor_id, impersonation=parsed_args.impersonate, project=project_id, role_ids=role_ids, expires_at=expires_at, ) trust._info.pop('roles_links', None) trust._info.pop('links', None) # Format roles into something sensible roles = trust._info.pop('roles') msg = ' '.join(r['name'] for r in roles) trust._info['roles'] = msg return zip(*sorted(six.iteritems(trust._info))) class DeleteTrust(command.Command): _description = _("Delete trust(s)") def get_parser(self, prog_name): parser = super(DeleteTrust, self).get_parser(prog_name) parser.add_argument( 'trust', metavar='', nargs="+", help=_('Trust(s) to delete'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity errors = 0 for trust in parsed_args.trust: try: trust_obj = utils.find_resource(identity_client.trusts, trust) identity_client.trusts.delete(trust_obj.id) except Exception as e: errors += 1 LOG.error(_("Failed to delete trust with " "name or ID '%(trust)s': %(e)s"), {'trust': trust, 'e': e}) if errors > 0: total = len(parsed_args.trust) msg = (_("%(errors)s of %(total)s trusts failed " "to delete.") % {'errors': errors, 'total': total}) raise exceptions.CommandError(msg) class ListTrust(command.Lister): _description = _("List trusts") def take_action(self, parsed_args): columns = ('ID', 'Expires At', 'Impersonation', 'Project ID', 'Trustee User ID', 'Trustor User ID') data = self.app.client_manager.identity.trusts.list() return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class ShowTrust(command.ShowOne): _description = _("Display trust details") def get_parser(self, prog_name): parser = super(ShowTrust, self).get_parser(prog_name) parser.add_argument( 'trust', metavar='', help=_('Trust to display'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity trust = utils.find_resource(identity_client.trusts, parsed_args.trust) trust._info.pop('roles_links', None) trust._info.pop('links', None) # Format roles into something sensible roles = trust._info.pop('roles') msg = ' '.join(r['name'] for r in roles) trust._info['roles'] = msg return zip(*sorted(six.iteritems(trust._info))) python-openstackclient-3.14.0/openstackclient/identity/v3/role_assignment.py0000666000175100017510000002051613232364361027453 0ustar zuulzuul00000000000000# 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. # """Identity v3 Assignment action implementations""" from osc_lib.command import command from osc_lib import utils from openstackclient.i18n import _ from openstackclient.identity import common class ListRoleAssignment(command.Lister): _description = _("List role assignments") def get_parser(self, prog_name): parser = super(ListRoleAssignment, self).get_parser(prog_name) parser.add_argument( '--effective', action="store_true", default=False, help=_('Returns only effective role assignments'), ) parser.add_argument( '--role', metavar='', help=_('Role to filter (name or ID)'), ) common.add_role_domain_option_to_parser(parser) parser.add_argument( '--names', action="store_true", help=_('Display names instead of IDs'), ) user_or_group = parser.add_mutually_exclusive_group() user_or_group.add_argument( '--user', metavar='', help=_('User to filter (name or ID)'), ) common.add_user_domain_option_to_parser(parser) user_or_group.add_argument( '--group', metavar='', help=_('Group to filter (name or ID)'), ) common.add_group_domain_option_to_parser(parser) domain_or_project = parser.add_mutually_exclusive_group() domain_or_project.add_argument( '--domain', metavar='', help=_('Domain to filter (name or ID)'), ) domain_or_project.add_argument( '--project', metavar='', help=_('Project to filter (name or ID)'), ) common.add_project_domain_option_to_parser(parser) common.add_inherited_option_to_parser(parser) parser.add_argument( '--auth-user', action="store_true", dest='authuser', help='Only list assignments for the authenticated user', ) parser.add_argument( '--auth-project', action="store_true", dest='authproject', help='Only list assignments for the project to which the ' 'authenticated user\'s token is scoped', ) return parser def _as_tuple(self, assignment): return (assignment.role, assignment.user, assignment.group, assignment.project, assignment.domain, assignment.inherited) def take_action(self, parsed_args): identity_client = self.app.client_manager.identity auth_ref = self.app.client_manager.auth_ref role = None role_domain_id = None if parsed_args.role_domain: role_domain_id = common.find_domain(identity_client, parsed_args.role_domain).id if parsed_args.role: role = utils.find_resource( identity_client.roles, parsed_args.role, domain_id=role_domain_id ) user = None if parsed_args.user: user = common.find_user( identity_client, parsed_args.user, parsed_args.user_domain, ) elif parsed_args.authuser: if auth_ref: user = common.find_user( identity_client, auth_ref.user_id ) domain = None if parsed_args.domain: domain = common.find_domain( identity_client, parsed_args.domain, ) project = None if parsed_args.project: project = common.find_project( identity_client, common._get_token_resource(identity_client, 'project', parsed_args.project), parsed_args.project_domain, ) elif parsed_args.authproject: if auth_ref: project = common.find_project( identity_client, auth_ref.project_id ) group = None if parsed_args.group: group = common.find_group( identity_client, parsed_args.group, parsed_args.group_domain, ) include_names = True if parsed_args.names else False effective = True if parsed_args.effective else False columns = ('Role', 'User', 'Group', 'Project', 'Domain', 'Inherited') inherited_to = 'projects' if parsed_args.inherited else None data = identity_client.role_assignments.list( domain=domain, user=user, group=group, project=project, role=role, effective=effective, os_inherit_extension_inherited_to=inherited_to, include_names=include_names) data_parsed = [] for assignment in data: # Removing the extra "scope" layer in the assignment json scope = assignment.scope if 'project' in scope: if include_names: prj = '@'.join([scope['project']['name'], scope['project']['domain']['name']]) setattr(assignment, 'project', prj) else: setattr(assignment, 'project', scope['project']['id']) assignment.domain = '' elif 'domain' in scope: if include_names: setattr(assignment, 'domain', scope['domain']['name']) else: setattr(assignment, 'domain', scope['domain']['id']) assignment.project = '' else: assignment.domain = '' assignment.project = '' inherited = scope.get('OS-INHERIT:inherited_to') == 'projects' assignment.inherited = inherited del assignment.scope if hasattr(assignment, 'user'): if include_names: usr = '@'.join([assignment.user['name'], assignment.user['domain']['name']]) setattr(assignment, 'user', usr) else: setattr(assignment, 'user', assignment.user['id']) assignment.group = '' elif hasattr(assignment, 'group'): if include_names: grp = '@'.join([assignment.group['name'], assignment.group['domain']['name']]) setattr(assignment, 'group', grp) else: setattr(assignment, 'group', assignment.group['id']) assignment.user = '' else: assignment.user = '' assignment.group = '' if hasattr(assignment, 'role'): if include_names: # TODO(henry-nash): If this is a domain specific role it # would be good show this as role@domain, although this # domain info is not yet included in the response from the # server. Although we could get it by re-reading the role # from the ID, let's wait until the server does the right # thing. setattr(assignment, 'role', assignment.role['name']) else: setattr(assignment, 'role', assignment.role['id']) else: assignment.role = '' # Creating a tuple from data object fields # (including the blank ones) data_parsed.append(self._as_tuple(assignment)) return columns, tuple(data_parsed) python-openstackclient-3.14.0/openstackclient/identity/v3/token.py0000666000175100017510000001570513232364361025406 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Identity v3 Token action implementations""" from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common class AuthorizeRequestToken(command.ShowOne): _description = _("Authorize a request token") def get_parser(self, prog_name): parser = super(AuthorizeRequestToken, self).get_parser(prog_name) parser.add_argument( '--request-key', metavar='', required=True, help=_('Request token to authorize (ID only) (required)'), ) parser.add_argument( '--role', metavar='', action='append', default=[], required=True, help=_('Roles to authorize (name or ID) ' '(repeat option to set multiple values) (required)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity # NOTE(stevemar): We want a list of role ids roles = [] for role in parsed_args.role: role_id = utils.find_resource( identity_client.roles, role, ).id roles.append(role_id) verifier_pin = identity_client.oauth1.request_tokens.authorize( parsed_args.request_key, roles) return zip(*sorted(six.iteritems(verifier_pin._info))) class CreateAccessToken(command.ShowOne): _description = _("Create an access token") def get_parser(self, prog_name): parser = super(CreateAccessToken, self).get_parser(prog_name) parser.add_argument( '--consumer-key', metavar='', help=_('Consumer key (required)'), required=True ) parser.add_argument( '--consumer-secret', metavar='', help=_('Consumer secret (required)'), required=True ) parser.add_argument( '--request-key', metavar='', help=_('Request token to exchange for access token (required)'), required=True ) parser.add_argument( '--request-secret', metavar='', help=_('Secret associated with (required)'), required=True ) parser.add_argument( '--verifier', metavar='', help=_('Verifier associated with (required)'), required=True ) return parser def take_action(self, parsed_args): token_client = self.app.client_manager.identity.oauth1.access_tokens access_token = token_client.create( parsed_args.consumer_key, parsed_args.consumer_secret, parsed_args.request_key, parsed_args.request_secret, parsed_args.verifier) return zip(*sorted(six.iteritems(access_token._info))) class CreateRequestToken(command.ShowOne): _description = _("Create a request token") def get_parser(self, prog_name): parser = super(CreateRequestToken, self).get_parser(prog_name) parser.add_argument( '--consumer-key', metavar='', help=_('Consumer key (required)'), required=True ) parser.add_argument( '--consumer-secret', metavar='', help=_('Consumer secret (required)'), required=True ) parser.add_argument( '--project', metavar='', help=_('Project that consumer wants to access (name or ID)' ' (required)'), required=True ) parser.add_argument( '--domain', metavar='', help=_('Domain owning (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain) project = utils.find_resource(identity_client.projects, parsed_args.project, domain_id=domain.id) else: project = utils.find_resource(identity_client.projects, parsed_args.project) token_client = identity_client.oauth1.request_tokens request_token = token_client.create( parsed_args.consumer_key, parsed_args.consumer_secret, project.id) return zip(*sorted(six.iteritems(request_token._info))) class IssueToken(command.ShowOne): _description = _("Issue new token") # scoped token is optional required_scope = False def get_parser(self, prog_name): parser = super(IssueToken, self).get_parser(prog_name) return parser def take_action(self, parsed_args): auth_ref = self.app.client_manager.auth_ref if not auth_ref: raise exceptions.AuthorizationFailure( _("Only an authorized user may issue a new token.")) data = {} if auth_ref.auth_token: data['id'] = auth_ref.auth_token if auth_ref.expires: datetime_obj = auth_ref.expires expires_str = datetime_obj.strftime('%Y-%m-%dT%H:%M:%S%z') data['expires'] = expires_str if auth_ref.project_id: data['project_id'] = auth_ref.project_id if auth_ref.user_id: data['user_id'] = auth_ref.user_id if auth_ref.domain_id: data['domain_id'] = auth_ref.domain_id return zip(*sorted(six.iteritems(data))) class RevokeToken(command.Command): _description = _("Revoke existing token") def get_parser(self, prog_name): parser = super(RevokeToken, self).get_parser(prog_name) parser.add_argument( 'token', metavar='', help=_('Token to be deleted'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity identity_client.tokens.revoke_token(parsed_args.token) python-openstackclient-3.14.0/openstackclient/identity/v3/role.py0000666000175100017510000004254213232364361025226 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Identity v3 Role action implementations""" import logging from keystoneauth1 import exceptions as ks_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common LOG = logging.getLogger(__name__) def _add_identity_and_resource_options_to_parser(parser): domain_or_project = parser.add_mutually_exclusive_group() domain_or_project.add_argument( '--domain', metavar='', help=_('Include (name or ID)'), ) domain_or_project.add_argument( '--project', metavar='', help=_('Include (name or ID)'), ) user_or_group = parser.add_mutually_exclusive_group() user_or_group.add_argument( '--user', metavar='', help=_('Include (name or ID)'), ) user_or_group.add_argument( '--group', metavar='', help=_('Include (name or ID)'), ) common.add_group_domain_option_to_parser(parser) common.add_project_domain_option_to_parser(parser) common.add_user_domain_option_to_parser(parser) common.add_inherited_option_to_parser(parser) def _process_identity_and_resource_options(parsed_args, identity_client_manager): kwargs = {} if parsed_args.user and parsed_args.domain: kwargs['user'] = common.find_user( identity_client_manager, parsed_args.user, parsed_args.user_domain, ).id kwargs['domain'] = common.find_domain( identity_client_manager, parsed_args.domain, ).id elif parsed_args.user and parsed_args.project: kwargs['user'] = common.find_user( identity_client_manager, parsed_args.user, parsed_args.user_domain, ).id kwargs['project'] = common.find_project( identity_client_manager, parsed_args.project, parsed_args.project_domain, ).id elif parsed_args.group and parsed_args.domain: kwargs['group'] = common.find_group( identity_client_manager, parsed_args.group, parsed_args.group_domain, ).id kwargs['domain'] = common.find_domain( identity_client_manager, parsed_args.domain, ).id elif parsed_args.group and parsed_args.project: kwargs['group'] = common.find_group( identity_client_manager, parsed_args.group, parsed_args.group_domain, ).id kwargs['project'] = common.find_project( identity_client_manager, parsed_args.project, parsed_args.project_domain, ).id kwargs['os_inherit_extension_inherited'] = parsed_args.inherited return kwargs class AddRole(command.Command): _description = _("Adds a role assignment to a user or group on a domain " "or project") def get_parser(self, prog_name): parser = super(AddRole, self).get_parser(prog_name) parser.add_argument( 'role', metavar='', help=_('Role to add to (name or ID)'), ) _add_identity_and_resource_options_to_parser(parser) common.add_role_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity if (not parsed_args.user and not parsed_args.domain and not parsed_args.group and not parsed_args.project): msg = _("Role not added, incorrect set of arguments " "provided. See openstack --help for more details") raise exceptions.CommandError(msg) domain_id = None if parsed_args.role_domain: domain_id = common.find_domain(identity_client, parsed_args.role_domain).id role = utils.find_resource( identity_client.roles, parsed_args.role, domain_id=domain_id ) kwargs = _process_identity_and_resource_options( parsed_args, self.app.client_manager.identity) identity_client.roles.grant(role.id, **kwargs) class CreateRole(command.ShowOne): _description = _("Create new role") def get_parser(self, prog_name): parser = super(CreateRole, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('New role name'), ) parser.add_argument( '--domain', metavar='', help=_('Domain the role belongs to (name or ID)'), ) parser.add_argument( '--or-show', action='store_true', help=_('Return existing role'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity domain_id = None if parsed_args.domain: domain_id = common.find_domain(identity_client, parsed_args.domain).id try: role = identity_client.roles.create( name=parsed_args.name, domain=domain_id) except ks_exc.Conflict: if parsed_args.or_show: role = utils.find_resource(identity_client.roles, parsed_args.name, domain_id=domain_id) LOG.info(_('Returning existing role %s'), role.name) else: raise role._info.pop('links') return zip(*sorted(six.iteritems(role._info))) class DeleteRole(command.Command): _description = _("Delete role(s)") def get_parser(self, prog_name): parser = super(DeleteRole, self).get_parser(prog_name) parser.add_argument( 'roles', metavar='', nargs="+", help=_('Role(s) to delete (name or ID)'), ) parser.add_argument( '--domain', metavar='', help=_('Domain the role belongs to (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity domain_id = None if parsed_args.domain: domain_id = common.find_domain(identity_client, parsed_args.domain).id errors = 0 for role in parsed_args.roles: try: role_obj = utils.find_resource( identity_client.roles, role, domain_id=domain_id ) identity_client.roles.delete(role_obj.id) except Exception as e: errors += 1 LOG.error(_("Failed to delete role with " "name or ID '%(role)s': %(e)s"), {'role': role, 'e': e}) if errors > 0: total = len(parsed_args.roles) msg = (_("%(errors)s of %(total)s roles failed " "to delete.") % {'errors': errors, 'total': total}) raise exceptions.CommandError(msg) class ListRole(command.Lister): _description = _("List roles") def get_parser(self, prog_name): parser = super(ListRole, self).get_parser(prog_name) # TODO(henry-nash): The use of the List Role command to list # assignments (as well as roles) has been deprecated. In order # to support domain specific roles, we are overriding the domain # option to allow specification of the domain for the role. This does # not conflict with any existing commands, since for the deprecated # assignments listing you were never allowed to only specify a domain # (you also needed to specify a user). # # Once we have removed the deprecated options entirely, we must # replace the call to _add_identity_and_resource_options_to_parser() # below with just adding the domain option into the parser. _add_identity_and_resource_options_to_parser(parser) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity if parsed_args.user: user = common.find_user( identity_client, parsed_args.user, parsed_args.user_domain, ) elif parsed_args.group: group = common.find_group( identity_client, parsed_args.group, parsed_args.group_domain, ) if parsed_args.domain: domain = common.find_domain( identity_client, parsed_args.domain, ) elif parsed_args.project: project = common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ) # no user or group specified, list all roles in the system if not parsed_args.user and not parsed_args.group: if not parsed_args.domain: columns = ('ID', 'Name') data = identity_client.roles.list() else: columns = ('ID', 'Name', 'Domain') data = identity_client.roles.list(domain_id=domain.id) for role in data: role.domain = domain.name elif parsed_args.user and parsed_args.domain: columns = ('ID', 'Name', 'Domain', 'User') data = identity_client.roles.list( user=user, domain=domain, os_inherit_extension_inherited=parsed_args.inherited ) for user_role in data: user_role.user = user.name user_role.domain = domain.name self.log.warning(_('Listing assignments using role list is ' 'deprecated. Use role assignment list --user ' ' --domain --names ' 'instead.')) elif parsed_args.user and parsed_args.project: columns = ('ID', 'Name', 'Project', 'User') data = identity_client.roles.list( user=user, project=project, os_inherit_extension_inherited=parsed_args.inherited ) for user_role in data: user_role.user = user.name user_role.project = project.name self.log.warning(_('Listing assignments using role list is ' 'deprecated. Use role assignment list --user ' ' --project --names ' 'instead.')) elif parsed_args.user: columns = ('ID', 'Name') data = identity_client.roles.list( user=user, domain='default', os_inherit_extension_inherited=parsed_args.inherited ) self.log.warning(_('Listing assignments using role list is ' 'deprecated. Use role assignment list --user ' ' --domain default --names ' 'instead.')) elif parsed_args.group and parsed_args.domain: columns = ('ID', 'Name', 'Domain', 'Group') data = identity_client.roles.list( group=group, domain=domain, os_inherit_extension_inherited=parsed_args.inherited ) for group_role in data: group_role.group = group.name group_role.domain = domain.name self.log.warning(_('Listing assignments using role list is ' 'deprecated. Use role assignment list --group ' ' --domain --names ' 'instead.')) elif parsed_args.group and parsed_args.project: columns = ('ID', 'Name', 'Project', 'Group') data = identity_client.roles.list( group=group, project=project, os_inherit_extension_inherited=parsed_args.inherited ) for group_role in data: group_role.group = group.name group_role.project = project.name self.log.warning(_('Listing assignments using role list is ' 'deprecated. Use role assignment list --group ' ' --project --names ' 'instead.')) else: msg = _("Error: If a user or group is specified, " "either --domain or --project must also be " "specified to list role grants.") raise exceptions.CommandError(msg) return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class RemoveRole(command.Command): _description = _("Removes a role assignment from domain/project : " "user/group") def get_parser(self, prog_name): parser = super(RemoveRole, self).get_parser(prog_name) parser.add_argument( 'role', metavar='', help=_('Role to remove (name or ID)'), ) _add_identity_and_resource_options_to_parser(parser) common.add_role_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity if (not parsed_args.user and not parsed_args.domain and not parsed_args.group and not parsed_args.project): msg = _("Incorrect set of arguments provided. " "See openstack --help for more details") raise exceptions.CommandError(msg) domain_id = None if parsed_args.role_domain: domain_id = common.find_domain(identity_client, parsed_args.role_domain).id role = utils.find_resource( identity_client.roles, parsed_args.role, domain_id=domain_id ) kwargs = _process_identity_and_resource_options( parsed_args, self.app.client_manager.identity) identity_client.roles.revoke(role.id, **kwargs) class SetRole(command.Command): _description = _("Set role properties") def get_parser(self, prog_name): parser = super(SetRole, self).get_parser(prog_name) parser.add_argument( 'role', metavar='', help=_('Role to modify (name or ID)'), ) parser.add_argument( '--domain', metavar='', help=_('Domain the role belongs to (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('Set role name'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity domain_id = None if parsed_args.domain: domain_id = common.find_domain(identity_client, parsed_args.domain).id role = utils.find_resource(identity_client.roles, parsed_args.role, domain_id=domain_id) identity_client.roles.update(role.id, name=parsed_args.name) class ShowRole(command.ShowOne): _description = _("Display role details") def get_parser(self, prog_name): parser = super(ShowRole, self).get_parser(prog_name) parser.add_argument( 'role', metavar='', help=_('Role to display (name or ID)'), ) parser.add_argument( '--domain', metavar='', help=_('Domain the role belongs to (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity domain_id = None if parsed_args.domain: domain_id = common.find_domain(identity_client, parsed_args.domain).id role = utils.find_resource(identity_client.roles, parsed_args.role, domain_id=domain_id) role._info.pop('links') return zip(*sorted(six.iteritems(role._info))) python-openstackclient-3.14.0/openstackclient/identity/v3/implied_role.py0000666000175100017510000001012413232364361026720 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Identity v3 Implied Role action implementations""" import logging from osc_lib.command import command import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) def _get_role_ids(identity_client, parsed_args): """Return prior and implied role id(s) If prior and implied role id(s) are retrievable from identity client, return tuple containing them. """ role_id = None implied_role_id = None roles = identity_client.roles.list() for role in roles: role_id_or_name = (role.name, role.id) if parsed_args.role in role_id_or_name: role_id = role.id elif parsed_args.implied_role in role_id_or_name: implied_role_id = role.id return (role_id, implied_role_id) class CreateImpliedRole(command.ShowOne): _description = _("Creates an association between prior and implied roles") def get_parser(self, prog_name): parser = super(CreateImpliedRole, self).get_parser(prog_name) parser.add_argument( 'role', metavar='', help=_('Role (name or ID) that implies another role'), ) parser.add_argument( '--implied-role', metavar='', help=' (name or ID) implied by another role', required=True, ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity (prior_role_id, implied_role_id) = _get_role_ids( identity_client, parsed_args) response = identity_client.roles.create_implied( prior_role_id, implied_role_id) response._info.pop('links', None) return zip(*sorted([(k, v['id']) for k, v in six.iteritems(response._info)])) class DeleteImpliedRole(command.Command): _description = _("Deletes an association between prior and implied roles") def get_parser(self, prog_name): parser = super(DeleteImpliedRole, self).get_parser(prog_name) parser.add_argument( 'role', metavar='', help=_('Role (name or ID) that implies another role'), ) parser.add_argument( '--implied-role', metavar='', help=' (name or ID) implied by another role', required=True, ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity (prior_role_id, implied_role_id) = _get_role_ids( identity_client, parsed_args) identity_client.roles.delete_implied( prior_role_id, implied_role_id) class ListImpliedRole(command.Lister): _description = _("List implied roles") _COLUMNS = ['Prior Role ID', 'Prior Role Name', 'Implied Role ID', 'Implied Role Name'] def get_parser(self, prog_name): parser = super(ListImpliedRole, self).get_parser(prog_name) return parser def take_action(self, parsed_args): def _list_implied(response): for rule in response: for implies in rule.implies: yield (rule.prior_role['id'], rule.prior_role['name'], implies['id'], implies['name']) identity_client = self.app.client_manager.identity response = identity_client.roles.list_inference_roles() return (self._COLUMNS, _list_implied(response)) python-openstackclient-3.14.0/openstackclient/identity/v3/credential.py0000666000175100017510000001666413232364361026405 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Identity v3 Credential action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common LOG = logging.getLogger(__name__) class CreateCredential(command.ShowOne): _description = _("Create new credential") def get_parser(self, prog_name): parser = super(CreateCredential, self).get_parser(prog_name) parser.add_argument( 'user', metavar='', help=_('user that owns the credential (name or ID)'), ) parser.add_argument( '--type', default="cert", metavar='', help=_('New credential type: cert, ec2, totp and so on'), ) parser.add_argument( 'data', metavar='', help=_('New credential data'), ) parser.add_argument( '--project', metavar='', help=_('Project which limits the scope of ' 'the credential (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity user_id = utils.find_resource(identity_client.users, parsed_args.user).id if parsed_args.project: project = utils.find_resource(identity_client.projects, parsed_args.project).id else: project = None credential = identity_client.credentials.create( user=user_id, type=parsed_args.type, blob=parsed_args.data, project=project) credential._info.pop('links') return zip(*sorted(six.iteritems(credential._info))) class DeleteCredential(command.Command): _description = _("Delete credential(s)") def get_parser(self, prog_name): parser = super(DeleteCredential, self).get_parser(prog_name) parser.add_argument( 'credential', metavar='', nargs='+', help=_('ID of credential(s) to delete'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity result = 0 for i in parsed_args.credential: try: identity_client.credentials.delete(i) except Exception as e: result += 1 LOG.error(_("Failed to delete credentials with " "ID '%(credential)s': %(e)s"), {'credential': i, 'e': e}) if result > 0: total = len(parsed_args.credential) msg = (_("%(result)s of %(total)s credential failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListCredential(command.Lister): _description = _("List credentials") def get_parser(self, prog_name): parser = super(ListCredential, self).get_parser(prog_name) parser.add_argument( '--user', metavar='', help=_('Filter credentials by (name or ID)'), ) common.add_user_domain_option_to_parser(parser) parser.add_argument( '--type', metavar='', help=_('Filter credentials by type: cert, ec2, totp and so on'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity kwargs = {} if parsed_args.user: user_id = common.find_user( identity_client, parsed_args.user, parsed_args.user_domain, ).id kwargs["user_id"] = user_id if parsed_args.type: kwargs["type"] = parsed_args.type columns = ('ID', 'Type', 'User ID', 'Blob', 'Project ID') column_headers = ('ID', 'Type', 'User ID', 'Data', 'Project ID') data = self.app.client_manager.identity.credentials.list(**kwargs) return (column_headers, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class SetCredential(command.Command): _description = _("Set credential properties") def get_parser(self, prog_name): parser = super(SetCredential, self).get_parser(prog_name) parser.add_argument( 'credential', metavar='', help=_('ID of credential to change'), ) parser.add_argument( '--user', metavar='', required=True, help=_('User that owns the credential (name or ID)'), ) parser.add_argument( '--type', metavar='', required=True, help=_('New credential type: cert, ec2, totp and so on'), ) parser.add_argument( '--data', metavar='', required=True, help=_('New credential data'), ) parser.add_argument( '--project', metavar='', help=_('Project which limits the scope of ' 'the credential (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity user_id = utils.find_resource(identity_client.users, parsed_args.user).id if parsed_args.project: project = utils.find_resource(identity_client.projects, parsed_args.project).id else: project = None identity_client.credentials.update(parsed_args.credential, user=user_id, type=parsed_args.type, blob=parsed_args.data, project=project) class ShowCredential(command.ShowOne): _description = _("Display credential details") def get_parser(self, prog_name): parser = super(ShowCredential, self).get_parser(prog_name) parser.add_argument( 'credential', metavar='', help=_('ID of credential to display'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity credential = utils.find_resource(identity_client.credentials, parsed_args.credential) credential._info.pop('links') return zip(*sorted(six.iteritems(credential._info))) python-openstackclient-3.14.0/openstackclient/identity/v3/identity_provider.py0000666000175100017510000002201713232364361030023 0ustar zuulzuul00000000000000# 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. # """Identity v3 IdentityProvider action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common LOG = logging.getLogger(__name__) class CreateIdentityProvider(command.ShowOne): _description = _("Create new identity provider") def get_parser(self, prog_name): parser = super(CreateIdentityProvider, self).get_parser(prog_name) parser.add_argument( 'identity_provider_id', metavar='', help=_('New identity provider name (must be unique)'), ) identity_remote_id_provider = parser.add_mutually_exclusive_group() identity_remote_id_provider.add_argument( '--remote-id', metavar='', action='append', help=_('Remote IDs to associate with the Identity Provider ' '(repeat option to provide multiple values)'), ) identity_remote_id_provider.add_argument( '--remote-id-file', metavar='', help=_('Name of a file that contains many remote IDs to associate ' 'with the identity provider, one per line'), ) parser.add_argument( '--description', metavar='', help=_('New identity provider description'), ) parser.add_argument( '--domain', metavar='', help=_('Domain to associate with the identity provider. If not ' 'specified, a domain will be created automatically. ' '(Name or ID)'), ) enable_identity_provider = parser.add_mutually_exclusive_group() enable_identity_provider.add_argument( '--enable', dest='enabled', action='store_true', default=True, help=_('Enable identity provider (default)'), ) enable_identity_provider.add_argument( '--disable', dest='enabled', action='store_false', help=_('Disable the identity provider'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity if parsed_args.remote_id_file: file_content = utils.read_blob_file_contents( parsed_args.remote_id_file) remote_ids = file_content.splitlines() remote_ids = list(map(str.strip, remote_ids)) else: remote_ids = (parsed_args.remote_id if parsed_args.remote_id else None) domain_id = None if parsed_args.domain: domain_id = common.find_domain(identity_client, parsed_args.domain).id idp = identity_client.federation.identity_providers.create( id=parsed_args.identity_provider_id, remote_ids=remote_ids, description=parsed_args.description, domain_id=domain_id, enabled=parsed_args.enabled) idp._info.pop('links', None) remote_ids = utils.format_list(idp._info.pop('remote_ids', [])) idp._info['remote_ids'] = remote_ids return zip(*sorted(six.iteritems(idp._info))) class DeleteIdentityProvider(command.Command): _description = _("Delete identity provider(s)") def get_parser(self, prog_name): parser = super(DeleteIdentityProvider, self).get_parser(prog_name) parser.add_argument( 'identity_provider', metavar='', nargs='+', help=_('Identity provider(s) to delete'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity result = 0 for i in parsed_args.identity_provider: try: identity_client.federation.identity_providers.delete(i) except Exception as e: result += 1 LOG.error(_("Failed to delete identity providers with " "name or ID '%(provider)s': %(e)s"), {'provider': i, 'e': e}) if result > 0: total = len(parsed_args.identity_provider) msg = (_("%(result)s of %(total)s identity providers failed" " to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListIdentityProvider(command.Lister): _description = _("List identity providers") def take_action(self, parsed_args): columns = ('ID', 'Enabled', 'Domain ID', 'Description') identity_client = self.app.client_manager.identity data = identity_client.federation.identity_providers.list() return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class SetIdentityProvider(command.Command): _description = _("Set identity provider properties") def get_parser(self, prog_name): parser = super(SetIdentityProvider, self).get_parser(prog_name) parser.add_argument( 'identity_provider', metavar='', help=_('Identity provider to modify'), ) parser.add_argument( '--description', metavar='', help=_('Set identity provider description'), ) identity_remote_id_provider = parser.add_mutually_exclusive_group() identity_remote_id_provider.add_argument( '--remote-id', metavar='', action='append', help=_('Remote IDs to associate with the Identity Provider ' '(repeat option to provide multiple values)'), ) identity_remote_id_provider.add_argument( '--remote-id-file', metavar='', help=_('Name of a file that contains many remote IDs to associate ' 'with the identity provider, one per line'), ) enable_identity_provider = parser.add_mutually_exclusive_group() enable_identity_provider.add_argument( '--enable', action='store_true', help=_('Enable the identity provider'), ) enable_identity_provider.add_argument( '--disable', action='store_true', help=_('Disable the identity provider'), ) return parser def take_action(self, parsed_args): federation_client = self.app.client_manager.identity.federation # Always set remote_ids if either is passed in if parsed_args.remote_id_file: file_content = utils.read_blob_file_contents( parsed_args.remote_id_file) remote_ids = file_content.splitlines() remote_ids = list(map(str.strip, remote_ids)) elif parsed_args.remote_id: remote_ids = parsed_args.remote_id # Setup keyword args for the client kwargs = {} if parsed_args.description: kwargs['description'] = parsed_args.description if parsed_args.enable: kwargs['enabled'] = True if parsed_args.disable: kwargs['enabled'] = False if parsed_args.remote_id_file or parsed_args.remote_id: kwargs['remote_ids'] = remote_ids federation_client.identity_providers.update( parsed_args.identity_provider, **kwargs ) class ShowIdentityProvider(command.ShowOne): _description = _("Display identity provider details") def get_parser(self, prog_name): parser = super(ShowIdentityProvider, self).get_parser(prog_name) parser.add_argument( 'identity_provider', metavar='', help=_('Identity provider to display'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity idp = utils.find_resource( identity_client.federation.identity_providers, parsed_args.identity_provider, id=parsed_args.identity_provider) idp._info.pop('links', None) remote_ids = utils.format_list(idp._info.pop('remote_ids', [])) idp._info['remote_ids'] = remote_ids return zip(*sorted(six.iteritems(idp._info))) python-openstackclient-3.14.0/openstackclient/identity/v3/unscoped_saml.py0000666000175100017510000000350513232364361027115 0ustar zuulzuul00000000000000# 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. # """Identity v3 unscoped SAML auth action implementations. The first step of federated auth is to fetch an unscoped token. From there, the user can list domains and projects they are allowed to access, and request a scoped token.""" from osc_lib.command import command from osc_lib import utils from openstackclient.i18n import _ class ListAccessibleDomains(command.Lister): _description = _("List accessible domains") def take_action(self, parsed_args): columns = ('ID', 'Enabled', 'Name', 'Description') identity_client = self.app.client_manager.identity data = identity_client.federation.domains.list() return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class ListAccessibleProjects(command.Lister): _description = _("List accessible projects") def take_action(self, parsed_args): columns = ('ID', 'Domain ID', 'Enabled', 'Name') identity_client = self.app.client_manager.identity data = identity_client.federation.projects.list() return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) python-openstackclient-3.14.0/openstackclient/identity/v3/catalog.py0000666000175100017510000000601213232364361025667 0ustar zuulzuul00000000000000# 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. # """Identity v3 Service Catalog action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) def _format_endpoints(eps=None): if not eps: return "" ret = '' for ep in eps: region = ep.get('region_id') or ep.get('region') or '' ret += region + '\n' ret += " %s: %s\n" % (ep['interface'], ep['url']) return ret class ListCatalog(command.Lister): _description = _("List services in the service catalog") def take_action(self, parsed_args): # Trigger auth if it has not happened yet auth_ref = self.app.client_manager.auth_ref if not auth_ref: raise exceptions.AuthorizationFailure( "Only an authorized user may issue a new token." ) data = auth_ref.service_catalog.catalog columns = ('Name', 'Type', 'Endpoints') return (columns, (utils.get_dict_properties( s, columns, formatters={ 'Endpoints': _format_endpoints, }, ) for s in data)) class ShowCatalog(command.ShowOne): _description = _("Display service catalog details") def get_parser(self, prog_name): parser = super(ShowCatalog, self).get_parser(prog_name) parser.add_argument( 'service', metavar='', help=_('Service to display (type or name)'), ) return parser def take_action(self, parsed_args): # Trigger auth if it has not happened yet auth_ref = self.app.client_manager.auth_ref if not auth_ref: raise exceptions.AuthorizationFailure( "Only an authorized user may issue a new token." ) data = None for service in auth_ref.service_catalog.catalog: if (service.get('name') == parsed_args.service or service.get('type') == parsed_args.service): data = dict(service) data['endpoints'] = _format_endpoints(data['endpoints']) if 'links' in data: data.pop('links') break if not data: LOG.error(_('service %s not found\n'), parsed_args.service) return ((), ()) return zip(*sorted(six.iteritems(data))) python-openstackclient-3.14.0/openstackclient/identity/v3/service_provider.py0000666000175100017510000001612213232364361027632 0ustar zuulzuul00000000000000# 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. # """Service Provider action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateServiceProvider(command.ShowOne): _description = _("Create new service provider") def get_parser(self, prog_name): parser = super(CreateServiceProvider, self).get_parser(prog_name) parser.add_argument( 'service_provider_id', metavar='', help=_('New service provider name (must be unique)'), ) parser.add_argument( '--auth-url', metavar='', required=True, help=_('Authentication URL of remote federated service provider ' '(required)'), ) parser.add_argument( '--description', metavar='', help=_('New service provider description'), ) parser.add_argument( '--service-provider-url', metavar='', required=True, help=_('A service URL where SAML assertions are being sent ' '(required)'), ) enable_service_provider = parser.add_mutually_exclusive_group() enable_service_provider.add_argument( '--enable', dest='enabled', action='store_true', default=True, help=_('Enable the service provider (default)'), ) enable_service_provider.add_argument( '--disable', dest='enabled', action='store_false', help=_('Disable the service provider'), ) return parser def take_action(self, parsed_args): service_client = self.app.client_manager.identity sp = service_client.federation.service_providers.create( id=parsed_args.service_provider_id, auth_url=parsed_args.auth_url, description=parsed_args.description, enabled=parsed_args.enabled, sp_url=parsed_args.service_provider_url) sp._info.pop('links', None) return zip(*sorted(six.iteritems(sp._info))) class DeleteServiceProvider(command.Command): _description = _("Delete service provider(s)") def get_parser(self, prog_name): parser = super(DeleteServiceProvider, self).get_parser(prog_name) parser.add_argument( 'service_provider', metavar='', nargs='+', help=_('Service provider(s) to delete'), ) return parser def take_action(self, parsed_args): service_client = self.app.client_manager.identity result = 0 for i in parsed_args.service_provider: try: service_client.federation.service_providers.delete(i) except Exception as e: result += 1 LOG.error(_("Failed to delete service provider with " "name or ID '%(provider)s': %(e)s"), {'provider': i, 'e': e}) if result > 0: total = len(parsed_args.service_provider) msg = (_("%(result)s of %(total)s service providers failed" " to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListServiceProvider(command.Lister): _description = _("List service providers") def take_action(self, parsed_args): service_client = self.app.client_manager.identity data = service_client.federation.service_providers.list() column_headers = ('ID', 'Enabled', 'Description', 'Auth URL') return (column_headers, (utils.get_item_properties( s, column_headers, formatters={}, ) for s in data)) class SetServiceProvider(command.Command): _description = _("Set service provider properties") def get_parser(self, prog_name): parser = super(SetServiceProvider, self).get_parser(prog_name) parser.add_argument( 'service_provider', metavar='', help=_('Service provider to modify'), ) parser.add_argument( '--auth-url', metavar='', help=_('New Authentication URL of remote ' 'federated service provider'), ) parser.add_argument( '--description', metavar='', help=_('New service provider description'), ) parser.add_argument( '--service-provider-url', metavar='', help=_('New service provider URL, where SAML assertions are sent'), ) enable_service_provider = parser.add_mutually_exclusive_group() enable_service_provider.add_argument( '--enable', action='store_true', help=_('Enable the service provider'), ) enable_service_provider.add_argument( '--disable', action='store_true', help=_('Disable the service provider'), ) return parser def take_action(self, parsed_args): federation_client = self.app.client_manager.identity.federation enabled = None if parsed_args.enable is True: enabled = True elif parsed_args.disable is True: enabled = False federation_client.service_providers.update( parsed_args.service_provider, enabled=enabled, description=parsed_args.description, auth_url=parsed_args.auth_url, sp_url=parsed_args.service_provider_url, ) class ShowServiceProvider(command.ShowOne): _description = _("Display service provider details") def get_parser(self, prog_name): parser = super(ShowServiceProvider, self).get_parser(prog_name) parser.add_argument( 'service_provider', metavar='', help=_('Service provider to display'), ) return parser def take_action(self, parsed_args): service_client = self.app.client_manager.identity service_provider = utils.find_resource( service_client.federation.service_providers, parsed_args.service_provider, id=parsed_args.service_provider) service_provider._info.pop('links', None) return zip(*sorted(six.iteritems(service_provider._info))) python-openstackclient-3.14.0/openstackclient/identity/v3/federation_protocol.py0000666000175100017510000001655313232364361030331 0ustar zuulzuul00000000000000# 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. # """Identity v3 Protocols actions implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateProtocol(command.ShowOne): _description = _("Create new federation protocol") def get_parser(self, prog_name): parser = super(CreateProtocol, self).get_parser(prog_name) parser.add_argument( 'federation_protocol', metavar='', help=_('New federation protocol name (must be unique ' 'per identity provider)'), ) parser.add_argument( '--identity-provider', metavar='', required=True, help=_('Identity provider that will support the new federation ' ' protocol (name or ID) (required)'), ) parser.add_argument( '--mapping', metavar='', required=True, help=_('Mapping that is to be used (name or ID) (required)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity protocol = identity_client.federation.protocols.create( protocol_id=parsed_args.federation_protocol, identity_provider=parsed_args.identity_provider, mapping=parsed_args.mapping) info = dict(protocol._info) # NOTE(marek-denis): Identity provider is not included in a response # from Keystone, however it should be listed to the user. Add it # manually to the output list, simply reusing value provided by the # user. info['identity_provider'] = parsed_args.identity_provider info['mapping'] = info.pop('mapping_id') info.pop('links', None) return zip(*sorted(six.iteritems(info))) class DeleteProtocol(command.Command): _description = _("Delete federation protocol(s)") def get_parser(self, prog_name): parser = super(DeleteProtocol, self).get_parser(prog_name) parser.add_argument( 'federation_protocol', metavar='', nargs='+', help=_('Federation protocol(s) to delete (name or ID)'), ) parser.add_argument( '--identity-provider', metavar='', required=True, help=_('Identity provider that supports ' '(name or ID) (required)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity result = 0 for i in parsed_args.federation_protocol: try: identity_client.federation.protocols.delete( parsed_args.identity_provider, i) except Exception as e: result += 1 LOG.error(_("Failed to delete federation protocol " "with name or ID '%(protocol)s': %(e)s"), {'protocol': i, 'e': e}) if result > 0: total = len(parsed_args.federation_protocol) msg = (_("%(result)s of %(total)s federation protocols failed" " to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListProtocols(command.Lister): _description = _("List federation protocols") def get_parser(self, prog_name): parser = super(ListProtocols, self).get_parser(prog_name) parser.add_argument( '--identity-provider', metavar='', required=True, help=_('Identity provider to list (name or ID) (required)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity protocols = identity_client.federation.protocols.list( parsed_args.identity_provider) columns = ('id', 'mapping') response_attributes = ('id', 'mapping_id') items = [utils.get_item_properties(s, response_attributes) for s in protocols] return (columns, items) class SetProtocol(command.Command): _description = _("Set federation protocol properties") def get_parser(self, prog_name): parser = super(SetProtocol, self).get_parser(prog_name) parser.add_argument( 'federation_protocol', metavar='', help=_('Federation protocol to modify (name or ID)'), ) parser.add_argument( '--identity-provider', metavar='', required=True, help=_('Identity provider that supports ' '(name or ID) (required)'), ) parser.add_argument( '--mapping', metavar='', help=_('Mapping that is to be used (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity protocol = identity_client.federation.protocols.update( parsed_args.identity_provider, parsed_args.federation_protocol, parsed_args.mapping) info = dict(protocol._info) # NOTE(marek-denis): Identity provider is not included in a response # from Keystone, however it should be listed to the user. Add it # manually to the output list, simply reusing value provided by the # user. info['identity_provider'] = parsed_args.identity_provider info['mapping'] = info.pop('mapping_id') return zip(*sorted(six.iteritems(info))) class ShowProtocol(command.ShowOne): _description = _("Display federation protocol details") def get_parser(self, prog_name): parser = super(ShowProtocol, self).get_parser(prog_name) parser.add_argument( 'federation_protocol', metavar='', help=_('Federation protocol to display (name or ID)'), ) parser.add_argument( '--identity-provider', metavar='', required=True, help=_('Identity provider that supports ' '(name or ID) (required)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity protocol = identity_client.federation.protocols.get( parsed_args.identity_provider, parsed_args.federation_protocol) info = dict(protocol._info) info['mapping'] = info.pop('mapping_id') info.pop('links', None) return zip(*sorted(six.iteritems(info))) python-openstackclient-3.14.0/openstackclient/identity/v3/domain.py0000666000175100017510000001477613232364361025544 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Identity v3 Domain action implementations""" import logging from keystoneauth1 import exceptions as ks_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common LOG = logging.getLogger(__name__) class CreateDomain(command.ShowOne): _description = _("Create new domain") def get_parser(self, prog_name): parser = super(CreateDomain, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('New domain name'), ) parser.add_argument( '--description', metavar='', help=_('New domain description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable domain (default)'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable domain'), ) parser.add_argument( '--or-show', action='store_true', help=_('Return existing domain'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity enabled = True if parsed_args.disable: enabled = False try: domain = identity_client.domains.create( name=parsed_args.name, description=parsed_args.description, enabled=enabled, ) except ks_exc.Conflict: if parsed_args.or_show: domain = utils.find_resource(identity_client.domains, parsed_args.name) LOG.info(_('Returning existing domain %s'), domain.name) else: raise domain._info.pop('links') return zip(*sorted(six.iteritems(domain._info))) class DeleteDomain(command.Command): _description = _("Delete domain(s)") def get_parser(self, prog_name): parser = super(DeleteDomain, self).get_parser(prog_name) parser.add_argument( 'domain', metavar='', nargs='+', help=_('Domain(s) to delete (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity result = 0 for i in parsed_args.domain: try: domain = utils.find_resource(identity_client.domains, i) identity_client.domains.delete(domain.id) except Exception as e: result += 1 LOG.error(_("Failed to delete domain with name or " "ID '%(domain)s': %(e)s"), {'domain': i, 'e': e}) if result > 0: total = len(parsed_args.domain) msg = (_("%(result)s of %(total)s domains failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListDomain(command.Lister): _description = _("List domains") def take_action(self, parsed_args): columns = ('ID', 'Name', 'Enabled', 'Description') data = self.app.client_manager.identity.domains.list() return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class SetDomain(command.Command): _description = _("Set domain properties") def get_parser(self, prog_name): parser = super(SetDomain, self).get_parser(prog_name) parser.add_argument( 'domain', metavar='', help=_('Domain to modify (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('New domain name'), ) parser.add_argument( '--description', metavar='', help=_('New domain description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', help=_('Enable domain'), ) enable_group.add_argument( '--disable', action='store_true', help=_('Disable domain'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity domain = utils.find_resource(identity_client.domains, parsed_args.domain) kwargs = {} if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.description: kwargs['description'] = parsed_args.description if parsed_args.enable: kwargs['enabled'] = True if parsed_args.disable: kwargs['enabled'] = False identity_client.domains.update(domain.id, **kwargs) class ShowDomain(command.ShowOne): _description = _("Display domain details") def get_parser(self, prog_name): parser = super(ShowDomain, self).get_parser(prog_name) parser.add_argument( 'domain', metavar='', help=_('Domain to display (name or ID)'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity domain_str = common._get_token_resource(identity_client, 'domain', parsed_args.domain) domain = utils.find_resource(identity_client.domains, domain_str) domain._info.pop('links') return zip(*sorted(six.iteritems(domain._info))) python-openstackclient-3.14.0/openstackclient/identity/v3/ec2creds.py0000666000175100017510000001616513232364361025761 0ustar zuulzuul00000000000000# 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. """Identity v3 EC2 Credentials action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common LOG = logging.getLogger(__name__) def _determine_ec2_user(parsed_args, client_manager): """Determine a user several different ways. Assumes parsed_args has user and user_domain arguments. Attempts to find the user if domain scoping is provided, otherwise revert to a basic user call. Lastly use the currently authenticated user. """ user_domain = None if parsed_args.user_domain: user_domain = common.find_domain(client_manager.identity, parsed_args.user_domain) if parsed_args.user: if user_domain is not None: user = utils.find_resource(client_manager.identity.users, parsed_args.user, domain_id=user_domain.id).id else: user = utils.find_resource( client_manager.identity.users, parsed_args.user).id else: # Get the user from the current auth user = client_manager.auth_ref.user_id return user class CreateEC2Creds(command.ShowOne): _description = _("Create EC2 credentials") def get_parser(self, prog_name): parser = super(CreateEC2Creds, self).get_parser(prog_name) parser.add_argument( '--project', metavar='', help=_('Create credentials in project ' '(name or ID; default: current authenticated project)'), ) parser.add_argument( '--user', metavar='', help=_('Create credentials for user ' '(name or ID; default: current authenticated user)'), ) common.add_user_domain_option_to_parser(parser) common.add_project_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity client_manager = self.app.client_manager user = _determine_ec2_user(parsed_args, client_manager) project_domain = None if parsed_args.project_domain: project_domain = common.find_domain(identity_client, parsed_args.project_domain) if parsed_args.project: if project_domain is not None: project = utils.find_resource(identity_client.projects, parsed_args.project, domain_id=project_domain.id).id else: project = utils.find_resource( identity_client.projects, parsed_args.project).id else: # Get the project from the current auth project = self.app.client_manager.auth_ref.project_id creds = identity_client.ec2.create(user, project) info = {} info.update(creds._info) if 'tenant_id' in info: info.update( {'project_id': info.pop('tenant_id')} ) return zip(*sorted(six.iteritems(info))) class DeleteEC2Creds(command.Command): _description = _("Delete EC2 credentials") def get_parser(self, prog_name): parser = super(DeleteEC2Creds, self).get_parser(prog_name) parser.add_argument( 'access_key', metavar='', nargs='+', help=_('Credentials access key(s)'), ) parser.add_argument( '--user', metavar='', help=_('Delete credentials for user (name or ID)'), ) common.add_user_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): client_manager = self.app.client_manager user = _determine_ec2_user(parsed_args, client_manager) result = 0 for i in parsed_args.access_key: try: client_manager.identity.ec2.delete(user, i) except Exception as e: result += 1 LOG.error(_("Failed to delete EC2 credentials with " "access key '%(access_key)s': %(e)s"), {'access_key': i, 'e': e}) if result > 0: total = len(parsed_args.access_key) msg = (_("%(result)s of %(total)s EC2 keys failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListEC2Creds(command.Lister): _description = _("List EC2 credentials") def get_parser(self, prog_name): parser = super(ListEC2Creds, self).get_parser(prog_name) parser.add_argument( '--user', metavar='', help=_('Filter list by user (name or ID)'), ) common.add_user_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): client_manager = self.app.client_manager user = _determine_ec2_user(parsed_args, client_manager) columns = ('access', 'secret', 'tenant_id', 'user_id') column_headers = ('Access', 'Secret', 'Project ID', 'User ID') data = client_manager.identity.ec2.list(user) return (column_headers, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class ShowEC2Creds(command.ShowOne): _description = _("Display EC2 credentials details") def get_parser(self, prog_name): parser = super(ShowEC2Creds, self).get_parser(prog_name) parser.add_argument( 'access_key', metavar='', help=_('Credentials access key'), ) parser.add_argument( '--user', metavar='', help=_('Show credentials for user (name or ID)'), ) common.add_user_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): client_manager = self.app.client_manager user = _determine_ec2_user(parsed_args, client_manager) creds = client_manager.identity.ec2.get(user, parsed_args.access_key) info = {} info.update(creds._info) if 'tenant_id' in info: info.update( {'project_id': info.pop('tenant_id')} ) return zip(*sorted(six.iteritems(info))) python-openstackclient-3.14.0/openstackclient/identity/v3/__init__.py0000666000175100017510000000000013232364361026003 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/identity/v3/consumer.py0000666000175100017510000001114013232364361026106 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Identity v3 Consumer action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateConsumer(command.ShowOne): _description = _("Create new consumer") def get_parser(self, prog_name): parser = super(CreateConsumer, self).get_parser(prog_name) parser.add_argument( '--description', metavar='', help=_('New consumer description'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity consumer = identity_client.oauth1.consumers.create( parsed_args.description ) consumer._info.pop('links', None) return zip(*sorted(six.iteritems(consumer._info))) class DeleteConsumer(command.Command): _description = _("Delete consumer(s)") def get_parser(self, prog_name): parser = super(DeleteConsumer, self).get_parser(prog_name) parser.add_argument( 'consumer', metavar='', nargs='+', help=_('Consumer(s) to delete'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity result = 0 for i in parsed_args.consumer: try: consumer = utils.find_resource( identity_client.oauth1.consumers, i) identity_client.oauth1.consumers.delete(consumer.id) except Exception as e: result += 1 LOG.error(_("Failed to delete consumer with name or " "ID '%(consumer)s': %(e)s"), {'consumer': i, 'e': e}) if result > 0: total = len(parsed_args.consumer) msg = (_("%(result)s of %(total)s consumers failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListConsumer(command.Lister): _description = _("List consumers") def take_action(self, parsed_args): columns = ('ID', 'Description') data = self.app.client_manager.identity.oauth1.consumers.list() return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data)) class SetConsumer(command.Command): _description = _("Set consumer properties") def get_parser(self, prog_name): parser = super(SetConsumer, self).get_parser(prog_name) parser.add_argument( 'consumer', metavar='', help=_('Consumer to modify'), ) parser.add_argument( '--description', metavar='', help=_('New consumer description'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity consumer = utils.find_resource( identity_client.oauth1.consumers, parsed_args.consumer) kwargs = {} if parsed_args.description: kwargs['description'] = parsed_args.description consumer = identity_client.oauth1.consumers.update( consumer.id, **kwargs) class ShowConsumer(command.ShowOne): _description = _("Display consumer details") def get_parser(self, prog_name): parser = super(ShowConsumer, self).get_parser(prog_name) parser.add_argument( 'consumer', metavar='', help=_('Consumer to display'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity consumer = utils.find_resource( identity_client.oauth1.consumers, parsed_args.consumer) consumer._info.pop('links', None) return zip(*sorted(six.iteritems(consumer._info))) python-openstackclient-3.14.0/openstackclient/identity/__init__.py0000666000175100017510000000000013232364361025453 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/api/0000775000175100017510000000000013232364654022277 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/api/image_v2.py0000666000175100017510000000453513232364361024346 0ustar zuulzuul00000000000000# 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. # """Image v2 API Library""" from openstackclient.api import image_v1 class APIv2(image_v1.APIv1): """Image v2 API""" _endpoint_suffix = '/v2' def _munge_url(self): # Hack this until discovery is up, and ignore parent endpoint setting if not self.endpoint.endswith(self._endpoint_suffix): self.endpoint = self.endpoint + self._endpoint_suffix def image_list( self, detailed=False, public=False, private=False, shared=False, **filter ): """Get available images can add limit/marker :param detailed: For v1 compatibility only, ignored as v2 is always 'detailed' :param public: Return public images if True :param private: Return private images if True :param shared: Return shared images if True If public, private and shared are all True or all False then all images are returned. All arguments False is equivalent to no filter and all images are returned. All arguments True is a filter that includes all public, private and shared images which is the same set as all images. http://docs.openstack.org/api/openstack-image-service/2.0/content/list-images.html """ if not public and not private and not shared: # No filtering for all False filter.pop('visibility', None) elif public: filter['visibility'] = 'public' elif private: filter['visibility'] = 'private' elif shared: filter['visibility'] = 'shared' url = "/images" if detailed: # Because we can't all use /details url += "/detail" return self.list(url, **filter)['images'] python-openstackclient-3.14.0/openstackclient/api/utils.py0000666000175100017510000000607113232364361024012 0ustar zuulzuul00000000000000# 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. # """API Utilities Library""" def simple_filter( data=None, attr=None, value=None, property_field=None, ): """Filter a list of dicts :param list data: The list to be filtered. The list is modified in-place and will be changed if any filtering occurs. :param string attr: The name of the attribute to filter. If attr does not exist no match will succeed and no rows will be returned. If attr is None no filtering will be performed and all rows will be returned. :param string value: The value to filter. None is considered to be a 'no filter' value. '' matches against a Python empty string. :param string property_field: The name of the data field containing a property dict to filter. If property_field is None, attr is a field name. If property_field is not None, attr is a property key name inside the named property field. :returns: Returns the filtered list :rtype list: This simple filter (one attribute, one exact-match value) searches a list of dicts to select items. It first searches the item dict for a matching ``attr`` then does an exact-match on the ``value``. If ``property_field`` is given, it will look inside that field (if it exists and is a dict) for a matching ``value``. """ # Take the do-nothing case shortcut if not data or not attr or value is None: return data # NOTE:(dtroyer): This filter modifies the provided list in-place using # list.remove() so we need to start at the end so the loop pointer does # not skip any items after a deletion. for d in reversed(data): if attr in d: # Searching data fields search_value = d[attr] elif (property_field and property_field in d and isinstance(d[property_field], dict)): # Searching a properties field - do this separately because # we don't want to fail over to checking the fields if a # property name is given. if attr in d[property_field]: search_value = d[property_field][attr] else: search_value = None else: search_value = None # could do regex here someday... if not search_value or search_value != value: # remove from list try: data.remove(d) except ValueError: # it's already gone! pass return data python-openstackclient-3.14.0/openstackclient/api/compute_v2.py0000666000175100017510000003105013232364361024730 0ustar zuulzuul00000000000000# 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. # """Compute v2 API Library""" from keystoneauth1 import exceptions as ksa_exceptions from osc_lib.api import api from osc_lib import exceptions from osc_lib.i18n import _ # TODO(dtroyer): Mingrate this to osc-lib class InvalidValue(Exception): """An argument value is not valid: wrong type, out of range, etc""" message = "Supplied value is not valid" class APIv2(api.BaseAPI): """Compute v2 API""" def __init__(self, **kwargs): super(APIv2, self).__init__(**kwargs) # Overrides def _check_integer(self, value, msg=None): """Attempt to convert value to an integer Raises InvalidValue on failure :param value: Convert this to an integer. None is converted to 0 (zero). :param msg: An alternate message for the exception, must include exactly one substitution to receive the attempted value. """ if value is None: return 0 try: value = int(value) except (TypeError, ValueError): if not msg: msg = "%s is not an integer" % value raise InvalidValue(msg) return value # TODO(dtroyer): Override find() until these fixes get into an osc-lib # minimum release def find( self, path, value=None, attr=None, ): """Find a single resource by name or ID :param string path: The API-specific portion of the URL path :param string value: search expression (required, really) :param string attr: name of attribute for secondary search """ try: ret = self._request('GET', "/%s/%s" % (path, value)).json() if isinstance(ret, dict): # strip off the enclosing dict key = list(ret.keys())[0] ret = ret[key] except ( ksa_exceptions.NotFound, ksa_exceptions.BadRequest, ): kwargs = {attr: value} try: ret = self.find_one(path, **kwargs) except ksa_exceptions.NotFound: msg = _("%s not found") % value raise exceptions.NotFound(msg) return ret # Flaoting IPs def floating_ip_create( self, pool=None, ): """Create a new floating ip https://developer.openstack.org/api-ref/compute/#create-allocate-floating-ip-address :param pool: Name of floating IP pool """ url = "/os-floating-ips" try: return self.create( url, json={'pool': pool}, )['floating_ip'] except ( ksa_exceptions.NotFound, ksa_exceptions.BadRequest, ): msg = _("%s not found") % pool raise exceptions.NotFound(msg) def floating_ip_delete( self, floating_ip_id=None, ): """Delete a floating IP https://developer.openstack.org/api-ref/compute/#delete-deallocate-floating-ip-address :param string floating_ip_id: Floating IP ID """ url = "/os-floating-ips" if floating_ip_id is not None: return self.delete('/%s/%s' % (url, floating_ip_id)) return None def floating_ip_find( self, floating_ip=None, ): """Return a security group given name or ID https://developer.openstack.org/api-ref/compute/#list-floating-ip-addresses :param string floating_ip: Floating IP address :returns: A dict of the floating IP attributes """ url = "/os-floating-ips" return self.find( url, attr='ip', value=floating_ip, ) def floating_ip_list( self, ): """Get floating IPs https://developer.openstack.org/api-ref/compute/#show-floating-ip-address-details :returns: list of floating IPs """ url = "/os-floating-ips" return self.list(url)["floating_ips"] # Floating IP Pools def floating_ip_pool_list( self, ): """Get floating IP pools https://developer.openstack.org/api-ref/compute/?expanded=#list-floating-ip-pools :returns: list of floating IP pools """ url = "/os-floating-ip-pools" return self.list(url)["floating_ip_pools"] # Networks def network_create( self, name=None, subnet=None, share_subnet=None, ): """Create a new network https://developer.openstack.org/api-ref/compute/#create-network :param string name: Network label (required) :param integer subnet: Subnet for IPv4 fixed addresses in CIDR notation (required) :param integer share_subnet: Shared subnet between projects, True or False :returns: A dict of the network attributes """ url = "/os-networks" params = { 'label': name, 'cidr': subnet, } if share_subnet is not None: params['share_address'] = share_subnet return self.create( url, json={'network': params}, )['network'] def network_delete( self, network=None, ): """Delete a network https://developer.openstack.org/api-ref/compute/#delete-network :param string network: Network name or ID """ url = "/os-networks" network = self.find( url, attr='label', value=network, )['id'] if network is not None: return self.delete('/%s/%s' % (url, network)) return None def network_find( self, network=None, ): """Return a network given name or ID https://developer.openstack.org/api-ref/compute/#show-network-details :param string network: Network name or ID :returns: A dict of the network attributes """ url = "/os-networks" return self.find( url, attr='label', value=network, ) def network_list( self, ): """Get networks https://developer.openstack.org/api-ref/compute/#list-networks :returns: list of networks """ url = "/os-networks" return self.list(url)["networks"] # Security Groups def security_group_create( self, name=None, description=None, ): """Create a new security group https://developer.openstack.org/api-ref/compute/#create-security-group :param string name: Security group name :param integer description: Security group description """ url = "/os-security-groups" params = { 'name': name, 'description': description, } return self.create( url, json={'security_group': params}, )['security_group'] def security_group_delete( self, security_group=None, ): """Delete a security group https://developer.openstack.org/api-ref/compute/#delete-security-group :param string security_group: Security group name or ID """ url = "/os-security-groups" security_group = self.find( url, attr='name', value=security_group, )['id'] if security_group is not None: return self.delete('/%s/%s' % (url, security_group)) return None def security_group_find( self, security_group=None, ): """Return a security group given name or ID https://developer.openstack.org/api-ref/compute/#show-security-group-details :param string security_group: Security group name or ID :returns: A dict of the security group attributes """ url = "/os-security-groups" return self.find( url, attr='name', value=security_group, ) def security_group_list( self, limit=None, marker=None, search_opts=None, ): """Get security groups https://developer.openstack.org/api-ref/compute/#list-security-groups :param integer limit: query return count limit :param string marker: query marker :param search_opts: (undocumented) Search filter dict all_tenants: True|False - return all projects :returns: list of security groups names """ params = {} if search_opts is not None: params = dict((k, v) for (k, v) in search_opts.items() if v) if limit: params['limit'] = limit if marker: params['offset'] = marker url = "/os-security-groups" return self.list(url, **params)["security_groups"] def security_group_set( self, security_group=None, # name=None, # description=None, **params ): """Update a security group https://developer.openstack.org/api-ref/compute/#update-security-group :param string security_group: Security group name or ID TODO(dtroyer): Create an update method in osc-lib """ # Short-circuit no-op if params is None: return None url = "/os-security-groups" security_group = self.find( url, attr='name', value=security_group, ) if security_group is not None: for (k, v) in params.items(): # Only set a value if it is already present if k in security_group: security_group[k] = v return self._request( "PUT", "/%s/%s" % (url, security_group['id']), json={'security_group': security_group}, ).json()['security_group'] return None # Security Group Rules def security_group_rule_create( self, security_group_id=None, ip_protocol=None, from_port=None, to_port=None, remote_ip=None, remote_group=None, ): """Create a new security group rule https://developer.openstack.org/api-ref/compute/#create-security-group-rule :param string security_group_id: Security group ID :param ip_protocol: IP protocol, 'tcp', 'udp' or 'icmp' :param from_port: Source port :param to_port: Destination port :param remote_ip: Source IP address in CIDR notation :param remote_group: Remote security group """ url = "/os-security-group-rules" if ip_protocol.lower() not in ['icmp', 'tcp', 'udp']: raise InvalidValue( "%(s) is not one of 'icmp', 'tcp', or 'udp'" % ip_protocol ) params = { 'parent_group_id': security_group_id, 'ip_protocol': ip_protocol, 'from_port': self._check_integer(from_port), 'to_port': self._check_integer(to_port), 'cidr': remote_ip, 'group_id': remote_group, } return self.create( url, json={'security_group_rule': params}, )['security_group_rule'] def security_group_rule_delete( self, security_group_rule_id=None, ): """Delete a security group rule https://developer.openstack.org/api-ref/compute/#delete-security-group-rule :param string security_group_rule_id: Security group rule ID """ url = "/os-security-group-rules" if security_group_rule_id is not None: return self.delete('/%s/%s' % (url, security_group_rule_id)) return None python-openstackclient-3.14.0/openstackclient/api/object_store_v1.py0000666000175100017510000004216413232364361025745 0ustar zuulzuul00000000000000# 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. # """Object Store v1 API Library""" import io import logging import os import sys from osc_lib import utils import six from six.moves import urllib from openstackclient.api import api class APIv1(api.BaseAPI): """Object Store v1 API""" def __init__(self, **kwargs): super(APIv1, self).__init__(**kwargs) def container_create( self, container=None, ): """Create a container :param string container: name of container to create :returns: dict of returned headers """ response = self.create(urllib.parse.quote(container), method='PUT') data = { 'account': self._find_account_id(), 'container': container, 'x-trans-id': response.headers.get('x-trans-id'), } return data def container_delete( self, container=None, ): """Delete a container :param string container: name of container to delete """ if container: self.delete(urllib.parse.quote(container)) def container_list( self, all_data=False, limit=None, marker=None, end_marker=None, prefix=None, **params ): """Get containers in an account :param boolean all_data: if True, return a full listing, else returns a max of 10000 listings :param integer limit: query return count limit :param string marker: query marker :param string end_marker: query end_marker :param string prefix: query prefix :returns: list of container names """ params['format'] = 'json' if all_data: data = listing = self.container_list( limit=limit, marker=marker, end_marker=end_marker, prefix=prefix, **params ) while listing: marker = listing[-1]['name'] listing = self.container_list( limit=limit, marker=marker, end_marker=end_marker, prefix=prefix, **params ) if listing: data.extend(listing) return data if limit: params['limit'] = limit if marker: params['marker'] = marker if end_marker: params['end_marker'] = end_marker if prefix: params['prefix'] = prefix return self.list('', **params) def container_save( self, container=None, ): """Save all the content from a container :param string container: name of container to save """ objects = self.object_list(container=container) for object in objects: self.object_save(container=container, object=object['name']) def container_set( self, container, properties, ): """Set container properties :param string container: name of container to modify :param dict properties: properties to add or update for the container """ headers = self._set_properties(properties, 'X-Container-Meta-%s') if headers: self.create(urllib.parse.quote(container), headers=headers) def container_show( self, container=None, ): """Get container details :param string container: name of container to show :returns: dict of returned headers """ response = self._request('HEAD', urllib.parse.quote(container)) data = { 'account': self._find_account_id(), 'container': container, 'object_count': response.headers.get( 'x-container-object-count' ), 'bytes_used': response.headers.get('x-container-bytes-used') } if 'x-container-read' in response.headers: data['read_acl'] = response.headers.get('x-container-read') if 'x-container-write' in response.headers: data['write_acl'] = response.headers.get('x-container-write') if 'x-container-sync-to' in response.headers: data['sync_to'] = response.headers.get('x-container-sync-to') if 'x-container-sync-key' in response.headers: data['sync_key'] = response.headers.get('x-container-sync-key') properties = self._get_properties(response.headers, 'x-container-meta-') if properties: data['properties'] = properties return data def container_unset( self, container, properties, ): """Unset container properties :param string container: name of container to modify :param dict properties: properties to remove from the container """ headers = self._unset_properties(properties, 'X-Remove-Container-Meta-%s') if headers: self.create(urllib.parse.quote(container), headers=headers) def object_create( self, container=None, object=None, name=None, ): """Create an object inside a container :param string container: name of container to store object :param string object: local path to object :param string name: name of object to create :returns: dict of returned headers """ if container is None or object is None: # TODO(dtroyer): What exception to raise here? return {} # For uploading a file, if name is provided then set it as the # object's name in the container. object_name_str = name if name else object full_url = "%s/%s" % (urllib.parse.quote(container), urllib.parse.quote(object_name_str)) with io.open(object, 'rb') as f: response = self.create( full_url, method='PUT', data=f, ) data = { 'account': self._find_account_id(), 'container': container, 'object': object_name_str, 'x-trans-id': response.headers.get('X-Trans-Id'), 'etag': response.headers.get('Etag'), } return data def object_delete( self, container=None, object=None, ): """Delete an object from a container :param string container: name of container that stores object :param string object: name of object to delete """ if container is None or object is None: return self.delete("%s/%s" % (urllib.parse.quote(container), urllib.parse.quote(object))) def object_list( self, container=None, all_data=False, limit=None, marker=None, end_marker=None, delimiter=None, prefix=None, **params ): """List objects in a container :param string container: container name to get a listing for :param boolean all_data: if True, return a full listing, else returns a max of 10000 listings :param integer limit: query return count limit :param string marker: query marker :param string end_marker: query end_marker :param string prefix: query prefix :param string delimiter: string to delimit the queries on :returns: a tuple of (response headers, a list of objects) The response headers will be a dict and all header names will be lowercase. """ if container is None or object is None: return None params['format'] = 'json' if all_data: data = listing = self.object_list( container=container, limit=limit, marker=marker, end_marker=end_marker, prefix=prefix, delimiter=delimiter, **params ) while listing: if delimiter: marker = listing[-1].get('name', listing[-1].get('subdir')) else: marker = listing[-1]['name'] listing = self.object_list( container=container, limit=limit, marker=marker, end_marker=end_marker, prefix=prefix, delimiter=delimiter, **params ) if listing: data.extend(listing) return data if limit: params['limit'] = limit if marker: params['marker'] = marker if end_marker: params['end_marker'] = end_marker if prefix: params['prefix'] = prefix if delimiter: params['delimiter'] = delimiter return self.list(urllib.parse.quote(container), **params) def object_save( self, container=None, object=None, file=None, ): """Save an object stored in a container :param string container: name of container that stores object :param string object: name of object to save :param string file: local name of object """ if not file: file = object response = self._request( 'GET', "%s/%s" % (urllib.parse.quote(container), urllib.parse.quote(object)), stream=True, ) if response.status_code == 200: if file == '-': for chunk in response.iter_content(64 * 1024): sys.stdout.write(chunk) else: if not os.path.exists(os.path.dirname(file)): if len(os.path.dirname(file)) > 0: os.makedirs(os.path.dirname(file)) with open(file, 'wb') as f: for chunk in response.iter_content(64 * 1024): f.write(chunk) def object_set( self, container, object, properties, ): """Set object properties :param string container: container name for object to modify :param string object: name of object to modify :param dict properties: properties to add or update for the container """ headers = self._set_properties(properties, 'X-Object-Meta-%s') if headers: self.create("%s/%s" % (urllib.parse.quote(container), urllib.parse.quote(object)), headers=headers) def object_unset( self, container, object, properties, ): """Unset object properties :param string container: container name for object to modify :param string object: name of object to modify :param dict properties: properties to remove from the object """ headers = self._unset_properties(properties, 'X-Remove-Object-Meta-%s') if headers: self.create("%s/%s" % (urllib.parse.quote(container), urllib.parse.quote(object)), headers=headers) def object_show( self, container=None, object=None, ): """Get object details :param string container: container name for object to get :param string object: name of object to get :returns: dict of object properties """ if container is None or object is None: return {} response = self._request('HEAD', "%s/%s" % (urllib.parse.quote(container), urllib.parse.quote(object))) data = { 'account': self._find_account_id(), 'container': container, 'object': object, 'content-type': response.headers.get('content-type'), } if 'content-length' in response.headers: data['content-length'] = response.headers.get( 'content-length' ) if 'last-modified' in response.headers: data['last-modified'] = response.headers.get('last-modified') if 'etag' in response.headers: data['etag'] = response.headers.get('etag') if 'x-object-manifest' in response.headers: data['x-object-manifest'] = response.headers.get( 'x-object-manifest' ) properties = self._get_properties(response.headers, 'x-object-meta-') if properties: data['properties'] = properties return data def account_set( self, properties, ): """Set account properties :param dict properties: properties to add or update for the account """ headers = self._set_properties(properties, 'X-Account-Meta-%s') if headers: # NOTE(stevemar): The URL (first argument) in this case is already # set to the swift account endpoint, because that's how it's # registered in the catalog self.create("", headers=headers) def account_show(self): """Show account details""" # NOTE(stevemar): Just a HEAD request to the endpoint already in the # catalog should be enough. response = self._request("HEAD", "") data = {} properties = self._get_properties(response.headers, 'x-account-meta-') if properties: data['properties'] = properties # Map containers, bytes and objects a bit nicer data['Containers'] = response.headers.get('x-account-container-count') data['Objects'] = response.headers.get('x-account-object-count') data['Bytes'] = response.headers.get('x-account-bytes-used') # Add in Account info too data['Account'] = self._find_account_id() return data def account_unset( self, properties, ): """Unset account properties :param dict properties: properties to remove from the account """ headers = self._unset_properties(properties, 'X-Remove-Account-Meta-%s') if headers: self.create("", headers=headers) def _find_account_id(self): url_parts = urllib.parse.urlparse(self.endpoint) return url_parts.path.split('/')[-1] def _unset_properties(self, properties, header_tag): # NOTE(stevemar): As per the API, the headers have to be in the form # of "X-Remove-Account-Meta-Book: x". In the case where metadata is # removed, we can set the value of the header to anything, so it's # set to 'x'. In the case of a Container property we use: # "X-Remove-Container-Meta-Book: x", and the same logic applies for # Object properties headers = {} for k in properties: header_name = header_tag % k headers[header_name] = 'x' return headers def _set_properties(self, properties, header_tag): # NOTE(stevemar): As per the API, the headers have to be in the form # of "X-Account-Meta-Book: MobyDick". In the case of a Container # property we use: "X-Add-Container-Meta-Book: MobyDick", and the same # logic applies for Object properties log = logging.getLogger(__name__ + '._set_properties') headers = {} for k, v in six.iteritems(properties): if not utils.is_ascii(k) or not utils.is_ascii(v): log.error('Cannot set property %s to non-ascii value', k) continue header_name = header_tag % k headers[header_name] = v return headers def _get_properties(self, headers, header_tag): # Add in properties as a top level key, this is consistent with other # OSC commands properties = {} for k, v in six.iteritems(headers): if k.lower().startswith(header_tag): properties[k[len(header_tag):]] = v return properties python-openstackclient-3.14.0/openstackclient/api/auth_plugin.py0000666000175100017510000000355413232364361025174 0ustar zuulzuul00000000000000# 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. # """Authentication Plugin Library""" from keystoneauth1 import loading from keystoneauth1 import token_endpoint from openstackclient.i18n import _ class TokenEndpoint(loading.BaseLoader): """Auth plugin to handle traditional token/endpoint usage Keystoneauth contains a Token plugin class that now correctly handles the token/endpoint auth compatible with OSC. However, the AdminToken loader deprecates the 'url' argument, which breaks OSC compatibility, so make one that works. """ @property def plugin_class(self): return token_endpoint.Token def load_from_options(self, url, token, **kwargs): """A plugin for static authentication with an existing token :param string url: Service endpoint :param string token: Existing token """ return super(TokenEndpoint, self).load_from_options( endpoint=url, token=token, ) def get_options(self): """Return the legacy options""" options = [ loading.Opt( 'url', help=_('Specific service endpoint to use'), ), loading.Opt( 'token', secret=True, help=_('Authentication token to use'), ), ] return options python-openstackclient-3.14.0/openstackclient/api/api.py0000666000175100017510000002373513232364361023431 0ustar zuulzuul00000000000000# 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. # """Base API Library""" import simplejson as json from keystoneauth1 import exceptions as ks_exceptions from keystoneauth1 import session as ks_session from osc_lib import exceptions from openstackclient.i18n import _ class KeystoneSession(object): """Wrapper for the Keystone Session Restore some requests.session.Session compatibility; keystoneauth1.session.Session.request() has the method and url arguments swapped from the rest of the requests-using world. """ def __init__( self, session=None, endpoint=None, **kwargs ): """Base object that contains some common API objects and methods :param Session session: The default session to be used for making the HTTP API calls. :param string endpoint: The URL from the Service Catalog to be used as the base for API requests on this API. """ super(KeystoneSession, self).__init__() # a requests.Session-style interface self.session = session self.endpoint = endpoint def _request(self, method, url, session=None, **kwargs): """Perform call into session All API calls are funneled through this method to provide a common place to finalize the passed URL and other things. :param string method: The HTTP method name, i.e. ``GET``, ``PUT``, etc :param string url: The API-specific portion of the URL path :param Session session: HTTP client session :param kwargs: keyword arguments passed to requests.request(). :return: the requests.Response object """ if not session: session = self.session if not session: session = ks_session.Session() if self.endpoint: if url: url = '/'.join([self.endpoint.rstrip('/'), url.lstrip('/')]) else: url = self.endpoint.rstrip('/') # Why is ksc session backwards??? return session.request(url, method, **kwargs) class BaseAPI(KeystoneSession): """Base API""" def __init__( self, session=None, service_type=None, endpoint=None, **kwargs ): """Base object that contains some common API objects and methods :param Session session: The default session to be used for making the HTTP API calls. :param string service_type: API name, i.e. ``identity`` or ``compute`` :param string endpoint: The URL from the Service Catalog to be used as the base for API requests on this API. """ super(BaseAPI, self).__init__(session=session, endpoint=endpoint) self.service_type = service_type # The basic action methods all take a Session and return dict/lists def create( self, url, session=None, method=None, **params ): """Create a new resource :param string url: The API-specific portion of the URL path :param Session session: HTTP client session :param string method: HTTP method (default POST) """ if not method: method = 'POST' ret = self._request(method, url, session=session, **params) # Should this move into _requests()? try: return ret.json() except json.JSONDecodeError: return ret def delete( self, url, session=None, **params ): """Delete a resource :param string url: The API-specific portion of the URL path :param Session session: HTTP client session """ return self._request('DELETE', url, **params) def list( self, path, session=None, body=None, detailed=False, **params ): """Return a list of resources GET ${ENDPOINT}/${PATH}?${PARAMS} path is often the object's plural resource type :param string path: The API-specific portion of the URL path :param Session session: HTTP client session :param body: data that will be encoded as JSON and passed in POST request (GET will be sent by default) :param bool detailed: Adds '/details' to path for some APIs to return extended attributes :returns: JSON-decoded response, could be a list or a dict-wrapped-list """ if detailed: path = '/'.join([path.rstrip('/'), 'details']) if body: ret = self._request( 'POST', path, # service=self.service_type, json=body, params=params, ) else: ret = self._request( 'GET', path, # service=self.service_type, params=params, ) try: return ret.json() except json.JSONDecodeError: return ret # Layered actions built on top of the basic action methods do not # explicitly take a Session but one may still be passed in kwargs def find_attr( self, path, value=None, attr=None, resource=None, ): """Find a resource via attribute or ID Most APIs return a list wrapped by a dict with the resource name as key. Some APIs (Identity) return a dict when a query string is present and there is one return value. Take steps to unwrap these bodies and return a single dict without any resource wrappers. :param string path: The API-specific portion of the URL path :param string value: value to search for :param string attr: attribute to use for resource search :param string resource: plural of the object resource name; defaults to path For example: n = find(netclient, 'network', 'networks', 'matrix') """ # Default attr is 'name' if attr is None: attr = 'name' # Default resource is path - in many APIs they are the same if resource is None: resource = path def getlist(kw): """Do list call, unwrap resource dict if present""" ret = self.list(path, **kw) if isinstance(ret, dict) and resource in ret: ret = ret[resource] return ret # Search by attribute kwargs = {attr: value} data = getlist(kwargs) if isinstance(data, dict): return data if len(data) == 1: return data[0] if len(data) > 1: msg = _("Multiple %(resource)s exist with %(attr)s='%(value)s'") raise exceptions.CommandError( msg % {'resource': resource, 'attr': attr, 'value': value} ) # Search by id kwargs = {'id': value} data = getlist(kwargs) if len(data) == 1: return data[0] msg = _("No %(resource)s with a %(attr)s or ID of '%(value)s' found") raise exceptions.CommandError( msg % {'resource': resource, 'attr': attr, 'value': value} ) def find_bulk( self, path, **kwargs ): """Bulk load and filter locally :param string path: The API-specific portion of the URL path :param kwargs: A dict of AVPs to match - logical AND :returns: list of resource dicts """ items = self.list(path) if isinstance(items, dict): # strip off the enclosing dict key = list(items.keys())[0] items = items[key] ret = [] for o in items: try: if all(o[attr] == kwargs[attr] for attr in kwargs.keys()): ret.append(o) except KeyError: continue return ret def find_one( self, path, **kwargs ): """Find a resource by name or ID :param string path: The API-specific portion of the URL path :returns: resource dict """ bulk_list = self.find_bulk(path, **kwargs) num_bulk = len(bulk_list) if num_bulk == 0: msg = _("none found") raise exceptions.NotFound(msg) elif num_bulk > 1: msg = _("many found") raise RuntimeError(msg) return bulk_list[0] def find( self, path, value=None, attr=None, ): """Find a single resource by name or ID :param string path: The API-specific portion of the URL path :param string value: search expression :param string attr: name of attribute for secondary search """ try: ret = self._request('GET', "/%s/%s" % (path, value)).json() except ks_exceptions.NotFound: kwargs = {attr: value} try: ret = self.find_one("/%s/detail" % (path), **kwargs) except ks_exceptions.NotFound: msg = _("%s not found") % value raise exceptions.NotFound(msg) return ret python-openstackclient-3.14.0/openstackclient/api/image_v1.py0000666000175100017510000000510313232364361024335 0ustar zuulzuul00000000000000# 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. # """Image v1 API Library""" from openstackclient.api import api class APIv1(api.BaseAPI): """Image v1 API""" _endpoint_suffix = '/v1' def __init__(self, endpoint=None, **kwargs): super(APIv1, self).__init__(endpoint=endpoint, **kwargs) self.endpoint = self.endpoint.rstrip('/') self._munge_url() def _munge_url(self): # Hack this until discovery is up if not self.endpoint.endswith(self._endpoint_suffix): self.endpoint = self.endpoint + self._endpoint_suffix def image_list( self, detailed=False, public=False, private=False, **filter ): """Get available images :param detailed: Retrieve detailed response from server if True :param public: Return public images if True :param private: Return private images if True If public and private are both True or both False then all images are returned. Both arguments False is equivalent to no filter and all images are returned. Both arguments True is a filter that includes both public and private images which is the same set as all images. http://docs.openstack.org/api/openstack-image-service/1.1/content/requesting-a-list-of-public-vm-images.html http://docs.openstack.org/api/openstack-image-service/1.1/content/requesting-detailed-metadata-on-public-vm-images.html http://docs.openstack.org/api/openstack-image-service/1.1/content/filtering-images-returned-via-get-images-and-get-imagesdetail.html """ url = "/images" if detailed or public or private: # Because we can't all use /details url += "/detail" image_list = self.list(url, **filter)['images'] if public != private: # One is True and one is False, so public represents the filter # state in either case image_list = [i for i in image_list if i['is_public'] == public] return image_list python-openstackclient-3.14.0/openstackclient/api/__init__.py0000666000175100017510000000000013232364361024373 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/volume/0000775000175100017510000000000013232364654023035 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/volume/v1/0000775000175100017510000000000013232364654023363 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/volume/v1/service.py0000666000175100017510000001010213232364361025364 0ustar zuulzuul00000000000000# # 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. # """Service action implementations""" from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ class ListService(command.Lister): _description = _("List service command") def get_parser(self, prog_name): parser = super(ListService, self).get_parser(prog_name) parser.add_argument( "--host", metavar="", help=_("List services on specified host (name only)") ) parser.add_argument( "--service", metavar="", help=_("List only specified service (name only)") ) parser.add_argument( "--long", action="store_true", default=False, help=_("List additional fields in output") ) return parser def take_action(self, parsed_args): service_client = self.app.client_manager.volume if parsed_args.long: columns = [ "Binary", "Host", "Zone", "Status", "State", "Updated At", "Disabled Reason" ] else: columns = [ "Binary", "Host", "Zone", "Status", "State", "Updated At" ] data = service_client.services.list(parsed_args.host, parsed_args.service) return (columns, (utils.get_item_properties( s, columns, ) for s in data)) class SetService(command.Command): _description = _("Set volume service properties") def get_parser(self, prog_name): parser = super(SetService, self).get_parser(prog_name) parser.add_argument( "host", metavar="", help=_("Name of host") ) parser.add_argument( "service", metavar="", help=_("Name of service (Binary name)") ) enabled_group = parser.add_mutually_exclusive_group() enabled_group.add_argument( "--enable", action="store_true", help=_("Enable volume service") ) enabled_group.add_argument( "--disable", action="store_true", help=_("Disable volume service") ) parser.add_argument( "--disable-reason", metavar="", help=_("Reason for disabling the service " "(should be used with --disable option)") ) return parser def take_action(self, parsed_args): if parsed_args.disable_reason and not parsed_args.disable: msg = _("Cannot specify option --disable-reason without " "--disable specified.") raise exceptions.CommandError(msg) service_client = self.app.client_manager.volume if parsed_args.enable: service_client.services.enable( parsed_args.host, parsed_args.service) if parsed_args.disable: if parsed_args.disable_reason: service_client.services.disable_log_reason( parsed_args.host, parsed_args.service, parsed_args.disable_reason) else: service_client.services.disable( parsed_args.host, parsed_args.service) python-openstackclient-3.14.0/openstackclient/volume/v1/snapshot.py0000666000175100017510000002525113232364361025576 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # # TODO(Huanxuan Ao): Remove this file and "snapshot create", "snapshot delete", # "snapshot set", "snapshot show" and "snapshot unset" # commands two cycles after Ocata. """Volume v1 Snapshot action implementations""" import copy import logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ deprecated = True LOG_DEP = logging.getLogger('deprecated') LOG = logging.getLogger(__name__) class CreateSnapshot(command.ShowOne): _description = _("Create new snapshot") def get_parser(self, prog_name): parser = super(CreateSnapshot, self).get_parser(prog_name) parser.add_argument( 'volume', metavar='', help=_('Volume to snapshot (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('Name of the snapshot'), ) parser.add_argument( '--description', metavar='', help=_('Description of the snapshot'), ) parser.add_argument( '--force', dest='force', action='store_true', default=False, help=_('Create a snapshot attached to an instance. ' 'Default is False'), ) return parser def take_action(self, parsed_args): LOG_DEP.warning(_('This command has been deprecated. ' 'Please use "volume snapshot create" instead.')) volume_client = self.app.client_manager.volume volume_id = utils.find_resource(volume_client.volumes, parsed_args.volume).id snapshot = volume_client.volume_snapshots.create( volume_id, parsed_args.force, parsed_args.name, parsed_args.description ) snapshot._info.update( {'properties': utils.format_dict(snapshot._info.pop('metadata'))} ) return zip(*sorted(six.iteritems(snapshot._info))) class DeleteSnapshot(command.Command): _description = _("Delete snapshot(s)") def get_parser(self, prog_name): parser = super(DeleteSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshots', metavar='', nargs="+", help=_('Snapshot(s) to delete (name or ID)'), ) return parser def take_action(self, parsed_args): LOG_DEP.warning(_('This command has been deprecated. ' 'Please use "volume snapshot delete" instead.')) volume_client = self.app.client_manager.volume result = 0 for i in parsed_args.snapshots: try: snapshot_id = utils.find_resource( volume_client.volume_snapshots, i).id volume_client.volume_snapshots.delete(snapshot_id) except Exception as e: result += 1 LOG.error(_("Failed to delete snapshot with " "name or ID '%(snapshot)s': %(e)s"), {'snapshot': i, 'e': e}) if result > 0: total = len(parsed_args.snapshots) msg = (_("%(result)s of %(total)s snapshots failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListSnapshot(command.Lister): _description = _("List snapshots") def get_parser(self, prog_name): parser = super(ListSnapshot, self).get_parser(prog_name) parser.add_argument( '--all-projects', action='store_true', default=False, help=_('Include all projects (admin only)'), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) return parser def take_action(self, parsed_args): LOG_DEP.warning(_('This command has been deprecated. ' 'Please use "volume snapshot list" instead.')) def _format_volume_id(volume_id): """Return a volume name if available :param volume_id: a volume ID :rtype: either the volume ID or name """ volume = volume_id if volume_id in volume_cache.keys(): volume = volume_cache[volume_id].display_name return volume if parsed_args.long: columns = ['ID', 'Display Name', 'Display Description', 'Status', 'Size', 'Created At', 'Volume ID', 'Metadata'] column_headers = copy.deepcopy(columns) column_headers[6] = 'Volume' column_headers[7] = 'Properties' else: columns = ['ID', 'Display Name', 'Display Description', 'Status', 'Size'] column_headers = copy.deepcopy(columns) # Always update Name and Description column_headers[1] = 'Name' column_headers[2] = 'Description' # Cache the volume list volume_cache = {} try: for s in self.app.client_manager.volume.volumes.list(): volume_cache[s.id] = s except Exception: # Just forget it if there's any trouble pass search_opts = { 'all_tenants': parsed_args.all_projects, } data = self.app.client_manager.volume.volume_snapshots.list( search_opts=search_opts) return (column_headers, (utils.get_item_properties( s, columns, formatters={'Metadata': utils.format_dict, 'Volume ID': _format_volume_id}, ) for s in data)) class SetSnapshot(command.Command): _description = _("Set snapshot properties") def get_parser(self, prog_name): parser = super(SetSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshot', metavar='', help=_('Snapshot to modify (name or ID)') ) parser.add_argument( '--name', metavar='', help=_('New snapshot name') ) parser.add_argument( '--description', metavar='', help=_('New snapshot description') ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Property to add/change for this snapshot ' '(repeat option to set multiple properties)'), ) return parser def take_action(self, parsed_args): LOG_DEP.warning(_('This command has been deprecated. ' 'Please use "volume snapshot set" instead.')) volume_client = self.app.client_manager.volume snapshot = utils.find_resource(volume_client.volume_snapshots, parsed_args.snapshot) result = 0 if parsed_args.property: try: volume_client.volume_snapshots.set_metadata( snapshot.id, parsed_args.property) except Exception as e: LOG.error(_("Failed to set snapshot property: %s"), e) result += 1 kwargs = {} if parsed_args.name: kwargs['display_name'] = parsed_args.name if parsed_args.description: kwargs['display_description'] = parsed_args.description if kwargs: try: snapshot.update(**kwargs) except Exception as e: LOG.error(_("Failed to update snapshot display name " "or display description: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("One or more of the " "set operations failed")) class ShowSnapshot(command.ShowOne): _description = _("Display snapshot details") def get_parser(self, prog_name): parser = super(ShowSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshot', metavar='', help=_('Snapshot to display (name or ID)') ) return parser def take_action(self, parsed_args): LOG_DEP.warning(_('This command has been deprecated. ' 'Please use "volume snapshot show" instead.')) volume_client = self.app.client_manager.volume snapshot = utils.find_resource(volume_client.volume_snapshots, parsed_args.snapshot) snapshot._info.update( {'properties': utils.format_dict(snapshot._info.pop('metadata'))} ) return zip(*sorted(six.iteritems(snapshot._info))) class UnsetSnapshot(command.Command): _description = _("Unset snapshot properties") def get_parser(self, prog_name): parser = super(UnsetSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshot', metavar='', help=_('Snapshot to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action='append', help=_('Property to remove from snapshot ' '(repeat option to remove multiple properties)'), ) return parser def take_action(self, parsed_args): LOG_DEP.warning(_('This command has been deprecated. ' 'Please use "volume snapshot unset" instead.')) volume_client = self.app.client_manager.volume snapshot = utils.find_resource( volume_client.volume_snapshots, parsed_args.snapshot) if parsed_args.property: volume_client.volume_snapshots.delete_metadata( snapshot.id, parsed_args.property, ) python-openstackclient-3.14.0/openstackclient/volume/v1/volume_transfer_request.py0000666000175100017510000001600713232364361030721 0ustar zuulzuul00000000000000# # 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. # """Volume v1 transfer action implementations""" import argparse import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class AcceptTransferRequest(command.ShowOne): _description = _("Accept volume transfer request.") def get_parser(self, prog_name): parser = super(AcceptTransferRequest, self).get_parser(prog_name) parser.add_argument( 'transfer_request', metavar="", help=_('Volume transfer request to accept (ID only)'), ) parser.add_argument( 'old_auth_key', metavar="", nargs="?", help=argparse.SUPPRESS, ) parser.add_argument( '--auth-key', metavar="", help=_('Volume transfer request authentication key'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume try: transfer_request_id = utils.find_resource( volume_client.transfers, parsed_args.transfer_request ).id except exceptions.CommandError: # Non-admin users will fail to lookup name -> ID so we just # move on and attempt with the user-supplied information transfer_request_id = parsed_args.transfer_request # Remain backward-compatible for the previous command layout # TODO(dtroyer): Remove this back-compat in 4.0 or Oct 2017 if not parsed_args.auth_key: if parsed_args.old_auth_key: # Move the old one into the correct place parsed_args.auth_key = parsed_args.old_auth_key self.log.warning(_( 'Specifying the auth-key as a positional argument ' 'has been deprecated. Please use the --auth-key ' 'option in the future.' )) else: msg = _("argument --auth-key is required") raise exceptions.CommandError(msg) transfer_accept = volume_client.transfers.accept( transfer_request_id, parsed_args.auth_key, ) transfer_accept._info.pop("links", None) return zip(*sorted(six.iteritems(transfer_accept._info))) class CreateTransferRequest(command.ShowOne): _description = _("Create volume transfer request.") def get_parser(self, prog_name): parser = super(CreateTransferRequest, self).get_parser(prog_name) parser.add_argument( '--name', metavar="", help=_('New transfer request name (default to None)') ) parser.add_argument( 'volume', metavar="", help=_('Volume to transfer (name or ID)') ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume_id = utils.find_resource( volume_client.volumes, parsed_args.volume, ).id volume_transfer_request = volume_client.transfers.create( volume_id, parsed_args.name, ) volume_transfer_request._info.pop("links", None) return zip(*sorted(six.iteritems(volume_transfer_request._info))) class DeleteTransferRequest(command.Command): _description = _("Delete volume transfer request(s).") def get_parser(self, prog_name): parser = super(DeleteTransferRequest, self).get_parser(prog_name) parser.add_argument( 'transfer_request', metavar="", nargs="+", help=_('Volume transfer request(s) to delete (name or ID)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for t in parsed_args.transfer_request: try: transfer_request_id = utils.find_resource( volume_client.transfers, t, ).id volume_client.transfers.delete(transfer_request_id) except Exception as e: result += 1 LOG.error(_("Failed to delete volume transfer request " "with name or ID '%(transfer)s': %(e)s") % {'transfer': t, 'e': e}) if result > 0: total = len(parsed_args.transfer_request) msg = (_("%(result)s of %(total)s volume transfer requests failed" " to delete") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListTransferRequest(command.Lister): _description = _("Lists all volume transfer requests.") def get_parser(self, prog_name): parser = super(ListTransferRequest, self).get_parser(prog_name) parser.add_argument( '--all-projects', dest='all_projects', action="store_true", default=False, help=_('Include all projects (admin only)'), ) return parser def take_action(self, parsed_args): columns = ['ID', 'Name', 'Volume ID'] column_headers = ['ID', 'Name', 'Volume'] volume_client = self.app.client_manager.volume volume_transfer_result = volume_client.transfers.list( detailed=True, search_opts={'all_tenants': parsed_args.all_projects}, ) return (column_headers, ( utils.get_item_properties(s, columns) for s in volume_transfer_result)) class ShowTransferRequest(command.ShowOne): _description = _("Show volume transfer request details.") def get_parser(self, prog_name): parser = super(ShowTransferRequest, self).get_parser(prog_name) parser.add_argument( 'transfer_request', metavar="", help=_('Volume transfer request to display (name or ID)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume_transfer_request = utils.find_resource( volume_client.transfers, parsed_args.transfer_request, ) volume_transfer_request._info.pop("links", None) return zip(*sorted(six.iteritems(volume_transfer_request._info))) python-openstackclient-3.14.0/openstackclient/volume/v1/volume_snapshot.py0000666000175100017510000002722113232364361027164 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Volume v1 Snapshot action implementations""" import copy import logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateVolumeSnapshot(command.ShowOne): _description = _("Create new volume snapshot") def get_parser(self, prog_name): parser = super(CreateVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshot_name', metavar='', help=_('Name of the new snapshot'), ) parser.add_argument( '--volume', metavar='', help=_('Volume to snapshot (name or ID) ' '(default is )'), ) parser.add_argument( '--description', metavar='', help=_('Description of the snapshot'), ) parser.add_argument( '--force', dest='force', action='store_true', default=False, help=_('Create a snapshot attached to an instance. ' 'Default is False'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume = parsed_args.volume if not parsed_args.volume: volume = parsed_args.snapshot_name volume_id = utils.find_resource(volume_client.volumes, volume).id snapshot = volume_client.volume_snapshots.create( volume_id, parsed_args.force, parsed_args.snapshot_name, parsed_args.description ) snapshot._info.update( {'properties': utils.format_dict(snapshot._info.pop('metadata'))} ) return zip(*sorted(six.iteritems(snapshot._info))) class DeleteVolumeSnapshot(command.Command): _description = _("Delete volume snapshot(s)") def get_parser(self, prog_name): parser = super(DeleteVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshots', metavar='', nargs="+", help=_('Snapshot(s) to delete (name or ID)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for i in parsed_args.snapshots: try: snapshot_id = utils.find_resource( volume_client.volume_snapshots, i).id volume_client.volume_snapshots.delete(snapshot_id) except Exception as e: result += 1 LOG.error(_("Failed to delete snapshot with " "name or ID '%(snapshot)s': %(e)s"), {'snapshot': i, 'e': e}) if result > 0: total = len(parsed_args.snapshots) msg = (_("%(result)s of %(total)s snapshots failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListVolumeSnapshot(command.Lister): _description = _("List volume snapshots") def get_parser(self, prog_name): parser = super(ListVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( '--all-projects', action='store_true', default=False, help=_('Include all projects (admin only)'), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( '--name', metavar='', default=None, help=_('Filters results by a name.') ) parser.add_argument( '--status', metavar='', choices=['available', 'error', 'creating', 'deleting', 'error-deleting'], help=_("Filters results by a status. " "('available', 'error', 'creating', 'deleting'" " or 'error-deleting')") ) parser.add_argument( '--volume', metavar='', default=None, help=_('Filters results by a volume (name or ID).') ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume def _format_volume_id(volume_id): """Return a volume name if available :param volume_id: a volume ID :rtype: either the volume ID or name """ volume = volume_id if volume_id in volume_cache.keys(): volume = volume_cache[volume_id].display_name return volume if parsed_args.long: columns = ['ID', 'Display Name', 'Display Description', 'Status', 'Size', 'Created At', 'Volume ID', 'Metadata'] column_headers = copy.deepcopy(columns) column_headers[6] = 'Volume' column_headers[7] = 'Properties' else: columns = ['ID', 'Display Name', 'Display Description', 'Status', 'Size'] column_headers = copy.deepcopy(columns) # Always update Name and Description column_headers[1] = 'Name' column_headers[2] = 'Description' # Cache the volume list volume_cache = {} try: for s in volume_client.volumes.list(): volume_cache[s.id] = s except Exception: # Just forget it if there's any trouble pass volume_id = None if parsed_args.volume: volume_id = utils.find_resource( volume_client.volumes, parsed_args.volume).id search_opts = { 'all_tenants': parsed_args.all_projects, 'display_name': parsed_args.name, 'status': parsed_args.status, 'volume_id': volume_id, } data = volume_client.volume_snapshots.list( search_opts=search_opts) return (column_headers, (utils.get_item_properties( s, columns, formatters={'Metadata': utils.format_dict, 'Volume ID': _format_volume_id}, ) for s in data)) class SetVolumeSnapshot(command.Command): _description = _("Set volume snapshot properties") def get_parser(self, prog_name): parser = super(SetVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshot', metavar='', help=_('Snapshot to modify (name or ID)') ) parser.add_argument( '--name', metavar='', help=_('New snapshot name') ) parser.add_argument( '--description', metavar='', help=_('New snapshot description') ) parser.add_argument( "--no-property", dest="no_property", action="store_true", help=_("Remove all properties from " "(specify both --no-property and --property to " "remove the current properties before setting " "new properties.)"), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Property to add/change for this snapshot ' '(repeat option to set multiple properties)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume snapshot = utils.find_resource(volume_client.volume_snapshots, parsed_args.snapshot) result = 0 if parsed_args.no_property: try: key_list = snapshot.metadata.keys() volume_client.volume_snapshots.delete_metadata( snapshot.id, list(key_list), ) except Exception as e: LOG.error(_("Failed to clean snapshot properties: %s"), e) result += 1 if parsed_args.property: try: volume_client.volume_snapshots.set_metadata( snapshot.id, parsed_args.property) except Exception as e: LOG.error(_("Failed to set snapshot property: %s"), e) result += 1 kwargs = {} if parsed_args.name: kwargs['display_name'] = parsed_args.name if parsed_args.description: kwargs['display_description'] = parsed_args.description if kwargs: try: snapshot.update(**kwargs) except Exception as e: LOG.error(_("Failed to update snapshot display name " "or display description: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("One or more of the " "set operations failed")) class ShowVolumeSnapshot(command.ShowOne): _description = _("Display volume snapshot details") def get_parser(self, prog_name): parser = super(ShowVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshot', metavar='', help=_('Snapshot to display (name or ID)') ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume snapshot = utils.find_resource(volume_client.volume_snapshots, parsed_args.snapshot) snapshot._info.update( {'properties': utils.format_dict(snapshot._info.pop('metadata'))} ) return zip(*sorted(six.iteritems(snapshot._info))) class UnsetVolumeSnapshot(command.Command): _description = _("Unset volume snapshot properties") def get_parser(self, prog_name): parser = super(UnsetVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshot', metavar='', help=_('Snapshot to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action='append', help=_('Property to remove from snapshot ' '(repeat option to remove multiple properties)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume snapshot = utils.find_resource( volume_client.volume_snapshots, parsed_args.snapshot) if parsed_args.property: volume_client.volume_snapshots.delete_metadata( snapshot.id, parsed_args.property, ) python-openstackclient-3.14.0/openstackclient/volume/v1/volume_type.py0000666000175100017510000003764413232364361026320 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Volume v1 Type action implementations""" import logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) def _create_encryption_type(volume_client, volume_type, parsed_args): if not parsed_args.encryption_provider: msg = _("'--encryption-provider' should be specified while " "creating a new encryption type") raise exceptions.CommandError(msg) # set the default of control location while creating control_location = 'front-end' if parsed_args.encryption_control_location: control_location = parsed_args.encryption_control_location body = { 'provider': parsed_args.encryption_provider, 'cipher': parsed_args.encryption_cipher, 'key_size': parsed_args.encryption_key_size, 'control_location': control_location } encryption = volume_client.volume_encryption_types.create( volume_type, body) return encryption class CreateVolumeType(command.ShowOne): _description = _("Create new volume type") def get_parser(self, prog_name): parser = super(CreateVolumeType, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('Volume type name'), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Set a property on this volume type ' '(repeat option to set multiple properties)'), ) # TODO(Huanxuan Ao): Add choices for each "--encryption-*" option. parser.add_argument( '--encryption-provider', metavar='', help=_('Set the class that provides encryption support for ' 'this volume type (e.g "LuksEncryptor") (admin only) ' '(This option is required when setting encryption type ' 'of a volume. Consider using other encryption options ' 'such as: "--encryption-cipher", "--encryption-key-size" ' 'and "--encryption-control-location")'), ) parser.add_argument( '--encryption-cipher', metavar='', help=_('Set the encryption algorithm or mode for this ' 'volume type (e.g "aes-xts-plain64") (admin only)'), ) parser.add_argument( '--encryption-key-size', metavar='', type=int, help=_('Set the size of the encryption key of this ' 'volume type (e.g "128" or "256") (admin only)'), ) parser.add_argument( '--encryption-control-location', metavar='', choices=['front-end', 'back-end'], help=_('Set the notional service where the encryption is ' 'performed ("front-end" or "back-end") (admin only) ' '(The default value for this option is "front-end" ' 'when setting encryption type of a volume. Consider ' 'using other encryption options such as: ' '"--encryption-cipher", "--encryption-key-size" and ' '"--encryption-provider")'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume_type = volume_client.volume_types.create(parsed_args.name) volume_type._info.pop('extra_specs') if parsed_args.property: result = volume_type.set_keys(parsed_args.property) volume_type._info.update({'properties': utils.format_dict(result)}) if (parsed_args.encryption_provider or parsed_args.encryption_cipher or parsed_args.encryption_key_size or parsed_args.encryption_control_location): try: # create new encryption encryption = _create_encryption_type( volume_client, volume_type, parsed_args) except Exception as e: LOG.error(_("Failed to set encryption information for this " "volume type: %s"), e) # add encryption info in result encryption._info.pop("volume_type_id", None) volume_type._info.update( {'encryption': utils.format_dict(encryption._info)}) volume_type._info.pop("os-volume-type-access:is_public", None) return zip(*sorted(six.iteritems(volume_type._info))) class DeleteVolumeType(command.Command): _description = _("Delete volume type(s)") def get_parser(self, prog_name): parser = super(DeleteVolumeType, self).get_parser(prog_name) parser.add_argument( 'volume_types', metavar='', nargs='+', help=_('Volume type(s) to delete (name or ID)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for volume_type in parsed_args.volume_types: try: vol_type = utils.find_resource(volume_client.volume_types, volume_type) volume_client.volume_types.delete(vol_type) except Exception as e: result += 1 LOG.error(_("Failed to delete volume type with " "name or ID '%(volume_type)s': %(e)s") % {'volume_type': volume_type, 'e': e}) if result > 0: total = len(parsed_args.volume_types) msg = (_("%(result)s of %(total)s volume types failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListVolumeType(command.Lister): _description = _("List volume types") def get_parser(self, prog_name): parser = super(ListVolumeType, self).get_parser(prog_name) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output') ) parser.add_argument( "--encryption-type", action="store_true", help=_("Display encryption information for each volume type " "(admin only)"), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume if parsed_args.long: columns = ['ID', 'Name', 'Is Public', 'Extra Specs'] column_headers = ['ID', 'Name', 'Is Public', 'Properties'] else: columns = ['ID', 'Name', 'Is Public'] column_headers = ['ID', 'Name', 'Is Public'] data = volume_client.volume_types.list() def _format_encryption_info(type_id, encryption_data=None): encryption_data = encryption encryption_info = '-' if type_id in encryption_data.keys(): encryption_info = encryption_data[type_id] return encryption_info if parsed_args.encryption_type: encryption = {} for d in volume_client.volume_encryption_types.list(): volume_type_id = d._info['volume_type_id'] # remove some redundant information del_key = [ 'deleted', 'created_at', 'updated_at', 'deleted_at', 'volume_type_id' ] for key in del_key: d._info.pop(key, None) # save the encryption information with their volume type ID encryption[volume_type_id] = utils.format_dict(d._info) # We need to get volume type ID, then show encryption # information according to the ID, so use "id" to keep # difference to the real "ID" column. columns += ['id'] column_headers += ['Encryption'] return (column_headers, (utils.get_item_properties( s, columns, formatters={'Extra Specs': utils.format_dict, 'id': _format_encryption_info}, ) for s in data)) class SetVolumeType(command.Command): _description = _("Set volume type properties") def get_parser(self, prog_name): parser = super(SetVolumeType, self).get_parser(prog_name) parser.add_argument( 'volume_type', metavar='', help=_('Volume type to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Set a property on this volume type ' '(repeat option to set multiple properties)'), ) # TODO(Huanxuan Ao): Add choices for each "--encryption-*" option. parser.add_argument( '--encryption-provider', metavar='', help=_('Set the class that provides encryption support for ' 'this volume type (e.g "LuksEncryptor") (admin only) ' '(This option is required when setting encryption type ' 'of a volume. Consider using other encryption options ' 'such as: "--encryption-cipher", "--encryption-key-size" ' 'and "--encryption-control-location")'), ) parser.add_argument( '--encryption-cipher', metavar='', help=_('Set the encryption algorithm or mode for this ' 'volume type (e.g "aes-xts-plain64") (admin only)'), ) parser.add_argument( '--encryption-key-size', metavar='', type=int, help=_('Set the size of the encryption key of this ' 'volume type (e.g "128" or "256") (admin only)'), ) parser.add_argument( '--encryption-control-location', metavar='', choices=['front-end', 'back-end'], help=_('Set the notional service where the encryption is ' 'performed ("front-end" or "back-end") (admin only) ' '(The default value for this option is "front-end" ' 'when setting encryption type of a volume. Consider ' 'using other encryption options such as: ' '"--encryption-cipher", "--encryption-key-size" and ' '"--encryption-provider")'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume_type = utils.find_resource( volume_client.volume_types, parsed_args.volume_type) result = 0 if parsed_args.property: try: volume_type.set_keys(parsed_args.property) except Exception as e: LOG.error(_("Failed to set volume type property: %s"), e) result += 1 if (parsed_args.encryption_provider or parsed_args.encryption_cipher or parsed_args.encryption_key_size or parsed_args.encryption_control_location): try: _create_encryption_type( volume_client, volume_type, parsed_args) except Exception as e: LOG.error(_("Failed to set encryption information for this " "volume type: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("Command Failed: One or more of" " the operations failed")) class ShowVolumeType(command.ShowOne): _description = _("Display volume type details") def get_parser(self, prog_name): parser = super(ShowVolumeType, self).get_parser(prog_name) parser.add_argument( "volume_type", metavar="", help=_("Volume type to display (name or ID)") ) parser.add_argument( "--encryption-type", action="store_true", help=_("Display encryption information of this volume type " "(admin only)"), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume_type = utils.find_resource( volume_client.volume_types, parsed_args.volume_type) properties = utils.format_dict(volume_type._info.pop('extra_specs')) volume_type._info.update({'properties': properties}) if parsed_args.encryption_type: # show encryption type information for this volume type try: encryption = volume_client.volume_encryption_types.get( volume_type.id) encryption._info.pop("volume_type_id", None) volume_type._info.update( {'encryption': utils.format_dict(encryption._info)}) except Exception as e: LOG.error(_("Failed to display the encryption information " "of this volume type: %s"), e) volume_type._info.pop("os-volume-type-access:is_public", None) return zip(*sorted(six.iteritems(volume_type._info))) class UnsetVolumeType(command.Command): _description = _("Unset volume type properties") def get_parser(self, prog_name): parser = super(UnsetVolumeType, self).get_parser(prog_name) parser.add_argument( 'volume_type', metavar='', help=_('Volume type to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action='append', help=_('Remove a property from this volume type ' '(repeat option to remove multiple properties)'), ) parser.add_argument( "--encryption-type", action="store_true", help=_("Remove the encryption type for this volume type " "(admin oly)"), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume_type = utils.find_resource( volume_client.volume_types, parsed_args.volume_type, ) result = 0 if parsed_args.property: try: volume_type.unset_keys(parsed_args.property) except Exception as e: LOG.error(_("Failed to unset volume type property: %s"), e) result += 1 if parsed_args.encryption_type: try: volume_client.volume_encryption_types.delete(volume_type) except Exception as e: LOG.error(_("Failed to remove the encryption type for this " "volume type: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("Command Failed: One or more of" " the operations failed")) python-openstackclient-3.14.0/openstackclient/volume/v1/backup.py0000666000175100017510000002561113232364361025204 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Volume v1 Backup action implementations""" import copy import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateVolumeBackup(command.ShowOne): _description = _("Create new volume backup") def get_parser(self, prog_name): parser = super(CreateVolumeBackup, self).get_parser(prog_name) parser.add_argument( 'volume', metavar='', help=_('Volume to backup (name or ID)'), ) parser.add_argument( '--container', metavar='', required=False, help=_('Optional backup container name'), ) parser.add_argument( '--name', metavar='', help=_('Name of the backup'), ) parser.add_argument( '--description', metavar='', help=_('Description of the backup'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume_id = utils.find_resource(volume_client.volumes, parsed_args.volume).id backup = volume_client.backups.create( volume_id, parsed_args.container, parsed_args.name, parsed_args.description ) backup._info.pop('links') return zip(*sorted(six.iteritems(backup._info))) class CreateBackup(CreateVolumeBackup): _description = _("Create new backup") # TODO(Huanxuan Ao): Remove this class and ``backup create`` command # two cycles after Newton. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "volume backup create" instead.')) return super(CreateBackup, self).take_action(parsed_args) class DeleteVolumeBackup(command.Command): _description = _("Delete volume backup(s)") def get_parser(self, prog_name): parser = super(DeleteVolumeBackup, self).get_parser(prog_name) parser.add_argument( 'backups', metavar='', nargs="+", help=_('Backup(s) to delete (name or ID)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for i in parsed_args.backups: try: backup_id = utils.find_resource( volume_client.backups, i).id volume_client.backups.delete(backup_id) except Exception as e: result += 1 LOG.error(_("Failed to delete backup with " "name or ID '%(backup)s': %(e)s"), {'backup': i, 'e': e}) if result > 0: total = len(parsed_args.backups) msg = (_("%(result)s of %(total)s backups failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class DeleteBackup(DeleteVolumeBackup): _description = _("Delete backup(s)") # TODO(Huanxuan Ao): Remove this class and ``backup delete`` command # two cycles after Newton. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "volume backup delete" instead.')) return super(DeleteBackup, self).take_action(parsed_args) class ListVolumeBackup(command.Lister): _description = _("List volume backups") def get_parser(self, prog_name): parser = super(ListVolumeBackup, self).get_parser(prog_name) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( "--name", metavar="", help=_("Filters results by the backup name") ) parser.add_argument( "--status", metavar="", choices=['creating', 'available', 'deleting', 'error', 'restoring', 'error_restoring'], help=_("Filters results by the backup status " "('creating', 'available', 'deleting', " "'error', 'restoring' or 'error_restoring')") ) parser.add_argument( "--volume", metavar="", help=_("Filters results by the volume which they " "backup (name or ID)") ) parser.add_argument( '--all-projects', action='store_true', default=False, help=_('Include all projects (admin only)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume def _format_volume_id(volume_id): """Return a volume name if available :param volume_id: a volume ID :rtype: either the volume ID or name """ volume = volume_id if volume_id in volume_cache.keys(): volume = volume_cache[volume_id].display_name return volume if parsed_args.long: columns = ['ID', 'Name', 'Description', 'Status', 'Size', 'Availability Zone', 'Volume ID', 'Container'] column_headers = copy.deepcopy(columns) column_headers[6] = 'Volume' else: columns = ['ID', 'Name', 'Description', 'Status', 'Size'] column_headers = columns # Cache the volume list volume_cache = {} try: for s in volume_client.volumes.list(): volume_cache[s.id] = s except Exception: # Just forget it if there's any trouble pass filter_volume_id = None if parsed_args.volume: filter_volume_id = utils.find_resource(volume_client.volumes, parsed_args.volume).id search_opts = { 'name': parsed_args.name, 'status': parsed_args.status, 'volume_id': filter_volume_id, 'all_tenants': parsed_args.all_projects, } data = volume_client.backups.list( search_opts=search_opts, ) return (column_headers, (utils.get_item_properties( s, columns, formatters={'Volume ID': _format_volume_id}, ) for s in data)) class ListBackup(ListVolumeBackup): _description = _("List backups") # TODO(Huanxuan Ao): Remove this class and ``backup list`` command # two cycles after Newton. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "volume backup list" instead.')) return super(ListBackup, self).take_action(parsed_args) class RestoreVolumeBackup(command.Command): _description = _("Restore volume backup") def get_parser(self, prog_name): parser = super(RestoreVolumeBackup, self).get_parser(prog_name) parser.add_argument( 'backup', metavar='', help=_('Backup to restore (name or ID)') ) parser.add_argument( 'volume', metavar='', help=_('Volume to restore to (name or ID)') ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume backup = utils.find_resource(volume_client.backups, parsed_args.backup) destination_volume = utils.find_resource(volume_client.volumes, parsed_args.volume) return volume_client.restores.restore(backup.id, destination_volume.id) class RestoreBackup(RestoreVolumeBackup): _description = _("Restore backup") # TODO(Huanxuan Ao): Remove this class and ``backup restore`` command # two cycles after Newton. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "volume backup restore" instead.')) return super(RestoreBackup, self).take_action(parsed_args) class ShowVolumeBackup(command.ShowOne): _description = _("Display volume backup details") def get_parser(self, prog_name): parser = super(ShowVolumeBackup, self).get_parser(prog_name) parser.add_argument( 'backup', metavar='', help=_('Backup to display (name or ID)') ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume backup = utils.find_resource(volume_client.backups, parsed_args.backup) backup._info.pop('links') return zip(*sorted(six.iteritems(backup._info))) class ShowBackup(ShowVolumeBackup): _description = _("Display backup details") # TODO(Huanxuan Ao): Remove this class and ``backup show`` command # two cycles after Newton. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "volume backup show" instead.')) return super(ShowBackup, self).take_action(parsed_args) python-openstackclient-3.14.0/openstackclient/volume/v1/volume.py0000666000175100017510000005077113232364361025253 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Volume v1 Volume action implementations""" import argparse import logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) def _check_size_arg(args): """Check whether --size option is required or not. Require size parameter only in case when snapshot or source volume is not specified. """ if ((args.snapshot or args.source) is None and args.size is None): msg = _("--size is a required option if snapshot " "or source volume is not specified.") raise exceptions.CommandError(msg) class CreateVolume(command.ShowOne): _description = _("Create new volume") def get_parser(self, prog_name): parser = super(CreateVolume, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('Volume name'), ) parser.add_argument( '--size', metavar='', type=int, help=_("Volume size in GB (Required unless --snapshot or " "--source is specified)"), ) parser.add_argument( '--type', metavar='', help=_("Set the type of volume"), ) source_group = parser.add_mutually_exclusive_group() source_group.add_argument( '--image', metavar='', help=_('Use as source of volume (name or ID)'), ) source_group.add_argument( '--snapshot', metavar='', help=_('Use as source of volume (name or ID)'), ) source_group.add_argument( '--snapshot-id', metavar='', help=argparse.SUPPRESS, ) source_group.add_argument( '--source', metavar='', help=_('Volume to clone (name or ID)'), ) parser.add_argument( '--description', metavar='', help=_('Volume description'), ) parser.add_argument( '--user', metavar='', help=_('Specify an alternate user (name or ID)'), ) parser.add_argument( '--project', metavar='', help=_('Specify an alternate project (name or ID)'), ) parser.add_argument( '--availability-zone', metavar='', help=_('Create volume in '), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Set a property on this volume ' '(repeat option to set multiple properties)'), ) bootable_group = parser.add_mutually_exclusive_group() bootable_group.add_argument( "--bootable", action="store_true", help=_("Mark volume as bootable") ) bootable_group.add_argument( "--non-bootable", action="store_true", help=_("Mark volume as non-bootable (default)") ) readonly_group = parser.add_mutually_exclusive_group() readonly_group.add_argument( "--read-only", action="store_true", help=_("Set volume to read-only access mode") ) readonly_group.add_argument( "--read-write", action="store_true", help=_("Set volume to read-write access mode (default)") ) return parser def take_action(self, parsed_args): _check_size_arg(parsed_args) identity_client = self.app.client_manager.identity image_client = self.app.client_manager.image volume_client = self.app.client_manager.volume source_volume = None if parsed_args.source: source_volume = utils.find_resource( volume_client.volumes, parsed_args.source, ).id project = None if parsed_args.project: project = utils.find_resource( identity_client.tenants, parsed_args.project, ).id user = None if parsed_args.user: user = utils.find_resource( identity_client.users, parsed_args.user, ).id image = None if parsed_args.image: image = utils.find_resource( image_client.images, parsed_args.image, ).id snapshot = parsed_args.snapshot or parsed_args.snapshot_id volume = volume_client.volumes.create( parsed_args.size, snapshot, source_volume, parsed_args.name, parsed_args.description, parsed_args.type, user, project, parsed_args.availability_zone, parsed_args.property, image, ) if parsed_args.bootable or parsed_args.non_bootable: try: volume_client.volumes.set_bootable( volume.id, parsed_args.bootable) except Exception as e: LOG.error(_("Failed to set volume bootable property: %s"), e) if parsed_args.read_only or parsed_args.read_write: try: volume_client.volumes.update_readonly_flag( volume.id, parsed_args.read_only) except Exception as e: LOG.error(_("Failed to set volume read-only access " "mode flag: %s"), e) # Map 'metadata' column to 'properties' volume._info.update( { 'properties': utils.format_dict(volume._info.pop('metadata')), 'type': volume._info.pop('volume_type'), }, ) # Replace "display_name" by "name", keep consistent in v1 and v2 if 'display_name' in volume._info: volume._info.update({'name': volume._info.pop('display_name')}) volume_info = utils.backward_compat_col_showone( volume._info, parsed_args.columns, {'display_name': 'name'} ) return zip(*sorted(six.iteritems(volume_info))) class DeleteVolume(command.Command): _description = _("Delete volume(s)") def get_parser(self, prog_name): parser = super(DeleteVolume, self).get_parser(prog_name) parser.add_argument( 'volumes', metavar='', nargs="+", help=_('Volume(s) to delete (name or ID)'), ) parser.add_argument( '--force', action='store_true', default=False, help=_('Attempt forced removal of volume(s), regardless of state ' '(defaults to False)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for i in parsed_args.volumes: try: volume_obj = utils.find_resource( volume_client.volumes, i) if parsed_args.force: volume_client.volumes.force_delete(volume_obj.id) else: volume_client.volumes.delete(volume_obj.id) except Exception as e: result += 1 LOG.error(_("Failed to delete volume with " "name or ID '%(volume)s': %(e)s"), {'volume': i, 'e': e}) if result > 0: total = len(parsed_args.volumes) msg = (_("%(result)s of %(total)s volumes failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListVolume(command.Lister): _description = _("List volumes") def get_parser(self, prog_name): parser = super(ListVolume, self).get_parser(prog_name) parser.add_argument( '--name', metavar='', help=_('Filter results by volume name'), ) parser.add_argument( '--status', metavar='', help=_('Filter results by status'), ) parser.add_argument( '--all-projects', action='store_true', default=False, help=_('Include all projects (admin only)'), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( '--limit', type=int, action=parseractions.NonNegativeAction, metavar='', help=_('Maximum number of volumes to display'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume compute_client = self.app.client_manager.compute def _format_attach(attachments): """Return a formatted string of a volume's attached instances :param attachments: a volume.attachments field :rtype: a string of formatted instances """ msg = '' for attachment in attachments: server = attachment['server_id'] if server in server_cache.keys(): server = server_cache[server].name device = attachment['device'] msg += 'Attached to %s on %s ' % (server, device) return msg if parsed_args.long: columns = ( 'ID', 'Display Name', 'Status', 'Size', 'Volume Type', 'Bootable', 'Attachments', 'Metadata', ) column_headers = ( 'ID', 'Name', 'Status', 'Size', 'Type', 'Bootable', 'Attached to', 'Properties', ) else: columns = ( 'ID', 'Display Name', 'Status', 'Size', 'Attachments', ) column_headers = ( 'ID', 'Name', 'Status', 'Size', 'Attached to', ) # Cache the server list server_cache = {} try: for s in compute_client.servers.list(): server_cache[s.id] = s except Exception: # Just forget it if there's any trouble pass search_opts = { 'all_tenants': parsed_args.all_projects, 'display_name': parsed_args.name, 'status': parsed_args.status, } data = volume_client.volumes.list( search_opts=search_opts, limit=parsed_args.limit, ) column_headers = utils.backward_compat_col_lister( column_headers, parsed_args.columns, {'Display Name': 'Name'}) return (column_headers, (utils.get_item_properties( s, columns, formatters={'Metadata': utils.format_dict, 'Attachments': _format_attach}, ) for s in data)) class MigrateVolume(command.Command): _description = _("Migrate volume to a new host") def get_parser(self, prog_name): parser = super(MigrateVolume, self).get_parser(prog_name) parser.add_argument( 'volume', metavar="", help=_("Volume to migrate (name or ID)") ) parser.add_argument( '--host', metavar="", required=True, help=_("Destination host (takes the form: host@backend-name#pool)") ) parser.add_argument( '--force-host-copy', action="store_true", help=_("Enable generic host-based force-migration, " "which bypasses driver optimizations") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume = utils.find_resource(volume_client.volumes, parsed_args.volume) volume_client.volumes.migrate_volume(volume.id, parsed_args.host, parsed_args.force_host_copy,) class SetVolume(command.Command): _description = _("Set volume properties") def get_parser(self, prog_name): parser = super(SetVolume, self).get_parser(prog_name) parser.add_argument( 'volume', metavar='', help=_('Volume to modify (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('New volume name'), ) parser.add_argument( '--description', metavar='', help=_('New volume description'), ) parser.add_argument( '--size', metavar='', type=int, help=_('Extend volume size in GB'), ) parser.add_argument( "--no-property", dest="no_property", action="store_true", help=_("Remove all properties from " "(specify both --no-property and --property to " "remove the current properties before setting " "new properties.)"), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Set a property on this volume ' '(repeat option to set multiple properties)'), ) bootable_group = parser.add_mutually_exclusive_group() bootable_group.add_argument( "--bootable", action="store_true", help=_("Mark volume as bootable") ) bootable_group.add_argument( "--non-bootable", action="store_true", help=_("Mark volume as non-bootable") ) readonly_group = parser.add_mutually_exclusive_group() readonly_group.add_argument( "--read-only", action="store_true", help=_("Set volume to read-only access mode") ) readonly_group.add_argument( "--read-write", action="store_true", help=_("Set volume to read-write access mode") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume = utils.find_resource(volume_client.volumes, parsed_args.volume) result = 0 if parsed_args.size: try: if volume.status != 'available': msg = (_("Volume is in %s state, it must be available " "before size can be extended") % volume.status) raise exceptions.CommandError(msg) if parsed_args.size <= volume.size: msg = (_("New size must be greater than %s GB") % volume.size) raise exceptions.CommandError(msg) volume_client.volumes.extend(volume.id, parsed_args.size) except Exception as e: LOG.error(_("Failed to set volume size: %s"), e) result += 1 if parsed_args.no_property: try: volume_client.volumes.delete_metadata( volume.id, volume.metadata.keys()) except Exception as e: LOG.error(_("Failed to clean volume properties: %s"), e) result += 1 if parsed_args.property: try: volume_client.volumes.set_metadata( volume.id, parsed_args.property) except Exception as e: LOG.error(_("Failed to set volume property: %s"), e) result += 1 if parsed_args.bootable or parsed_args.non_bootable: try: volume_client.volumes.set_bootable( volume.id, parsed_args.bootable) except Exception as e: LOG.error(_("Failed to set volume bootable property: %s"), e) result += 1 if parsed_args.read_only or parsed_args.read_write: try: volume_client.volumes.update_readonly_flag( volume.id, parsed_args.read_only) except Exception as e: LOG.error(_("Failed to set volume read-only access " "mode flag: %s"), e) result += 1 kwargs = {} if parsed_args.name: kwargs['display_name'] = parsed_args.name if parsed_args.description: kwargs['display_description'] = parsed_args.description if kwargs: try: volume_client.volumes.update(volume.id, **kwargs) except Exception as e: LOG.error(_("Failed to update volume display name " "or display description: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("One or more of the " "set operations failed")) class ShowVolume(command.ShowOne): _description = _("Show volume details") def get_parser(self, prog_name): parser = super(ShowVolume, self).get_parser(prog_name) parser.add_argument( 'volume', metavar='', help=_('Volume to display (name or ID)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume = utils.find_resource(volume_client.volumes, parsed_args.volume) # Map 'metadata' column to 'properties' volume._info.update( { 'properties': utils.format_dict(volume._info.pop('metadata')), 'type': volume._info.pop('volume_type'), }, ) if 'os-vol-tenant-attr:tenant_id' in volume._info: volume._info.update( {'project_id': volume._info.pop( 'os-vol-tenant-attr:tenant_id')} ) # Replace "display_name" by "name", keep consistent in v1 and v2 if 'display_name' in volume._info: volume._info.update({'name': volume._info.pop('display_name')}) volume_info = utils.backward_compat_col_showone( volume._info, parsed_args.columns, {'display_name': 'name'} ) return zip(*sorted(six.iteritems(volume_info))) class UnsetVolume(command.Command): _description = _("Unset volume properties") def get_parser(self, prog_name): parser = super(UnsetVolume, self).get_parser(prog_name) parser.add_argument( 'volume', metavar='', help=_('Volume to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action='append', help=_('Remove a property from volume ' '(repeat option to remove multiple properties)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume = utils.find_resource( volume_client.volumes, parsed_args.volume) if parsed_args.property: volume_client.volumes.delete_metadata( volume.id, parsed_args.property, ) python-openstackclient-3.14.0/openstackclient/volume/v1/qos_specs.py0000666000175100017510000002477013232364361025743 0ustar zuulzuul00000000000000# Copyright 2015 iWeb Technologies 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. # """Volume v1 QoS action implementations""" import logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class AssociateQos(command.Command): _description = _("Associate a QoS specification to a volume type") def get_parser(self, prog_name): parser = super(AssociateQos, self).get_parser(prog_name) parser.add_argument( 'qos_spec', metavar='', help=_('QoS specification to modify (name or ID)'), ) parser.add_argument( 'volume_type', metavar='', help=_('Volume type to associate the QoS (name or ID)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume qos_spec = utils.find_resource(volume_client.qos_specs, parsed_args.qos_spec) volume_type = utils.find_resource(volume_client.volume_types, parsed_args.volume_type) volume_client.qos_specs.associate(qos_spec.id, volume_type.id) class CreateQos(command.ShowOne): _description = _("Create new QoS specification") def get_parser(self, prog_name): parser = super(CreateQos, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('New QoS specification name'), ) consumer_choices = ['front-end', 'back-end', 'both'] parser.add_argument( '--consumer', metavar='', choices=consumer_choices, default='both', help=(_('Consumer of the QoS. Valid consumers: %s ' "(defaults to 'both')") % utils.format_list(consumer_choices)) ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Set a QoS specification property ' '(repeat option to set multiple properties)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume specs = {} specs.update({'consumer': parsed_args.consumer}) if parsed_args.property: specs.update(parsed_args.property) qos_spec = volume_client.qos_specs.create(parsed_args.name, specs) qos_spec._info.update( {'properties': utils.format_dict(qos_spec._info.pop('specs'))} ) return zip(*sorted(six.iteritems(qos_spec._info))) class DeleteQos(command.Command): _description = _("Delete QoS specification") def get_parser(self, prog_name): parser = super(DeleteQos, self).get_parser(prog_name) parser.add_argument( 'qos_specs', metavar='', nargs="+", help=_('QoS specification(s) to delete (name or ID)'), ) parser.add_argument( '--force', action='store_true', default=False, help=_("Allow to delete in-use QoS specification(s)") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for i in parsed_args.qos_specs: try: qos_spec = utils.find_resource(volume_client.qos_specs, i) volume_client.qos_specs.delete(qos_spec.id, parsed_args.force) except Exception as e: result += 1 LOG.error(_("Failed to delete QoS specification with " "name or ID '%(qos)s': %(e)s"), {'qos': i, 'e': e}) if result > 0: total = len(parsed_args.qos_specs) msg = (_("%(result)s of %(total)s QoS specifications failed" " to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class DisassociateQos(command.Command): _description = _("Disassociate a QoS specification from a volume type") def get_parser(self, prog_name): parser = super(DisassociateQos, self).get_parser(prog_name) parser.add_argument( 'qos_spec', metavar='', help=_('QoS specification to modify (name or ID)'), ) volume_type_group = parser.add_mutually_exclusive_group() volume_type_group.add_argument( '--volume-type', metavar='', help=_('Volume type to disassociate the QoS from (name or ID)'), ) volume_type_group.add_argument( '--all', action='store_true', default=False, help=_('Disassociate the QoS from every volume type'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume qos_spec = utils.find_resource(volume_client.qos_specs, parsed_args.qos_spec) if parsed_args.volume_type: volume_type = utils.find_resource(volume_client.volume_types, parsed_args.volume_type) volume_client.qos_specs.disassociate(qos_spec.id, volume_type.id) elif parsed_args.all: volume_client.qos_specs.disassociate_all(qos_spec.id) class ListQos(command.Lister): _description = _("List QoS specifications") def take_action(self, parsed_args): volume_client = self.app.client_manager.volume qos_specs_list = volume_client.qos_specs.list() for qos in qos_specs_list: try: qos_associations = volume_client.qos_specs.get_associations( qos, ) if qos_associations: associations = [ association.name for association in qos_associations ] qos._info.update({'associations': associations}) except Exception as ex: if type(ex).__name__ == 'NotFound': qos._info.update({'associations': None}) else: raise display_columns = ( 'ID', 'Name', 'Consumer', 'Associations', 'Properties') columns = ('ID', 'Name', 'Consumer', 'Associations', 'Specs') return (display_columns, (utils.get_dict_properties( s._info, columns, formatters={ 'Specs': utils.format_dict, 'Associations': utils.format_list }, ) for s in qos_specs_list)) class SetQos(command.Command): _description = _("Set QoS specification properties") def get_parser(self, prog_name): parser = super(SetQos, self).get_parser(prog_name) parser.add_argument( 'qos_spec', metavar='', help=_('QoS specification to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Property to add or modify for this QoS specification ' '(repeat option to set multiple properties)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume qos_spec = utils.find_resource(volume_client.qos_specs, parsed_args.qos_spec) if parsed_args.property: volume_client.qos_specs.set_keys(qos_spec.id, parsed_args.property) class ShowQos(command.ShowOne): _description = _("Display QoS specification details") def get_parser(self, prog_name): parser = super(ShowQos, self).get_parser(prog_name) parser.add_argument( 'qos_spec', metavar='', help=_('QoS specification to display (name or ID)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume qos_spec = utils.find_resource(volume_client.qos_specs, parsed_args.qos_spec) qos_associations = volume_client.qos_specs.get_associations(qos_spec) if qos_associations: associations = [association.name for association in qos_associations] qos_spec._info.update({ 'associations': utils.format_list(associations) }) qos_spec._info.update( {'properties': utils.format_dict(qos_spec._info.pop('specs'))}) return zip(*sorted(six.iteritems(qos_spec._info))) class UnsetQos(command.Command): _description = _("Unset QoS specification properties") def get_parser(self, prog_name): parser = super(UnsetQos, self).get_parser(prog_name) parser.add_argument( 'qos_spec', metavar='', help=_('QoS specification to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action='append', help=_('Property to remove from the QoS specification. ' '(repeat option to unset multiple properties)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume qos_spec = utils.find_resource(volume_client.qos_specs, parsed_args.qos_spec) if parsed_args.property: volume_client.qos_specs.unset_keys(qos_spec.id, parsed_args.property) python-openstackclient-3.14.0/openstackclient/volume/v1/__init__.py0000666000175100017510000000000013232364361025457 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/volume/client.py0000666000175100017510000000475013232364361024670 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # import logging from osc_lib import utils from openstackclient.i18n import _ LOG = logging.getLogger(__name__) DEFAULT_API_VERSION = '2' API_VERSION_OPTION = 'os_volume_api_version' API_NAME = "volume" API_VERSIONS = { "1": "cinderclient.v1.client.Client", "2": "cinderclient.v2.client.Client", "3": "cinderclient.v3.client.Client", } def make_client(instance): """Returns a volume service client.""" # Defer client imports until we actually need them from cinderclient import extension from cinderclient.v1.contrib import list_extensions from cinderclient.v1 import volume_snapshots from cinderclient.v1 import volumes # Monkey patch for v1 cinderclient volumes.Volume.NAME_ATTR = 'display_name' volume_snapshots.Snapshot.NAME_ATTR = 'display_name' volume_client = utils.get_client_class( API_NAME, instance._api_version[API_NAME], API_VERSIONS ) LOG.debug('Instantiating volume client: %s', volume_client) # Set client http_log_debug to True if verbosity level is high enough http_log_debug = utils.get_effective_log_level() <= logging.DEBUG extensions = [extension.Extension('list_extensions', list_extensions)] # Remember interface only if it is set kwargs = utils.build_kwargs_dict('endpoint_type', instance.interface) client = volume_client( session=instance.session, extensions=extensions, http_log_debug=http_log_debug, region_name=instance.region_name, **kwargs ) return client def build_option_parser(parser): """Hook to add global options""" parser.add_argument( '--os-volume-api-version', metavar='', default=utils.env('OS_VOLUME_API_VERSION'), help=_('Volume API version, default=%s ' '(Env: OS_VOLUME_API_VERSION)') % DEFAULT_API_VERSION ) return parser python-openstackclient-3.14.0/openstackclient/volume/v2/0000775000175100017510000000000013232364654023364 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/volume/v2/service.py0000666000175100017510000001010213232364361025365 0ustar zuulzuul00000000000000# # 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. # """Service action implementations""" from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ class ListService(command.Lister): _description = _("List service command") def get_parser(self, prog_name): parser = super(ListService, self).get_parser(prog_name) parser.add_argument( "--host", metavar="", help=_("List services on specified host (name only)") ) parser.add_argument( "--service", metavar="", help=_("List only specified service (name only)") ) parser.add_argument( "--long", action="store_true", default=False, help=_("List additional fields in output") ) return parser def take_action(self, parsed_args): service_client = self.app.client_manager.volume if parsed_args.long: columns = [ "Binary", "Host", "Zone", "Status", "State", "Updated At", "Disabled Reason" ] else: columns = [ "Binary", "Host", "Zone", "Status", "State", "Updated At" ] data = service_client.services.list(parsed_args.host, parsed_args.service) return (columns, (utils.get_item_properties( s, columns, ) for s in data)) class SetService(command.Command): _description = _("Set volume service properties") def get_parser(self, prog_name): parser = super(SetService, self).get_parser(prog_name) parser.add_argument( "host", metavar="", help=_("Name of host") ) parser.add_argument( "service", metavar="", help=_("Name of service (Binary name)") ) enabled_group = parser.add_mutually_exclusive_group() enabled_group.add_argument( "--enable", action="store_true", help=_("Enable volume service") ) enabled_group.add_argument( "--disable", action="store_true", help=_("Disable volume service") ) parser.add_argument( "--disable-reason", metavar="", help=_("Reason for disabling the service " "(should be used with --disable option)") ) return parser def take_action(self, parsed_args): if parsed_args.disable_reason and not parsed_args.disable: msg = _("Cannot specify option --disable-reason without " "--disable specified.") raise exceptions.CommandError(msg) service_client = self.app.client_manager.volume if parsed_args.enable: service_client.services.enable( parsed_args.host, parsed_args.service) if parsed_args.disable: if parsed_args.disable_reason: service_client.services.disable_log_reason( parsed_args.host, parsed_args.service, parsed_args.disable_reason) else: service_client.services.disable( parsed_args.host, parsed_args.service) python-openstackclient-3.14.0/openstackclient/volume/v2/snapshot.py0000666000175100017510000003003213232364361025570 0ustar zuulzuul00000000000000# # 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. # # TODO(Huanxuan Ao): Remove this file and "snapshot create", "snapshot delete", # "snapshot set", "snapshot show" and "snapshot unset" # commands two cycles after Ocata. """Volume v2 snapshot action implementations""" import copy import logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ deprecated = True LOG_DEP = logging.getLogger('deprecated') LOG = logging.getLogger(__name__) class CreateSnapshot(command.ShowOne): _description = _("Create new snapshot") def get_parser(self, prog_name): parser = super(CreateSnapshot, self).get_parser(prog_name) parser.add_argument( "volume", metavar="", help=_("Volume to snapshot (name or ID)") ) parser.add_argument( "--name", metavar="", help=_("Name of the snapshot") ) parser.add_argument( "--description", metavar="", help=_("Description of the snapshot") ) parser.add_argument( "--force", action="store_true", default=False, help=_("Create a snapshot attached to an instance. " "Default is False") ) parser.add_argument( "--property", metavar="", action=parseractions.KeyValueAction, help=_("Set a property to this snapshot " "(repeat option to set multiple properties)"), ) return parser def take_action(self, parsed_args): LOG_DEP.warning(_('This command has been deprecated. ' 'Please use "volume snapshot create" instead.')) volume_client = self.app.client_manager.volume volume_id = utils.find_resource( volume_client.volumes, parsed_args.volume).id snapshot = volume_client.volume_snapshots.create( volume_id, force=parsed_args.force, name=parsed_args.name, description=parsed_args.description, metadata=parsed_args.property, ) snapshot._info.update( {'properties': utils.format_dict(snapshot._info.pop('metadata'))} ) return zip(*sorted(six.iteritems(snapshot._info))) class DeleteSnapshot(command.Command): _description = _("Delete volume snapshot(s)") def get_parser(self, prog_name): parser = super(DeleteSnapshot, self).get_parser(prog_name) parser.add_argument( "snapshots", metavar="", nargs="+", help=_("Snapshot(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): LOG_DEP.warning(_('This command has been deprecated. ' 'Please use "volume snapshot delete" instead.')) volume_client = self.app.client_manager.volume result = 0 for i in parsed_args.snapshots: try: snapshot_id = utils.find_resource( volume_client.volume_snapshots, i).id volume_client.volume_snapshots.delete(snapshot_id) except Exception as e: result += 1 LOG.error(_("Failed to delete snapshot with " "name or ID '%(snapshot)s': %(e)s") % {'snapshot': i, 'e': e}) if result > 0: total = len(parsed_args.snapshots) msg = (_("%(result)s of %(total)s snapshots failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListSnapshot(command.Lister): _description = _("List snapshots") def get_parser(self, prog_name): parser = super(ListSnapshot, self).get_parser(prog_name) parser.add_argument( '--all-projects', action='store_true', default=False, help=_('Include all projects (admin only)'), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( '--marker', metavar='', help=_('The last snapshot ID of the previous page'), ) parser.add_argument( '--limit', type=int, action=parseractions.NonNegativeAction, metavar='', help=_('Maximum number of snapshots to display'), ) return parser def take_action(self, parsed_args): LOG_DEP.warning(_('This command has been deprecated. ' 'Please use "volume snapshot list" instead.')) def _format_volume_id(volume_id): """Return a volume name if available :param volume_id: a volume ID :rtype: either the volume ID or name """ volume = volume_id if volume_id in volume_cache.keys(): volume = volume_cache[volume_id].name return volume if parsed_args.long: columns = ['ID', 'Name', 'Description', 'Status', 'Size', 'Created At', 'Volume ID', 'Metadata'] column_headers = copy.deepcopy(columns) column_headers[6] = 'Volume' column_headers[7] = 'Properties' else: columns = ['ID', 'Name', 'Description', 'Status', 'Size'] column_headers = copy.deepcopy(columns) # Cache the volume list volume_cache = {} try: for s in self.app.client_manager.volume.volumes.list(): volume_cache[s.id] = s except Exception: # Just forget it if there's any trouble pass search_opts = { 'all_tenants': parsed_args.all_projects, } data = self.app.client_manager.volume.volume_snapshots.list( search_opts=search_opts, marker=parsed_args.marker, limit=parsed_args.limit, ) return (column_headers, (utils.get_item_properties( s, columns, formatters={'Metadata': utils.format_dict, 'Volume ID': _format_volume_id}, ) for s in data)) class SetSnapshot(command.Command): _description = _("Set snapshot properties") def get_parser(self, prog_name): parser = super(SetSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshot', metavar='', help=_('Snapshot to modify (name or ID)') ) parser.add_argument( '--name', metavar='', help=_('New snapshot name') ) parser.add_argument( '--description', metavar='', help=_('New snapshot description') ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Property to add/change for this snapshot ' '(repeat option to set multiple properties)'), ) parser.add_argument( '--state', metavar='', choices=['available', 'error', 'creating', 'deleting', 'error-deleting'], help=_('New snapshot state. ("available", "error", "creating", ' '"deleting", or "error_deleting") (admin only) ' '(This option simply changes the state of the snapshot ' 'in the database with no regard to actual status, ' 'exercise caution when using)'), ) return parser def take_action(self, parsed_args): LOG_DEP.warning(_('This command has been deprecated. ' 'Please use "volume snapshot set" instead.')) volume_client = self.app.client_manager.volume snapshot = utils.find_resource(volume_client.volume_snapshots, parsed_args.snapshot) result = 0 if parsed_args.property: try: volume_client.volume_snapshots.set_metadata( snapshot.id, parsed_args.property) except Exception as e: LOG.error(_("Failed to set snapshot property: %s"), e) result += 1 if parsed_args.state: try: volume_client.volume_snapshots.reset_state( snapshot.id, parsed_args.state) except Exception as e: LOG.error(_("Failed to set snapshot state: %s"), e) result += 1 kwargs = {} if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.description: kwargs['description'] = parsed_args.description if kwargs: try: volume_client.volume_snapshots.update( snapshot.id, **kwargs) except Exception as e: LOG.error(_("Failed to update snapshot name " "or description: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("One or more of the " "set operations failed")) class ShowSnapshot(command.ShowOne): _description = _("Display snapshot details") def get_parser(self, prog_name): parser = super(ShowSnapshot, self).get_parser(prog_name) parser.add_argument( "snapshot", metavar="", help=_("Snapshot to display (name or ID)") ) return parser def take_action(self, parsed_args): LOG_DEP.warning(_('This command has been deprecated. ' 'Please use "volume snapshot show" instead.')) volume_client = self.app.client_manager.volume snapshot = utils.find_resource( volume_client.volume_snapshots, parsed_args.snapshot) snapshot._info.update( {'properties': utils.format_dict(snapshot._info.pop('metadata'))} ) return zip(*sorted(six.iteritems(snapshot._info))) class UnsetSnapshot(command.Command): _description = _("Unset snapshot properties") def get_parser(self, prog_name): parser = super(UnsetSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshot', metavar='', help=_('Snapshot to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action='append', default=[], help=_('Property to remove from snapshot ' '(repeat option to remove multiple properties)'), ) return parser def take_action(self, parsed_args): LOG_DEP.warning(_('This command has been deprecated. ' 'Please use "volume snapshot unset" instead.')) volume_client = self.app.client_manager.volume snapshot = utils.find_resource( volume_client.volume_snapshots, parsed_args.snapshot) if parsed_args.property: volume_client.volume_snapshots.delete_metadata( snapshot.id, parsed_args.property, ) python-openstackclient-3.14.0/openstackclient/volume/v2/volume_transfer_request.py0000666000175100017510000001601113232364361030715 0ustar zuulzuul00000000000000# # 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. # """Volume v2 transfer action implementations""" import argparse import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class AcceptTransferRequest(command.ShowOne): _description = _("Accept volume transfer request.") def get_parser(self, prog_name): parser = super(AcceptTransferRequest, self).get_parser(prog_name) parser.add_argument( 'transfer_request', metavar="", help=_('Volume transfer request to accept (ID only)'), ) parser.add_argument( 'old_auth_key', metavar="", nargs="?", help=argparse.SUPPRESS, ) parser.add_argument( '--auth-key', metavar="", help=_('Volume transfer request authentication key'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume try: transfer_request_id = utils.find_resource( volume_client.transfers, parsed_args.transfer_request ).id except exceptions.CommandError: # Non-admin users will fail to lookup name -> ID so we just # move on and attempt with the user-supplied information transfer_request_id = parsed_args.transfer_request # Remain backward-compatible for the previous command layout # TODO(dtroyer): Remove this back-compat in 4.0 or Oct 2017 if not parsed_args.auth_key: if parsed_args.old_auth_key: # Move the old one into the correct place parsed_args.auth_key = parsed_args.old_auth_key self.log.warning(_( 'Specifying the auth-key as a positional argument ' 'has been deprecated. Please use the --auth-key ' 'option in the future.' )) else: msg = _("argument --auth-key is required") raise exceptions.CommandError(msg) transfer_accept = volume_client.transfers.accept( transfer_request_id, parsed_args.auth_key, ) transfer_accept._info.pop("links", None) return zip(*sorted(six.iteritems(transfer_accept._info))) class CreateTransferRequest(command.ShowOne): _description = _("Create volume transfer request.") def get_parser(self, prog_name): parser = super(CreateTransferRequest, self).get_parser(prog_name) parser.add_argument( '--name', metavar="", help=_('New transfer request name (default to None)'), ) parser.add_argument( 'volume', metavar="", help=_('Volume to transfer (name or ID)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume_id = utils.find_resource( volume_client.volumes, parsed_args.volume, ).id volume_transfer_request = volume_client.transfers.create( volume_id, parsed_args.name, ) volume_transfer_request._info.pop("links", None) return zip(*sorted(six.iteritems(volume_transfer_request._info))) class DeleteTransferRequest(command.Command): _description = _("Delete volume transfer request(s).") def get_parser(self, prog_name): parser = super(DeleteTransferRequest, self).get_parser(prog_name) parser.add_argument( 'transfer_request', metavar="", nargs="+", help=_('Volume transfer request(s) to delete (name or ID)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for t in parsed_args.transfer_request: try: transfer_request_id = utils.find_resource( volume_client.transfers, t, ).id volume_client.transfers.delete(transfer_request_id) except Exception as e: result += 1 LOG.error(_("Failed to delete volume transfer request " "with name or ID '%(transfer)s': %(e)s") % {'transfer': t, 'e': e}) if result > 0: total = len(parsed_args.transfer_request) msg = (_("%(result)s of %(total)s volume transfer requests failed" " to delete") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListTransferRequest(command.Lister): _description = _("Lists all volume transfer requests.") def get_parser(self, prog_name): parser = super(ListTransferRequest, self).get_parser(prog_name) parser.add_argument( '--all-projects', dest='all_projects', action="store_true", default=False, help=_('Include all projects (admin only)'), ) return parser def take_action(self, parsed_args): columns = ['ID', 'Name', 'Volume ID'] column_headers = ['ID', 'Name', 'Volume'] volume_client = self.app.client_manager.volume volume_transfer_result = volume_client.transfers.list( detailed=True, search_opts={'all_tenants': parsed_args.all_projects}, ) return (column_headers, ( utils.get_item_properties(s, columns) for s in volume_transfer_result)) class ShowTransferRequest(command.ShowOne): _description = _("Show volume transfer request details.") def get_parser(self, prog_name): parser = super(ShowTransferRequest, self).get_parser(prog_name) parser.add_argument( 'transfer_request', metavar="", help=_('Volume transfer request to display (name or ID)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume_transfer_request = utils.find_resource( volume_client.transfers, parsed_args.transfer_request, ) volume_transfer_request._info.pop("links", None) return zip(*sorted(six.iteritems(volume_transfer_request._info))) python-openstackclient-3.14.0/openstackclient/volume/v2/consistency_group.py0000666000175100017510000003004413232364361027511 0ustar zuulzuul00000000000000# # 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. # """Volume v2 consistency group action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) def _find_volumes(parsed_args_volumes, volume_client): result = 0 uuid = '' for volume in parsed_args_volumes: try: volume_id = utils.find_resource( volume_client.volumes, volume).id uuid += volume_id + ',' except Exception as e: result += 1 LOG.error(_("Failed to find volume with " "name or ID '%(volume)s':%(e)s") % {'volume': volume, 'e': e}) return result, uuid class AddVolumeToConsistencyGroup(command.Command): _description = _("Add volume(s) to consistency group") def get_parser(self, prog_name): parser = super(AddVolumeToConsistencyGroup, self).get_parser(prog_name) parser.add_argument( 'consistency_group', metavar="", help=_('Consistency group to contain (name or ID)'), ) parser.add_argument( 'volumes', metavar='', nargs='+', help=_('Volume(s) to add to (name or ID) ' '(repeat option to add multiple volumes)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result, add_uuid = _find_volumes(parsed_args.volumes, volume_client) if result > 0: total = len(parsed_args.volumes) LOG.error(_("%(result)s of %(total)s volumes failed " "to add.") % {'result': result, 'total': total}) if add_uuid: add_uuid = add_uuid.rstrip(',') consistency_group_id = utils.find_resource( volume_client.consistencygroups, parsed_args.consistency_group).id volume_client.consistencygroups.update( consistency_group_id, add_volumes=add_uuid) class CreateConsistencyGroup(command.ShowOne): _description = _("Create new consistency group.") def get_parser(self, prog_name): parser = super(CreateConsistencyGroup, self).get_parser(prog_name) parser.add_argument( "name", metavar="", nargs="?", help=_("Name of new consistency group (default to None)") ) exclusive_group = parser.add_mutually_exclusive_group(required=True) exclusive_group.add_argument( "--volume-type", metavar="", help=_("Volume type of this consistency group (name or ID)") ) exclusive_group.add_argument( "--consistency-group-source", metavar="", help=_("Existing consistency group (name or ID)") ) exclusive_group.add_argument( "--consistency-group-snapshot", metavar="", help=_("Existing consistency group snapshot (name or ID)") ) parser.add_argument( "--description", metavar="", help=_("Description of this consistency group") ) parser.add_argument( "--availability-zone", metavar="", help=_("Availability zone for this consistency group " "(not available if creating consistency group " "from source)"), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume if parsed_args.volume_type: volume_type_id = utils.find_resource( volume_client.volume_types, parsed_args.volume_type).id consistency_group = volume_client.consistencygroups.create( volume_type_id, name=parsed_args.name, description=parsed_args.description, availability_zone=parsed_args.availability_zone ) else: if parsed_args.availability_zone: msg = _("'--availability-zone' option will not work " "if creating consistency group from source") LOG.warning(msg) consistency_group_id = None consistency_group_snapshot = None if parsed_args.consistency_group_source: consistency_group_id = utils.find_resource( volume_client.consistencygroups, parsed_args.consistency_group_source).id elif parsed_args.consistency_group_snapshot: consistency_group_snapshot = utils.find_resource( volume_client.cgsnapshots, parsed_args.consistency_group_snapshot).id consistency_group = ( volume_client.consistencygroups.create_from_src( consistency_group_snapshot, consistency_group_id, name=parsed_args.name, description=parsed_args.description ) ) return zip(*sorted(six.iteritems(consistency_group._info))) class DeleteConsistencyGroup(command.Command): _description = _("Delete consistency group(s).") def get_parser(self, prog_name): parser = super(DeleteConsistencyGroup, self).get_parser(prog_name) parser.add_argument( 'consistency_groups', metavar='', nargs="+", help=_('Consistency group(s) to delete (name or ID)'), ) parser.add_argument( '--force', action='store_true', default=False, help=_("Allow delete in state other than error or available"), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for i in parsed_args.consistency_groups: try: consistency_group_id = utils.find_resource( volume_client.consistencygroups, i).id volume_client.consistencygroups.delete( consistency_group_id, parsed_args.force) except Exception as e: result += 1 LOG.error(_("Failed to delete consistency group with " "name or ID '%(consistency_group)s':%(e)s") % {'consistency_group': i, 'e': e}) if result > 0: total = len(parsed_args.consistency_groups) msg = (_("%(result)s of %(total)s consistency groups failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListConsistencyGroup(command.Lister): _description = _("List consistency groups.") def get_parser(self, prog_name): parser = super(ListConsistencyGroup, self).get_parser(prog_name) parser.add_argument( '--all-projects', action="store_true", help=_('Show details for all projects. Admin only. ' '(defaults to False)') ) parser.add_argument( '--long', action="store_true", help=_('List additional fields in output') ) return parser def take_action(self, parsed_args): if parsed_args.long: columns = ['ID', 'Status', 'Availability Zone', 'Name', 'Description', 'Volume Types'] else: columns = ['ID', 'Status', 'Name'] volume_client = self.app.client_manager.volume consistency_groups = volume_client.consistencygroups.list( detailed=True, search_opts={'all_tenants': parsed_args.all_projects} ) return (columns, ( utils.get_item_properties( s, columns, formatters={'Volume Types': utils.format_list}) for s in consistency_groups)) class RemoveVolumeFromConsistencyGroup(command.Command): _description = _("Remove volume(s) from consistency group") def get_parser(self, prog_name): parser = \ super(RemoveVolumeFromConsistencyGroup, self).get_parser(prog_name) parser.add_argument( 'consistency_group', metavar="", help=_('Consistency group containing (name or ID)'), ) parser.add_argument( 'volumes', metavar='', nargs='+', help=_('Volume(s) to remove from (name or ID) ' '(repeat option to remove multiple volumes)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result, remove_uuid = _find_volumes(parsed_args.volumes, volume_client) if result > 0: total = len(parsed_args.volumes) LOG.error(_("%(result)s of %(total)s volumes failed " "to remove.") % {'result': result, 'total': total}) if remove_uuid: remove_uuid = remove_uuid.rstrip(',') consistency_group_id = utils.find_resource( volume_client.consistencygroups, parsed_args.consistency_group).id volume_client.consistencygroups.update( consistency_group_id, remove_volumes=remove_uuid) class SetConsistencyGroup(command.Command): _description = _("Set consistency group properties") def get_parser(self, prog_name): parser = super(SetConsistencyGroup, self).get_parser(prog_name) parser.add_argument( 'consistency_group', metavar='', help=_('Consistency group to modify (name or ID)') ) parser.add_argument( '--name', metavar='', help=_('New consistency group name'), ) parser.add_argument( '--description', metavar='', help=_('New consistency group description'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume kwargs = {} if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.description: kwargs['description'] = parsed_args.description if kwargs: consistency_group_id = utils.find_resource( volume_client.consistencygroups, parsed_args.consistency_group).id volume_client.consistencygroups.update( consistency_group_id, **kwargs) class ShowConsistencyGroup(command.ShowOne): _description = _("Display consistency group details.") def get_parser(self, prog_name): parser = super(ShowConsistencyGroup, self).get_parser(prog_name) parser.add_argument( "consistency_group", metavar="", help=_("Consistency group to display (name or ID)") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume consistency_group = utils.find_resource( volume_client.consistencygroups, parsed_args.consistency_group) return zip(*sorted(six.iteritems(consistency_group._info))) python-openstackclient-3.14.0/openstackclient/volume/v2/volume_snapshot.py0000666000175100017510000003630513232364361027170 0ustar zuulzuul00000000000000# # 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. # """Volume v2 snapshot action implementations""" import copy import logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common as identity_common LOG = logging.getLogger(__name__) class CreateVolumeSnapshot(command.ShowOne): _description = _("Create new volume snapshot") def get_parser(self, prog_name): parser = super(CreateVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( "snapshot_name", metavar="", help=_("Name of the new snapshot"), ) parser.add_argument( "--volume", metavar="", help=_("Volume to snapshot (name or ID) " "(default is )") ) parser.add_argument( "--description", metavar="", help=_("Description of the snapshot") ) parser.add_argument( "--force", action="store_true", default=False, help=_("Create a snapshot attached to an instance. " "Default is False") ) parser.add_argument( "--property", metavar="", action=parseractions.KeyValueAction, help=_("Set a property to this snapshot " "(repeat option to set multiple properties)"), ) parser.add_argument( "--remote-source", metavar="", action=parseractions.KeyValueAction, help=_("The attribute(s) of the exsiting remote volume snapshot " "(admin required) (repeat option to specify multiple " "attributes) e.g.: '--remote-source source-name=test_name " "--remote-source source-id=test_id'"), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume = parsed_args.volume if not parsed_args.volume: volume = parsed_args.snapshot_name volume_id = utils.find_resource( volume_client.volumes, volume).id if parsed_args.remote_source: # Create a new snapshot from an existing remote snapshot source if parsed_args.force: msg = (_("'--force' option will not work when you create " "new volume snapshot from an existing remote " "volume snapshot")) LOG.warning(msg) snapshot = volume_client.volume_snapshots.manage( volume_id=volume_id, ref=parsed_args.remote_source, name=parsed_args.snapshot_name, description=parsed_args.description, metadata=parsed_args.property, ) else: # create a new snapshot from scratch snapshot = volume_client.volume_snapshots.create( volume_id, force=parsed_args.force, name=parsed_args.snapshot_name, description=parsed_args.description, metadata=parsed_args.property, ) snapshot._info.update( {'properties': utils.format_dict(snapshot._info.pop('metadata'))} ) return zip(*sorted(six.iteritems(snapshot._info))) class DeleteVolumeSnapshot(command.Command): _description = _("Delete volume snapshot(s)") def get_parser(self, prog_name): parser = super(DeleteVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( "snapshots", metavar="", nargs="+", help=_("Snapshot(s) to delete (name or ID)") ) parser.add_argument( '--force', action='store_true', help=_("Attempt forced removal of snapshot(s), " "regardless of state (defaults to False)") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for i in parsed_args.snapshots: try: snapshot_id = utils.find_resource( volume_client.volume_snapshots, i).id volume_client.volume_snapshots.delete( snapshot_id, parsed_args.force) except Exception as e: result += 1 LOG.error(_("Failed to delete snapshot with " "name or ID '%(snapshot)s': %(e)s") % {'snapshot': i, 'e': e}) if result > 0: total = len(parsed_args.snapshots) msg = (_("%(result)s of %(total)s snapshots failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListVolumeSnapshot(command.Lister): _description = _("List volume snapshots") def get_parser(self, prog_name): parser = super(ListVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( '--all-projects', action='store_true', default=False, help=_('Include all projects (admin only)'), ) parser.add_argument( '--project', metavar='', help=_('Filter results by project (name or ID) (admin only)') ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( '--marker', metavar='', help=_('The last snapshot ID of the previous page'), ) parser.add_argument( '--limit', type=int, action=parseractions.NonNegativeAction, metavar='', help=_('Maximum number of snapshots to display'), ) parser.add_argument( '--name', metavar='', default=None, help=_('Filters results by a name.') ) parser.add_argument( '--status', metavar='', choices=['available', 'error', 'creating', 'deleting', 'error-deleting'], help=_("Filters results by a status. " "('available', 'error', 'creating', 'deleting'" " or 'error-deleting')") ) parser.add_argument( '--volume', metavar='', default=None, help=_('Filters results by a volume (name or ID).') ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume identity_client = self.app.client_manager.identity def _format_volume_id(volume_id): """Return a volume name if available :param volume_id: a volume ID :rtype: either the volume ID or name """ volume = volume_id if volume_id in volume_cache.keys(): volume = volume_cache[volume_id].name return volume if parsed_args.long: columns = ['ID', 'Name', 'Description', 'Status', 'Size', 'Created At', 'Volume ID', 'Metadata'] column_headers = copy.deepcopy(columns) column_headers[6] = 'Volume' column_headers[7] = 'Properties' else: columns = ['ID', 'Name', 'Description', 'Status', 'Size'] column_headers = copy.deepcopy(columns) # Cache the volume list volume_cache = {} try: for s in volume_client.volumes.list(): volume_cache[s.id] = s except Exception: # Just forget it if there's any trouble pass volume_id = None if parsed_args.volume: volume_id = utils.find_resource( volume_client.volumes, parsed_args.volume).id project_id = None if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain).id # set value of 'all_tenants' when using project option all_projects = True if parsed_args.project else \ parsed_args.all_projects search_opts = { 'all_tenants': all_projects, 'project_id': project_id, 'name': parsed_args.name, 'status': parsed_args.status, 'volume_id': volume_id, } data = volume_client.volume_snapshots.list( search_opts=search_opts, marker=parsed_args.marker, limit=parsed_args.limit, ) return (column_headers, (utils.get_item_properties( s, columns, formatters={'Metadata': utils.format_dict, 'Volume ID': _format_volume_id}, ) for s in data)) class SetVolumeSnapshot(command.Command): _description = _("Set volume snapshot properties") def get_parser(self, prog_name): parser = super(SetVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshot', metavar='', help=_('Snapshot to modify (name or ID)') ) parser.add_argument( '--name', metavar='', help=_('New snapshot name') ) parser.add_argument( '--description', metavar='', help=_('New snapshot description') ) parser.add_argument( "--no-property", dest="no_property", action="store_true", help=_("Remove all properties from " "(specify both --no-property and --property to " "remove the current properties before setting " "new properties.)"), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Property to add/change for this snapshot ' '(repeat option to set multiple properties)'), ) parser.add_argument( '--state', metavar='', choices=['available', 'error', 'creating', 'deleting', 'error-deleting'], help=_('New snapshot state. ("available", "error", "creating", ' '"deleting", or "error_deleting") (admin only) ' '(This option simply changes the state of the snapshot ' 'in the database with no regard to actual status, ' 'exercise caution when using)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume snapshot = utils.find_resource(volume_client.volume_snapshots, parsed_args.snapshot) result = 0 if parsed_args.no_property: try: key_list = snapshot.metadata.keys() volume_client.volume_snapshots.delete_metadata( snapshot.id, list(key_list), ) except Exception as e: LOG.error(_("Failed to clean snapshot properties: %s"), e) result += 1 if parsed_args.property: try: volume_client.volume_snapshots.set_metadata( snapshot.id, parsed_args.property) except Exception as e: LOG.error(_("Failed to set snapshot property: %s"), e) result += 1 if parsed_args.state: try: volume_client.volume_snapshots.reset_state( snapshot.id, parsed_args.state) except Exception as e: LOG.error(_("Failed to set snapshot state: %s"), e) result += 1 kwargs = {} if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.description: kwargs['description'] = parsed_args.description if kwargs: try: volume_client.volume_snapshots.update( snapshot.id, **kwargs) except Exception as e: LOG.error(_("Failed to update snapshot name " "or description: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("One or more of the " "set operations failed")) class ShowVolumeSnapshot(command.ShowOne): _description = _("Display volume snapshot details") def get_parser(self, prog_name): parser = super(ShowVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( "snapshot", metavar="", help=_("Snapshot to display (name or ID)") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume snapshot = utils.find_resource( volume_client.volume_snapshots, parsed_args.snapshot) snapshot._info.update( {'properties': utils.format_dict(snapshot._info.pop('metadata'))} ) return zip(*sorted(six.iteritems(snapshot._info))) class UnsetVolumeSnapshot(command.Command): _description = _("Unset volume snapshot properties") def get_parser(self, prog_name): parser = super(UnsetVolumeSnapshot, self).get_parser(prog_name) parser.add_argument( 'snapshot', metavar='', help=_('Snapshot to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action='append', default=[], help=_('Property to remove from snapshot ' '(repeat option to remove multiple properties)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume snapshot = utils.find_resource( volume_client.volume_snapshots, parsed_args.snapshot) if parsed_args.property: volume_client.volume_snapshots.delete_metadata( snapshot.id, parsed_args.property, ) python-openstackclient-3.14.0/openstackclient/volume/v2/volume_host.py0000666000175100017510000000506213232364361026302 0ustar zuulzuul00000000000000# # 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. # """Volume v2 host action implementations""" from osc_lib.command import command from openstackclient.i18n import _ class FailoverVolumeHost(command.Command): _description = _("Failover volume host to different backend") def get_parser(self, prog_name): parser = super(FailoverVolumeHost, self).get_parser(prog_name) parser.add_argument( "host", metavar="", help=_("Name of volume host") ) parser.add_argument( "--volume-backend", metavar="", required=True, help=_("The ID of the volume backend replication " "target where the host will failover to (required)") ) return parser def take_action(self, parsed_args): service_client = self.app.client_manager.volume service_client.services.failover_host(parsed_args.host, parsed_args.volume_backend) class SetVolumeHost(command.Command): _description = _("Set volume host properties") def get_parser(self, prog_name): parser = super(SetVolumeHost, self).get_parser(prog_name) parser.add_argument( "host", metavar="", help=_("Name of volume host") ) enabled_group = parser.add_mutually_exclusive_group() enabled_group.add_argument( "--disable", action="store_true", help=_("Freeze and disable the specified volume host") ) enabled_group.add_argument( "--enable", action="store_true", help=_("Thaw and enable the specified volume host") ) return parser def take_action(self, parsed_args): service_client = self.app.client_manager.volume if parsed_args.enable: service_client.services.thaw_host(parsed_args.host) if parsed_args.disable: service_client.services.freeze_host(parsed_args.host) python-openstackclient-3.14.0/openstackclient/volume/v2/volume_type.py0000666000175100017510000005571113232364361026314 0ustar zuulzuul00000000000000# # 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. # """Volume v2 Type action implementations""" import logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common as identity_common LOG = logging.getLogger(__name__) def _create_encryption_type(volume_client, volume_type, parsed_args): if not parsed_args.encryption_provider: msg = _("'--encryption-provider' should be specified while " "creating a new encryption type") raise exceptions.CommandError(msg) # set the default of control location while creating control_location = 'front-end' if parsed_args.encryption_control_location: control_location = parsed_args.encryption_control_location body = { 'provider': parsed_args.encryption_provider, 'cipher': parsed_args.encryption_cipher, 'key_size': parsed_args.encryption_key_size, 'control_location': control_location } encryption = volume_client.volume_encryption_types.create( volume_type, body) return encryption def _set_encryption_type(volume_client, volume_type, parsed_args): # update the existing encryption type body = {} for attr in ['provider', 'cipher', 'key_size', 'control_location']: info = getattr(parsed_args, 'encryption_' + attr, None) if info is not None: body[attr] = info try: volume_client.volume_encryption_types.update(volume_type, body) except Exception as e: if type(e).__name__ == 'NotFound': # create new encryption type LOG.warning(_("No existing encryption type found, creating " "new encryption type for this volume type ...")) _create_encryption_type( volume_client, volume_type, parsed_args) class CreateVolumeType(command.ShowOne): _description = _("Create new volume type") def get_parser(self, prog_name): parser = super(CreateVolumeType, self).get_parser(prog_name) parser.add_argument( "name", metavar="", help=_("Volume type name"), ) parser.add_argument( "--description", metavar="", help=_("Volume type description"), ) public_group = parser.add_mutually_exclusive_group() public_group.add_argument( "--public", action="store_true", default=False, help=_("Volume type is accessible to the public"), ) public_group.add_argument( "--private", action="store_true", default=False, help=_("Volume type is not accessible to the public"), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Set a property on this volume type ' '(repeat option to set multiple properties)'), ) parser.add_argument( '--project', metavar='', help=_("Allow to access private type (name or ID) " "(Must be used with --private option)"), ) # TODO(Huanxuan Ao): Add choices for each "--encryption-*" option. parser.add_argument( '--encryption-provider', metavar='', help=_('Set the class that provides encryption support for ' 'this volume type (e.g "LuksEncryptor") (admin only) ' '(This option is required when setting encryption type ' 'of a volume. Consider using other encryption options ' 'such as: "--encryption-cipher", "--encryption-key-size" ' 'and "--encryption-control-location")'), ) parser.add_argument( '--encryption-cipher', metavar='', help=_('Set the encryption algorithm or mode for this ' 'volume type (e.g "aes-xts-plain64") (admin only)'), ) parser.add_argument( '--encryption-key-size', metavar='', type=int, help=_('Set the size of the encryption key of this ' 'volume type (e.g "128" or "256") (admin only)'), ) parser.add_argument( '--encryption-control-location', metavar='', choices=['front-end', 'back-end'], help=_('Set the notional service where the encryption is ' 'performed ("front-end" or "back-end") (admin only) ' '(The default value for this option is "front-end" ' 'when setting encryption type of a volume. Consider ' 'using other encryption options such as: ' '"--encryption-cipher", "--encryption-key-size" and ' '"--encryption-provider")'), ) identity_common.add_project_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity volume_client = self.app.client_manager.volume if parsed_args.project and not parsed_args.private: msg = _("--project is only allowed with --private") raise exceptions.CommandError(msg) kwargs = {} if parsed_args.public: kwargs['is_public'] = True if parsed_args.private: kwargs['is_public'] = False volume_type = volume_client.volume_types.create( parsed_args.name, description=parsed_args.description, **kwargs ) volume_type._info.pop('extra_specs') if parsed_args.project: try: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id volume_client.volume_type_access.add_project_access( volume_type.id, project_id) except Exception as e: msg = _("Failed to add project %(project)s access to " "type: %(e)s") LOG.error(msg % {'project': parsed_args.project, 'e': e}) if parsed_args.property: result = volume_type.set_keys(parsed_args.property) volume_type._info.update({'properties': utils.format_dict(result)}) if (parsed_args.encryption_provider or parsed_args.encryption_cipher or parsed_args.encryption_key_size or parsed_args.encryption_control_location): try: # create new encryption encryption = _create_encryption_type( volume_client, volume_type, parsed_args) except Exception as e: LOG.error(_("Failed to set encryption information for this " "volume type: %s"), e) # add encryption info in result encryption._info.pop("volume_type_id", None) volume_type._info.update( {'encryption': utils.format_dict(encryption._info)}) volume_type._info.pop("os-volume-type-access:is_public", None) return zip(*sorted(six.iteritems(volume_type._info))) class DeleteVolumeType(command.Command): _description = _("Delete volume type(s)") def get_parser(self, prog_name): parser = super(DeleteVolumeType, self).get_parser(prog_name) parser.add_argument( "volume_types", metavar="", nargs="+", help=_("Volume type(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for volume_type in parsed_args.volume_types: try: vol_type = utils.find_resource(volume_client.volume_types, volume_type) volume_client.volume_types.delete(vol_type) except Exception as e: result += 1 LOG.error(_("Failed to delete volume type with " "name or ID '%(volume_type)s': %(e)s") % {'volume_type': volume_type, 'e': e}) if result > 0: total = len(parsed_args.volume_types) msg = (_("%(result)s of %(total)s volume types failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListVolumeType(command.Lister): _description = _("List volume types") def get_parser(self, prog_name): parser = super(ListVolumeType, self).get_parser(prog_name) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output') ) public_group = parser.add_mutually_exclusive_group() public_group.add_argument( "--default", action='store_true', default=False, help=_('List the default volume type') ) public_group.add_argument( "--public", action="store_true", help=_("List only public types") ) public_group.add_argument( "--private", action="store_true", help=_("List only private types (admin only)") ) parser.add_argument( "--encryption-type", action="store_true", help=_("Display encryption information for each volume type " "(admin only)"), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume if parsed_args.long: columns = ['ID', 'Name', 'Is Public', 'Description', 'Extra Specs'] column_headers = [ 'ID', 'Name', 'Is Public', 'Description', 'Properties'] else: columns = ['ID', 'Name', 'Is Public'] column_headers = ['ID', 'Name', 'Is Public'] if parsed_args.default: data = [volume_client.volume_types.default()] else: is_public = None if parsed_args.public: is_public = True if parsed_args.private: is_public = False data = volume_client.volume_types.list( is_public=is_public) def _format_encryption_info(type_id, encryption_data=None): encryption_data = encryption encryption_info = '-' if type_id in encryption_data.keys(): encryption_info = encryption_data[type_id] return encryption_info if parsed_args.encryption_type: encryption = {} for d in volume_client.volume_encryption_types.list(): volume_type_id = d._info['volume_type_id'] # remove some redundant information del_key = [ 'deleted', 'created_at', 'updated_at', 'deleted_at', 'volume_type_id' ] for key in del_key: d._info.pop(key, None) # save the encryption information with their volume type ID encryption[volume_type_id] = utils.format_dict(d._info) # We need to get volume type ID, then show encryption # information according to the ID, so use "id" to keep # difference to the real "ID" column. columns += ['id'] column_headers += ['Encryption'] return (column_headers, (utils.get_item_properties( s, columns, formatters={'Extra Specs': utils.format_dict, 'id': _format_encryption_info}, ) for s in data)) class SetVolumeType(command.Command): _description = _("Set volume type properties") def get_parser(self, prog_name): parser = super(SetVolumeType, self).get_parser(prog_name) parser.add_argument( 'volume_type', metavar='', help=_('Volume type to modify (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('Set volume type name'), ) parser.add_argument( '--description', metavar='', help=_('Set volume type description'), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Set a property on this volume type ' '(repeat option to set multiple properties)'), ) parser.add_argument( '--project', metavar='', help=_('Set volume type access to project (name or ID) ' '(admin only)'), ) identity_common.add_project_domain_option_to_parser(parser) # TODO(Huanxuan Ao): Add choices for each "--encryption-*" option. parser.add_argument( '--encryption-provider', metavar='', help=_('Set the class that provides encryption support for ' 'this volume type (e.g "LuksEncryptor") (admin only) ' '(This option is required when setting encryption type ' 'of a volume for the first time. Consider using other ' 'encryption options such as: "--encryption-cipher", ' '"--encryption-key-size" and ' '"--encryption-control-location")'), ) parser.add_argument( '--encryption-cipher', metavar='', help=_('Set the encryption algorithm or mode for this ' 'volume type (e.g "aes-xts-plain64") (admin only)'), ) parser.add_argument( '--encryption-key-size', metavar='', type=int, help=_('Set the size of the encryption key of this ' 'volume type (e.g "128" or "256") (admin only)'), ) parser.add_argument( '--encryption-control-location', metavar='', choices=['front-end', 'back-end'], help=_('Set the notional service where the encryption is ' 'performed ("front-end" or "back-end") (admin only) ' '(The default value for this option is "front-end" ' 'when setting encryption type of a volume for the ' 'first time. Consider using other encryption options ' 'such as: "--encryption-cipher", "--encryption-key-size" ' 'and "--encryption-provider")'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume identity_client = self.app.client_manager.identity volume_type = utils.find_resource( volume_client.volume_types, parsed_args.volume_type) result = 0 kwargs = {} if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.description: kwargs['description'] = parsed_args.description if kwargs: try: volume_client.volume_types.update( volume_type.id, **kwargs ) except Exception as e: LOG.error(_("Failed to update volume type name or" " description: %s"), e) result += 1 if parsed_args.property: try: volume_type.set_keys(parsed_args.property) except Exception as e: LOG.error(_("Failed to set volume type property: %s"), e) result += 1 if parsed_args.project: project_info = None try: project_info = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain) volume_client.volume_type_access.add_project_access( volume_type.id, project_info.id) except Exception as e: LOG.error(_("Failed to set volume type access to " "project: %s"), e) result += 1 if (parsed_args.encryption_provider or parsed_args.encryption_cipher or parsed_args.encryption_key_size or parsed_args.encryption_control_location): try: _set_encryption_type(volume_client, volume_type, parsed_args) except Exception as e: LOG.error(_("Failed to set encryption information for this " "volume type: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("Command Failed: One or more of" " the operations failed")) class ShowVolumeType(command.ShowOne): _description = _("Display volume type details") def get_parser(self, prog_name): parser = super(ShowVolumeType, self).get_parser(prog_name) parser.add_argument( "volume_type", metavar="", help=_("Volume type to display (name or ID)") ) parser.add_argument( "--encryption-type", action="store_true", help=_("Display encryption information of this volume type " "(admin only)"), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume_type = utils.find_resource( volume_client.volume_types, parsed_args.volume_type) properties = utils.format_dict( volume_type._info.pop('extra_specs', {})) volume_type._info.update({'properties': properties}) access_project_ids = None if not volume_type.is_public: try: volume_type_access = volume_client.volume_type_access.list( volume_type.id) project_ids = [utils.get_field(item, 'project_id') for item in volume_type_access] # TODO(Rui Chen): This format list case can be removed after # patch https://review.openstack.org/#/c/330223/ merged. access_project_ids = utils.format_list(project_ids) except Exception as e: msg = _('Failed to get access project list for volume type ' '%(type)s: %(e)s') LOG.error(msg % {'type': volume_type.id, 'e': e}) volume_type._info.update({'access_project_ids': access_project_ids}) if parsed_args.encryption_type: # show encryption type information for this volume type try: encryption = volume_client.volume_encryption_types.get( volume_type.id) encryption._info.pop("volume_type_id", None) volume_type._info.update( {'encryption': utils.format_dict(encryption._info)}) except Exception as e: LOG.error(_("Failed to display the encryption information " "of this volume type: %s"), e) volume_type._info.pop("os-volume-type-access:is_public", None) return zip(*sorted(six.iteritems(volume_type._info))) class UnsetVolumeType(command.Command): _description = _("Unset volume type properties") def get_parser(self, prog_name): parser = super(UnsetVolumeType, self).get_parser(prog_name) parser.add_argument( 'volume_type', metavar='', help=_('Volume type to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action='append', help=_('Remove a property from this volume type ' '(repeat option to remove multiple properties)'), ) parser.add_argument( '--project', metavar='', help=_('Removes volume type access to project (name or ID) ' '(admin only)'), ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( "--encryption-type", action="store_true", help=_("Remove the encryption type for this volume type " "(admin only)"), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume identity_client = self.app.client_manager.identity volume_type = utils.find_resource( volume_client.volume_types, parsed_args.volume_type, ) result = 0 if parsed_args.property: try: volume_type.unset_keys(parsed_args.property) except Exception as e: LOG.error(_("Failed to unset volume type property: %s"), e) result += 1 if parsed_args.project: project_info = None try: project_info = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain) volume_client.volume_type_access.remove_project_access( volume_type.id, project_info.id) except Exception as e: LOG.error(_("Failed to remove volume type access from " "project: %s"), e) result += 1 if parsed_args.encryption_type: try: volume_client.volume_encryption_types.delete(volume_type) except Exception as e: LOG.error(_("Failed to remove the encryption type for this " "volume type: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("Command Failed: One or more of" " the operations failed")) python-openstackclient-3.14.0/openstackclient/volume/v2/backup.py0000666000175100017510000003513613232364361025210 0ustar zuulzuul00000000000000# # 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. # """Volume v2 Backup action implementations""" import copy import logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateVolumeBackup(command.ShowOne): _description = _("Create new volume backup") def get_parser(self, prog_name): parser = super(CreateVolumeBackup, self).get_parser(prog_name) parser.add_argument( "volume", metavar="", help=_("Volume to backup (name or ID)") ) parser.add_argument( "--name", metavar="", help=_("Name of the backup") ) parser.add_argument( "--description", metavar="", help=_("Description of the backup") ) parser.add_argument( "--container", metavar="", help=_("Optional backup container name") ) parser.add_argument( "--snapshot", metavar="", help=_("Snapshot to backup (name or ID)") ) parser.add_argument( '--force', action='store_true', default=False, help=_("Allow to back up an in-use volume") ) parser.add_argument( '--incremental', action='store_true', default=False, help=_("Perform an incremental backup") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume_id = utils.find_resource( volume_client.volumes, parsed_args.volume).id snapshot_id = None if parsed_args.snapshot: snapshot_id = utils.find_resource( volume_client.volume_snapshots, parsed_args.snapshot).id backup = volume_client.backups.create( volume_id, container=parsed_args.container, name=parsed_args.name, description=parsed_args.description, force=parsed_args.force, incremental=parsed_args.incremental, snapshot_id=snapshot_id, ) backup._info.pop("links", None) return zip(*sorted(six.iteritems(backup._info))) class CreateBackup(CreateVolumeBackup): _description = _("Create new backup") # TODO(Huanxuan Ao): Remove this class and ``backup create`` command # two cycles after Newton. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "volume backup create" instead.')) return super(CreateBackup, self).take_action(parsed_args) class DeleteVolumeBackup(command.Command): _description = _("Delete volume backup(s)") def get_parser(self, prog_name): parser = super(DeleteVolumeBackup, self).get_parser(prog_name) parser.add_argument( "backups", metavar="", nargs="+", help=_("Backup(s) to delete (name or ID)") ) parser.add_argument( '--force', action='store_true', default=False, help=_("Allow delete in state other than error or available") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for i in parsed_args.backups: try: backup_id = utils.find_resource( volume_client.backups, i).id volume_client.backups.delete(backup_id, parsed_args.force) except Exception as e: result += 1 LOG.error(_("Failed to delete backup with " "name or ID '%(backup)s': %(e)s") % {'backup': i, 'e': e}) if result > 0: total = len(parsed_args.backups) msg = (_("%(result)s of %(total)s backups failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class DeleteBackup(DeleteVolumeBackup): _description = _("Delete backup(s)") # TODO(Huanxuan Ao): Remove this class and ``backup delete`` command # two cycles after Newton. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "volume backup delete" instead.')) return super(DeleteBackup, self).take_action(parsed_args) class ListVolumeBackup(command.Lister): _description = _("List volume backups") def get_parser(self, prog_name): parser = super(ListVolumeBackup, self).get_parser(prog_name) parser.add_argument( "--long", action="store_true", default=False, help=_("List additional fields in output") ) parser.add_argument( "--name", metavar="", help=_("Filters results by the backup name") ) parser.add_argument( "--status", metavar="", choices=['creating', 'available', 'deleting', 'error', 'restoring', 'error_restoring'], help=_("Filters results by the backup status " "('creating', 'available', 'deleting', " "'error', 'restoring' or 'error_restoring')") ) parser.add_argument( "--volume", metavar="", help=_("Filters results by the volume which they " "backup (name or ID)") ) parser.add_argument( '--marker', metavar='', help=_('The last backup of the previous page (name or ID)'), ) parser.add_argument( '--limit', type=int, action=parseractions.NonNegativeAction, metavar='', help=_('Maximum number of backups to display'), ) parser.add_argument( '--all-projects', action='store_true', default=False, help=_('Include all projects (admin only)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume def _format_volume_id(volume_id): """Return a volume name if available :param volume_id: a volume ID :rtype: either the volume ID or name """ volume = volume_id if volume_id in volume_cache.keys(): volume = volume_cache[volume_id].name return volume if parsed_args.long: columns = ['ID', 'Name', 'Description', 'Status', 'Size', 'Availability Zone', 'Volume ID', 'Container'] column_headers = copy.deepcopy(columns) column_headers[6] = 'Volume' else: columns = ['ID', 'Name', 'Description', 'Status', 'Size'] column_headers = columns # Cache the volume list volume_cache = {} try: for s in volume_client.volumes.list(): volume_cache[s.id] = s except Exception: # Just forget it if there's any trouble pass filter_volume_id = None if parsed_args.volume: filter_volume_id = utils.find_resource(volume_client.volumes, parsed_args.volume).id marker_backup_id = None if parsed_args.marker: marker_backup_id = utils.find_resource(volume_client.backups, parsed_args.marker).id search_opts = { 'name': parsed_args.name, 'status': parsed_args.status, 'volume_id': filter_volume_id, 'all_tenants': parsed_args.all_projects, } data = volume_client.backups.list( search_opts=search_opts, marker=marker_backup_id, limit=parsed_args.limit, ) return (column_headers, (utils.get_item_properties( s, columns, formatters={'Volume ID': _format_volume_id}, ) for s in data)) class ListBackup(ListVolumeBackup): _description = _("List backups") # TODO(Huanxuan Ao): Remove this class and ``backup list`` command # two cycles after Newton. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "volume backup list" instead.')) return super(ListBackup, self).take_action(parsed_args) class RestoreVolumeBackup(command.ShowOne): _description = _("Restore volume backup") def get_parser(self, prog_name): parser = super(RestoreVolumeBackup, self).get_parser(prog_name) parser.add_argument( "backup", metavar="", help=_("Backup to restore (name or ID)") ) parser.add_argument( "volume", metavar="", help=_("Volume to restore to (name or ID)") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume backup = utils.find_resource(volume_client.backups, parsed_args.backup) destination_volume = utils.find_resource(volume_client.volumes, parsed_args.volume) return volume_client.restores.restore(backup.id, destination_volume.id) class RestoreBackup(RestoreVolumeBackup): _description = _("Restore backup") # TODO(Huanxuan Ao): Remove this class and ``backup restore`` command # two cycles after Newton. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "volume backup restore" instead.')) return super(RestoreBackup, self).take_action(parsed_args) class SetVolumeBackup(command.Command): _description = _("Set volume backup properties") def get_parser(self, prog_name): parser = super(SetVolumeBackup, self).get_parser(prog_name) parser.add_argument( "backup", metavar="", help=_("Backup to modify (name or ID)") ) parser.add_argument( '--name', metavar='', help=_('New backup name') ) parser.add_argument( '--description', metavar='', help=_('New backup description') ) parser.add_argument( '--state', metavar='', choices=['available', 'error'], help=_('New backup state ("available" or "error") (admin only) ' '(This option simply changes the state of the backup ' 'in the database with no regard to actual status, ' 'exercise caution when using)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume backup = utils.find_resource(volume_client.backups, parsed_args.backup) result = 0 if parsed_args.state: try: volume_client.backups.reset_state( backup.id, parsed_args.state) except Exception as e: LOG.error(_("Failed to set backup state: %s"), e) result += 1 kwargs = {} if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.description: kwargs['description'] = parsed_args.description if kwargs: try: volume_client.backups.update(backup.id, **kwargs) except Exception as e: LOG.error(_("Failed to update backup name " "or description: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("One or more of the " "set operations failed")) class ShowVolumeBackup(command.ShowOne): _description = _("Display volume backup details") def get_parser(self, prog_name): parser = super(ShowVolumeBackup, self).get_parser(prog_name) parser.add_argument( "backup", metavar="", help=_("Backup to display (name or ID)") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume backup = utils.find_resource(volume_client.backups, parsed_args.backup) backup._info.pop("links", None) return zip(*sorted(six.iteritems(backup._info))) class ShowBackup(ShowVolumeBackup): _description = _("Display backup details") # TODO(Huanxuan Ao): Remove this class and ``backup show`` command # two cycles after Newton. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "volume backup show" instead.')) return super(ShowBackup, self).take_action(parsed_args) python-openstackclient-3.14.0/openstackclient/volume/v2/volume.py0000666000175100017510000006671713232364361025263 0ustar zuulzuul00000000000000# # 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. # """Volume V2 Volume action implementations""" import copy import logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ from openstackclient.identity import common as identity_common LOG = logging.getLogger(__name__) def _check_size_arg(args): """Check whether --size option is required or not. Require size parameter only in case when snapshot or source volume is not specified. """ if ((args.snapshot or args.source or args.source_replicated) is None and args.size is None): msg = _("--size is a required option if snapshot " "or source volume is not specified.") raise exceptions.CommandError(msg) class CreateVolume(command.ShowOne): _description = _("Create new volume") def get_parser(self, prog_name): parser = super(CreateVolume, self).get_parser(prog_name) parser.add_argument( "name", metavar="", help=_("Volume name"), ) parser.add_argument( "--size", metavar="", type=int, help=_("Volume size in GB (Required unless --snapshot or " "--source or --source-replicated is specified)"), ) parser.add_argument( "--type", metavar="", help=_("Set the type of volume"), ) source_group = parser.add_mutually_exclusive_group() source_group.add_argument( "--image", metavar="", help=_("Use as source of volume (name or ID)"), ) source_group.add_argument( "--snapshot", metavar="", help=_("Use as source of volume (name or ID)"), ) source_group.add_argument( "--source", metavar="", help=_("Volume to clone (name or ID)"), ) source_group.add_argument( "--source-replicated", metavar="", help=_("Replicated volume to clone (name or ID)"), ) parser.add_argument( "--description", metavar="", help=_("Volume description"), ) parser.add_argument( '--user', metavar='', help=_('Specify an alternate user (name or ID)'), ) parser.add_argument( '--project', metavar='', help=_('Specify an alternate project (name or ID)'), ) parser.add_argument( "--availability-zone", metavar="", help=_("Create volume in "), ) parser.add_argument( "--consistency-group", metavar="consistency-group>", help=_("Consistency group where the new volume belongs to"), ) parser.add_argument( "--property", metavar="", action=parseractions.KeyValueAction, help=_("Set a property to this volume " "(repeat option to set multiple properties)"), ) parser.add_argument( "--hint", metavar="", action=parseractions.KeyValueAction, help=_("Arbitrary scheduler hint key-value pairs to help boot " "an instance (repeat option to set multiple hints)"), ) parser.add_argument( "--multi-attach", action="store_true", help=_("Allow volume to be attached more than once " "(default to False)") ) bootable_group = parser.add_mutually_exclusive_group() bootable_group.add_argument( "--bootable", action="store_true", help=_("Mark volume as bootable") ) bootable_group.add_argument( "--non-bootable", action="store_true", help=_("Mark volume as non-bootable (default)") ) readonly_group = parser.add_mutually_exclusive_group() readonly_group.add_argument( "--read-only", action="store_true", help=_("Set volume to read-only access mode") ) readonly_group.add_argument( "--read-write", action="store_true", help=_("Set volume to read-write access mode (default)") ) return parser def take_action(self, parsed_args): _check_size_arg(parsed_args) identity_client = self.app.client_manager.identity volume_client = self.app.client_manager.volume image_client = self.app.client_manager.image source_volume = None if parsed_args.source: source_volume = utils.find_resource( volume_client.volumes, parsed_args.source).id replicated_source_volume = None if parsed_args.source_replicated: replicated_source_volume = utils.find_resource( volume_client.volumes, parsed_args.source_replicated).id consistency_group = None if parsed_args.consistency_group: consistency_group = utils.find_resource( volume_client.consistencygroups, parsed_args.consistency_group).id image = None if parsed_args.image: image = utils.find_resource( image_client.images, parsed_args.image).id snapshot = None if parsed_args.snapshot: snapshot = utils.find_resource( volume_client.volume_snapshots, parsed_args.snapshot).id project = None if parsed_args.project: project = utils.find_resource( identity_client.projects, parsed_args.project).id user = None if parsed_args.user: user = utils.find_resource( identity_client.users, parsed_args.user).id volume = volume_client.volumes.create( size=parsed_args.size, snapshot_id=snapshot, name=parsed_args.name, description=parsed_args.description, volume_type=parsed_args.type, user_id=user, project_id=project, availability_zone=parsed_args.availability_zone, metadata=parsed_args.property, imageRef=image, source_volid=source_volume, consistencygroup_id=consistency_group, source_replica=replicated_source_volume, multiattach=parsed_args.multi_attach, scheduler_hints=parsed_args.hint, ) if parsed_args.bootable or parsed_args.non_bootable: try: volume_client.volumes.set_bootable( volume.id, parsed_args.bootable) except Exception as e: LOG.error(_("Failed to set volume bootable property: %s"), e) if parsed_args.read_only or parsed_args.read_write: try: volume_client.volumes.update_readonly_flag( volume.id, parsed_args.read_only) except Exception as e: LOG.error(_("Failed to set volume read-only access " "mode flag: %s"), e) # Remove key links from being displayed volume._info.update( { 'properties': utils.format_dict(volume._info.pop('metadata')), 'type': volume._info.pop('volume_type') } ) volume._info.pop("links", None) return zip(*sorted(six.iteritems(volume._info))) class DeleteVolume(command.Command): _description = _("Delete volume(s)") def get_parser(self, prog_name): parser = super(DeleteVolume, self).get_parser(prog_name) parser.add_argument( "volumes", metavar="", nargs="+", help=_("Volume(s) to delete (name or ID)") ) group = parser.add_mutually_exclusive_group() group.add_argument( "--force", action="store_true", help=_("Attempt forced removal of volume(s), regardless of state " "(defaults to False)") ) group.add_argument( "--purge", action="store_true", help=_("Remove any snapshots along with volume(s) " "(defaults to False)") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for i in parsed_args.volumes: try: volume_obj = utils.find_resource( volume_client.volumes, i) if parsed_args.force: volume_client.volumes.force_delete(volume_obj.id) else: volume_client.volumes.delete(volume_obj.id, cascade=parsed_args.purge) except Exception as e: result += 1 LOG.error(_("Failed to delete volume with " "name or ID '%(volume)s': %(e)s"), {'volume': i, 'e': e}) if result > 0: total = len(parsed_args.volumes) msg = (_("%(result)s of %(total)s volumes failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListVolume(command.Lister): _description = _("List volumes") def get_parser(self, prog_name): parser = super(ListVolume, self).get_parser(prog_name) parser.add_argument( '--project', metavar='', help=_('Filter results by project (name or ID) (admin only)') ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--user', metavar='', help=_('Filter results by user (name or ID) (admin only)') ) identity_common.add_user_domain_option_to_parser(parser) parser.add_argument( '--name', metavar='', help=_('Filter results by volume name'), ) parser.add_argument( '--status', metavar='', help=_('Filter results by status'), ) parser.add_argument( '--all-projects', action='store_true', default=False, help=_('Include all projects (admin only)'), ) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( '--marker', metavar='', help=_('The last volume ID of the previous page'), ) parser.add_argument( '--limit', type=int, action=parseractions.NonNegativeAction, metavar='', help=_('Maximum number of volumes to display'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume compute_client = self.app.client_manager.compute identity_client = self.app.client_manager.identity def _format_attach(attachments): """Return a formatted string of a volume's attached instances :param attachments: a volume.attachments field :rtype: a string of formatted instances """ msg = '' for attachment in attachments: server = attachment['server_id'] if server in server_cache: server = server_cache[server].name device = attachment['device'] msg += 'Attached to %s on %s ' % (server, device) return msg if parsed_args.long: columns = [ 'ID', 'Name', 'Status', 'Size', 'Volume Type', 'Bootable', 'Attachments', 'Metadata', ] column_headers = copy.deepcopy(columns) column_headers[4] = 'Type' column_headers[6] = 'Attached to' column_headers[7] = 'Properties' else: columns = [ 'ID', 'Name', 'Status', 'Size', 'Attachments', ] column_headers = copy.deepcopy(columns) column_headers[4] = 'Attached to' # Cache the server list server_cache = {} try: for s in compute_client.servers.list(): server_cache[s.id] = s except Exception: # Just forget it if there's any trouble pass project_id = None if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain).id user_id = None if parsed_args.user: user_id = identity_common.find_user(identity_client, parsed_args.user, parsed_args.user_domain).id # set value of 'all_tenants' when using project option all_projects = bool(parsed_args.project) or parsed_args.all_projects search_opts = { 'all_tenants': all_projects, 'project_id': project_id, 'user_id': user_id, 'name': parsed_args.name, 'status': parsed_args.status, } data = volume_client.volumes.list( search_opts=search_opts, marker=parsed_args.marker, limit=parsed_args.limit, ) column_headers = utils.backward_compat_col_lister( column_headers, parsed_args.columns, {'Display Name': 'Name'}) return (column_headers, (utils.get_item_properties( s, columns, formatters={'Metadata': utils.format_dict, 'Attachments': _format_attach}, ) for s in data)) class MigrateVolume(command.Command): _description = _("Migrate volume to a new host") def get_parser(self, prog_name): parser = super(MigrateVolume, self).get_parser(prog_name) parser.add_argument( 'volume', metavar="", help=_("Volume to migrate (name or ID)") ) parser.add_argument( '--host', metavar="", required=True, help=_("Destination host (takes the form: host@backend-name#pool)") ) parser.add_argument( '--force-host-copy', action="store_true", help=_("Enable generic host-based force-migration, " "which bypasses driver optimizations") ) lock_group = parser.add_mutually_exclusive_group() lock_group.add_argument( '--lock-volume', action="store_true", help=_("If specified, the volume state will be locked " "and will not allow a migration to be aborted " "(possibly by another operation)") ) lock_group.add_argument( '--unlock-volume', action="store_true", help=_("If specified, the volume state will not be " "locked and the a migration can be aborted " "(default) (possibly by another operation)") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume = utils.find_resource(volume_client.volumes, parsed_args.volume) volume_client.volumes.migrate_volume(volume.id, parsed_args.host, parsed_args.force_host_copy, parsed_args.lock_volume,) class SetVolume(command.Command): _description = _("Set volume properties") def get_parser(self, prog_name): parser = super(SetVolume, self).get_parser(prog_name) parser.add_argument( 'volume', metavar='', help=_('Volume to modify (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('New volume name'), ) parser.add_argument( '--size', metavar='', type=int, help=_('Extend volume size in GB'), ) parser.add_argument( '--description', metavar='', help=_('New volume description'), ) parser.add_argument( "--no-property", dest="no_property", action="store_true", help=_("Remove all properties from " "(specify both --no-property and --property to " "remove the current properties before setting " "new properties.)"), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Set a property on this volume ' '(repeat option to set multiple properties)'), ) parser.add_argument( '--image-property', metavar='', action=parseractions.KeyValueAction, help=_('Set an image property on this volume ' '(repeat option to set multiple image properties)'), ) parser.add_argument( "--state", metavar="", choices=['available', 'error', 'creating', 'deleting', 'in-use', 'attaching', 'detaching', 'error_deleting', 'maintenance'], help=_('New volume state ("available", "error", "creating", ' '"deleting", "in-use", "attaching", "detaching", ' '"error_deleting" or "maintenance") (admin only) ' '(This option simply changes the state of the volume ' 'in the database with no regard to actual status, ' 'exercise caution when using)'), ) parser.add_argument( '--type', metavar='', help=_('New volume type (name or ID)'), ) parser.add_argument( '--retype-policy', metavar='', choices=['never', 'on-demand'], help=_('Migration policy while re-typing volume ' '("never" or "on-demand", default is "never" ) ' '(available only when --type option is specified)'), ) bootable_group = parser.add_mutually_exclusive_group() bootable_group.add_argument( "--bootable", action="store_true", help=_("Mark volume as bootable") ) bootable_group.add_argument( "--non-bootable", action="store_true", help=_("Mark volume as non-bootable") ) readonly_group = parser.add_mutually_exclusive_group() readonly_group.add_argument( "--read-only", action="store_true", help=_("Set volume to read-only access mode") ) readonly_group.add_argument( "--read-write", action="store_true", help=_("Set volume to read-write access mode") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume = utils.find_resource(volume_client.volumes, parsed_args.volume) result = 0 if parsed_args.size: try: if volume.status != 'available': msg = (_("Volume is in %s state, it must be available " "before size can be extended") % volume.status) raise exceptions.CommandError(msg) if parsed_args.size <= volume.size: msg = (_("New size must be greater than %s GB") % volume.size) raise exceptions.CommandError(msg) volume_client.volumes.extend(volume.id, parsed_args.size) except Exception as e: LOG.error(_("Failed to set volume size: %s"), e) result += 1 if parsed_args.no_property: try: volume_client.volumes.delete_metadata( volume.id, volume.metadata.keys()) except Exception as e: LOG.error(_("Failed to clean volume properties: %s"), e) result += 1 if parsed_args.property: try: volume_client.volumes.set_metadata( volume.id, parsed_args.property) except Exception as e: LOG.error(_("Failed to set volume property: %s"), e) result += 1 if parsed_args.image_property: try: volume_client.volumes.set_image_metadata( volume.id, parsed_args.image_property) except Exception as e: LOG.error(_("Failed to set image property: %s"), e) result += 1 if parsed_args.state: try: volume_client.volumes.reset_state( volume.id, parsed_args.state) except Exception as e: LOG.error(_("Failed to set volume state: %s"), e) result += 1 if parsed_args.bootable or parsed_args.non_bootable: try: volume_client.volumes.set_bootable( volume.id, parsed_args.bootable) except Exception as e: LOG.error(_("Failed to set volume bootable property: %s"), e) result += 1 if parsed_args.read_only or parsed_args.read_write: try: volume_client.volumes.update_readonly_flag( volume.id, parsed_args.read_only) except Exception as e: LOG.error(_("Failed to set volume read-only access " "mode flag: %s"), e) result += 1 if parsed_args.type: # get the migration policy migration_policy = 'never' if parsed_args.retype_policy: migration_policy = parsed_args.retype_policy try: # find the volume type volume_type = utils.find_resource( volume_client.volume_types, parsed_args.type) # reset to the new volume type volume_client.volumes.retype( volume.id, volume_type.id, migration_policy) except Exception as e: LOG.error(_("Failed to set volume type: %s"), e) result += 1 elif parsed_args.retype_policy: # If the "--retype-policy" is specified without "--type" LOG.warning(_("'--retype-policy' option will not work " "without '--type' option")) kwargs = {} if parsed_args.name: kwargs['display_name'] = parsed_args.name if parsed_args.description: kwargs['display_description'] = parsed_args.description if kwargs: try: volume_client.volumes.update(volume.id, **kwargs) except Exception as e: LOG.error(_("Failed to update volume display name " "or display description: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("One or more of the " "set operations failed")) class ShowVolume(command.ShowOne): _description = _("Display volume details") def get_parser(self, prog_name): parser = super(ShowVolume, self).get_parser(prog_name) parser.add_argument( 'volume', metavar="", help=_("Volume to display (name or ID)") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume = utils.find_resource(volume_client.volumes, parsed_args.volume) # Special mapping for columns to make the output easier to read: # 'metadata' --> 'properties' # 'volume_type' --> 'type' volume._info.update( { 'properties': utils.format_dict(volume._info.pop('metadata')), 'type': volume._info.pop('volume_type'), }, ) # Remove key links from being displayed volume._info.pop("links", None) return zip(*sorted(six.iteritems(volume._info))) class UnsetVolume(command.Command): _description = _("Unset volume properties") def get_parser(self, prog_name): parser = super(UnsetVolume, self).get_parser(prog_name) parser.add_argument( 'volume', metavar='', help=_('Volume to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action='append', help=_('Remove a property from volume ' '(repeat option to remove multiple properties)'), ) parser.add_argument( '--image-property', metavar='', action='append', help=_('Remove an image property from volume ' '(repeat option to remove multiple image properties)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume volume = utils.find_resource( volume_client.volumes, parsed_args.volume) result = 0 if parsed_args.property: try: volume_client.volumes.delete_metadata( volume.id, parsed_args.property) except Exception as e: LOG.error(_("Failed to unset volume property: %s"), e) result += 1 if parsed_args.image_property: try: volume_client.volumes.delete_image_metadata( volume.id, parsed_args.image_property) except Exception as e: LOG.error(_("Failed to unset image property: %s"), e) result += 1 if result > 0: raise exceptions.CommandError(_("One or more of the " "unset operations failed")) python-openstackclient-3.14.0/openstackclient/volume/v2/qos_specs.py0000666000175100017510000002502113232364361025732 0ustar zuulzuul00000000000000# Copyright 2015 iWeb Technologies 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. # """Volume v2 QoS action implementations""" import logging from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class AssociateQos(command.Command): _description = _("Associate a QoS specification to a volume type") def get_parser(self, prog_name): parser = super(AssociateQos, self).get_parser(prog_name) parser.add_argument( 'qos_spec', metavar='', help=_('QoS specification to modify (name or ID)'), ) parser.add_argument( 'volume_type', metavar='', help=_('Volume type to associate the QoS (name or ID)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume qos_spec = utils.find_resource(volume_client.qos_specs, parsed_args.qos_spec) volume_type = utils.find_resource(volume_client.volume_types, parsed_args.volume_type) volume_client.qos_specs.associate(qos_spec.id, volume_type.id) class CreateQos(command.ShowOne): _description = _("Create new QoS specification") def get_parser(self, prog_name): parser = super(CreateQos, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('New QoS specification name'), ) consumer_choices = ['front-end', 'back-end', 'both'] parser.add_argument( '--consumer', metavar='', choices=consumer_choices, default='both', help=(_('Consumer of the QoS. Valid consumers: %s ' "(defaults to 'both')") % utils.format_list(consumer_choices)) ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Set a QoS specification property ' '(repeat option to set multiple properties)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume specs = {} specs.update({'consumer': parsed_args.consumer}) if parsed_args.property: specs.update(parsed_args.property) qos_spec = volume_client.qos_specs.create(parsed_args.name, specs) qos_spec._info.update( {'properties': utils.format_dict(qos_spec._info.pop('specs'))} ) return zip(*sorted(six.iteritems(qos_spec._info))) class DeleteQos(command.Command): _description = _("Delete QoS specification") def get_parser(self, prog_name): parser = super(DeleteQos, self).get_parser(prog_name) parser.add_argument( 'qos_specs', metavar='', nargs="+", help=_('QoS specification(s) to delete (name or ID)'), ) parser.add_argument( '--force', action='store_true', default=False, help=_("Allow to delete in-use QoS specification(s)") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for i in parsed_args.qos_specs: try: qos_spec = utils.find_resource(volume_client.qos_specs, i) volume_client.qos_specs.delete(qos_spec.id, parsed_args.force) except Exception as e: result += 1 LOG.error(_("Failed to delete QoS specification with " "name or ID '%(qos)s': %(e)s") % {'qos': i, 'e': e}) if result > 0: total = len(parsed_args.qos_specs) msg = (_("%(result)s of %(total)s QoS specifications failed" " to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class DisassociateQos(command.Command): _description = _("Disassociate a QoS specification from a volume type") def get_parser(self, prog_name): parser = super(DisassociateQos, self).get_parser(prog_name) parser.add_argument( 'qos_spec', metavar='', help=_('QoS specification to modify (name or ID)'), ) volume_type_group = parser.add_mutually_exclusive_group() volume_type_group.add_argument( '--volume-type', metavar='', help=_('Volume type to disassociate the QoS from (name or ID)'), ) volume_type_group.add_argument( '--all', action='store_true', default=False, help=_('Disassociate the QoS from every volume type'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume qos_spec = utils.find_resource(volume_client.qos_specs, parsed_args.qos_spec) if parsed_args.volume_type: volume_type = utils.find_resource(volume_client.volume_types, parsed_args.volume_type) volume_client.qos_specs.disassociate(qos_spec.id, volume_type.id) elif parsed_args.all: volume_client.qos_specs.disassociate_all(qos_spec.id) class ListQos(command.Lister): _description = _("List QoS specifications") def take_action(self, parsed_args): volume_client = self.app.client_manager.volume qos_specs_list = volume_client.qos_specs.list() for qos in qos_specs_list: try: qos_associations = volume_client.qos_specs.get_associations( qos, ) if qos_associations: associations = [ association.name for association in qos_associations ] qos._info.update({'associations': associations}) except Exception as ex: if type(ex).__name__ == 'NotFound': qos._info.update({'associations': None}) else: raise display_columns = ( 'ID', 'Name', 'Consumer', 'Associations', 'Properties') columns = ('ID', 'Name', 'Consumer', 'Associations', 'Specs') return (display_columns, (utils.get_dict_properties( s._info, columns, formatters={ 'Specs': utils.format_dict, 'Associations': utils.format_list }, ) for s in qos_specs_list)) class SetQos(command.Command): _description = _("Set QoS specification properties") def get_parser(self, prog_name): parser = super(SetQos, self).get_parser(prog_name) parser.add_argument( 'qos_spec', metavar='', help=_('QoS specification to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Property to add or modify for this QoS specification ' '(repeat option to set multiple properties)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume qos_spec = utils.find_resource(volume_client.qos_specs, parsed_args.qos_spec) if parsed_args.property: volume_client.qos_specs.set_keys(qos_spec.id, parsed_args.property) class ShowQos(command.ShowOne): _description = _("Display QoS specification details") def get_parser(self, prog_name): parser = super(ShowQos, self).get_parser(prog_name) parser.add_argument( 'qos_spec', metavar='', help=_('QoS specification to display (name or ID)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume qos_spec = utils.find_resource(volume_client.qos_specs, parsed_args.qos_spec) qos_associations = volume_client.qos_specs.get_associations(qos_spec) if qos_associations: associations = [association.name for association in qos_associations] qos_spec._info.update({ 'associations': utils.format_list(associations) }) qos_spec._info.update( {'properties': utils.format_dict(qos_spec._info.pop('specs'))}) return zip(*sorted(six.iteritems(qos_spec._info))) class UnsetQos(command.Command): _description = _("Unset QoS specification properties") def get_parser(self, prog_name): parser = super(UnsetQos, self).get_parser(prog_name) parser.add_argument( 'qos_spec', metavar='', help=_('QoS specification to modify (name or ID)'), ) parser.add_argument( '--property', metavar='', action='append', default=[], help=_('Property to remove from the QoS specification. ' '(repeat option to unset multiple properties)'), ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume qos_spec = utils.find_resource(volume_client.qos_specs, parsed_args.qos_spec) if parsed_args.property: volume_client.qos_specs.unset_keys(qos_spec.id, parsed_args.property) python-openstackclient-3.14.0/openstackclient/volume/v2/__init__.py0000666000175100017510000000000013232364361025460 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/volume/v2/consistency_group_snapshot.py0000666000175100017510000001554413232364361031440 0ustar zuulzuul00000000000000# # 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. # """Volume v2 consistency group snapshot action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateConsistencyGroupSnapshot(command.ShowOne): _description = _("Create new consistency group snapshot.") def get_parser(self, prog_name): parser = super( CreateConsistencyGroupSnapshot, self).get_parser(prog_name) parser.add_argument( "snapshot_name", metavar="", nargs="?", help=_("Name of new consistency group snapshot (default to None)") ) parser.add_argument( "--consistency-group", metavar="", help=_("Consistency group to snapshot (name or ID) " "(default to be the same as )") ) parser.add_argument( "--description", metavar="", help=_("Description of this consistency group snapshot") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume consistency_group = parsed_args.consistency_group if not parsed_args.consistency_group: # If "--consistency-group" not specified, then consistency_group # will be the same as the new consistency group snapshot name consistency_group = parsed_args.snapshot_name consistency_group_id = utils.find_resource( volume_client.consistencygroups, consistency_group).id consistency_group_snapshot = volume_client.cgsnapshots.create( consistency_group_id, name=parsed_args.snapshot_name, description=parsed_args.description, ) return zip(*sorted(six.iteritems(consistency_group_snapshot._info))) class DeleteConsistencyGroupSnapshot(command.Command): _description = _("Delete consistency group snapshot(s).") def get_parser(self, prog_name): parser = super( DeleteConsistencyGroupSnapshot, self).get_parser(prog_name) parser.add_argument( "consistency_group_snapshot", metavar="", nargs="+", help=_("Consistency group snapshot(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume result = 0 for snapshot in parsed_args.consistency_group_snapshot: try: snapshot_id = utils.find_resource(volume_client.cgsnapshots, snapshot).id volume_client.cgsnapshots.delete(snapshot_id) except Exception as e: result += 1 LOG.error(_("Failed to delete consistency group snapshot " "with name or ID '%(snapshot)s': %(e)s") % {'snapshot': snapshot, 'e': e}) if result > 0: total = len(parsed_args.consistency_group_snapshot) msg = (_("%(result)s of %(total)s consistency group snapshots " "failed to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListConsistencyGroupSnapshot(command.Lister): _description = _("List consistency group snapshots.") def get_parser(self, prog_name): parser = super( ListConsistencyGroupSnapshot, self).get_parser(prog_name) parser.add_argument( '--all-projects', action="store_true", help=_('Show detail for all projects (admin only) ' '(defaults to False)') ) parser.add_argument( '--long', action="store_true", help=_('List additional fields in output') ) parser.add_argument( '--status', metavar="", choices=['available', 'error', 'creating', 'deleting', 'error-deleting'], help=_('Filters results by a status ("available", "error", ' '"creating", "deleting" or "error_deleting")') ) parser.add_argument( '--consistency-group', metavar="", help=_('Filters results by a consistency group (name or ID)') ) return parser def take_action(self, parsed_args): if parsed_args.long: columns = ['ID', 'Status', 'ConsistencyGroup ID', 'Name', 'Description', 'Created At'] else: columns = ['ID', 'Status', 'Name'] volume_client = self.app.client_manager.volume consistency_group_id = None if parsed_args.consistency_group: consistency_group_id = utils.find_resource( volume_client.consistencygroups, parsed_args.consistency_group, ).id search_opts = { 'all_tenants': parsed_args.all_projects, 'status': parsed_args.status, 'consistencygroup_id': consistency_group_id, } consistency_group_snapshots = volume_client.cgsnapshots.list( detailed=True, search_opts=search_opts, ) return (columns, ( utils.get_item_properties( s, columns) for s in consistency_group_snapshots)) class ShowConsistencyGroupSnapshot(command.ShowOne): _description = _("Display consistency group snapshot details") def get_parser(self, prog_name): parser = super( ShowConsistencyGroupSnapshot, self).get_parser(prog_name) parser.add_argument( "consistency_group_snapshot", metavar="", help=_("Consistency group snapshot to display (name or ID)") ) return parser def take_action(self, parsed_args): volume_client = self.app.client_manager.volume consistency_group_snapshot = utils.find_resource( volume_client.cgsnapshots, parsed_args.consistency_group_snapshot) return zip(*sorted(six.iteritems(consistency_group_snapshot._info))) python-openstackclient-3.14.0/openstackclient/volume/v3/0000775000175100017510000000000013232364654023365 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/volume/v3/__init__.py0000666000175100017510000000000013232364361025461 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/volume/__init__.py0000666000175100017510000000000013232364361025131 0ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/compute/0000775000175100017510000000000013232364654023202 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/compute/client.py0000666000175100017510000001141213232364361025026 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # import logging from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ LOG = logging.getLogger(__name__) DEFAULT_API_VERSION = '2.1' API_VERSION_OPTION = 'os_compute_api_version' API_NAME = 'compute' API_VERSIONS = { "2": "novaclient.client", "2.1": "novaclient.client", } COMPUTE_API_TYPE = 'compute' COMPUTE_API_VERSIONS = { '2': 'openstackclient.api.compute_v2.APIv2', } # Save the microversion if in use _compute_api_version = None def make_client(instance): """Returns a compute service client.""" # Defer client import until we actually need them from novaclient import client as nova_client if _compute_api_version is not None: version = _compute_api_version else: version = instance._api_version[API_NAME] from novaclient import api_versions # convert to APIVersion object version = api_versions.get_api_version(version) if version.is_latest(): import novaclient # NOTE(RuiChen): executing version discovery make sense, but that need # an initialized REST client, it's not available now, # fallback to use the max version of novaclient side. version = novaclient.API_MAX_VERSION LOG.debug('Instantiating compute client for %s', version) compute_api = utils.get_client_class( API_NAME, version.ver_major, COMPUTE_API_VERSIONS, ) LOG.debug('Instantiating compute api: %s', compute_api) # Set client http_log_debug to True if verbosity level is high enough http_log_debug = utils.get_effective_log_level() <= logging.DEBUG extensions = [ext for ext in nova_client.discover_extensions(version) if ext.name == "list_extensions"] # Remember interface only if it is set kwargs = utils.build_kwargs_dict('endpoint_type', instance.interface) client = nova_client.Client( version, session=instance.session, extensions=extensions, http_log_debug=http_log_debug, timings=instance.timing, region_name=instance.region_name, **kwargs ) client.api = compute_api( session=instance.session, service_type=COMPUTE_API_TYPE, endpoint=instance.get_endpoint_for_service_type( COMPUTE_API_TYPE, region_name=instance.region_name, interface=instance.interface, ) ) return client def build_option_parser(parser): """Hook to add global options""" parser.add_argument( '--os-compute-api-version', metavar='', default=utils.env('OS_COMPUTE_API_VERSION'), help=_("Compute API version, default=%s " "(Env: OS_COMPUTE_API_VERSION)") % DEFAULT_API_VERSION ) return parser def check_api_version(check_version): """Validate version supplied by user Returns: * True if version is OK * False if the version has not been checked and the previous plugin check should be performed * throws an exception if the version is no good TODO(dtroyer): make the exception thrown a version-related one """ # Defer client imports until we actually need them import novaclient from novaclient import api_versions global _compute_api_version # Copy some logic from novaclient 3.3.0 for basic version detection # NOTE(dtroyer): This is only enough to resume operations using API # version 2.0 or any valid version supplied by the user. _compute_api_version = api_versions.get_api_version(check_version) # Bypass X.latest format microversion if not _compute_api_version.is_latest(): if _compute_api_version > api_versions.APIVersion("2.0"): if not _compute_api_version.matches( novaclient.API_MIN_VERSION, novaclient.API_MAX_VERSION, ): msg = _("versions supported by client: %(min)s - %(max)s") % { "min": novaclient.API_MIN_VERSION.get_string(), "max": novaclient.API_MAX_VERSION.get_string(), } raise exceptions.CommandError(msg) return True python-openstackclient-3.14.0/openstackclient/compute/v2/0000775000175100017510000000000013232364654023531 5ustar zuulzuul00000000000000python-openstackclient-3.14.0/openstackclient/compute/v2/server_image.py0000666000175100017510000000660613232364361026560 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Compute v2 Server action implementations""" import logging import sys from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from oslo_utils import importutils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) def _show_progress(progress): if progress: sys.stdout.write('\rProgress: %s' % progress) sys.stdout.flush() class CreateServerImage(command.ShowOne): _description = _("Create a new server disk image from an existing server") IMAGE_API_VERSIONS = { "1": "openstackclient.image.v1.image", "2": "openstackclient.image.v2.image", } def get_parser(self, prog_name): parser = super(CreateServerImage, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_('Server to create image (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('Name of new disk image (default: server name)'), ) parser.add_argument( '--wait', action='store_true', help=_('Wait for operation to complete'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server, ) if parsed_args.name: image_name = parsed_args.name else: image_name = server.name image_id = compute_client.servers.create_image( server.id, image_name, ) image_client = self.app.client_manager.image image = utils.find_resource( image_client.images, image_id, ) if parsed_args.wait: if utils.wait_for_status( image_client.images.get, image_id, callback=_show_progress, ): sys.stdout.write('\n') else: LOG.error(_('Error creating server image: %s'), parsed_args.server) raise exceptions.CommandError if self.app.client_manager._api_version['image'] == '1': info = {} info.update(image._info) info['properties'] = utils.format_dict(info.get('properties', {})) else: # Get the right image module to format the output image_module = importutils.import_module( self.IMAGE_API_VERSIONS[ self.app.client_manager._api_version['image'] ] ) info = image_module._format_image(image) return zip(*sorted(six.iteritems(info))) python-openstackclient-3.14.0/openstackclient/compute/v2/console.py0000666000175100017510000001060613232364361025545 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Compute v2 Console action implementations""" import sys from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import utils import six from openstackclient.i18n import _ class ShowConsoleLog(command.Command): _description = _("Show server's console output") def get_parser(self, prog_name): parser = super(ShowConsoleLog, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_("Server to show console log (name or ID)") ) parser.add_argument( '--lines', metavar='', type=int, default=None, action=parseractions.NonNegativeAction, help=_("Number of lines to display from the end of the log " "(default=all)") ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server, ) length = parsed_args.lines if length: # NOTE(dtroyer): get_console_output() appears to shortchange the # output by one line length += 1 data = server.get_console_output(length=length) sys.stdout.write(data) class ShowConsoleURL(command.ShowOne): _description = _("Show server's remote console URL") def get_parser(self, prog_name): parser = super(ShowConsoleURL, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_("Server to show URL (name or ID)") ) type_group = parser.add_mutually_exclusive_group() type_group.add_argument( '--novnc', dest='url_type', action='store_const', const='novnc', default='novnc', help=_("Show noVNC console URL (default)") ) type_group.add_argument( '--xvpvnc', dest='url_type', action='store_const', const='xvpvnc', help=_("Show xvpvnc console URL") ) type_group.add_argument( '--spice', dest='url_type', action='store_const', const='spice-html5', help=_("Show SPICE console URL") ) type_group.add_argument( '--rdp', dest='url_type', action='store_const', const='rdp-html5', help=_("Show RDP console URL"), ) type_group.add_argument( '--serial', dest='url_type', action='store_const', const='serial', help=_("Show serial console URL"), ) type_group.add_argument( '--mks', dest='url_type', action='store_const', const='webmks', help=_("Show WebMKS console URL"), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server, ) data = server.get_console_url(parsed_args.url_type) if not data: return ({}, {}) info = {} # NOTE(Rui Chen): Return 'remote_console' in compute microversion API # 2.6 and later, return 'console' in compute # microversion API from 2.0 to 2.5, do compatibility # handle for different microversion API. console_data = data.get('remote_console', data.get('console')) info.update(console_data) return zip(*sorted(six.iteritems(info))) python-openstackclient-3.14.0/openstackclient/compute/v2/keypair.py0000666000175100017510000001455113232364361025552 0ustar zuulzuul00000000000000# Copyright 2013 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. # """Keypair action implementations""" import io import logging import os import sys from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class CreateKeypair(command.ShowOne): _description = _("Create new public or private key for server ssh access") def get_parser(self, prog_name): parser = super(CreateKeypair, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_("New public or private key name") ) key_group = parser.add_mutually_exclusive_group() key_group.add_argument( '--public-key', metavar='', help=_("Filename for public key to add. If not used, " "creates a private key.") ) key_group.add_argument( '--private-key', metavar='', help=_("Filename for private key to save. If not used, " "print private key in console.") ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute public_key = parsed_args.public_key if public_key: try: with io.open(os.path.expanduser(parsed_args.public_key)) as p: public_key = p.read() except IOError as e: msg = _("Key file %(public_key)s not found: %(exception)s") raise exceptions.CommandError( msg % {"public_key": parsed_args.public_key, "exception": e} ) keypair = compute_client.keypairs.create( parsed_args.name, public_key=public_key, ) private_key = parsed_args.private_key # Save private key into specified file if private_key: try: with io.open( os.path.expanduser(parsed_args.private_key), 'w+' ) as p: p.write(keypair.private_key) except IOError as e: msg = _("Key file %(private_key)s can not be saved: " "%(exception)s") raise exceptions.CommandError( msg % {"private_key": parsed_args.private_key, "exception": e} ) # NOTE(dtroyer): how do we want to handle the display of the private # key when it needs to be communicated back to the user # For now, duplicate nova keypair-add command output info = {} if public_key or private_key: info.update(keypair._info) if 'public_key' in info: del info['public_key'] if 'private_key' in info: del info['private_key'] return zip(*sorted(six.iteritems(info))) else: sys.stdout.write(keypair.private_key) return ({}, {}) class DeleteKeypair(command.Command): _description = _("Delete public or private key(s)") def get_parser(self, prog_name): parser = super(DeleteKeypair, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', nargs='+', help=_("Name of key(s) to delete (name only)") ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute result = 0 for n in parsed_args.name: try: data = utils.find_resource( compute_client.keypairs, n) compute_client.keypairs.delete(data.name) except Exception as e: result += 1 LOG.error(_("Failed to delete key with name " "'%(name)s': %(e)s"), {'name': n, 'e': e}) if result > 0: total = len(parsed_args.name) msg = (_("%(result)s of %(total)s keys failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListKeypair(command.Lister): _description = _("List key fingerprints") def take_action(self, parsed_args): compute_client = self.app.client_manager.compute columns = ( "Name", "Fingerprint" ) data = compute_client.keypairs.list() return (columns, (utils.get_item_properties( s, columns, ) for s in data)) class ShowKeypair(command.ShowOne): _description = _("Display key details") def get_parser(self, prog_name): parser = super(ShowKeypair, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_("Public or private key to display (name only)") ) parser.add_argument( '--public-key', action='store_true', default=False, help=_("Show only bare public key paired with the generated key") ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute keypair = utils.find_resource(compute_client.keypairs, parsed_args.name) info = {} info.update(keypair._info) if not parsed_args.public_key: del info['public_key'] return zip(*sorted(six.iteritems(info))) else: # NOTE(dtroyer): a way to get the public key in a similar form # as the private key in the create command sys.stdout.write(keypair.public_key) return ({}, {}) python-openstackclient-3.14.0/openstackclient/compute/v2/fixedip.py0000666000175100017510000000623513232364361025536 0ustar zuulzuul00000000000000# Copyright 2013 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. # """Fixed IP action implementations""" import logging from osc_lib.command import command from osc_lib import utils from openstackclient.i18n import _ class AddFixedIP(command.Command): _description = _("Add fixed IP address to server") # TODO(tangchen): Remove this class and ``ip fixed add`` command # two cycles after Mitaka. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def get_parser(self, prog_name): parser = super(AddFixedIP, self).get_parser(prog_name) parser.add_argument( "network", metavar="", help=_("Network to fetch an IP address from (name or ID)"), ) parser.add_argument( "server", metavar="", help=_("Server to receive the IP address (name or ID)"), ) return parser def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "server add fixed ip" instead.')) compute_client = self.app.client_manager.compute network = utils.find_resource( compute_client.networks, parsed_args.network) server = utils.find_resource( compute_client.servers, parsed_args.server) server.add_fixed_ip(network.id) class RemoveFixedIP(command.Command): _description = _("Remove fixed IP address from server") # TODO(tangchen): Remove this class and ``ip fixed remove`` command # two cycles after Mitaka. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def get_parser(self, prog_name): parser = super(RemoveFixedIP, self).get_parser(prog_name) parser.add_argument( "ip_address", metavar="", help=_("IP address to remove from server (name only)"), ) parser.add_argument( "server", metavar="", help=_("Server to remove the IP address from (name or ID)"), ) return parser def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "server remove fixed ip" instead.')) compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server) server.remove_fixed_ip(parsed_args.ip_address) python-openstackclient-3.14.0/openstackclient/compute/v2/hypervisor_stats.py0000666000175100017510000000201513232364361027526 0ustar zuulzuul00000000000000# 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. # """Hypervisor Stats action implementations""" from osc_lib.command import command import six from openstackclient.i18n import _ class ShowHypervisorStats(command.ShowOne): _description = _("Display hypervisor stats details") def take_action(self, parsed_args): compute_client = self.app.client_manager.compute hypervisor_stats = compute_client.hypervisors.statistics().to_dict() return zip(*sorted(six.iteritems(hypervisor_stats))) python-openstackclient-3.14.0/openstackclient/compute/v2/server_backup.py0000666000175100017510000001011313232364361026727 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Compute v2 Server action implementations""" import sys from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from oslo_utils import importutils import six from openstackclient.i18n import _ def _show_progress(progress): if progress: sys.stderr.write('\rProgress: %s' % progress) sys.stderr.flush() class CreateServerBackup(command.ShowOne): _description = _("Create a server backup image") IMAGE_API_VERSIONS = { "1": "openstackclient.image.v1.image", "2": "openstackclient.image.v2.image", } def get_parser(self, prog_name): parser = super(CreateServerBackup, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_('Server to back up (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('Name of the backup image (default: server name)'), ) parser.add_argument( '--type', metavar='', help=_( 'Used to populate the backup_type property of the backup ' 'image (default: empty)' ), ) parser.add_argument( '--rotate', metavar='', type=int, help=_('Number of backups to keep (default: 1)'), ) parser.add_argument( '--wait', action='store_true', help=_('Wait for backup image create to complete'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server, ) # Set sane defaults as this API wants all mouths to be fed if parsed_args.name is None: backup_name = server.name else: backup_name = parsed_args.name if parsed_args.type is None: backup_type = "" else: backup_type = parsed_args.type if parsed_args.rotate is None: backup_rotation = 1 else: backup_rotation = parsed_args.rotate compute_client.servers.backup( server.id, backup_name, backup_type, backup_rotation, ) image_client = self.app.client_manager.image image = utils.find_resource( image_client.images, backup_name, ) if parsed_args.wait: if utils.wait_for_status( image_client.images.get, image.id, callback=_show_progress, ): sys.stdout.write('\n') else: msg = _('Error creating server backup: %s') % parsed_args.name raise exceptions.CommandError(msg) if self.app.client_manager._api_version['image'] == '1': info = {} info.update(image._info) info['properties'] = utils.format_dict(info.get('properties', {})) else: # Get the right image module to format the output image_module = importutils.import_module( self.IMAGE_API_VERSIONS[ self.app.client_manager._api_version['image'] ] ) info = image_module._format_image(image) return zip(*sorted(six.iteritems(info))) python-openstackclient-3.14.0/openstackclient/compute/v2/service.py0000666000175100017510000001547013232364361025547 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Service action implementations""" import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ LOG = logging.getLogger(__name__) class DeleteService(command.Command): _description = _("Delete compute service(s)") def get_parser(self, prog_name): parser = super(DeleteService, self).get_parser(prog_name) parser.add_argument( "service", metavar="", nargs='+', help=_("Compute service(s) to delete (ID only)") ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute result = 0 for s in parsed_args.service: try: compute_client.services.delete(s) except Exception as e: result += 1 LOG.error(_("Failed to delete compute service with " "ID '%(service)s': %(e)s"), {'service': s, 'e': e}) if result > 0: total = len(parsed_args.service) msg = (_("%(result)s of %(total)s compute services failed " "to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) class ListService(command.Lister): _description = _("List compute services") def get_parser(self, prog_name): parser = super(ListService, self).get_parser(prog_name) parser.add_argument( "--host", metavar="", help=_("List services on specified host (name only)") ) parser.add_argument( "--service", metavar="", help=_("List only specified service (name only)") ) parser.add_argument( "--long", action="store_true", default=False, help=_("List additional fields in output") ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute if parsed_args.long: columns = ( "ID", "Binary", "Host", "Zone", "Status", "State", "Updated At", "Disabled Reason" ) else: columns = ( "ID", "Binary", "Host", "Zone", "Status", "State", "Updated At" ) data = compute_client.services.list(parsed_args.host, parsed_args.service) return (columns, (utils.get_item_properties( s, columns, ) for s in data)) class SetService(command.Command): _description = _("Set compute service properties") def get_parser(self, prog_name): parser = super(SetService, self).get_parser(prog_name) parser.add_argument( "host", metavar="", help=_("Name of host") ) parser.add_argument( "service", metavar="", help=_("Name of service (Binary name)") ) enabled_group = parser.add_mutually_exclusive_group() enabled_group.add_argument( "--enable", action="store_true", help=_("Enable service") ) enabled_group.add_argument( "--disable", action="store_true", help=_("Disable service") ) parser.add_argument( "--disable-reason", default=None, metavar="", help=_("Reason for disabling the service (in quotes). " "Should be used with --disable option.") ) up_down_group = parser.add_mutually_exclusive_group() up_down_group.add_argument( '--up', action='store_true', help=_('Force up service'), ) up_down_group.add_argument( '--down', action='store_true', help=_('Force down service'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute cs = compute_client.services if (parsed_args.enable or not parsed_args.disable) and \ parsed_args.disable_reason: msg = _("Cannot specify option --disable-reason without " "--disable specified.") raise exceptions.CommandError(msg) result = 0 enabled = None try: if parsed_args.enable: enabled = True if parsed_args.disable: enabled = False if enabled is not None: if enabled: cs.enable(parsed_args.host, parsed_args.service) else: if parsed_args.disable_reason: cs.disable_log_reason(parsed_args.host, parsed_args.service, parsed_args.disable_reason) else: cs.disable(parsed_args.host, parsed_args.service) except Exception: status = "enabled" if enabled else "disabled" LOG.error("Failed to set service status to %s", status) result += 1 force_down = None try: if parsed_args.down: force_down = True if parsed_args.up: force_down = False if force_down is not None: cs.force_down(parsed_args.host, parsed_args.service, force_down=force_down) except Exception: state = "down" if force_down else "up" LOG.error("Failed to set service state to %s", state) result += 1 if result > 0: msg = _("Compute service %(service)s of host %(host)s failed to " "set.") % {"service": parsed_args.service, "host": parsed_args.host} raise exceptions.CommandError(msg) python-openstackclient-3.14.0/openstackclient/compute/v2/server.py0000666000175100017510000022515013232364361025413 0ustar zuulzuul00000000000000# Copyright 2012-2013 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. # """Compute v2 Server action implementations""" import argparse import getpass import io import logging import os import sys from novaclient.v2 import servers from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from oslo_utils import timeutils import six from openstackclient.i18n import _ from openstackclient.identity import common as identity_common LOG = logging.getLogger(__name__) def _format_servers_list_networks(networks): """Return a formatted string of a server's networks :param networks: a Server.networks field :rtype: a string of formatted network addresses """ output = [] for (network, addresses) in networks.items(): if not addresses: continue addresses_csv = ', '.join(addresses) group = "%s=%s" % (network, addresses_csv) output.append(group) return '; '.join(output) def _format_servers_list_power_state(state): """Return a formatted string of a server's power state :param state: the power state number of a server :rtype: a string mapped to the power state number """ power_states = [ 'NOSTATE', # 0x00 'Running', # 0x01 '', # 0x02 'Paused', # 0x03 'Shutdown', # 0x04 '', # 0x05 'Crashed', # 0x06 'Suspended' # 0x07 ] try: return power_states[state] except Exception: return 'N/A' def _get_ip_address(addresses, address_type, ip_address_family): # Old style addresses if address_type in addresses: for addy in addresses[address_type]: if int(addy['version']) in ip_address_family: return addy['addr'] # New style addresses new_address_type = address_type if address_type == 'public': new_address_type = 'floating' if address_type == 'private': new_address_type = 'fixed' for network in addresses: for addy in addresses[network]: # Case where it is list of strings if isinstance(addy, six.string_types): if new_address_type == 'fixed': return addresses[network][0] else: return addresses[network][-1] # Case where it is a dict if 'OS-EXT-IPS:type' not in addy: continue if addy['OS-EXT-IPS:type'] == new_address_type: if int(addy['version']) in ip_address_family: return addy['addr'] msg = _("ERROR: No %(type)s IP version %(family)s address found") raise exceptions.CommandError( msg % {"type": address_type, "family": ip_address_family} ) def _prefix_checked_value(prefix): def func(value): if ',' in value or '=' in value: msg = _("Invalid argument %s, " "characters ',' and '=' are not allowed") % value raise argparse.ArgumentTypeError(msg) return prefix + value return func def _prep_server_detail(compute_client, image_client, server): """Prepare the detailed server dict for printing :param compute_client: a compute client instance :param server: a Server resource :rtype: a dict of server details """ info = server._info.copy() server = utils.find_resource(compute_client.servers, info['id']) info.update(server._info) # Convert the image blob to a name image_info = info.get('image', {}) if image_info: image_id = image_info.get('id', '') try: image = utils.find_resource(image_client.images, image_id) info['image'] = "%s (%s)" % (image.name, image_id) except Exception: info['image'] = image_id # Convert the flavor blob to a name flavor_info = info.get('flavor', {}) flavor_id = flavor_info.get('id', '') try: flavor = utils.find_resource(compute_client.flavors, flavor_id) info['flavor'] = "%s (%s)" % (flavor.name, flavor_id) except Exception: info['flavor'] = flavor_id if 'os-extended-volumes:volumes_attached' in info: info.update( { 'volumes_attached': utils.format_list_of_dicts( info.pop('os-extended-volumes:volumes_attached')) } ) if 'security_groups' in info: info.update( { 'security_groups': utils.format_list_of_dicts( info.pop('security_groups')) } ) # NOTE(dtroyer): novaclient splits these into separate entries... # Format addresses in a useful way info['addresses'] = _format_servers_list_networks(server.networks) # Map 'metadata' field to 'properties' info.update( {'properties': utils.format_dict(info.pop('metadata'))} ) # Migrate tenant_id to project_id naming if 'tenant_id' in info: info['project_id'] = info.pop('tenant_id') # Map power state num to meanful string if 'OS-EXT-STS:power_state' in info: info['OS-EXT-STS:power_state'] = _format_servers_list_power_state( info['OS-EXT-STS:power_state']) # Remove values that are long and not too useful info.pop('links', None) return info def _show_progress(progress): if progress: sys.stdout.write('\rProgress: %s' % progress) sys.stdout.flush() class AddFixedIP(command.Command): _description = _("Add fixed IP address to server") def get_parser(self, prog_name): parser = super(AddFixedIP, self).get_parser(prog_name) parser.add_argument( "server", metavar="", help=_("Server to receive the fixed IP address (name or ID)"), ) parser.add_argument( "network", metavar="", help=_( "Network to allocate the fixed IP address from (name or ID)" ), ) parser.add_argument( "--fixed-ip-address", metavar="", help=_("Requested fixed IP address"), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server) network = compute_client.api.network_find(parsed_args.network) server.interface_attach( port_id=None, net_id=network['id'], fixed_ip=parsed_args.fixed_ip_address, ) class AddFloatingIP(command.Command): _description = _("Add floating IP address to server") def get_parser(self, prog_name): parser = super(AddFloatingIP, self).get_parser(prog_name) parser.add_argument( "server", metavar="", help=_("Server to receive the floating IP address (name or ID)"), ) parser.add_argument( "ip_address", metavar="", help=_("Floating IP address to assign to server (IP only)"), ) parser.add_argument( "--fixed-ip-address", metavar="", help=_("Fixed IP address to associate with this floating IP " "address"), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server) server.add_floating_ip(parsed_args.ip_address, parsed_args.fixed_ip_address) class AddPort(command.Command): _description = _("Add port to server") def get_parser(self, prog_name): parser = super(AddPort, self).get_parser(prog_name) parser.add_argument( "server", metavar="", help=_("Server to add the port to (name or ID)"), ) parser.add_argument( "port", metavar="", help=_("Port to add to the server (name or ID)"), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server) if self.app.client_manager.is_network_endpoint_enabled(): network_client = self.app.client_manager.network port_id = network_client.find_port( parsed_args.port, ignore_missing=False).id else: port_id = parsed_args.port server.interface_attach(port_id=port_id, net_id=None, fixed_ip=None) class AddNetwork(command.Command): _description = _("Add network to server") def get_parser(self, prog_name): parser = super(AddNetwork, self).get_parser(prog_name) parser.add_argument( "server", metavar="", help=_("Server to add the network to (name or ID)"), ) parser.add_argument( "network", metavar="", help=_("Network to add to the server (name or ID)"), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server) if self.app.client_manager.is_network_endpoint_enabled(): network_client = self.app.client_manager.network net_id = network_client.find_network( parsed_args.network, ignore_missing=False).id else: net_id = parsed_args.network server.interface_attach(port_id=None, net_id=net_id, fixed_ip=None) class AddServerSecurityGroup(command.Command): _description = _("Add security group to server") def get_parser(self, prog_name): parser = super(AddServerSecurityGroup, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_('Server (name or ID)'), ) parser.add_argument( 'group', metavar='', help=_('Security group to add (name or ID)'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server, ) security_group = compute_client.api.security_group_find( parsed_args.group, ) server.add_security_group(security_group['id']) class AddServerVolume(command.Command): _description = _("Add volume to server") def get_parser(self, prog_name): parser = super(AddServerVolume, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_('Server (name or ID)'), ) parser.add_argument( 'volume', metavar='', help=_('Volume to add (name or ID)'), ) parser.add_argument( '--device', metavar='', help=_('Server internal device name for volume'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute volume_client = self.app.client_manager.volume server = utils.find_resource( compute_client.servers, parsed_args.server, ) volume = utils.find_resource( volume_client.volumes, parsed_args.volume, ) compute_client.volumes.create_server_volume( server.id, volume.id, parsed_args.device, ) class CreateServer(command.ShowOne): _description = _("Create a new server") def get_parser(self, prog_name): parser = super(CreateServer, self).get_parser(prog_name) parser.add_argument( 'server_name', metavar='', help=_('New server name'), ) disk_group = parser.add_mutually_exclusive_group( required=True, ) disk_group.add_argument( '--image', metavar='', help=_('Create server boot disk from this image (name or ID)'), ) disk_group.add_argument( '--volume', metavar='', help=_('Create server using this volume as the boot disk (name ' 'or ID).\n' 'This option automatically creates a block device mapping ' 'with a boot index of 0. On many hypervisors (libvirt/kvm ' 'for example) this will be device vda. Do not create a ' 'duplicate mapping using --block-device-mapping for this ' 'volume.'), ) parser.add_argument( '--flavor', metavar='', required=True, help=_('Create server with this flavor (name or ID)'), ) parser.add_argument( '--security-group', metavar='', action='append', default=[], help=_('Security group to assign to this server (name or ID) ' '(repeat option to set multiple groups)'), ) parser.add_argument( '--key-name', metavar='', help=_('Keypair to inject into this server (optional extension)'), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, help=_('Set a property on this server ' '(repeat option to set multiple values)'), ) parser.add_argument( '--file', metavar='', action='append', default=[], help=_('File to inject into image before boot ' '(repeat option to set multiple files)'), ) parser.add_argument( '--user-data', metavar='', help=_('User data file to serve from the metadata server'), ) parser.add_argument( '--availability-zone', metavar='', help=_('Select an availability zone for the server'), ) parser.add_argument( '--block-device-mapping', metavar='', action=parseractions.KeyValueAction, default={}, # NOTE(RuiChen): Add '\n' at the end of line to put each item in # the separated line, avoid the help message looks # messy, see _SmartHelpFormatter in cliff. help=_('Create a block device on the server.\n' 'Block device mapping in the format\n' '=:::\n' ': block device name, like: vdb, xvdc ' '(required)\n' ': UUID of the volume or snapshot (required)\n' ': volume or snapshot; default: volume (optional)\n' ': volume size if create from snapshot ' '(optional)\n' ': true or false; default: false ' '(optional)\n' '(optional extension)'), ) parser.add_argument( '--nic', metavar="", action='append', help=_("Create a NIC on the server. " "Specify option multiple times to create multiple NICs. " "Either net-id or port-id must be provided, but not both. " "net-id: attach NIC to network with this UUID, " "port-id: attach NIC to port with this UUID, " "v4-fixed-ip: IPv4 fixed address for NIC (optional), " "v6-fixed-ip: IPv6 fixed address for NIC (optional), " "none: (v2.37+) no network is attached, " "auto: (v2.37+) the compute service will automatically " "allocate a network. Specifying a --nic of auto or none " "cannot be used with any other --nic value."), ) parser.add_argument( '--network', metavar="", action='append', dest='nic', type=_prefix_checked_value('net-id='), help=_("Create a NIC on the server and connect it to network. " "Specify option multiple times to create multiple NICs. " "This is a wrapper for the '--nic net-id=' " "parameter that provides simple syntax for the standard " "use case of connecting a new server to a given network. " "For more advanced use cases, refer to the '--nic' " "parameter."), ) parser.add_argument( '--port', metavar="", action='append', dest='nic', type=_prefix_checked_value('port-id='), help=_("Create a NIC on the server and connect it to port. " "Specify option multiple times to create multiple NICs. " "This is a wrapper for the '--nic port-id=' " "parameter that provides simple syntax for the standard " "use case of connecting a new server to a given port. For " "more advanced use cases, refer to the '--nic' parameter."), ) parser.add_argument( '--hint', metavar='', action='append', default=[], help=_('Hints for the scheduler (optional extension)'), ) parser.add_argument( '--config-drive', metavar='|True', default=False, help=_('Use specified volume as the config drive, ' 'or \'True\' to use an ephemeral drive'), ) parser.add_argument( '--min', metavar='', type=int, default=1, help=_('Minimum number of servers to launch (default=1)'), ) parser.add_argument( '--max', metavar='', type=int, default=1, help=_('Maximum number of servers to launch (default=1)'), ) parser.add_argument( '--wait', action='store_true', help=_('Wait for build to complete'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute volume_client = self.app.client_manager.volume image_client = self.app.client_manager.image # Lookup parsed_args.image image = None if parsed_args.image: image = utils.find_resource( image_client.images, parsed_args.image, ) # Lookup parsed_args.volume volume = None if parsed_args.volume: volume = utils.find_resource( volume_client.volumes, parsed_args.volume, ).id # Lookup parsed_args.flavor flavor = utils.find_resource(compute_client.flavors, parsed_args.flavor) boot_args = [parsed_args.server_name, image, flavor] files = {} for f in parsed_args.file: dst, src = f.split('=', 1) try: files[dst] = io.open(src, 'rb') except IOError as e: msg = _("Can't open '%(source)s': %(exception)s") raise exceptions.CommandError( msg % {"source": src, "exception": e} ) if parsed_args.min > parsed_args.max: msg = _("min instances should be <= max instances") raise exceptions.CommandError(msg) if parsed_args.min < 1: msg = _("min instances should be > 0") raise exceptions.CommandError(msg) if parsed_args.max < 1: msg = _("max instances should be > 0") raise exceptions.CommandError(msg) userdata = None if parsed_args.user_data: try: userdata = io.open(parsed_args.user_data) except IOError as e: msg = _("Can't open '%(data)s': %(exception)s") raise exceptions.CommandError( msg % {"data": parsed_args.user_data, "exception": e} ) block_device_mapping_v2 = [] if volume: block_device_mapping_v2 = [{'uuid': volume, 'boot_index': '0', 'source_type': 'volume', 'destination_type': 'volume' }] # Handle block device by device name order, like: vdb -> vdc -> vdd for dev_name in sorted(six.iterkeys(parsed_args.block_device_mapping)): dev_map = parsed_args.block_device_mapping[dev_name] dev_map = dev_map.split(':') if dev_map[0]: mapping = {'device_name': dev_name} # 1. decide source and destination type if (len(dev_map) > 1 and dev_map[1] in ('volume', 'snapshot')): mapping['source_type'] = dev_map[1] else: mapping['source_type'] = 'volume' mapping['destination_type'] = 'volume' # 2. check target exist, update target uuid according by # source type if mapping['source_type'] == 'volume': volume_id = utils.find_resource( volume_client.volumes, dev_map[0]).id mapping['uuid'] = volume_id elif mapping['source_type'] == 'snapshot': snapshot_id = utils.find_resource( volume_client.volume_snapshots, dev_map[0]).id mapping['uuid'] = snapshot_id # 3. append size and delete_on_termination if exist if len(dev_map) > 2 and dev_map[2]: mapping['volume_size'] = dev_map[2] if len(dev_map) > 3 and dev_map[3]: mapping['delete_on_termination'] = dev_map[3] else: msg = _("Volume or snapshot (name or ID) must be specified if " "--block-device-mapping is specified") raise exceptions.CommandError(msg) block_device_mapping_v2.append(mapping) nics = [] auto_or_none = False if parsed_args.nic is None: parsed_args.nic = [] for nic_str in parsed_args.nic: # Handle the special auto/none cases if nic_str in ('auto', 'none'): auto_or_none = True nics.append(nic_str) else: nic_info = {"net-id": "", "v4-fixed-ip": "", "v6-fixed-ip": "", "port-id": ""} for kv_str in nic_str.split(","): k, sep, v = kv_str.partition("=") if k in nic_info and v: nic_info[k] = v else: msg = (_("Invalid nic argument '%s'. Nic arguments " "must be of the form --nic .")) raise exceptions.CommandError(msg % k) if bool(nic_info["net-id"]) == bool(nic_info["port-id"]): msg = _("either network or port should be specified " "but not both") raise exceptions.CommandError(msg) if self.app.client_manager.is_network_endpoint_enabled(): network_client = self.app.client_manager.network if nic_info["net-id"]: net = network_client.find_network( nic_info["net-id"], ignore_missing=False) nic_info["net-id"] = net.id if nic_info["port-id"]: port = network_client.find_port( nic_info["port-id"], ignore_missing=False) nic_info["port-id"] = port.id else: if nic_info["net-id"]: nic_info["net-id"] = compute_client.api.network_find( nic_info["net-id"] )['id'] if nic_info["port-id"]: msg = _("can't create server with port specified " "since network endpoint not enabled") raise exceptions.CommandError(msg) nics.append(nic_info) if nics: if auto_or_none: if len(nics) > 1: msg = _('Specifying a --nic of auto or none cannot ' 'be used with any other --nic, --network ' 'or --port value.') raise exceptions.CommandError(msg) nics = nics[0] else: # Default to empty list if nothing was specified, let nova side to # decide the default behavior. nics = [] # Check security group exist and convert ID to name security_group_names = [] if self.app.client_manager.is_network_endpoint_enabled(): network_client = self.app.client_manager.network for each_sg in parsed_args.security_group: sg = network_client.find_security_group(each_sg, ignore_missing=False) # Use security group ID to avoid multiple security group have # same name in neutron networking backend security_group_names.append(sg.id) else: # Handle nova-network case for each_sg in parsed_args.security_group: sg = compute_client.api.security_group_find(each_sg) security_group_names.append(sg['name']) hints = {} for hint in parsed_args.hint: key, _sep, value = hint.partition('=') # NOTE(vish): multiple copies of the same hint will # result in a list of values if key in hints: if isinstance(hints[key], six.string_types): hints[key] = [hints[key]] hints[key] += [value] else: hints[key] = value # What does a non-boolean value for config-drive do? # --config-drive argument is either a volume id or # 'True' (or '1') to use an ephemeral volume if str(parsed_args.config_drive).lower() in ("true", "1"): config_drive = True elif str(parsed_args.config_drive).lower() in ("false", "0", "", "none"): config_drive = None else: config_drive = parsed_args.config_drive boot_kwargs = dict( meta=parsed_args.property, files=files, reservation_id=None, min_count=parsed_args.min, max_count=parsed_args.max, security_groups=security_group_names, userdata=userdata, key_name=parsed_args.key_name, availability_zone=parsed_args.availability_zone, block_device_mapping_v2=block_device_mapping_v2, nics=nics, scheduler_hints=hints, config_drive=config_drive) LOG.debug('boot_args: %s', boot_args) LOG.debug('boot_kwargs: %s', boot_kwargs) # Wrap the call to catch exceptions in order to close files try: server = compute_client.servers.create(*boot_args, **boot_kwargs) finally: # Clean up open files - make sure they are not strings for f in files: if hasattr(f, 'close'): f.close() if hasattr(userdata, 'close'): userdata.close() if parsed_args.wait: if utils.wait_for_status( compute_client.servers.get, server.id, callback=_show_progress, ): sys.stdout.write('\n') else: LOG.error(_('Error creating server: %s'), parsed_args.server_name) sys.stdout.write(_('Error creating server\n')) raise SystemExit details = _prep_server_detail(compute_client, image_client, server) return zip(*sorted(six.iteritems(details))) class CreateServerDump(command.Command): """Create a dump file in server(s) Trigger crash dump in server(s) with features like kdump in Linux. It will create a dump file in the server(s) dumping the server(s)' memory, and also crash the server(s). OSC sees the dump file (server dump) as a kind of resource. """ def get_parser(self, prog_name): parser = super(CreateServerDump, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', nargs='+', help=_('Server(s) to create dump file (name or ID)'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute for server in parsed_args.server: utils.find_resource( compute_client.servers, server, ).trigger_crash_dump() class DeleteServer(command.Command): _description = _("Delete server(s)") def get_parser(self, prog_name): parser = super(DeleteServer, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', nargs="+", help=_('Server(s) to delete (name or ID)'), ) parser.add_argument( '--wait', action='store_true', help=_('Wait for delete to complete'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute for server in parsed_args.server: server_obj = utils.find_resource( compute_client.servers, server) compute_client.servers.delete(server_obj.id) if parsed_args.wait: if utils.wait_for_delete( compute_client.servers, server_obj.id, callback=_show_progress, ): sys.stdout.write('\n') else: LOG.error(_('Error deleting server: %s'), server_obj.id) sys.stdout.write(_('Error deleting server\n')) raise SystemExit class ListServer(command.Lister): _description = _("List servers") def get_parser(self, prog_name): parser = super(ListServer, self).get_parser(prog_name) parser.add_argument( '--reservation-id', metavar='', help=_('Only return instances that match the reservation'), ) parser.add_argument( '--ip', metavar='', help=_('Regular expression to match IP addresses'), ) parser.add_argument( '--ip6', metavar='', help=_('Regular expression to match IPv6 addresses'), ) parser.add_argument( '--name', metavar='', help=_('Regular expression to match names'), ) parser.add_argument( '--instance-name', metavar='', help=_('Regular expression to match instance name (admin only)'), ) parser.add_argument( '--status', metavar='', # FIXME(dhellmann): Add choices? help=_('Search by server status'), ) parser.add_argument( '--flavor', metavar='', help=_('Search by flavor (name or ID)'), ) parser.add_argument( '--image', metavar='', help=_('Search by image (name or ID)'), ) parser.add_argument( '--host', metavar='', help=_('Search by hostname'), ) parser.add_argument( '--all-projects', action='store_true', default=bool(int(os.environ.get("ALL_PROJECTS", 0))), help=_('Include all projects (admin only)'), ) parser.add_argument( '--project', metavar='', help=_("Search by project (admin only) (name or ID)") ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--user', metavar='', help=_('Search by user (admin only) (name or ID)'), ) identity_common.add_user_domain_option_to_parser(parser) parser.add_argument( '--long', action='store_true', default=False, help=_('List additional fields in output'), ) parser.add_argument( '-n', '--no-name-lookup', action='store_true', default=False, help=_('Skip flavor and image name lookup.'), ) parser.add_argument( '--marker', metavar='', default=None, help=_('The last server of the previous page. Display ' 'list of servers after marker. Display all servers if not ' 'specified. (name or ID)') ) parser.add_argument( '--limit', metavar='', type=int, default=None, help=_("Maximum number of servers to display. If limit equals -1, " "all servers will be displayed. If limit is greater than " "'osapi_max_limit' option of Nova API, " "'osapi_max_limit' will be used instead."), ) parser.add_argument( '--deleted', action="store_true", default=False, help=_('Only display deleted servers (Admin only).') ) parser.add_argument( '--changes-since', metavar='', default=None, help=_("List only servers changed after a certain point of time." " The provided time should be an ISO 8061 formatted time." " ex 2016-03-04T06:27:59Z .") ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute identity_client = self.app.client_manager.identity image_client = self.app.client_manager.image project_id = None if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id parsed_args.all_projects = True user_id = None if parsed_args.user: user_id = identity_common.find_user( identity_client, parsed_args.user, parsed_args.user_domain, ).id # Nova only supports list servers searching by flavor ID. So if a # flavor name is given, map it to ID. flavor_id = None if parsed_args.flavor: flavor_id = utils.find_resource(compute_client.flavors, parsed_args.flavor).id # Nova only supports list servers searching by image ID. So if a # image name is given, map it to ID. image_id = None if parsed_args.image: image_id = utils.find_resource(image_client.images, parsed_args.image).id search_opts = { 'reservation_id': parsed_args.reservation_id, 'ip': parsed_args.ip, 'ip6': parsed_args.ip6, 'name': parsed_args.name, 'instance_name': parsed_args.instance_name, 'status': parsed_args.status, 'flavor': flavor_id, 'image': image_id, 'host': parsed_args.host, 'tenant_id': project_id, 'all_tenants': parsed_args.all_projects, 'user_id': user_id, 'deleted': parsed_args.deleted, 'changes-since': parsed_args.changes_since, } LOG.debug('search options: %s', search_opts) if search_opts['changes-since']: try: timeutils.parse_isotime(search_opts['changes-since']) except ValueError: raise exceptions.CommandError( _('Invalid changes-since value: %s') % search_opts['changes-since'] ) if parsed_args.long: columns = ( 'ID', 'Name', 'Status', 'OS-EXT-STS:task_state', 'OS-EXT-STS:power_state', 'Networks', 'Image Name', 'Image ID', 'Flavor Name', 'Flavor ID', 'OS-EXT-AZ:availability_zone', 'OS-EXT-SRV-ATTR:host', 'Metadata', ) column_headers = ( 'ID', 'Name', 'Status', 'Task State', 'Power State', 'Networks', 'Image Name', 'Image ID', 'Flavor Name', 'Flavor ID', 'Availability Zone', 'Host', 'Properties', ) mixed_case_fields = [ 'OS-EXT-STS:task_state', 'OS-EXT-STS:power_state', 'OS-EXT-AZ:availability_zone', 'OS-EXT-SRV-ATTR:host', ] else: if parsed_args.no_name_lookup: columns = ( 'ID', 'Name', 'Status', 'Networks', 'Image ID', 'Flavor ID', ) else: columns = ( 'ID', 'Name', 'Status', 'Networks', 'Image Name', 'Flavor Name', ) column_headers = ( 'ID', 'Name', 'Status', 'Networks', 'Image', 'Flavor', ) mixed_case_fields = [] marker_id = None if parsed_args.marker: marker_id = utils.find_resource(compute_client.servers, parsed_args.marker).id data = compute_client.servers.list(search_opts=search_opts, marker=marker_id, limit=parsed_args.limit) images = {} # Create a dict that maps image_id to image object. # Needed so that we can display the "Image Name" column. # "Image Name" is not crucial, so we swallow any exceptions. if not parsed_args.no_name_lookup: try: images_list = self.app.client_manager.image.images.list() for i in images_list: images[i.id] = i except Exception: pass flavors = {} # Create a dict that maps flavor_id to flavor object. # Needed so that we can display the "Flavor Name" column. # "Flavor Name" is not crucial, so we swallow any exceptions. if not parsed_args.no_name_lookup: try: flavors_list = compute_client.flavors.list() for i in flavors_list: flavors[i.id] = i except Exception: pass # Populate image_name, image_id, flavor_name and flavor_id attributes # of server objects so that we can display those columns. for s in data: if 'id' in s.image: image = images.get(s.image['id']) if image: s.image_name = image.name s.image_id = s.image['id'] else: s.image_name = '' s.image_id = '' if 'id' in s.flavor: flavor = flavors.get(s.flavor['id']) if flavor: s.flavor_name = flavor.name s.flavor_id = s.flavor['id'] else: s.flavor_name = '' s.flavor_id = '' table = (column_headers, (utils.get_item_properties( s, columns, mixed_case_fields=mixed_case_fields, formatters={ 'OS-EXT-STS:power_state': _format_servers_list_power_state, 'Networks': _format_servers_list_networks, 'Metadata': utils.format_dict, }, ) for s in data)) return table class LockServer(command.Command): _description = _("Lock server(s). A non-admin user will not be able to " "execute actions") def get_parser(self, prog_name): parser = super(LockServer, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', nargs='+', help=_('Server(s) to lock (name or ID)'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute for server in parsed_args.server: utils.find_resource( compute_client.servers, server, ).lock() # FIXME(dtroyer): Here is what I want, how with argparse/cliff? # server migrate [--wait] \ # [--live # [--shared-migration | --block-migration] # [--disk-overcommit | --no-disk-overcommit]] # # # live_parser = parser.add_argument_group(title='Live migration options') # then adding the groups doesn't seem to work class MigrateServer(command.Command): _description = _("Migrate server to different host") def get_parser(self, prog_name): parser = super(MigrateServer, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_('Server (name or ID)'), ) parser.add_argument( '--live', metavar='', help=_('Target hostname'), ) migration_group = parser.add_mutually_exclusive_group() migration_group.add_argument( '--shared-migration', dest='block_migration', action='store_false', default=False, help=_('Perform a shared live migration (default)'), ) migration_group.add_argument( '--block-migration', dest='block_migration', action='store_true', help=_('Perform a block live migration'), ) disk_group = parser.add_mutually_exclusive_group() disk_group.add_argument( '--disk-overcommit', action='store_true', default=False, help=_('Allow disk over-commit on the destination host'), ) disk_group.add_argument( '--no-disk-overcommit', dest='disk_overcommit', action='store_false', default=False, help=_('Do not over-commit disk on the' ' destination host (default)'), ) parser.add_argument( '--wait', action='store_true', help=_('Wait for migrate to complete'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server, ) if parsed_args.live: server.live_migrate( host=parsed_args.live, block_migration=parsed_args.block_migration, disk_over_commit=parsed_args.disk_overcommit, ) else: if parsed_args.block_migration or parsed_args.disk_overcommit: raise exceptions.CommandError("--live must be specified if " "--block-migration or " "--disk-overcommit is specified") server.migrate() if parsed_args.wait: if utils.wait_for_status( compute_client.servers.get, server.id, callback=_show_progress, ): sys.stdout.write(_('Complete\n')) else: LOG.error(_('Error migrating server: %s'), server.id) sys.stdout.write(_('Error migrating server\n')) raise SystemExit class PauseServer(command.Command): _description = _("Pause server(s)") def get_parser(self, prog_name): parser = super(PauseServer, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', nargs='+', help=_('Server(s) to pause (name or ID)'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute for server in parsed_args.server: utils.find_resource( compute_client.servers, server ).pause() class RebootServer(command.Command): _description = _("Perform a hard or soft server reboot") def get_parser(self, prog_name): parser = super(RebootServer, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_('Server (name or ID)'), ) group = parser.add_mutually_exclusive_group() group.add_argument( '--hard', dest='reboot_type', action='store_const', const=servers.REBOOT_HARD, default=servers.REBOOT_SOFT, help=_('Perform a hard reboot'), ) group.add_argument( '--soft', dest='reboot_type', action='store_const', const=servers.REBOOT_SOFT, default=servers.REBOOT_SOFT, help=_('Perform a soft reboot'), ) parser.add_argument( '--wait', action='store_true', help=_('Wait for reboot to complete'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server) server.reboot(parsed_args.reboot_type) if parsed_args.wait: if utils.wait_for_status( compute_client.servers.get, server.id, callback=_show_progress, ): sys.stdout.write(_('Complete\n')) else: LOG.error(_('Error rebooting server: %s'), server.id) sys.stdout.write(_('Error rebooting server\n')) raise SystemExit class RebuildServer(command.ShowOne): _description = _("Rebuild server") def get_parser(self, prog_name): parser = super(RebuildServer, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_('Server (name or ID)'), ) parser.add_argument( '--image', metavar='', help=_('Recreate server from the specified image (name or ID).' ' Defaults to the currently used one.'), ) parser.add_argument( '--password', metavar='', help=_("Set the password on the rebuilt instance"), ) parser.add_argument( '--wait', action='store_true', help=_('Wait for rebuild to complete'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute image_client = self.app.client_manager.image server = utils.find_resource( compute_client.servers, parsed_args.server) # If parsed_args.image is not set, default to the currently used one. image_id = parsed_args.image or server._info.get('image', {}).get('id') image = utils.find_resource(image_client.images, image_id) server = server.rebuild(image, parsed_args.password) if parsed_args.wait: if utils.wait_for_status( compute_client.servers.get, server.id, callback=_show_progress, ): sys.stdout.write(_('Complete\n')) else: LOG.error(_('Error rebuilding server: %s'), server.id) sys.stdout.write(_('Error rebuilding server\n')) raise SystemExit details = _prep_server_detail(compute_client, image_client, server) return zip(*sorted(six.iteritems(details))) class RemoveFixedIP(command.Command): _description = _("Remove fixed IP address from server") def get_parser(self, prog_name): parser = super(RemoveFixedIP, self).get_parser(prog_name) parser.add_argument( "server", metavar="", help=_("Server to remove the fixed IP address from (name or ID)"), ) parser.add_argument( "ip_address", metavar="", help=_("Fixed IP address to remove from the server (IP only)"), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server) server.remove_fixed_ip(parsed_args.ip_address) class RemoveFloatingIP(command.Command): _description = _("Remove floating IP address from server") def get_parser(self, prog_name): parser = super(RemoveFloatingIP, self).get_parser(prog_name) parser.add_argument( "server", metavar="", help=_( "Server to remove the floating IP address from (name or ID)" ), ) parser.add_argument( "ip_address", metavar="", help=_("Floating IP address to remove from server (IP only)"), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server) server.remove_floating_ip(parsed_args.ip_address) class RemovePort(command.Command): _description = _("Remove port from server") def get_parser(self, prog_name): parser = super(RemovePort, self).get_parser(prog_name) parser.add_argument( "server", metavar="", help=_("Server to remove the port from (name or ID)"), ) parser.add_argument( "port", metavar="", help=_("Port to remove from the server (name or ID)"), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server) if self.app.client_manager.is_network_endpoint_enabled(): network_client = self.app.client_manager.network port_id = network_client.find_port( parsed_args.port, ignore_missing=False).id else: port_id = parsed_args.port server.interface_detach(port_id) class RemoveNetwork(command.Command): _description = _("Remove all ports of a network from server") def get_parser(self, prog_name): parser = super(RemoveNetwork, self).get_parser(prog_name) parser.add_argument( "server", metavar="", help=_("Server to remove the port from (name or ID)"), ) parser.add_argument( "network", metavar="", help=_("Network to remove from the server (name or ID)"), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server) if self.app.client_manager.is_network_endpoint_enabled(): network_client = self.app.client_manager.network net_id = network_client.find_network( parsed_args.network, ignore_missing=False).id else: net_id = parsed_args.network for inf in server.interface_list(): if inf.net_id == net_id: server.interface_detach(inf.port_id) class RemoveServerSecurityGroup(command.Command): _description = _("Remove security group from server") def get_parser(self, prog_name): parser = super(RemoveServerSecurityGroup, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_('Name or ID of server to use'), ) parser.add_argument( 'group', metavar='', help=_('Name or ID of security group to remove from server'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server, ) security_group = compute_client.api.security_group_find( parsed_args.group, ) server.remove_security_group(security_group['id']) class RemoveServerVolume(command.Command): _description = _("Remove volume from server") def get_parser(self, prog_name): parser = super(RemoveServerVolume, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_('Server (name or ID)'), ) parser.add_argument( 'volume', metavar='', help=_('Volume to remove (name or ID)'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute volume_client = self.app.client_manager.volume server = utils.find_resource( compute_client.servers, parsed_args.server, ) volume = utils.find_resource( volume_client.volumes, parsed_args.volume, ) compute_client.volumes.delete_server_volume( server.id, volume.id, ) class RescueServer(command.Command): _description = _("Put server in rescue mode") def get_parser(self, prog_name): parser = super(RescueServer, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_('Server (name or ID)'), ) parser.add_argument( '--image', metavar='', help=_('Image (name or ID) to use for the rescue mode.' ' Defaults to the currently used one.'), ) parser.add_argument( '--password', metavar='', help=_("Set the password on the rescued instance"), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute image_client = self.app.client_manager.image image = None if parsed_args.image: image = utils.find_resource( image_client.images, parsed_args.image, ) utils.find_resource( compute_client.servers, parsed_args.server, ).rescue(image=image, password=parsed_args.password) class ResizeServer(command.Command): _description = _("""Scale server to a new flavor. A resize operation is implemented by creating a new server and copying the contents of the original disk into a new one. It is also a two-step process for the user: the first is to perform the resize, the second is to either confirm (verify) success and release the old server, or to declare a revert to release the new server and restart the old one.""") def get_parser(self, prog_name): parser = super(ResizeServer, self).get_parser(prog_name) phase_group = parser.add_mutually_exclusive_group() parser.add_argument( 'server', metavar='', help=_('Server (name or ID)'), ) phase_group.add_argument( '--flavor', metavar='', help=_('Resize server to specified flavor'), ) phase_group.add_argument( '--confirm', action="store_true", help=_('Confirm server resize is complete'), ) phase_group.add_argument( '--revert', action="store_true", help=_('Restore server state before resize'), ) parser.add_argument( '--wait', action='store_true', help=_('Wait for resize to complete'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server, ) if parsed_args.flavor: flavor = utils.find_resource( compute_client.flavors, parsed_args.flavor, ) compute_client.servers.resize(server, flavor) if parsed_args.wait: if utils.wait_for_status( compute_client.servers.get, server.id, success_status=['active', 'verify_resize'], callback=_show_progress, ): sys.stdout.write(_('Complete\n')) else: LOG.error(_('Error resizing server: %s'), server.id) sys.stdout.write(_('Error resizing server\n')) raise SystemExit elif parsed_args.confirm: compute_client.servers.confirm_resize(server) elif parsed_args.revert: compute_client.servers.revert_resize(server) class RestoreServer(command.Command): _description = _("Restore server(s)") def get_parser(self, prog_name): parser = super(RestoreServer, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', nargs='+', help=_('Server(s) to restore (name or ID)'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute for server in parsed_args.server: utils.find_resource( compute_client.servers, server ).restore() class ResumeServer(command.Command): _description = _("Resume server(s)") def get_parser(self, prog_name): parser = super(ResumeServer, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', nargs='+', help=_('Server(s) to resume (name or ID)'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute for server in parsed_args.server: utils.find_resource( compute_client.servers, server, ).resume() class SetServer(command.Command): _description = _("Set server properties") def get_parser(self, prog_name): parser = super(SetServer, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_('Server (name or ID)'), ) parser.add_argument( '--name', metavar='', help=_('New server name'), ) parser.add_argument( '--root-password', action="store_true", help=_('Set new root password (interactive only)'), ) parser.add_argument( "--property", metavar="", action=parseractions.KeyValueAction, help=_('Property to add/change for this server ' '(repeat option to set multiple properties)'), ) parser.add_argument( '--state', metavar='', choices=['active', 'error'], help=_('New server state (valid value: active, error)'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server, ) if parsed_args.name: server.update(name=parsed_args.name) if parsed_args.property: compute_client.servers.set_meta( server, parsed_args.property, ) if parsed_args.state: server.reset_state(state=parsed_args.state) if parsed_args.root_password: p1 = getpass.getpass(_('New password: ')) p2 = getpass.getpass(_('Retype new password: ')) if p1 == p2: server.change_password(p1) else: msg = _("Passwords do not match, password unchanged") raise exceptions.CommandError(msg) class ShelveServer(command.Command): _description = _("Shelve server(s)") def get_parser(self, prog_name): parser = super(ShelveServer, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', nargs='+', help=_('Server(s) to shelve (name or ID)'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute for server in parsed_args.server: utils.find_resource( compute_client.servers, server, ).shelve() class ShowServer(command.ShowOne): _description = _("Show server details") def get_parser(self, prog_name): parser = super(ShowServer, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_('Server (name or ID)'), ) parser.add_argument( '--diagnostics', action='store_true', default=False, help=_('Display server diagnostics information'), ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource(compute_client.servers, parsed_args.server) if parsed_args.diagnostics: (resp, data) = server.diagnostics() if not resp.status_code == 200: sys.stderr.write(_("Error retrieving diagnostics data\n")) return ({}, {}) else: data = _prep_server_detail(compute_client, self.app.client_manager.image, server) return zip(*sorted(six.iteritems(data))) class SshServer(command.Command): _description = _("SSH to server") def get_parser(self, prog_name): parser = super(SshServer, self).get_parser(prog_name) parser.add_argument( 'server', metavar='', help=_('Server (name or ID)'), ) parser.add_argument( '--login', metavar='', help=_('Login name (ssh -l option)'), ) parser.add_argument( '-l', dest='login', metavar='', help=argparse.SUPPRESS, ) parser.add_argument( '--port', metavar='', type=int, help=_('Destination port (ssh -p option)'), ) parser.add_argument( '-p', metavar='', dest='port', type=int, help=argparse.SUPPRESS, ) parser.add_argument( '--identity', metavar='', help=_('Private key file (ssh -i option)'), ) parser.add_argument( '-i', metavar='', dest='identity', help=argparse.SUPPRESS, ) parser.add_argument( '--option', metavar='', help=_('Options in ssh_config(5) format (ssh -o option)'), ) parser.add_argument( '-o', metavar='