diff -Nru python-openstackclient-5.7.0/AUTHORS python-openstackclient-5.8.0/AUTHORS --- python-openstackclient-5.7.0/AUTHORS 2021-11-12 15:18:32.000000000 +0000 +++ python-openstackclient-5.8.0/AUTHORS 2022-03-08 13:00:44.000000000 +0000 @@ -89,6 +89,7 @@ Dao Cong Tien Davanum Srinivas Dave Chen +David Caro David Moreau Simard David Moreau Simard David Rabel @@ -106,6 +107,7 @@ Doug Hellmann Doug Wiegley Dougal Matthews +Dr. Jens Harbott Einst Crazy Elena Ezhova Elod Illes @@ -118,6 +120,7 @@ Felix Yan Flavio Percoco Florent Flament +Frode Nordahl Gabriel Ramirez Gage Hugo Gary Kotton @@ -179,6 +182,7 @@ Jeremy Liu Jeremy Stanley Jerry George +JieonLee Jim Rollenhagen Jimmy McCrory JingLiu @@ -207,6 +211,7 @@ Kendall Nelson Kenneth Chu Kevin_Zheng +Khomesh Thakre Kristi Nikolla Kyrylo Romanenko LEE JAE YONG @@ -269,6 +274,7 @@ Noam Angel Nobuto Murata Noorul Islam K M +Nurmatov Mamatisa Oleksii Chuprykov Ondřej Nový OpenStack Release Bot @@ -293,6 +299,7 @@ Reedip Richard Theis Rikimaru Honjo +Ritvik Vinodkumar Robert Francis Robin Cernin Rodolfo Alonso Hernandez @@ -334,6 +341,7 @@ SongmingYan Stephen Finucane Stephen Finucane +Stephen Finucane Steve Martinelli Steve Martinelli Steven Hardy @@ -350,6 +358,7 @@ Terry Howe TerryHowe Thomas Goirand +Thrivikram Mudunuri Tim Burke Tom Cocozzello Tom Jose Kalapura diff -Nru python-openstackclient-5.7.0/ChangeLog python-openstackclient-5.8.0/ChangeLog --- python-openstackclient-5.7.0/ChangeLog 2021-11-12 15:18:32.000000000 +0000 +++ python-openstackclient-5.8.0/ChangeLog 2022-03-08 13:00:44.000000000 +0000 @@ -1,10 +1,51 @@ CHANGES ======= +5.8.0 +----- + +* Add support for setting extra DHCP options on existing ports +* docs: Document additional 'server migration' commands +* Add support for 'remote-managed' vnic type +* Don't fail on extlinks warnings for reno build +* Support Neutron Local IP CRUD +* Get rid of tenant\_id in the network commands +* Switch compute service list, delete and set to sdk +* Skip original\_name from flavor info +* Fix volume set functional test +* Add location to fake network objects +* Hide location columns for network objects +* compute: Pass through args to ssh +* compute: Fix weird option definition for 'server ssh' +* compute: Return information about fixed IP +* Switch add fixed IP to SDK +* Allow setting gateway when creating a router +* Fix RemoveServerVolume +* Add network update quota "limit\_check" parameter +* Add --security-group to port list +* compute: Show flavor in 'server list' with API >= 2.47 +* compute: Reorder building of columns for 'server list' +* Switch server suspend and server resume to SDK +* Switch server pause and server unpause to SDK +* Switch openstack server remove port/network to using sdk +* Allow unset port's host\_id +* Switch command server remove volume to sdk +* Add functional test for server add/remove volume +* Temporarily drop aodhclient from doc build +* Switch command server add volume to sdk +* Add missing command mapping in nova +* image: Sanity check the 'SetImage' command +* tests: Update fake image client in tests +* image: Remove FakeImage test helper +* image: Remove dead test helper methods +* Switch server image create to SDK +* Switch openstack server add port/network to using sdk + 5.7.0 ----- * compute: Return details of attached volumes +* compute: Don't warn if disk overcommit params unset * Switch server backup to sdk * Remove remnants of 'six' * Remove 'get\_osc\_show\_columns\_for\_sdk\_resource' duplicates @@ -52,6 +93,7 @@ * docs: Update glanceclient comparison doc * docs: Update novaclient comparison doc * docs: Update cinderclient comparison doc +* Include hosts in aggregate list --long * compute: Fix typo * setup.cfg: Replace dashes with underscores * Make functional Neutron tests running fine on ML2/OVN environments @@ -75,6 +117,7 @@ 5.5.0 ----- +* Add --subnet-pool to subnet list * Update the file paths mentioned in README.rst * Add pre-commit * compute: Remove 'file://' prefix from '--block-device' diff -Nru python-openstackclient-5.7.0/debian/changelog python-openstackclient-5.8.0/debian/changelog --- python-openstackclient-5.7.0/debian/changelog 2021-12-01 07:51:45.000000000 +0000 +++ python-openstackclient-5.8.0/debian/changelog 2022-04-04 13:41:18.000000000 +0000 @@ -1,3 +1,10 @@ +python-openstackclient (5.8.0-0ubuntu1) jammy; urgency=medium + + * New upstream release for OpenStack Yoga. + * d/control: Bump minimum version of openstacksdk. + + -- James Page Mon, 04 Apr 2022 14:41:18 +0100 + python-openstackclient (5.7.0-0ubuntu1) jammy; urgency=medium * New upstream release for OpenStack Yoga. diff -Nru python-openstackclient-5.7.0/debian/control python-openstackclient-5.8.0/debian/control --- python-openstackclient-5.7.0/debian/control 2021-12-01 07:51:45.000000000 +0000 +++ python-openstackclient-5.8.0/debian/control 2022-04-04 13:41:18.000000000 +0000 @@ -39,7 +39,7 @@ python3-novaclient (>= 2:17.0.0), python3-octaviaclient (>= 1.11.0), python3-openstackdocstheme (>= 2.2.1), - python3-openstacksdk (>= 0.56.0), + python3-openstacksdk (>= 0.61.0), python3-os-client-config (>= 1.28.0), python3-osc-lib (>= 2.3.0), python3-osc-placement (>= 1.7.0), @@ -99,7 +99,7 @@ python3-iso8601 (>= 0.1.11), python3-keystoneclient (>= 1:3.22.0), python3-novaclient (>= 2:17.0.0), - python3-openstacksdk (>= 0.56.0), + python3-openstacksdk (>= 0.61.0), python3-osc-lib (>= 2.3.0), python3-oslo.i18n (>= 3.15.3), python3-oslo.serialization (>= 1.2.0), diff -Nru python-openstackclient-5.7.0/doc/source/cli/command-objects/local-ip-association.rst python-openstackclient-5.8.0/doc/source/cli/command-objects/local-ip-association.rst --- python-openstackclient-5.7.0/doc/source/cli/command-objects/local-ip-association.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-openstackclient-5.8.0/doc/source/cli/command-objects/local-ip-association.rst 2022-03-08 13:00:10.000000000 +0000 @@ -0,0 +1,11 @@ +============================================= +Local IP Associations (local_ip_associations) +============================================= + +The resource lets users assign Local IPs to user Ports. +This is a sub-resource of the Local IP resource. + +Network v2 + +.. autoprogram-cliff:: openstack.network.v2 + :command: local ip association * diff -Nru python-openstackclient-5.7.0/doc/source/cli/command-objects/local-ip.rst python-openstackclient-5.8.0/doc/source/cli/command-objects/local-ip.rst --- python-openstackclient-5.7.0/doc/source/cli/command-objects/local-ip.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-openstackclient-5.8.0/doc/source/cli/command-objects/local-ip.rst 2022-03-08 13:00:10.000000000 +0000 @@ -0,0 +1,12 @@ +===================== +Local IPs (local_ips) +===================== + +Extension that allows users to create a virtual IP that can later be assigned +to multiple ports/VMs (similar to anycast IP) and is guaranteed to only be +reachable within the same physical server/node boundaries + +Network v2 + +.. autoprogram-cliff:: openstack.network.v2 + :command: local ip * diff -Nru python-openstackclient-5.7.0/doc/source/cli/command-objects/server-migration.rst python-openstackclient-5.8.0/doc/source/cli/command-objects/server-migration.rst --- python-openstackclient-5.7.0/doc/source/cli/command-objects/server-migration.rst 2021-11-12 15:17:53.000000000 +0000 +++ python-openstackclient-5.8.0/doc/source/cli/command-objects/server-migration.rst 2022-03-08 13:00:10.000000000 +0000 @@ -9,4 +9,4 @@ Compute v2 .. autoprogram-cliff:: openstack.compute.v2 - :command: server migration list + :command: server migration * diff -Nru python-openstackclient-5.7.0/doc/source/cli/data/nova.csv python-openstackclient-5.8.0/doc/source/cli/data/nova.csv --- python-openstackclient-5.7.0/doc/source/cli/data/nova.csv 2021-11-12 15:17:53.000000000 +0000 +++ python-openstackclient-5.8.0/doc/source/cli/data/nova.csv 2022-03-08 13:00:10.000000000 +0000 @@ -46,7 +46,7 @@ hypervisor-stats,hypervisor stats show,Get hypervisor statistics over all compute nodes. hypervisor-uptime,,Display the uptime of the specified hypervisor. image-create,server image create,Create a new image by taking a snapshot of a running server. -instance-action,,Show an action. +instance-action,server event show,Show an action. instance-action-list,,List actions on a server. instance-usage-audit-log,,List/Get server usage audits. interface-attach,server add port / server add floating ip / server add fixed ip,Attach a network interface to a server. diff -Nru python-openstackclient-5.7.0/doc/source/cli/plugin-commands/aodh.rst python-openstackclient-5.8.0/doc/source/cli/plugin-commands/aodh.rst --- python-openstackclient-5.7.0/doc/source/cli/plugin-commands/aodh.rst 2021-11-12 15:17:53.000000000 +0000 +++ python-openstackclient-5.8.0/doc/source/cli/plugin-commands/aodh.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -aodh ----- - -.. autoprogram-cliff:: openstack.alarming.v2 diff -Nru python-openstackclient-5.7.0/doc/source/cli/plugin-commands/index.rst python-openstackclient-5.8.0/doc/source/cli/plugin-commands/index.rst --- python-openstackclient-5.7.0/doc/source/cli/plugin-commands/index.rst 2021-11-12 15:17:53.000000000 +0000 +++ python-openstackclient-5.8.0/doc/source/cli/plugin-commands/index.rst 2022-03-08 13:00:10.000000000 +0000 @@ -7,7 +7,6 @@ .. toctree:: :maxdepth: 1 - aodh barbican designate gnocchi @@ -29,6 +28,10 @@ .. TODO(efried): Make pages for the following once they're fixed. +.. aodh +.. # aodhclient docs build is failing with recent pyparsing +.. # autoprogram-cliff:: openstack.alarming.v2 + .. cue .. # cueclient is not in global-requirements .. # list-plugins:: openstack.mb.v1 diff -Nru python-openstackclient-5.7.0/lower-constraints.txt python-openstackclient-5.8.0/lower-constraints.txt --- python-openstackclient-5.7.0/lower-constraints.txt 2021-11-12 15:17:53.000000000 +0000 +++ python-openstackclient-5.8.0/lower-constraints.txt 2022-03-08 13:00:10.000000000 +0000 @@ -38,7 +38,7 @@ munch==2.1.0 netaddr==0.7.18 netifaces==0.10.4 -openstacksdk==0.56.0 +openstacksdk==0.61.0 os-client-config==2.1.0 os-service-types==1.7.0 osc-lib==2.3.0 diff -Nru python-openstackclient-5.7.0/openstackclient/common/quota.py python-openstackclient-5.8.0/openstackclient/common/quota.py --- python-openstackclient-5.7.0/openstackclient/common/quota.py 2021-11-12 15:17:53.000000000 +0000 +++ python-openstackclient-5.8.0/openstackclient/common/quota.py 2022-03-08 13:00:10.000000000 +0000 @@ -535,6 +535,12 @@ action='store_true', help=_('Force quota update (only supported by compute)') ) + parser.add_argument( + '--check-limit', + action='store_true', + help=_('Check quota limit when updating (only supported by ' + 'network)') + ) return parser def take_action(self, parsed_args): @@ -561,6 +567,9 @@ volume_kwargs[k] = value network_kwargs = {} + if parsed_args.check_limit: + network_kwargs['check_limit'] = True + if self.app.client_manager.is_network_endpoint_enabled(): for k, v in NETWORK_QUOTAS.items(): value = getattr(parsed_args, k, None) diff -Nru python-openstackclient-5.7.0/openstackclient/compute/v2/aggregate.py python-openstackclient-5.8.0/openstackclient/compute/v2/aggregate.py --- python-openstackclient-5.7.0/openstackclient/compute/v2/aggregate.py 2021-11-12 15:17:53.000000000 +0000 +++ python-openstackclient-5.8.0/openstackclient/compute/v2/aggregate.py 2022-03-08 13:00:10.000000000 +0000 @@ -193,12 +193,14 @@ "Name", "Availability Zone", "Properties", + "Hosts", ) columns = ( "ID", "Name", "Availability Zone", "Metadata", + "Hosts", ) else: column_headers = columns = ( diff -Nru python-openstackclient-5.7.0/openstackclient/compute/v2/flavor.py python-openstackclient-5.8.0/openstackclient/compute/v2/flavor.py --- python-openstackclient-5.7.0/openstackclient/compute/v2/flavor.py 2021-11-12 15:17:53.000000000 +0000 +++ python-openstackclient-5.8.0/openstackclient/compute/v2/flavor.py 2022-03-08 13:00:10.000000000 +0000 @@ -48,7 +48,7 @@ 'is_public': 'os-flavor-access:is_public' } - hidden_columns = ['links', 'location'] + hidden_columns = ['links', 'location', 'original_name'] return utils.get_osc_show_columns_for_sdk_resource( item, column_map, hidden_columns) diff -Nru python-openstackclient-5.7.0/openstackclient/compute/v2/server_image.py python-openstackclient-5.8.0/openstackclient/compute/v2/server_image.py --- python-openstackclient-5.7.0/openstackclient/compute/v2/server_image.py 2021-11-12 15:17:53.000000000 +0000 +++ python-openstackclient-5.8.0/openstackclient/compute/v2/server_image.py 2022-03-08 13:00:10.000000000 +0000 @@ -73,25 +73,23 @@ self.app.stdout.write('\rProgress: %s' % progress) self.app.stdout.flush() - compute_client = self.app.client_manager.compute + compute_client = self.app.client_manager.sdk_connection.compute + image_client = self.app.client_manager.image - server = utils.find_resource( - compute_client.servers, - parsed_args.server, + server = compute_client.find_server( + parsed_args.server, ignore_missing=False, ) + if parsed_args.name: image_name = parsed_args.name else: image_name = server.name - image_id = compute_client.servers.create_image( + image_id = compute_client.create_server_image( server.id, image_name, parsed_args.properties, - ) - - image_client = self.app.client_manager.image - image = image_client.find_image(image_id) + ).id if parsed_args.wait: if utils.wait_for_status( @@ -105,6 +103,8 @@ _('Error creating server image: %s'), parsed_args.server) raise exceptions.CommandError + image = image_client.find_image(image_id, ignore_missing=False) + if self.app.client_manager._api_version['image'] == '1': info = {} info.update(image._info) diff -Nru python-openstackclient-5.7.0/openstackclient/compute/v2/server.py python-openstackclient-5.8.0/openstackclient/compute/v2/server.py --- python-openstackclient-5.7.0/openstackclient/compute/v2/server.py 2021-11-12 15:17:53.000000000 +0000 +++ python-openstackclient-5.8.0/openstackclient/compute/v2/server.py 2022-03-08 13:00:10.000000000 +0000 @@ -27,6 +27,7 @@ from novaclient import api_versions from novaclient.v2 import servers from openstack import exceptions as sdk_exceptions +from openstack import utils as sdk_utils from osc_lib.cli import format_columns from osc_lib.cli import parseractions from osc_lib.command import command @@ -203,7 +204,7 @@ return default -class AddFixedIP(command.Command): +class AddFixedIP(command.ShowOne): _description = _("Add fixed IP address to server") def get_parser(self, prog_name): @@ -230,36 +231,73 @@ metavar='', help=_( 'Tag for the attached interface. ' - '(supported by --os-compute-api-version 2.52 or above)' + '(supported by --os-compute-api-version 2.49 or above)' ) ) 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) - - kwargs = { - 'port_id': None, - 'net_id': network['id'], - 'fixed_ip': parsed_args.fixed_ip_address, - } + compute_client = self.app.client_manager.sdk_connection.compute + server = compute_client.find_server( + parsed_args.server, + ignore_missing=False + ) if parsed_args.tag: - if compute_client.api_version < api_versions.APIVersion('2.49'): + if not sdk_utils.supports_microversion(compute_client, '2.49'): msg = _( '--os-compute-api-version 2.49 or greater is required to ' 'support the --tag option' ) raise exceptions.CommandError(msg) + 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 + + if not sdk_utils.supports_microversion(compute_client, '2.44'): + compute_client.add_fixed_ip_to_server( + server.id, + net_id + ) + return ((), ()) + + kwargs = { + 'net_id': net_id, + 'fixed_ip': parsed_args.fixed_ip_address, + } + if parsed_args.tag: kwargs['tag'] = parsed_args.tag - server.interface_attach(**kwargs) + interface = compute_client.create_server_interface(server.id, **kwargs) + + columns = ( + 'port_id', 'server_id', 'net_id', 'mac_addr', 'port_state', + 'fixed_ips', + ) + column_headers = ( + 'Port ID', 'Server ID', 'Network ID', 'MAC Address', 'Port State', + 'Fixed IPs', + ) + if sdk_utils.supports_microversion(compute_client, '2.49'): + columns += ('tag',) + column_headers += ('Tag',) + + return ( + column_headers, + utils.get_item_properties( + interface, + columns, + formatters={ + 'fixed_ips': format_columns.ListDictColumn, + }, + ), + ) class AddFloatingIP(network_common.NetworkAndComputeCommand): @@ -378,10 +416,10 @@ return parser def take_action(self, parsed_args): - compute_client = self.app.client_manager.compute + compute_client = self.app.client_manager.sdk_connection.compute - server = utils.find_resource( - compute_client.servers, parsed_args.server) + server = compute_client.find_server( + parsed_args.server, ignore_missing=False) if self.app.client_manager.is_network_endpoint_enabled(): network_client = self.app.client_manager.network @@ -392,12 +430,11 @@ kwargs = { 'port_id': port_id, - 'net_id': None, 'fixed_ip': None, } if parsed_args.tag: - if compute_client.api_version < api_versions.APIVersion("2.49"): + if not sdk_utils.supports_microversion(compute_client, '2.49'): msg = _( '--os-compute-api-version 2.49 or greater is required to ' 'support the --tag option' @@ -405,7 +442,7 @@ raise exceptions.CommandError(msg) kwargs['tag'] = parsed_args.tag - server.interface_attach(**kwargs) + compute_client.create_server_interface(server, **kwargs) class AddNetwork(command.Command): @@ -434,10 +471,10 @@ return parser def take_action(self, parsed_args): - compute_client = self.app.client_manager.compute + compute_client = self.app.client_manager.sdk_connection.compute - server = utils.find_resource( - compute_client.servers, parsed_args.server) + server = compute_client.find_server( + parsed_args.server, ignore_missing=False) if self.app.client_manager.is_network_endpoint_enabled(): network_client = self.app.client_manager.network @@ -447,13 +484,12 @@ net_id = parsed_args.network kwargs = { - 'port_id': None, 'net_id': net_id, 'fixed_ip': None, } if parsed_args.tag: - if compute_client.api_version < api_versions.APIVersion('2.49'): + if not sdk_utils.supports_microversion(compute_client, '2.49'): msg = _( '--os-compute-api-version 2.49 or greater is required to ' 'support the --tag option' @@ -462,7 +498,7 @@ kwargs['tag'] = parsed_args.tag - server.interface_attach(**kwargs) + compute_client.create_server_interface(server, **kwargs) class AddServerSecurityGroup(command.Command): @@ -549,24 +585,25 @@ return parser def take_action(self, parsed_args): - compute_client = self.app.client_manager.compute - volume_client = self.app.client_manager.volume + compute_client = self.app.client_manager.sdk_connection.compute + volume_client = self.app.client_manager.sdk_connection.volume - server = utils.find_resource( - compute_client.servers, + server = compute_client.find_server( parsed_args.server, + ignore_missing=False, ) - volume = utils.find_resource( - volume_client.volumes, + volume = volume_client.find_volume( parsed_args.volume, + ignore_missing=False, ) kwargs = { + "volumeId": volume.id, "device": parsed_args.device } if parsed_args.tag: - if compute_client.api_version < api_versions.APIVersion('2.49'): + if not sdk_utils.supports_microversion(compute_client, '2.49'): msg = _( '--os-compute-api-version 2.49 or greater is required to ' 'support the --tag option' @@ -576,7 +613,7 @@ kwargs['tag'] = parsed_args.tag if parsed_args.enable_delete_on_termination: - if compute_client.api_version < api_versions.APIVersion('2.79'): + if not sdk_utils.supports_microversion(compute_client, '2.79'): msg = _( '--os-compute-api-version 2.79 or greater is required to ' 'support the --enable-delete-on-termination option.' @@ -586,7 +623,7 @@ kwargs['delete_on_termination'] = True if parsed_args.disable_delete_on_termination: - if compute_client.api_version < api_versions.APIVersion('2.79'): + if not sdk_utils.supports_microversion(compute_client, '2.79'): msg = _( '--os-compute-api-version 2.79 or greater is required to ' 'support the --disable-delete-on-termination option.' @@ -595,28 +632,23 @@ kwargs['delete_on_termination'] = False - volume_attachment = compute_client.volumes.create_server_volume( - server.id, - volume.id, - **kwargs + volume_attachment = compute_client.create_volume_attachment( + server, + **kwargs, ) - columns = ('id', 'serverId', 'volumeId', 'device') + columns = ('id', 'server id', 'volume id', 'device') column_headers = ('ID', 'Server ID', 'Volume ID', 'Device') - if compute_client.api_version >= api_versions.APIVersion('2.49'): + if sdk_utils.supports_microversion(compute_client, '2.49'): columns += ('tag',) column_headers += ('Tag',) - if compute_client.api_version >= api_versions.APIVersion('2.79'): + if sdk_utils.supports_microversion(compute_client, '2.79'): columns += ('delete_on_termination',) column_headers += ('Delete On Termination',) return ( column_headers, - utils.get_item_properties( - volume_attachment, - columns, - mixed_case_fields=('serverId', 'volumeId'), - ) + utils.get_item_properties(volume_attachment, columns,) ) @@ -2209,15 +2241,19 @@ # 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 + 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 = image_client.find_image(parsed_args.image, - ignore_missing=False).id + image_id = image_client.find_image( + parsed_args.image, + ignore_missing=False, + ).id search_opts = { 'reservation_id': parsed_args.reservation_id, @@ -2325,95 +2361,100 @@ try: iso8601.parse_date(search_opts['changes-since']) except (TypeError, iso8601.ParseError): + msg = _('Invalid changes-since value: %s') raise exceptions.CommandError( - _('Invalid changes-since value: %s') % - search_opts['changes-since'] + msg % search_opts['changes-since'] ) + columns = ( + 'id', + 'name', + 'status', + ) + column_headers = ( + 'ID', + 'Name', + 'Status', + ) + if parsed_args.long: - columns = ( - 'ID', - 'Name', - 'Status', + columns += ( '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', + column_headers += ( 'Task State', 'Power State', - 'Networks', + ) + + columns += ('networks',) + column_headers += ('Networks',) + + if parsed_args.long: + columns += ( + 'image_name', + 'image_id', + ) + column_headers += ( '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', - ) + columns += ('image_id',) else: - columns = ( - 'ID', - 'Name', - 'Status', - 'Networks', - 'Image Name', + columns += ('image_name',) + column_headers += ('Image',) + + # microversion 2.47 puts the embedded flavor into the server response + # body but omits the id, so if not present we just expose the original + # flavor name in the output + if compute_client.api_version >= api_versions.APIVersion('2.47'): + columns += ('flavor_name',) + column_headers += ('Flavor',) + else: + if parsed_args.long: + columns += ( + 'flavor_name', + 'flavor_id', + ) + column_headers += ( 'Flavor Name', + 'Flavor ID', ) - column_headers = ( - 'ID', - 'Name', - 'Status', - 'Networks', - 'Image', - 'Flavor', + else: + if parsed_args.no_name_lookup: + columns += ('flavor_id',) + else: + columns += ('flavor_name',) + column_headers += ('Flavor',) + + if parsed_args.long: + columns += ( + 'OS-EXT-AZ:availability_zone', + 'OS-EXT-SRV-ATTR:host', + 'metadata', + ) + column_headers += ( + 'Availability Zone', + 'Host', + 'Properties', ) - mixed_case_fields = [] marker_id = None # support for additional columns if parsed_args.columns: - # convert tuple to list to edit them - column_headers = list(column_headers) - columns = list(columns) - for c in parsed_args.columns: if c in ('Project ID', 'project_id'): - columns.append('tenant_id') - column_headers.append('Project ID') + columns += ('tenant_id',) + column_headers += ('Project ID',) if c in ('User ID', 'user_id'): - columns.append('user_id') - column_headers.append('User ID') + columns += ('user_id',) + column_headers += ('User ID',) if c in ('Created At', 'created_at'): - columns.append('created') - column_headers.append('Created At') + columns += ('created',) + column_headers += ('Created At',) # convert back to tuple column_headers = tuple(column_headers) @@ -2427,25 +2468,29 @@ if parsed_args.deleted: marker_id = parsed_args.marker else: - marker_id = utils.find_resource(compute_client.servers, - parsed_args.marker).id + 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) + data = compute_client.servers.list( + search_opts=search_opts, + marker=marker_id, + limit=parsed_args.limit) images = {} flavors = {} if data and not parsed_args.no_name_lookup: - # 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. - # The 'image' attribute can be an empty string if the server was - # booted from a volume. + # create a dict that maps image_id to image object, which is used + # to display the "Image Name" column. Note that 'image.id' can be + # empty for BFV instances and 'image' can be missing entirely if + # there are infra failures if parsed_args.name_lookup_one_by_one or image_id: - for i_id in set(filter(lambda x: x is not None, - (s.image.get('id') for s in data - if s.image))): + for i_id in set( + s.image['id'] for s in data + if s.image and s.image.get('id') + ): + # "Image Name" is not crucial, so we swallow any exceptions try: images[i_id] = image_client.get_image(i_id) except Exception: @@ -2458,12 +2503,17 @@ except Exception: pass - # 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. + # create a dict that maps flavor_id to flavor object, which is used + # to display the "Flavor Name" column. Note that 'flavor.id' is not + # present on microversion 2.47 or later and 'flavor' won't be + # present if there are infra failures if parsed_args.name_lookup_one_by_one or flavor_id: - for f_id in set(filter(lambda x: x is not None, - (s.flavor.get('id') for s in data))): + for f_id in set( + s.flavor['id'] for s in data + if s.flavor and s.flavor.get('id') + ): + # "Flavor Name" is not crucial, so we swallow any + # exceptions try: flavors[f_id] = compute_client.flavors.get(f_id) except Exception: @@ -2487,6 +2537,7 @@ # processing of the image and flavor informations. if not hasattr(s, 'image') or not hasattr(s, 'flavor'): continue + if 'id' in s.image: image = images.get(s.image['id']) if image: @@ -2499,29 +2550,30 @@ # able to grep for boot-from-volume servers when using the CLI. s.image_name = IMAGE_STRING_FOR_BFV s.image_id = IMAGE_STRING_FOR_BFV - if 'id' in s.flavor: + + if compute_client.api_version < api_versions.APIVersion('2.47'): flavor = flavors.get(s.flavor['id']) if flavor: s.flavor_name = flavor.name s.flavor_id = s.flavor['id'] else: - # TODO(mriedem): Fix this for microversion >= 2.47 where the - # flavor is embedded in the server response without the id. - # We likely need to drop the Flavor ID column in that case if - # --long is specified. - s.flavor_name = '' - s.flavor_id = '' + s.flavor_name = s.flavor['original_name'] table = ( column_headers, ( utils.get_item_properties( s, columns, - mixed_case_fields=mixed_case_fields, + mixed_case_fields=( + 'OS-EXT-STS:task_state', + 'OS-EXT-STS:power_state', + 'OS-EXT-AZ:availability_zone', + 'OS-EXT-SRV-ATTR:host', + ), formatters={ 'OS-EXT-STS:power_state': PowerStateColumn, - 'Networks': format_columns.DictListColumn, - 'Metadata': format_columns.DictColumn, + 'networks': format_columns.DictListColumn, + 'metadata': format_columns.DictColumn, }, ) for s in data ), @@ -2639,7 +2691,7 @@ disk_group.add_argument( '--disk-overcommit', action='store_true', - default=False, + default=None, help=_( 'Allow disk over-commit on the destination host' '(supported with --os-compute-api-version 2.24 or below)' @@ -2649,7 +2701,6 @@ '--no-disk-overcommit', dest='disk_overcommit', action='store_false', - default=False, help=_( 'Do not over-commit disk on the destination host (default)' '(supported with --os-compute-api-version 2.24 or below)' @@ -2711,6 +2762,11 @@ if compute_client.api_version < api_versions.APIVersion('2.25'): kwargs['disk_over_commit'] = parsed_args.disk_overcommit + # We can't use an argparse default value because then we can't + # distinguish between explicit 'False' and unset for the below + # case (microversion >= 2.25) + if kwargs['disk_over_commit'] is None: + kwargs['disk_over_commit'] = False elif parsed_args.disk_overcommit is not None: # TODO(stephenfin): Raise an error here in OSC 7.0 msg = _( @@ -3135,12 +3191,13 @@ return parser def take_action(self, parsed_args): - compute_client = self.app.client_manager.compute + compute_client = self.app.client_manager.sdk_connection.compute for server in parsed_args.server: - utils.find_resource( - compute_client.servers, - server - ).pause() + server_id = compute_client.find_server( + server, + ignore_missing=False, + ).id + compute_client.pause_server(server_id) class RebootServer(command.Command): @@ -3695,10 +3752,10 @@ return parser def take_action(self, parsed_args): - compute_client = self.app.client_manager.compute + compute_client = self.app.client_manager.sdk_connection.compute - server = utils.find_resource( - compute_client.servers, parsed_args.server) + server = compute_client.find_server( + parsed_args.server, ignore_missing=False) if self.app.client_manager.is_network_endpoint_enabled(): network_client = self.app.client_manager.network @@ -3707,7 +3764,11 @@ else: port_id = parsed_args.port - server.interface_detach(port_id) + compute_client.delete_server_interface( + port_id, + server=server, + ignore_missing=False, + ) class RemoveNetwork(command.Command): @@ -3728,10 +3789,10 @@ return parser def take_action(self, parsed_args): - compute_client = self.app.client_manager.compute + compute_client = self.app.client_manager.sdk_connection.compute - server = utils.find_resource( - compute_client.servers, parsed_args.server) + server = compute_client.find_server( + parsed_args.server, ignore_missing=False) if self.app.client_manager.is_network_endpoint_enabled(): network_client = self.app.client_manager.network @@ -3740,9 +3801,12 @@ else: net_id = parsed_args.network - for inf in server.interface_list(): + for inf in compute_client.server_interfaces(server): if inf.net_id == net_id: - server.interface_detach(inf.port_id) + compute_client.delete_server_interface( + inf.port_id, + server=server, + ) class RemoveServerSecurityGroup(command.Command): @@ -3798,21 +3862,22 @@ return parser def take_action(self, parsed_args): - compute_client = self.app.client_manager.compute - volume_client = self.app.client_manager.volume + compute_client = self.app.client_manager.sdk_connection.compute + volume_client = self.app.client_manager.sdk_connection.volume - server = utils.find_resource( - compute_client.servers, + server = compute_client.find_server( parsed_args.server, + ignore_missing=False, ) - volume = utils.find_resource( - volume_client.volumes, + volume = volume_client.find_volume( parsed_args.volume, + ignore_missing=False, ) - compute_client.volumes.delete_server_volume( - server.id, - volume.id, + compute_client.delete_volume_attachment( + volume, + server, + ignore_missing=False, ) @@ -4078,13 +4143,13 @@ return parser def take_action(self, parsed_args): - - compute_client = self.app.client_manager.compute + compute_client = self.app.client_manager.sdk_connection.compute for server in parsed_args.server: - utils.find_resource( - compute_client.servers, + server_id = compute_client.find_server( server, - ).resume() + ignore_missing=False, + ).id + compute_client.resume_server(server_id) class SetServer(command.Command): @@ -4437,50 +4502,29 @@ metavar='', help=_('Server (name or ID)'), ) + # Deprecated during the Yoga cycle parser.add_argument( - '--login', - metavar='', - help=_('Login name (ssh -l option)'), - ) - parser.add_argument( - '-l', - dest='login', + '--login', '-l', metavar='', help=argparse.SUPPRESS, ) + # Deprecated during the Yoga cycle parser.add_argument( - '--port', - metavar='', - type=int, - help=_('Destination port (ssh -p option)'), - ) - parser.add_argument( - '-p', + '--port', '-p', metavar='', - dest='port', type=int, help=argparse.SUPPRESS, ) + # Deprecated during the Yoga cycle parser.add_argument( - '--identity', + '--identity', '-i', metavar='', - help=_('Private key file (ssh -i option)'), - ) - parser.add_argument( - '-i', - metavar='', - dest='identity', help=argparse.SUPPRESS, ) + # Deprecated during the Yoga cycle parser.add_argument( - '--option', + '--option', '-o', metavar='', - help=_('Options in ssh_config(5) format (ssh -o option)'), - ) - parser.add_argument( - '-o', - metavar='