Merge "Abort operation for live migration"
This commit is contained in:
@@ -139,4 +139,10 @@ class BaseAction(loadable.Loadable):
|
||||
raise NotImplementedError()
|
||||
|
||||
def check_abort(self):
|
||||
return bool(self.__class__.__name__ in self.ABORT_TRUE)
|
||||
if self.__class__.__name__ is 'Migrate':
|
||||
if self.migration_type == self.LIVE_MIGRATION:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return bool(self.__class__.__name__ in self.ABORT_TRUE)
|
||||
|
||||
@@ -151,6 +151,18 @@ class Migrate(base.BaseAction):
|
||||
"host.", self.instance_uuid)
|
||||
return result
|
||||
|
||||
def _abort_cold_migrate(self, nova):
|
||||
# TODO(adisky): currently watcher uses its own version of cold migrate
|
||||
# implement cold migrate using nova dependent on the blueprint
|
||||
# https://blueprints.launchpad.net/nova/+spec/cold-migration-with-target
|
||||
# Abort operation for cold migrate is dependent on blueprint
|
||||
# https://blueprints.launchpad.net/nova/+spec/abort-cold-migration
|
||||
LOG.warning("Abort operation for cold migration is not implemented")
|
||||
|
||||
def _abort_live_migrate(self, nova, source, destination):
|
||||
return nova.abort_live_migrate(instance_id=self.instance_uuid,
|
||||
source=source, destination=destination)
|
||||
|
||||
def migrate(self, destination):
|
||||
nova = nova_helper.NovaHelper(osc=self.osc)
|
||||
LOG.debug("Migrate instance %s to %s", self.instance_uuid,
|
||||
@@ -176,8 +188,17 @@ class Migrate(base.BaseAction):
|
||||
return self.migrate(destination=self.source_node)
|
||||
|
||||
def abort(self):
|
||||
# TODO(adisky): implement abort for migration
|
||||
LOG.warning("Abort for migration not implemented")
|
||||
nova = nova_helper.NovaHelper(osc=self.osc)
|
||||
instance = nova.find_instance(self.instance_uuid)
|
||||
if instance:
|
||||
if self.migration_type == self.COLD_MIGRATION:
|
||||
return self._abort_cold_migrate(nova)
|
||||
elif self.migration_type == self.LIVE_MIGRATION:
|
||||
return self._abort_live_migrate(
|
||||
nova, source=self.source_node,
|
||||
destination=self.destination_node)
|
||||
else:
|
||||
raise exception.InstanceNotFound(name=self.instance_uuid)
|
||||
|
||||
def pre_condition(self):
|
||||
# TODO(jed): check if the instance exists / check if the instance is on
|
||||
|
||||
@@ -83,3 +83,4 @@ class Nop(base.BaseAction):
|
||||
|
||||
def abort(self):
|
||||
LOG.debug("Abort action NOP")
|
||||
return True
|
||||
|
||||
@@ -86,3 +86,4 @@ class Sleep(base.BaseAction):
|
||||
|
||||
def abort(self):
|
||||
LOG.debug("Abort action sleep")
|
||||
return True
|
||||
|
||||
@@ -88,10 +88,6 @@ class BaseWorkFlowEngine(loadable.Loadable):
|
||||
def notify(self, action, state):
|
||||
db_action = objects.Action.get_by_uuid(self.context, action.uuid,
|
||||
eager=True)
|
||||
if (db_action.state in [objects.action.State.CANCELLING,
|
||||
objects.action.State.CANCELLED] and
|
||||
state == objects.action.State.SUCCEEDED):
|
||||
return
|
||||
db_action.state = state
|
||||
db_action.save()
|
||||
|
||||
@@ -204,7 +200,7 @@ class BaseTaskFlowActionContainer(flow_task.Task):
|
||||
objects.action.State.FAILED] or
|
||||
action_plan_object.state in CANCEL_STATE):
|
||||
break
|
||||
time.sleep(2)
|
||||
time.sleep(1)
|
||||
try:
|
||||
# NOTE: kill the action execution thread, if action plan is
|
||||
# cancelled for all other cases wait for the result from action
|
||||
@@ -246,15 +242,19 @@ class BaseTaskFlowActionContainer(flow_task.Task):
|
||||
# if due to some other exception keep the flow intact.
|
||||
if action_plan.state not in CANCEL_STATE:
|
||||
self.do_revert()
|
||||
return
|
||||
|
||||
action_object = objects.Action.get_by_uuid(
|
||||
self.engine.context, self._db_action.uuid, eager=True)
|
||||
if action_object.state == objects.action.State.ONGOING:
|
||||
action_object.state = objects.action.State.CANCELLING
|
||||
action_object.save()
|
||||
self.abort()
|
||||
if action_object.state == objects.action.State.PENDING:
|
||||
elif action_object.state == objects.action.State.PENDING:
|
||||
action_object.state = objects.action.State.CANCELLED
|
||||
action_object.save()
|
||||
else:
|
||||
pass
|
||||
|
||||
def abort(self, *args, **kwargs):
|
||||
self.do_abort(*args, **kwargs)
|
||||
|
||||
@@ -143,8 +143,14 @@ class TaskFlowActionContainer(base.BaseTaskFlowActionContainer):
|
||||
def do_abort(self, *args, **kwargs):
|
||||
LOG.warning("Aborting action: %s", self.name)
|
||||
try:
|
||||
self.action.abort()
|
||||
self.engine.notify(self._db_action, objects.action.State.CANCELLED)
|
||||
result = self.action.abort()
|
||||
if result:
|
||||
# Aborted the action.
|
||||
self.engine.notify(self._db_action,
|
||||
objects.action.State.CANCELLED)
|
||||
else:
|
||||
self.engine.notify(self._db_action,
|
||||
objects.action.State.SUCCEEDED)
|
||||
except Exception as e:
|
||||
self.engine.notify(self._db_action, objects.action.State.FAILED)
|
||||
LOG.exception(e)
|
||||
|
||||
Reference in New Issue
Block a user