Ejemplo n.º 1
0
    def show(self, req, server_id, id):
        """Return data about the given interface attachment."""
        context = req.environ['compute.context']
        authorize(context)

        port_id = id
        # NOTE(mriedem): We need to verify the instance actually exists from
        # the server_id even though we're not using the instance for anything,
        # just the port id.
        common.get_instance(self.compute_api, context, server_id)

        try:
            port_info = self.network_api.show_port(context, port_id)
        except exception.NotFound as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.Forbidden as e:
            raise exc.HTTPForbidden(explanation=e.format_message())

        if port_info['port']['device_id'] != server_id:
            msg = _("Instance %(instance)s does not have a port with id "
                    "%(port)s") % {'instance': server_id, 'port': port_id}
            raise exc.HTTPNotFound(explanation=msg)

        return {'interfaceAttachment': _translate_interface_attachment_view(
                port_info['port'])}
Ejemplo n.º 2
0
    def show(self, req, server_id, id):
        """Return the migration of an instance in progress by id."""
        context = req.environ['compute.context']
        authorize(context, action="show")

        # NOTE(Shaohe Feng) just check the instance is available. To keep
        # consistency with other API, check it before get migrations.
        common.get_instance(self.compute_api, context, server_id)

        try:
            migration = self.compute_api.get_migration_by_id_and_instance(
                    context, id, server_id)
        except exception.MigrationNotFoundForInstance:
            msg = _("In-progress live migration %(id)s is not found for"
                    " server %(uuid)s.") % {"id": id, "uuid": server_id}
            raise exc.HTTPNotFound(explanation=msg)

        if migration.get("migration_type") != "live-migration":
            msg = _("Migration %(id)s for server %(uuid)s is not"
                    " live-migration.") % {"id": id, "uuid": server_id}
            raise exc.HTTPNotFound(explanation=msg)

        # TODO(Shaohe Feng) we should share the in-progress list.
        in_progress = ['queued', 'preparing', 'running', 'post-migrating']
        if migration.get("status") not in in_progress:
            msg = _("Live migration %(id)s for server %(uuid)s is not in"
                    " progress.") % {"id": id, "uuid": server_id}
            raise exc.HTTPNotFound(explanation=msg)

        return {'migration': output(migration)}
Ejemplo n.º 3
0
    def index(self, req, server_id):
        """Return all migrations of an instance in progress."""
        context = req.environ['compute.context']
        authorize(context, action="index")

        # NOTE(Shaohe Feng) just check the instance is available. To keep
        # consistency with other API, check it before get migrations.
        common.get_instance(self.compute_api, context, server_id)

        migrations = self.compute_api.get_migrations_in_progress_by_instance(
                context, server_id, 'live-migration')

        return {'migrations': [output(migration) for migration in migrations]}
Ejemplo n.º 4
0
    def index(self, req, server_id):
        """Return all migrations of an instance in progress."""
        context = req.environ['compute.context']
        authorize(context, action="index")

        # NOTE(Shaohe Feng) just check the instance is available. To keep
        # consistency with other API, check it before get migrations.
        common.get_instance(self.compute_api, context, server_id)

        migrations = self.compute_api.get_migrations_in_progress_by_instance(
            context, server_id, 'live-migration')

        return {'migrations': [output(migration) for migration in migrations]}
Ejemplo n.º 5
0
    def _reset_state(self, req, id, body):
        """Permit admins to reset the state of a server."""
        context = req.environ["compute.context"]
        authorize(context, 'resetState')

        # Identify the desired state from the body
        try:
            state = state_map[body["os-resetState"]["state"]]
        except (TypeError, KeyError):
            msg = _("Desired state must be specified.  Valid states "
                    "are: %s") % ', '.join(sorted(state_map.keys()))
            raise exc.HTTPBadRequest(explanation=msg)

        instance = common.get_instance(self.compute_api, context, id)
        try:
            instance.vm_state = state
            instance.task_state = None
            instance.save(admin_state_reset=True)
        except exception.InstanceNotFound:
            msg = _("Server not found")
            raise exc.HTTPNotFound(explanation=msg)
        except Exception:
            readable = traceback.format_exc()
            LOG.exception(_LE("Compute.api::resetState %s"), readable)
            raise exc.HTTPUnprocessableEntity()
        return webob.Response(status_int=202)
Ejemplo n.º 6
0
    def _update_instance_metadata(self, context, server_id, metadata,
                                  delete=False):
        try:
            server = common.get_instance(self.compute_api, context, server_id)
            return self.compute_api.update_instance_metadata(context,
                                                             server,
                                                             metadata,
                                                             delete)

        except exception.InstanceNotFound:
            msg = _('Server does not exist')
            raise exc.HTTPNotFound(explanation=msg)

        except (ValueError, AttributeError):
            msg = _("Malformed request body")
            raise exc.HTTPBadRequest(explanation=msg)

        except exception.InvalidMetadata as error:
            raise exc.HTTPBadRequest(explanation=error.format_message())

        except exception.InvalidMetadataSize as error:
            raise exc.HTTPRequestEntityTooLarge(
                explanation=error.format_message())

        except exception.QuotaError as error:
            raise exc.HTTPForbidden(explanation=error.format_message())

        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())

        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                    'update metadata', server_id)
Ejemplo n.º 7
0
    def get_spice_console(self, req, id, body):
        """Get spice connection information to access a server."""
        context = req.environ['compute.context']
        authorize(context)

        # If type is not supplied or unknown, get_spice_console below will cope
        console_type = body['os-getSPICEConsole'].get('type')
        instance = common.get_instance(self.compute_api, context, id)

        try:
            output = self.compute_api.get_spice_console(
                context, instance, console_type)
        except (exception.ConsoleTypeUnavailable,
                exception.ConsoleTypeInvalid) as e:
            raise webob.exc.HTTPBadRequest(explanation=e.format_message())
        except exception.InstanceNotFound as e:
            raise webob.exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceNotReady as e:
            raise webob.exc.HTTPConflict(explanation=e.format_message())
        except NotImplementedError:
            msg = _("Unable to get spice console, "
                    "functionality not implemented")
            raise webob.exc.HTTPNotImplemented(explanation=msg)

        return {'console': {'type': console_type, 'url': output['url']}}
Ejemplo n.º 8
0
    def get_serial_console(self, req, id, body):
        """Get connection to a serial console."""
        context = req.environ['compute.context']
        authorize(context)

        # If type is not supplied or unknown get_serial_console below will cope
        console_type = body['os-getSerialConsole'].get('type')
        instance = common.get_instance(self.compute_api, context, id)
        try:
            output = self.compute_api.get_serial_console(
                context, instance, console_type)
        except exception.InstanceNotFound as e:
            raise webob.exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceNotReady as e:
            raise webob.exc.HTTPConflict(explanation=e.format_message())
        except (exception.ConsoleTypeUnavailable, exception.ConsoleTypeInvalid,
                exception.ImageSerialPortNumberInvalid,
                exception.ImageSerialPortNumberExceedFlavorValue,
                exception.SocketPortRangeExhaustedException) as e:
            raise webob.exc.HTTPBadRequest(explanation=e.format_message())
        except NotImplementedError:
            msg = _("Unable to get serial console, "
                    "functionality not implemented")
            raise webob.exc.HTTPNotImplemented(explanation=msg)

        return {'console': {'type': console_type, 'url': output['url']}}
Ejemplo n.º 9
0
    def get_console_output(self, req, id, body):
        """Get text console output."""
        context = req.environ['compute.context']
        authorize(context)

        instance = common.get_instance(self.compute_api, context, id)
        length = body['os-getConsoleOutput'].get('length')
        # TODO(cyeoh): In a future API update accept a length of -1
        # as meaning unlimited length (convert to None)

        try:
            output = self.compute_api.get_console_output(context,
                                                         instance,
                                                         length)
        # NOTE(cyeoh): This covers race conditions where the instance is
        # deleted between common.get_instance and get_console_output
        # being called
        except (exception.InstanceNotFound,
                exception.ConsoleNotAvailable) as e:
            raise webob.exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceNotReady as e:
            raise webob.exc.HTTPConflict(explanation=e.format_message())
        except NotImplementedError:
            common.raise_feature_not_supported()

        # XML output is not correctly escaped, so remove invalid characters
        # NOTE(cyeoh): We don't support XML output with V2.1, but for
        # backwards compatibility reasons we continue to filter the output
        # We should remove this in the future
        remove_re = re.compile('[\x00-\x08\x0B-\x1F]')
        output = remove_re.sub('', output)

        return {'output': output}
Ejemplo n.º 10
0
    def show(self, req, server_id, id):
        """Return data about the given volume attachment."""
        context = req.environ['compute.context']
        authorize(context)
        authorize_attach(context, action='show')

        volume_id = id
        instance = common.get_instance(self.compute_api, context, server_id)
        bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
                context, instance.uuid)

        if not bdms:
            msg = _("Instance %s is not attached.") % server_id
            raise exc.HTTPNotFound(explanation=msg)

        assigned_mountpoint = None

        for bdm in bdms:
            if bdm.volume_id == volume_id:
                assigned_mountpoint = bdm.device_name
                break

        if assigned_mountpoint is None:
            msg = _("volume_id not found: %s") % volume_id
            raise exc.HTTPNotFound(explanation=msg)

        return {'volumeAttachment': _translate_attachment_detail_view(
            volume_id,
            instance.uuid,
            assigned_mountpoint)}
Ejemplo n.º 11
0
    def index(self, req, server_id):
        context = req.environ['compute.context']
        authorize(context)
        instance = common.get_instance(self.compute_api, context, server_id)

        passw = password.extract_password(instance)
        return {'password': passw or ''}
Ejemplo n.º 12
0
    def index(self, req, server_id):
        context = req.environ['compute.context']
        authorize(context)
        instance = common.get_instance(self.compute_api, context, server_id)

        passw = password.extract_password(instance)
        return {'password': passw or ''}
Ejemplo n.º 13
0
    def _reset_state(self, req, id, body):
        """Permit admins to reset the state of a server."""
        context = req.environ["compute.context"]
        authorize(context, 'resetState')

        # Identify the desired state from the body
        try:
            state = state_map[body["os-resetState"]["state"]]
        except (TypeError, KeyError):
            msg = _("Desired state must be specified.  Valid states "
                    "are: %s") % ', '.join(sorted(state_map.keys()))
            raise exc.HTTPBadRequest(explanation=msg)

        instance = common.get_instance(self.compute_api, context, id)
        try:
            instance.vm_state = state
            instance.task_state = None
            instance.save(admin_state_reset=True)
        except exception.InstanceNotFound:
            msg = _("Server not found")
            raise exc.HTTPNotFound(explanation=msg)
        except Exception:
            readable = traceback.format_exc()
            LOG.exception(_LE("Compute.api::resetState %s"), readable)
            raise exc.HTTPUnprocessableEntity()
        return webob.Response(status_int=202)
Ejemplo n.º 14
0
    def create(self, req, server_id, body):
        context = req.environ['compute.context']
        authorize(context)
        instance = common.get_instance(self.compute_api, context, server_id)
        protocol = body['remote_console']['protocol']
        console_type = body['remote_console']['type']
        try:
            handler = self.handlers.get(protocol)
            output = handler(context, instance, console_type)
            return {'remote_console': {'protocol': protocol,
                                       'type': console_type,
                                       'url': output['url']}}

        except exception.InstanceNotFound as e:
            raise webob.exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceNotReady as e:
            raise webob.exc.HTTPConflict(explanation=e.format_message())
        except (exception.ConsoleTypeInvalid,
                exception.ConsoleTypeUnavailable,
                exception.ImageSerialPortNumberInvalid,
                exception.ImageSerialPortNumberExceedFlavorValue,
                exception.SocketPortRangeExhaustedException) as e:
            raise webob.exc.HTTPBadRequest(explanation=e.format_message())
        except NotImplementedError:
            common.raise_feature_not_supported()
Ejemplo n.º 15
0
    def get_rdp_console(self, req, id, body):
        """Get text console output."""
        context = req.environ['compute.context']
        authorize(context)

        # If type is not supplied or unknown, get_rdp_console below will cope
        console_type = body['os-getRDPConsole'].get('type')

        instance = common.get_instance(self.compute_api, context, id)
        try:
            # NOTE(mikal): get_rdp_console() can raise InstanceNotFound, so
            # we still need to catch it here.
            output = self.compute_api.get_rdp_console(context, instance,
                                                      console_type)
        except exception.ConsoleTypeUnavailable as e:
            raise webob.exc.HTTPBadRequest(explanation=e.format_message())
        except (exception.InstanceUnknownCell,
                exception.InstanceNotFound) as e:
            raise webob.exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceNotReady as e:
            raise webob.exc.HTTPConflict(explanation=e.format_message())
        except NotImplementedError:
            common.raise_feature_not_supported()

        return {'console': {'type': console_type, 'url': output['url']}}
Ejemplo n.º 16
0
    def get_rdp_console(self, req, id, body):
        """Get text console output."""
        context = req.environ['compute.context']
        authorize(context)

        # If type is not supplied or unknown, get_rdp_console below will cope
        console_type = body['os-getRDPConsole'].get('type')

        instance = common.get_instance(self.compute_api, context, id)
        try:
            # NOTE(mikal): get_rdp_console() can raise InstanceNotFound, so
            # we still need to catch it here.
            output = self.compute_api.get_rdp_console(context,
                                                      instance,
                                                      console_type)
        except exception.ConsoleTypeUnavailable as e:
            raise webob.exc.HTTPBadRequest(explanation=e.format_message())
        except (exception.InstanceUnknownCell,
                     exception.InstanceNotFound) as e:
            raise webob.exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceNotReady as e:
            raise webob.exc.HTTPConflict(explanation=e.format_message())
        except NotImplementedError:
            common.raise_feature_not_supported()

        return {'console': {'type': console_type, 'url': output['url']}}
Ejemplo n.º 17
0
 def delete(self, req, server_id):
     context = req.environ['compute.context']
     authorize(context)
     instance = common.get_instance(self.compute_api, context, server_id)
     meta = password.convert_password(context, None)
     instance.system_metadata.update(meta)
     instance.save()
Ejemplo n.º 18
0
    def create(self, req, server_id, body):
        context = req.environ['compute.context']
        authorize(context)
        instance = common.get_instance(self.compute_api, context, server_id)
        protocol = body['remote_console']['protocol']
        console_type = body['remote_console']['type']
        try:
            handler = self.handlers.get(protocol)
            output = handler(context, instance, console_type)
            return {
                'remote_console': {
                    'protocol': protocol,
                    'type': console_type,
                    'url': output['url']
                }
            }

        except exception.InstanceNotFound as e:
            raise webob.exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceNotReady as e:
            raise webob.exc.HTTPConflict(explanation=e.format_message())
        except (exception.ConsoleTypeInvalid, exception.ConsoleTypeUnavailable,
                exception.ImageSerialPortNumberInvalid,
                exception.ImageSerialPortNumberExceedFlavorValue,
                exception.SocketPortRangeExhaustedException) as e:
            raise webob.exc.HTTPBadRequest(explanation=e.format_message())
        except NotImplementedError:
            common.raise_feature_not_supported()
Ejemplo n.º 19
0
    def _update_instance_metadata(self,
                                  context,
                                  server_id,
                                  metadata,
                                  delete=False):
        try:
            server = common.get_instance(self.compute_api, context, server_id)
            return self.compute_api.update_instance_metadata(
                context, server, metadata, delete)

        except exception.InstanceNotFound:
            msg = _('Server does not exist')
            raise exc.HTTPNotFound(explanation=msg)

        except (ValueError, AttributeError):
            msg = _("Malformed request body")
            raise exc.HTTPBadRequest(explanation=msg)

        except exception.InvalidMetadata as error:
            raise exc.HTTPBadRequest(explanation=error.format_message())

        except exception.InvalidMetadataSize as error:
            raise exc.HTTPRequestEntityTooLarge(
                explanation=error.format_message())

        except exception.QuotaError as error:
            raise exc.HTTPForbidden(explanation=error.format_message())

        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())

        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(
                state_error, 'update metadata', server_id)
Ejemplo n.º 20
0
    def _rescue(self, req, id, body):
        """Rescue an instance."""
        context = req.environ["compute.context"]
        authorize(context)

        if body['rescue'] and 'adminPass' in body['rescue']:
            password = body['rescue']['adminPass']
        else:
            password = utils.generate_password()

        instance = common.get_instance(self.compute_api, context, id)
        try:
            rescue_image_ref = None
            if self.ext_mgr.is_loaded("os-extended-rescue-with-image"):
                if body['rescue'] and 'rescue_image_ref' in body['rescue']:
                    rescue_image_ref = self._rescue_image_validation(
                        body['rescue']['rescue_image_ref'])
            self.compute_api.rescue(context,
                                    instance,
                                    rescue_password=password,
                                    rescue_image_ref=rescue_image_ref)
        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(
                state_error, 'rescue', id)
        except exception.InvalidVolume as volume_error:
            raise exc.HTTPConflict(explanation=volume_error.format_message())
        except exception.InstanceNotRescuable as non_rescuable:
            raise exc.HTTPBadRequest(
                explanation=non_rescuable.format_message())

        return {'adminPass': password}
Ejemplo n.º 21
0
    def get_serial_console(self, req, id, body):
        """Get connection to a serial console."""
        context = req.environ['compute.context']
        authorize(context)

        # If type is not supplied or unknown get_serial_console below will cope
        console_type = body['os-getSerialConsole'].get('type')
        try:
            instance = common.get_instance(self.compute_api, context, id)
            output = self.compute_api.get_serial_console(context,
                                                         instance,
                                                         console_type)
        except (exception.InstanceUnknownCell,
                     exception.InstanceNotFound) as e:
            raise webob.exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceNotReady as e:
            raise webob.exc.HTTPConflict(explanation=e.format_message())
        except (exception.ConsoleTypeUnavailable,
                exception.ImageSerialPortNumberInvalid,
                exception.ImageSerialPortNumberExceedFlavorValue,
                exception.SocketPortRangeExhaustedException) as e:
            raise webob.exc.HTTPBadRequest(explanation=e.format_message())
        except NotImplementedError:
            common.raise_feature_not_supported()

        return {'console': {'type': console_type, 'url': output['url']}}
Ejemplo n.º 22
0
    def _rescue(self, req, id, body):
        """Rescue an instance."""
        context = req.environ["compute.context"]
        authorize(context)

        if body['rescue'] and 'adminPass' in body['rescue']:
            password = body['rescue']['adminPass']
        else:
            password = utils.generate_password()

        instance = common.get_instance(self.compute_api, context, id)
        try:
            rescue_image_ref = None
            if self.ext_mgr.is_loaded("os-extended-rescue-with-image"):
                if body['rescue'] and 'rescue_image_ref' in body['rescue']:
                    rescue_image_ref = self._rescue_image_validation(
                       body['rescue']['rescue_image_ref'])
            self.compute_api.rescue(context, instance,
                rescue_password=password, rescue_image_ref=rescue_image_ref)
        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                                                                  'rescue', id)
        except exception.InvalidVolume as volume_error:
            raise exc.HTTPConflict(explanation=volume_error.format_message())
        except exception.InstanceNotRescuable as non_rescuable:
            raise exc.HTTPBadRequest(
                explanation=non_rescuable.format_message())

        return {'adminPass': password}
Ejemplo n.º 23
0
    def get_rdp_console(self, req, id, body):
        """Get text console output."""
        context = req.environ['compute.context']
        authorize(context)

        # If type is not supplied or unknown, get_rdp_console below will cope
        console_type = body['os-getRDPConsole'].get('type')
        instance = common.get_instance(self.compute_api, context, id)

        try:
            output = self.compute_api.get_rdp_console(context,
                                                      instance,
                                                      console_type)
        except (exception.ConsoleTypeUnavailable,
                exception.ConsoleTypeInvalid) as e:
            raise webob.exc.HTTPBadRequest(explanation=e.format_message())
        except exception.InstanceNotFound as e:
            raise webob.exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceNotReady as e:
            raise webob.exc.HTTPConflict(explanation=e.format_message())
        except NotImplementedError:
            msg = _("Unable to get rdp console, functionality not implemented")
            raise webob.exc.HTTPNotImplemented(explanation=msg)

        return {'console': {'type': console_type, 'url': output['url']}}
Ejemplo n.º 24
0
 def delete(self, req, server_id):
     context = req.environ['compute.context']
     authorize(context)
     instance = common.get_instance(self.compute_api, context, server_id)
     meta = password.convert_password(context, None)
     instance.system_metadata.update(meta)
     instance.save()
Ejemplo n.º 25
0
    def create(self, req, server_id, body):
        """Attach an interface to an instance."""
        context = req.environ['compute.context']
        authorize(context)

        network_id = None
        port_id = None
        req_ip = None
        if body:
            attachment = body['interfaceAttachment']
            network_id = attachment.get('net_id', None)
            port_id = attachment.get('port_id', None)
            try:
                req_ip = attachment['fixed_ips'][0]['ip_address']
            except Exception:
                pass

        if network_id and port_id:
            msg = _("Must not input both network_id and port_id")
            raise exc.HTTPBadRequest(explanation=msg)
        if req_ip and not network_id:
            msg = _("Must input network_id when request IP address")
            raise exc.HTTPBadRequest(explanation=msg)

        if req_ip:
            try:
                netaddr.IPAddress(req_ip)
            except netaddr.AddrFormatError as e:
                raise exc.HTTPBadRequest(explanation=six.text_type(e))

        try:
            instance = common.get_instance(self.compute_api,
                                           context, server_id)
            LOG.info(_LI("Attach interface"), instance=instance)
            vif = self.compute_api.attach_interface(context,
                instance, network_id, port_id, req_ip)
        except (exception.PortNotFound,
                exception.NetworkNotFound) as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except (exception.FixedIpAlreadyInUse,
                exception.InterfaceAttachFailedNoNetwork,
                exception.NoMoreFixedIps,
                exception.PortInUse,
                exception.NetworkDuplicated,
                exception.NetworkAmbiguous,
                exception.PortNotUsable) as e:
            raise exc.HTTPBadRequest(explanation=e.format_message())
        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except NotImplementedError:
            msg = _("Network driver does not support this function.")
            raise webob.exc.HTTPNotImplemented(explanation=msg)
        except exception.InterfaceAttachFailed:
            msg = _("Failed to attach interface")
            raise webob.exc.HTTPInternalServerError(explanation=msg)
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                    'attach_interface', server_id)

        return self.show(req, server_id, vif['id'])
Ejemplo n.º 26
0
 def index(self, req, server_id):
     """Returns the list of actions recorded for a given instance."""
     context = req.environ["compute.context"]
     instance = common.get_instance(self.compute_api, context, server_id)
     authorize_actions(context, target=instance)
     actions_raw = self.action_api.actions_get(context, instance)
     actions = [self._format_action(action) for action in actions_raw]
     return {'instanceActions': actions}
Ejemplo n.º 27
0
    def _migrate_live(self, req, id, body):
        """Permit admins to (live) migrate a server to a new host."""
        context = req.environ["compute.context"]
        authorize(context, 'migrateLive')

        try:
            block_migration = body["os-migrateLive"]["block_migration"]
            disk_over_commit = body["os-migrateLive"]["disk_over_commit"]
            host = body["os-migrateLive"]["host"]
        except (TypeError, KeyError):
            msg = _("host, block_migration and disk_over_commit must "
                    "be specified for live migration.")
            raise exc.HTTPBadRequest(explanation=msg)

        try:
            block_migration = strutils.bool_from_string(block_migration,
                                                        strict=True)
            disk_over_commit = strutils.bool_from_string(disk_over_commit,
                                                         strict=True)
        except ValueError as err:
            raise exc.HTTPBadRequest(explanation=six.text_type(err))

        instance = common.get_instance(self.compute_api, context, id)
        try:
            self.compute_api.live_migrate(context, instance, block_migration,
                                          disk_over_commit, host)
        except (exception.NoValidHost, exception.ComputeServiceUnavailable,
                exception.InvalidHypervisorType, exception.InvalidCPUInfo,
                exception.UnableToMigrateToSelf,
                exception.DestinationHypervisorTooOld,
                exception.InvalidLocalStorage, exception.InvalidSharedStorage,
                exception.HypervisorUnavailable,
                exception.MigrationPreCheckError,
                exception.LiveMigrationWithOldNovaNotSafe) as ex:
            raise exc.HTTPBadRequest(explanation=ex.format_message())
        except exception.InstanceNotFound as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(
                state_error, 'os-migrateLive', id)
        except Exception:
            if host is None:
                msg = _("Live migration of instance %s to another host "
                        "failed") % id
            else:
                msg = _("Live migration of instance %(id)s to host %(host)s "
                        "failed") % {
                            'id': id,
                            'host': host
                        }
            LOG.exception(msg)
            # Return messages from scheduler
            raise exc.HTTPInternalServerError(explanation=msg)

        return webob.Response(status_int=202)
Ejemplo n.º 28
0
 def _force_delete(self, req, id, body):
     """Force delete of instance before deferred cleanup."""
     context = req.environ["compute.context"]
     authorize(context)
     instance = common.get_instance(self.compute_api, context, id)
     try:
         self.compute_api.force_delete(context, instance)
     except exception.InstanceIsLocked as e:
         raise webob.exc.HTTPConflict(explanation=e.format_message())
Ejemplo n.º 29
0
    def _migrate_live(self, req, id, body):
        """Permit admins to (live) migrate a server to a new host."""
        context = req.environ["compute.context"]
        authorize(context, 'migrateLive')

        try:
            block_migration = body["os-migrateLive"]["block_migration"]
            disk_over_commit = body["os-migrateLive"]["disk_over_commit"]
            host = body["os-migrateLive"]["host"]
        except (TypeError, KeyError):
            msg = _("host, block_migration and disk_over_commit must "
                    "be specified for live migration.")
            raise exc.HTTPBadRequest(explanation=msg)

        try:
            block_migration = strutils.bool_from_string(block_migration,
                                                        strict=True)
            disk_over_commit = strutils.bool_from_string(disk_over_commit,
                                                         strict=True)
        except ValueError as err:
            raise exc.HTTPBadRequest(explanation=six.text_type(err))

        instance = common.get_instance(self.compute_api, context, id)
        try:
            self.compute_api.live_migrate(context, instance, block_migration,
                                          disk_over_commit, host)
        except (exception.NoValidHost,
                exception.ComputeServiceUnavailable,
                exception.InvalidHypervisorType,
                exception.InvalidCPUInfo,
                exception.UnableToMigrateToSelf,
                exception.DestinationHypervisorTooOld,
                exception.InvalidLocalStorage,
                exception.InvalidSharedStorage,
                exception.HypervisorUnavailable,
                exception.MigrationPreCheckError,
                exception.LiveMigrationWithOldNovaNotSafe) as ex:
            raise exc.HTTPBadRequest(explanation=ex.format_message())
        except exception.InstanceNotFound as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                    'os-migrateLive', id)
        except Exception:
            if host is None:
                msg = _("Live migration of instance %s to another host "
                        "failed") % id
            else:
                msg = _("Live migration of instance %(id)s to host %(host)s "
                        "failed") % {'id': id, 'host': host}
            LOG.exception(msg)
            # Return messages from scheduler
            raise exc.HTTPInternalServerError(explanation=msg)

        return webob.Response(status_int=202)
Ejemplo n.º 30
0
    def delete(self, req, server_id, id):
        """Detach a volume from an instance."""
        context = req.environ['compute.context']
        authorize(context)
        authorize_attach(context, action='delete')

        volume_id = id

        instance = common.get_instance(self.compute_api, context, server_id)
        if instance.vm_state in (vm_states.SHELVED,
                                 vm_states.SHELVED_OFFLOADED):
            _check_request_version(req, '2.20', 'detach_volume',
                                   server_id, instance.vm_state)
        try:
            volume = self.volume_api.get(context, volume_id)
        except exception.VolumeNotFound as e:
            raise exc.HTTPNotFound(explanation=e.format_message())

        bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
                context, instance.uuid)
        if not bdms:
            msg = _("Instance %s is not attached.") % server_id
            raise exc.HTTPNotFound(explanation=msg)

        found = False
        try:
            for bdm in bdms:
                if bdm.volume_id != volume_id:
                    continue
                if bdm.is_root:
                    msg = _("Can't detach root device volume")
                    raise exc.HTTPForbidden(explanation=msg)
                try:
                    self.compute_api.detach_volume(context, instance, volume)
                    found = True
                    break
                except exception.VolumeUnattached:
                    # The volume is not attached.  Treat it as NotFound
                    # by falling through.
                    pass
                except exception.InvalidVolume as e:
                    raise exc.HTTPBadRequest(explanation=e.format_message())
                except exception.InstanceUnknownCell as e:
                    raise exc.HTTPNotFound(explanation=e.format_message())
                except exception.InvalidInput as e:
                    raise exc.HTTPBadRequest(explanation=e.format_message())

        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                    'detach_volume', server_id)

        if not found:
            msg = _("volume_id not found: %s") % volume_id
            raise exc.HTTPNotFound(explanation=msg)
Ejemplo n.º 31
0
    def show(self, req, server_id, id):
        context = req.environ["compute.context"]
        authorize(context, action='show')
        instance = common.get_instance(self._compute_api, context, server_id)
        networks = common.get_networks_for_instance(context, instance)
        if id not in networks:
            msg = _("Instance is not a member of specified network")
            raise exc.HTTPNotFound(explanation=msg)

        return self._view_builder.show(networks[id], id)
Ejemplo n.º 32
0
    def show(self, req, server_id, id):
        context = req.environ["compute.context"]
        authorize(context, action='show')
        instance = common.get_instance(self._compute_api, context, server_id)
        networks = common.get_networks_for_instance(context, instance)
        if id not in networks:
            msg = _("Instance is not a member of specified network")
            raise exc.HTTPNotFound(explanation=msg)

        return self._view_builder.show(networks[id], id)
Ejemplo n.º 33
0
    def _unlock(self, req, id, body):
        """Unlock a server instance."""
        context = req.environ['compute.context']
        authorize(context, action='unlock')
        instance = common.get_instance(self.compute_api, context, id)
        if not self.compute_api.is_expected_locked_by(context, instance):
            authorize(context, target=instance,
                      action='unlock:unlock_override')

        self.compute_api.unlock(context, instance)
Ejemplo n.º 34
0
    def create(self, req, server_id, body):
        """Attach a volume to an instance."""
        context = req.environ['compute.context']
        authorize(context)
        authorize_attach(context, action='create')

        if not self.is_valid_body(body, 'volumeAttachment'):
            msg = _("volumeAttachment not specified")
            raise exc.HTTPBadRequest(explanation=msg)
        try:
            volume_id = body['volumeAttachment']['volumeId']
        except KeyError:
            msg = _("volumeId must be specified.")
            raise exc.HTTPBadRequest(explanation=msg)
        device = body['volumeAttachment'].get('device')

        self._validate_volume_id(volume_id)

        LOG.info(_LI("Attach volume %(volume_id)s to instance %(server_id)s "
                    "at %(device)s"),
                  {'volume_id': volume_id,
                   'device': device,
                   'server_id': server_id},
                  context=context)

        instance = common.get_instance(self.compute_api, context, server_id)
        try:
            device = self.compute_api.attach_volume(context, instance,
                                                    volume_id, device)
        except exception.NotFound as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                    'attach_volume', server_id)

        # The attach is async
        attachment = {}
        attachment['id'] = volume_id
        attachment['serverId'] = server_id
        attachment['volumeId'] = volume_id
        attachment['device'] = device

        # NOTE(justinsb): And now, we have a problem...
        # The attach is async, so there's a window in which we don't see
        # the attachment (until the attachment completes).  We could also
        # get problems with concurrent requests.  I think we need an
        # attachment state, and to write to the DB here, but that's a bigger
        # change.
        # For now, we'll probably have to rely on libraries being smart

        # TODO(justinsb): How do I return "accepted" here?
        return {'volumeAttachment': attachment}
Ejemplo n.º 35
0
    def _unlock(self, req, id, body):
        """Unlock a server instance."""
        context = req.environ['compute.context']
        authorize(context, action='unlock')
        instance = common.get_instance(self.compute_api, context, id)
        if not self.compute_api.is_expected_locked_by(context, instance):
            authorize(context,
                      target=instance,
                      action='unlock:unlock_override')

        self.compute_api.unlock(context, instance)
Ejemplo n.º 36
0
 def _inject_network_info(self, req, id, body):
     """Permit admins to inject network info into a server."""
     context = req.environ['compute.context']
     authorize(context, action='inject_network_info')
     try:
         instance = common.get_instance(self.compute_api, context, id)
         self.compute_api.inject_network_info(context, instance)
     except exception.InstanceUnknownCell as e:
         raise exc.HTTPNotFound(explanation=e.format_message())
     except exception.InstanceIsLocked as e:
         raise exc.HTTPConflict(explanation=e.format_message())
Ejemplo n.º 37
0
    def _get_metadata(self, context, server_id):
        try:
            server = common.get_instance(self.compute_api, context, server_id)
            meta = self.compute_api.get_instance_metadata(context, server)
        except exception.InstanceNotFound:
            msg = _('Server does not exist')
            raise exc.HTTPNotFound(explanation=msg)

        meta_dict = {}
        for key, value in six.iteritems(meta):
            meta_dict[key] = value
        return meta_dict
Ejemplo n.º 38
0
    def _get_metadata(self, context, server_id):
        try:
            server = common.get_instance(self.compute_api, context, server_id)
            meta = self.compute_api.get_instance_metadata(context, server)
        except exception.InstanceNotFound:
            msg = _('Server does not exist')
            raise exc.HTTPNotFound(explanation=msg)

        meta_dict = {}
        for key, value in six.iteritems(meta):
            meta_dict[key] = value
        return meta_dict
Ejemplo n.º 39
0
    def _reset_state(self, req, id, body):
        """Permit admins to reset the state of a server."""
        context = req.environ["compute.context"]
        authorize(context, action='reset_state')

        # Identify the desired state from the body
        state = state_map[body["os-resetState"]["state"]]

        instance = common.get_instance(self.compute_api, context, id)
        instance.vm_state = state
        instance.task_state = None
        instance.save(admin_state_reset=True)
Ejemplo n.º 40
0
    def update(self, req, server_id, id, body):
        if (not self.ext_mgr or
                not self.ext_mgr.is_loaded('os-volume-attachment-update')):
            raise exc.HTTPBadRequest()
        context = req.environ['compute.context']
        authorize(context)
        authorize_attach(context, action='update')

        if not self.is_valid_body(body, 'volumeAttachment'):
            msg = _("volumeAttachment not specified")
            raise exc.HTTPBadRequest(explanation=msg)

        old_volume_id = id
        old_volume = self.volume_api.get(context, old_volume_id)

        try:
            new_volume_id = body['volumeAttachment']['volumeId']
        except KeyError:
            msg = _("volumeId must be specified.")
            raise exc.HTTPBadRequest(explanation=msg)
        self._validate_volume_id(new_volume_id)
        new_volume = self.volume_api.get(context, new_volume_id)

        instance = common.get_instance(self.compute_api, context, server_id)

        bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
                context, instance.uuid)
        found = False
        try:
            for bdm in bdms:
                if bdm.volume_id != old_volume_id:
                    continue
                try:
                    self.compute_api.swap_volume(context, instance, old_volume,
                                                 new_volume)
                    found = True
                    break
                except exception.VolumeUnattached:
                    # The volume is not attached.  Treat it as NotFound
                    # by falling through.
                    pass
        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                    'swap_volume', server_id)

        if not found:
            msg = _("volume_id not found: %s") % old_volume_id
            raise exc.HTTPNotFound(explanation=msg)
        else:
            return webob.Response(status_int=202)
Ejemplo n.º 41
0
    def show(self, req, server_id, id):
        """Return the migration of an instance in progress by id."""
        context = req.environ['compute.context']
        authorize(context, action="show")

        # NOTE(Shaohe Feng) just check the instance is available. To keep
        # consistency with other API, check it before get migrations.
        common.get_instance(self.compute_api, context, server_id)

        try:
            migration = self.compute_api.get_migration_by_id_and_instance(
                context, id, server_id)
        except exception.MigrationNotFoundForInstance:
            msg = _("In-progress live migration %(id)s is not found for"
                    " server %(uuid)s.") % {
                        "id": id,
                        "uuid": server_id
                    }
            raise exc.HTTPNotFound(explanation=msg)

        if migration.get("migration_type") != "live-migration":
            msg = _("Migration %(id)s for server %(uuid)s is not"
                    " live-migration.") % {
                        "id": id,
                        "uuid": server_id
                    }
            raise exc.HTTPNotFound(explanation=msg)

        # TODO(Shaohe Feng) we should share the in-progress list.
        in_progress = ['queued', 'preparing', 'running', 'post-migrating']
        if migration.get("status") not in in_progress:
            msg = _("Live migration %(id)s for server %(uuid)s is not in"
                    " progress.") % {
                        "id": id,
                        "uuid": server_id
                    }
            raise exc.HTTPNotFound(explanation=msg)

        return {'migration': output(migration)}
Ejemplo n.º 42
0
def get_instance_by_floating_ip_addr(self, context, address):
    try:
        instance_id =\
            self.network_api.get_instance_id_by_floating_address(
                context, address)
    except exception.FloatingIpNotFoundForAddress as ex:
        raise webob.exc.HTTPNotFound(explanation=ex.format_message())
    except exception.FloatingIpMultipleFoundForAddress as ex:
        raise webob.exc.HTTPConflict(explanation=ex.format_message())

    if instance_id:
        return common.get_instance(self.compute_api, context, instance_id,
                                   expected_attrs=['flavor'])
Ejemplo n.º 43
0
    def clear(self, req, server_id):
        """Removes the encrypted server password from the metadata server

        Note that this does not actually change the instance server
        password.
        """

        context = req.environ['compute.context']
        authorize(context)
        instance = common.get_instance(self.compute_api, context, server_id)
        meta = password.convert_password(context, None)
        instance.system_metadata.update(meta)
        instance.save()
Ejemplo n.º 44
0
    def clear(self, req, server_id):
        """Removes the encrypted server password from the metadata server

        Note that this does not actually change the instance server
        password.
        """

        context = req.environ['compute.context']
        authorize(context)
        instance = common.get_instance(self.compute_api, context, server_id)
        meta = password.convert_password(context, None)
        instance.system_metadata.update(meta)
        instance.save()
Ejemplo n.º 45
0
    def _add_fixed_ip(self, req, id, body):
        """Adds an IP on a given network to an instance."""
        context = req.environ['compute.context']
        authorize(context)

        instance = common.get_instance(self.compute_api, context, id)
        network_id = body['addFixedIp']['networkId']
        try:
            self.compute_api.add_fixed_ip(context, instance, network_id)
        except exception.InstanceUnknownCell as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.NoMoreFixedIps as e:
            raise exc.HTTPBadRequest(explanation=e.format_message())
Ejemplo n.º 46
0
 def _unshelve(self, req, id, body):
     """Restore an instance from shelved mode."""
     context = req.environ["compute.context"]
     auth_unshelve(context)
     instance = common.get_instance(self.compute_api, context, id)
     try:
         self.compute_api.unshelve(context, instance)
     except exception.InstanceIsLocked as e:
         raise exc.HTTPConflict(explanation=e.format_message())
     except exception.InstanceInvalidState as state_error:
         common.raise_http_conflict_for_instance_invalid_state(
             state_error, 'unshelve', id)
     return webob.Response(status_int=202)
Ejemplo n.º 47
0
 def _resume(self, req, id, body):
     """Permit admins to resume the server from suspend."""
     context = req.environ['compute.context']
     authorize(context, action='resume')
     try:
         server = common.get_instance(self.compute_api, context, id)
         self.compute_api.resume(context, server)
     except exception.InstanceUnknownCell as e:
         raise exc.HTTPNotFound(explanation=e.format_message())
     except exception.InstanceIsLocked as e:
         raise exc.HTTPConflict(explanation=e.format_message())
     except exception.InstanceInvalidState as state_error:
         common.raise_http_conflict_for_instance_invalid_state(state_error,
                 'resume', id)
Ejemplo n.º 48
0
    def _items(self, req, server_id, entity_maker):
        """Returns a list of VIFs, transformed through entity_maker."""
        context = req.environ['compute.context']
        instance = common.get_instance(self.compute_api, context, server_id)

        try:
            vifs = self.network_api.get_vifs_by_instance(context, instance)
        except NotImplementedError:
            msg = _('Listing virtual interfaces is not supported by this '
                    'cloud.')
            raise webob.exc.HTTPBadRequest(explanation=msg)
        limited_list = common.limited(vifs, req)
        res = [entity_maker(vif) for vif in limited_list]
        return {'virtual_interfaces': res}
Ejemplo n.º 49
0
 def _unshelve(self, req, id, body):
     """Restore an instance from shelved mode."""
     context = req.environ["compute.context"]
     auth_unshelve(context)
     instance = common.get_instance(self.compute_api, context, id)
     try:
         self.compute_api.unshelve(context, instance)
     except exception.InstanceIsLocked as e:
         raise exc.HTTPConflict(explanation=e.format_message())
     except exception.InstanceInvalidState as state_error:
         common.raise_http_conflict_for_instance_invalid_state(state_error,
                                                               'unshelve',
                                                               id)
     return webob.Response(status_int=202)
Ejemplo n.º 50
0
 def show(self, req, id):
     context = req.environ["compute.context"]
     authorize(context)
     self.check_fping()
     instance = common.get_instance(self.compute_api, context, id)
     ips = [str(ip) for ip in self._get_instance_ips(context, instance)]
     alive_ips = self.fping(ips)
     return {
         "server": {
             "id": instance.uuid,
             "project_id": instance.project_id,
             "alive": bool(set(ips) & alive_ips),
         }
     }
Ejemplo n.º 51
0
 def _get_metadata(self, context, server_id):
     server = common.get_instance(self.compute_api, context, server_id)
     try:
         # NOTE(mikal): get_instanc_metadata sometimes returns
         # InstanceNotFound in unit tests, even though the instance is
         # fetched on the line above. I blame mocking.
         meta = self.compute_api.get_instance_metadata(context, server)
     except exception.InstanceNotFound:
         msg = _('Server does not exist')
         raise exc.HTTPNotFound(explanation=msg)
     meta_dict = {}
     for key, value in six.iteritems(meta):
         meta_dict[key] = value
     return meta_dict
Ejemplo n.º 52
0
 def _restore(self, req, id, body):
     """Restore a previously deleted instance."""
     context = req.environ["compute.context"]
     authorize(context)
     instance = common.get_instance(self.compute_api, context, id)
     try:
         self.compute_api.restore(context, instance)
     except exception.InstanceUnknownCell as error:
         raise webob.exc.HTTPNotFound(explanation=error.format_message())
     except exception.QuotaError as error:
         raise webob.exc.HTTPForbidden(explanation=error.format_message())
     except exception.InstanceInvalidState as state_error:
         common.raise_http_conflict_for_instance_invalid_state(state_error,
                 'restore', id)
Ejemplo n.º 53
0
    def create(self, req, server_id, body):
        """Attach a volume to an instance."""
        context = req.environ['compute.context']
        authorize(context)
        authorize_attach(context, action='create')

        volume_id = body['volumeAttachment']['volumeId']
        device = body['volumeAttachment'].get('device')

        instance = common.get_instance(self.compute_api, context, server_id)

        if instance.vm_state in (vm_states.SHELVED,
                                 vm_states.SHELVED_OFFLOADED):
            _check_request_version(req, '2.20', 'attach_volume',
                                   server_id, instance.vm_state)

        try:
            device = self.compute_api.attach_volume(context, instance,
                                                    volume_id, device)
        except exception.InstanceUnknownCell as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.VolumeNotFound as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                    'attach_volume', server_id)
        except (exception.InvalidVolume,
                exception.InvalidDevicePath) as e:
            raise exc.HTTPBadRequest(explanation=e.format_message())

        # The attach is async
        attachment = {}
        attachment['id'] = volume_id
        attachment['serverId'] = server_id
        attachment['volumeId'] = volume_id
        attachment['device'] = device

        # NOTE(justinsb): And now, we have a problem...
        # The attach is async, so there's a window in which we don't see
        # the attachment (until the attachment completes).  We could also
        # get problems with concurrent requests.  I think we need an
        # attachment state, and to write to the DB here, but that's a bigger
        # change.
        # For now, we'll probably have to rely on libraries being smart

        # TODO(justinsb): How do I return "accepted" here?
        return {'volumeAttachment': attachment}