diff options
| author | Zuul <zuul@review.opendev.org> | 2020-11-09 16:56:19 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2020-11-09 16:56:19 +0000 |
| commit | 4d3bad9f198628954f6c50fdb76b56e2d8ecc070 (patch) | |
| tree | 1c11a9050684e5592b58c412eb1174d9a7e42fd1 /openstackclient/compute | |
| parent | 0a7f2692c62846bb0d49d366df65f1cfc2565f03 (diff) | |
| parent | 01eb4e839394fe433a92a06daf1499fb00f2fe69 (diff) | |
| download | python-openstackclient-4d3bad9f198628954f6c50fdb76b56e2d8ecc070.tar.gz | |
Merge "Add 'openstack server evacuate' command"
Diffstat (limited to 'openstackclient/compute')
| -rw-r--r-- | openstackclient/compute/v2/server.py | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py index fddafaee..ab15599f 100644 --- a/openstackclient/compute/v2/server.py +++ b/openstackclient/compute/v2/server.py @@ -2513,6 +2513,118 @@ class RebuildServer(command.ShowOne): return zip(*sorted(details.items())) +class EvacuateServer(command.ShowOne): + _description = _("""Evacuate a server to a different host. + +This command is used to recreate a server after the host it was on has failed. +It can only be used if the compute service that manages the server is down. +This command should only be used by an admin after they have confirmed that the +instance is not running on the failed host. + +If the server instance was created with an ephemeral root disk on non-shared +storage the server will be rebuilt using the original glance image preserving +the ports and any attached data volumes. + +If the server uses boot for volume or has its root disk on shared storage the +root disk will be preserved and reused for the evacuated instance on the new +host.""") + + def get_parser(self, prog_name): + parser = super(EvacuateServer, self).get_parser(prog_name) + parser.add_argument( + 'server', + metavar='<server>', + help=_('Server (name or ID)'), + ) + + parser.add_argument( + '--wait', action='store_true', + help=_('Wait for evacuation to complete'), + ) + parser.add_argument( + '--host', metavar='<host>', default=None, + help=_( + 'Set the preferred host on which to rebuild the evacuated ' + 'server. The host will be validated by the scheduler. ' + '(supported by --os-compute-api-version 2.29 or above)' + ), + ) + shared_storage_group = parser.add_mutually_exclusive_group() + shared_storage_group.add_argument( + '--password', metavar='<password>', default=None, + help=_( + 'Set the password on the evacuated instance. This option is ' + 'mutually exclusive with the --shared-storage option' + ), + ) + shared_storage_group.add_argument( + '--shared-storage', action='store_true', dest='shared_storage', + help=_( + 'Indicate that the instance is on shared storage. ' + 'This will be auto-calculated with ' + '--os-compute-api-version 2.14 and greater and should not ' + 'be used with later microversions. This option is mutually ' + 'exclusive with the --password option' + ), + ) + return parser + + def take_action(self, parsed_args): + + def _show_progress(progress): + if progress: + self.app.stdout.write('\rProgress: %s' % progress) + self.app.stdout.flush() + + compute_client = self.app.client_manager.compute + image_client = self.app.client_manager.image + + if parsed_args.host: + if compute_client.api_version < api_versions.APIVersion('2.29'): + msg = _( + '--os-compute-api-version 2.29 or later is required ' + 'to specify a preferred host.' + ) + raise exceptions.CommandError(msg) + + if parsed_args.shared_storage: + if compute_client.api_version > api_versions.APIVersion('2.13'): + msg = _( + '--os-compute-api-version 2.13 or earlier is required ' + 'to specify shared-storage.' + ) + raise exceptions.CommandError(msg) + + kwargs = { + 'host': parsed_args.host, + 'password': parsed_args.password, + } + + if compute_client.api_version <= api_versions.APIVersion('2.13'): + kwargs['on_shared_storage'] = parsed_args.shared_storage + + server = utils.find_resource( + compute_client.servers, parsed_args.server) + + server = server.evacuate(**kwargs) + + if parsed_args.wait: + if utils.wait_for_status( + compute_client.servers.get, + server.id, + callback=_show_progress, + ): + self.app.stdout.write(_('Complete\n')) + else: + LOG.error(_('Error evacuating server: %s'), server.id) + self.app.stdout.write(_('Error evacuating server\n')) + raise SystemExit + + details = _prep_server_detail( + compute_client, image_client, server, refresh=False) + return zip(*sorted(details.items())) + + class RemoveFixedIP(command.Command): _description = _("Remove fixed IP address from server") |
