From 7e435fa8f39537f1d915b1b3775c14866281ed6a Mon Sep 17 00:00:00 2001 From: Ryan Rossiter Date: Tue, 28 Jun 2016 14:11:44 +0000 Subject: [PATCH] Removed enum duplication from nova.compute There are many state constants held within nova.compute. Because these now need to be used in versioned notifications, they were converted into enums within nova.objects.fields. In order to prevent duplication, the constants in nova.compute were converted over to use the enums created for the notifications. Also, because the comments in nova.compute.vm_states were not the best, they were rearranged to more appropriately fit the lines they were attempting to comment. The object hash changes are ignored as it is only caused by the new sentinel enum value _UNUSED which is not intended to be used. Change-Id: I4c147a1a1145295b6ccfe9680706abe34cb35170 --- nova/compute/power_state.py | 27 +++--- nova/compute/task_states.py | 88 ++++++++++--------- nova/compute/vm_states.py | 60 ++++++++----- nova/objects/fields.py | 52 +++++++---- .../objects/test_notification.py | 6 +- 5 files changed, 136 insertions(+), 97 deletions(-) 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',