diff --git a/nova/compute/power_state.py b/nova/compute/power_state.py index 523577c6bfc5..a22b6fabbeea 100644 --- a/nova/compute/power_state.py +++ b/nova/compute/power_state.py @@ -24,24 +24,23 @@ updated, and should also be updated at the end of a task if the task is supposed to affect power_state. """ +from nova.objects import fields + # NOTE(maoy): These are *not* virDomainState values from libvirt. # The hex value happens to match virDomainState for backward-compatibility # reasons. -NOSTATE = 0x00 -RUNNING = 0x01 -PAUSED = 0x03 -SHUTDOWN = 0x04 # the VM is powered off -CRASHED = 0x06 -SUSPENDED = 0x07 +NOSTATE = fields.InstancePowerState.index(fields.InstancePowerState.NOSTATE) +RUNNING = fields.InstancePowerState.index(fields.InstancePowerState.RUNNING) +PAUSED = fields.InstancePowerState.index(fields.InstancePowerState.PAUSED) +# the VM is powered off +SHUTDOWN = fields.InstancePowerState.index(fields.InstancePowerState.SHUTDOWN) +CRASHED = fields.InstancePowerState.index(fields.InstancePowerState.CRASHED) +SUSPENDED = fields.InstancePowerState.index( + fields.InstancePowerState.SUSPENDED) # TODO(justinsb): Power state really needs to be a proper class, # so that we're not locked into the libvirt status codes and can put mapping # logic here rather than spread throughout the code -STATE_MAP = { - NOSTATE: 'pending', - RUNNING: 'running', - PAUSED: 'paused', - SHUTDOWN: 'shutdown', - CRASHED: 'crashed', - SUSPENDED: 'suspended', -} +STATE_MAP = {fields.InstancePowerState.index(state): state + for state in fields.InstancePowerState.ALL + if state != fields.InstancePowerState._UNUSED} diff --git a/nova/compute/task_states.py b/nova/compute/task_states.py index 589cc73cfbd3..2b793aebb3bf 100644 --- a/nova/compute/task_states.py +++ b/nova/compute/task_states.py @@ -23,95 +23,99 @@ necessary. """ +from nova.objects import fields + # possible task states during create() -SCHEDULING = 'scheduling' -BLOCK_DEVICE_MAPPING = 'block_device_mapping' -NETWORKING = 'networking' -SPAWNING = 'spawning' +SCHEDULING = fields.InstanceTaskState.SCHEDULING +BLOCK_DEVICE_MAPPING = fields.InstanceTaskState.BLOCK_DEVICE_MAPPING +NETWORKING = fields.InstanceTaskState.NETWORKING +SPAWNING = fields.InstanceTaskState.SPAWNING # possible task states during snapshot() -IMAGE_SNAPSHOT = 'image_snapshot' -IMAGE_SNAPSHOT_PENDING = 'image_snapshot_pending' -IMAGE_PENDING_UPLOAD = 'image_pending_upload' -IMAGE_UPLOADING = 'image_uploading' +IMAGE_SNAPSHOT = fields.InstanceTaskState.IMAGE_SNAPSHOT +IMAGE_SNAPSHOT_PENDING = fields.InstanceTaskState.IMAGE_SNAPSHOT_PENDING +IMAGE_PENDING_UPLOAD = fields.InstanceTaskState.IMAGE_PENDING_UPLOAD +IMAGE_UPLOADING = fields.InstanceTaskState.IMAGE_UPLOADING # possible task states during backup() -IMAGE_BACKUP = 'image_backup' +IMAGE_BACKUP = fields.InstanceTaskState.IMAGE_BACKUP # possible task states during set_admin_password() -UPDATING_PASSWORD = 'updating_password' +UPDATING_PASSWORD = fields.InstanceTaskState.UPDATING_PASSWORD # possible task states during resize() -RESIZE_PREP = 'resize_prep' -RESIZE_MIGRATING = 'resize_migrating' -RESIZE_MIGRATED = 'resize_migrated' -RESIZE_FINISH = 'resize_finish' +RESIZE_PREP = fields.InstanceTaskState.RESIZE_PREP +RESIZE_MIGRATING = fields.InstanceTaskState.RESIZE_MIGRATING +RESIZE_MIGRATED = fields.InstanceTaskState.RESIZE_MIGRATED +RESIZE_FINISH = fields.InstanceTaskState.RESIZE_FINISH # possible task states during revert_resize() -RESIZE_REVERTING = 'resize_reverting' +RESIZE_REVERTING = fields.InstanceTaskState.RESIZE_REVERTING # possible task states during confirm_resize() -RESIZE_CONFIRMING = 'resize_confirming' +RESIZE_CONFIRMING = fields.InstanceTaskState.RESIZE_CONFIRMING # possible task states during reboot() -REBOOTING = 'rebooting' -REBOOT_PENDING = 'reboot_pending' -REBOOT_STARTED = 'reboot_started' -REBOOTING_HARD = 'rebooting_hard' -REBOOT_PENDING_HARD = 'reboot_pending_hard' -REBOOT_STARTED_HARD = 'reboot_started_hard' +REBOOTING = fields.InstanceTaskState.REBOOTING +REBOOT_PENDING = fields.InstanceTaskState.REBOOT_PENDING +REBOOT_STARTED = fields.InstanceTaskState.REBOOT_STARTED +REBOOTING_HARD = fields.InstanceTaskState.REBOOTING_HARD +REBOOT_PENDING_HARD = fields.InstanceTaskState.REBOOT_PENDING_HARD +REBOOT_STARTED_HARD = fields.InstanceTaskState.REBOOT_STARTED_HARD # possible task states during pause() -PAUSING = 'pausing' +PAUSING = fields.InstanceTaskState.PAUSING # possible task states during unpause() -UNPAUSING = 'unpausing' +UNPAUSING = fields.InstanceTaskState.UNPAUSING # possible task states during suspend() -SUSPENDING = 'suspending' +SUSPENDING = fields.InstanceTaskState.SUSPENDING # possible task states during resume() -RESUMING = 'resuming' +RESUMING = fields.InstanceTaskState.RESUMING # possible task states during power_off() -POWERING_OFF = 'powering-off' +POWERING_OFF = fields.InstanceTaskState.POWERING_OFF # possible task states during power_on() -POWERING_ON = 'powering-on' +POWERING_ON = fields.InstanceTaskState.POWERING_ON # possible task states during rescue() -RESCUING = 'rescuing' +RESCUING = fields.InstanceTaskState.RESCUING # possible task states during unrescue() -UNRESCUING = 'unrescuing' +UNRESCUING = fields.InstanceTaskState.UNRESCUING # possible task states during rebuild() -REBUILDING = 'rebuilding' -REBUILD_BLOCK_DEVICE_MAPPING = "rebuild_block_device_mapping" -REBUILD_SPAWNING = 'rebuild_spawning' +REBUILDING = fields.InstanceTaskState.REBUILDING +REBUILD_BLOCK_DEVICE_MAPPING = \ + fields.InstanceTaskState.REBUILD_BLOCK_DEVICE_MAPPING +REBUILD_SPAWNING = fields.InstanceTaskState.REBUILD_SPAWNING # possible task states during live_migrate() -MIGRATING = "migrating" +MIGRATING = fields.InstanceTaskState.MIGRATING # possible task states during delete() -DELETING = 'deleting' +DELETING = fields.InstanceTaskState.DELETING # possible task states during soft_delete() -SOFT_DELETING = 'soft-deleting' +SOFT_DELETING = fields.InstanceTaskState.SOFT_DELETING # possible task states during restore() -RESTORING = 'restoring' +RESTORING = fields.InstanceTaskState.RESTORING # possible task states during shelve() -SHELVING = 'shelving' -SHELVING_IMAGE_PENDING_UPLOAD = 'shelving_image_pending_upload' -SHELVING_IMAGE_UPLOADING = 'shelving_image_uploading' +SHELVING = fields.InstanceTaskState.SHELVING +SHELVING_IMAGE_PENDING_UPLOAD = \ + fields.InstanceTaskState.SHELVING_IMAGE_PENDING_UPLOAD +SHELVING_IMAGE_UPLOADING = fields.InstanceTaskState.SHELVING_IMAGE_UPLOADING # possible task states during shelve_offload() -SHELVING_OFFLOADING = 'shelving_offloading' +SHELVING_OFFLOADING = fields.InstanceTaskState.SHELVING_OFFLOADING # possible task states during unshelve() -UNSHELVING = 'unshelving' +UNSHELVING = fields.InstanceTaskState.UNSHELVING ALLOW_REBOOT = [None, REBOOTING, REBOOT_PENDING, REBOOT_STARTED, RESUMING, REBOOTING_HARD, UNPAUSING, PAUSING, SUSPENDING] diff --git a/nova/compute/vm_states.py b/nova/compute/vm_states.py index 229f0a6af7db..633894c1ea43 100644 --- a/nova/compute/vm_states.py +++ b/nova/compute/vm_states.py @@ -27,32 +27,52 @@ health and progress. See http://wiki.openstack.org/VMState """ -ACTIVE = 'active' # VM is running -BUILDING = 'building' # VM only exists in DB -PAUSED = 'paused' -SUSPENDED = 'suspended' # VM is suspended to disk. -STOPPED = 'stopped' # VM is powered off, the disk image is still there. -RESCUED = 'rescued' # A rescue image is running with the original VM image -# attached. -RESIZED = 'resized' # a VM with the new size is active. The user is expected -# to manually confirm or revert. +from nova.objects import fields -SOFT_DELETED = 'soft-delete' # VM is marked as deleted but the disk images are -# still available to restore. -DELETED = 'deleted' # VM is permanently deleted. -ERROR = 'error' +# VM is running +ACTIVE = fields.InstanceState.ACTIVE -SHELVED = 'shelved' # VM is powered off, resources still on hypervisor -SHELVED_OFFLOADED = 'shelved_offloaded' # VM and associated resources are -# not on hypervisor +# VM only exists in DB +BUILDING = fields.InstanceState.BUILDING + +PAUSED = fields.InstanceState.PAUSED + +# VM is suspended to disk. +SUSPENDED = fields.InstanceState.SUSPENDED + +# VM is powered off, the disk image is still there. +STOPPED = fields.InstanceState.STOPPED + +# A rescue image is running with the original VM image attached +RESCUED = fields.InstanceState.RESCUED + +# a VM with the new size is active. The user is expected to manually confirm +# or revert. +RESIZED = fields.InstanceState.RESIZED + +# VM is marked as deleted but the disk images are still available to restore. +SOFT_DELETED = fields.InstanceState.SOFT_DELETED + +# VM is permanently deleted. +DELETED = fields.InstanceState.DELETED + +ERROR = fields.InstanceState.ERROR + +# VM is powered off, resources still on hypervisor +SHELVED = fields.InstanceState.SHELVED + +# VM and associated resources are not on hypervisor +SHELVED_OFFLOADED = fields.InstanceState.SHELVED_OFFLOADED + +# states we can soft reboot from +ALLOW_SOFT_REBOOT = [ACTIVE] -ALLOW_SOFT_REBOOT = [ACTIVE] # states we can soft reboot from -ALLOW_HARD_REBOOT = ALLOW_SOFT_REBOOT + [STOPPED, PAUSED, SUSPENDED, ERROR] # states we allow hard reboot from +ALLOW_HARD_REBOOT = ALLOW_SOFT_REBOOT + [STOPPED, PAUSED, SUSPENDED, ERROR] -ALLOW_TRIGGER_CRASH_DUMP = [ACTIVE, PAUSED, RESCUED, RESIZED, ERROR] # states we allow to trigger crash dump +ALLOW_TRIGGER_CRASH_DUMP = [ACTIVE, PAUSED, RESCUED, RESIZED, ERROR] -ALLOW_RESOURCE_REMOVAL = [DELETED, SHELVED_OFFLOADED] # states we allow resources to be freed in +ALLOW_RESOURCE_REMOVAL = [DELETED, SHELVED_OFFLOADED] diff --git a/nova/objects/fields.py b/nova/objects/fields.py index 526d0ea92ec7..7673b2ef5214 100644 --- a/nova/objects/fields.py +++ b/nova/objects/fields.py @@ -522,9 +522,10 @@ class NotificationAction(BaseNovaEnum): POWER_OFF, SHELVE, RESUME, RESTORE) +# TODO(rlrossit): These should be changed over to be a StateMachine enum from +# oslo.versionedobjects using the valid state transitions described in +# nova.compute.vm_states class InstanceState(BaseNovaEnum): - # TODO(gibi): this is currently a copy of nova.compute.vm_states, remove - # the duplication ACTIVE = 'active' BUILDING = 'building' PAUSED = 'paused' @@ -542,9 +543,10 @@ class InstanceState(BaseNovaEnum): SOFT_DELETED, DELETED, ERROR, SHELVED, SHELVED_OFFLOADED) +# TODO(rlrossit): These should be changed over to be a StateMachine enum from +# oslo.versionedobjects using the valid state transitions described in +# nova.compute.task_states class InstanceTaskState(BaseNovaEnum): - # TODO(gibi): this is currently a copy of nova.compute.task_states, remove - # the duplication SCHEDULING = 'scheduling' BLOCK_DEVICE_MAPPING = 'block_device_mapping' NETWORKING = 'networking' @@ -601,35 +603,49 @@ class InstanceTaskState(BaseNovaEnum): SHELVING_OFFLOADING, UNSHELVING) -class InstancePowerState(BaseNovaEnum): - # TODO(gibi): this is currently a copy of nova.compute.power_state, remove - # the duplication +class InstancePowerState(Enum): + _UNUSED = '_unused' NOSTATE = 'pending' RUNNING = 'running' PAUSED = 'paused' SHUTDOWN = 'shutdown' CRASHED = 'crashed' SUSPENDED = 'suspended' + # The order is important here. If you make changes, only *append* + # values to the end of the list. + ALL = ( + NOSTATE, + RUNNING, + _UNUSED, + PAUSED, + SHUTDOWN, + _UNUSED, + CRASHED, + SUSPENDED, + ) - VALUE_MAP = { - 0x00: NOSTATE, - 0x01: RUNNING, - 0x03: PAUSED, - 0x04: SHUTDOWN, - 0x06: CRASHED, - 0x07: SUSPENDED - } - - ALL = (NOSTATE, RUNNING, PAUSED, SHUTDOWN, CRASHED, SUSPENDED) + def __init__(self): + super(InstancePowerState, self).__init__( + valid_values=InstancePowerState.ALL) def coerce(self, obj, attr, value): try: value = int(value) - value = InstancePowerState.VALUE_MAP[value] + value = self.from_index(value) except (ValueError, KeyError): pass return super(InstancePowerState, self).coerce(obj, attr, value) + @classmethod + def index(cls, value): + """Return an index into the Enum given a value.""" + return cls.ALL.index(value) + + @classmethod + def from_index(cls, index): + """Return the Enum value at a given index.""" + return cls.ALL[index] + class IPV4AndV6Address(IPAddress): @staticmethod diff --git a/nova/tests/unit/notifications/objects/test_notification.py b/nova/tests/unit/notifications/objects/test_notification.py index 471183f5adf7..fca9faeec388 100644 --- a/nova/tests/unit/notifications/objects/test_notification.py +++ b/nova/tests/unit/notifications/objects/test_notification.py @@ -264,11 +264,11 @@ notification_object_data = { 'ExceptionPayload': '1.0-4516ae282a55fe2fd5c754967ee6248b', 'FlavorPayload': '1.0-8ad962ab0bafc7270f474c7dda0b7c20', 'InstanceActionNotification': '1.0-a73147b93b520ff0061865849d3dfa56', - 'InstanceActionPayload': '1.0-aa6a322cf1a3a19d090259fee65d1094', - 'InstancePayload': '1.0-878bbc5a7a20bdeac7c6570f438a53aa', + 'InstanceActionPayload': '1.0-d94994d6043bb87fde603976ce811cba', + 'InstancePayload': '1.0-4473793aa2a0a4083d328847f3ab638a', 'InstanceStateUpdatePayload': '1.0-a934d04e1b314318e42e8062647edd11', 'InstanceUpdateNotification': '1.0-a73147b93b520ff0061865849d3dfa56', - 'InstanceUpdatePayload': '1.0-c69e17e00400455bfe602e5573a61f0b', + 'InstanceUpdatePayload': '1.0-2e21e6950fbb04e701e54e8563a21dbc', 'IpPayload': '1.0-26b40117c41ed95a61ae104f0fcb5fdc', 'NotificationPublisher': '1.0-bbbc1402fb0e443a3eb227cc52b61545', 'ServiceStatusNotification': '1.0-a73147b93b520ff0061865849d3dfa56',