Introduce new orchestration tasks

There are 3 new orchestration tasks:

* master_shell

  Run task on master node with a context of other node. If 'roles'
  selects N nodes, the task will be executed N times.

* erase_node

  Erase node. It's necessary task if we want to remove nodes by means
  of graphs and not pre-hardcoded actions in Astute.

* move_to_bootstrap

  Change node's PXE config to boot via LAN (into bootstrap). As a
  previous one, it's necessary task for deletion graph.

Change-Id: Ie8f852762b837a68e0e0b49e11653a8f2e56a014
Blueprint: graph-concept-extension
This commit is contained in:
Bulat Gaifullin 2016-08-15 16:54:44 +03:00
parent 963014eb3c
commit 8e2220b789
6 changed files with 81 additions and 28 deletions

View File

@ -382,7 +382,10 @@ ORCHESTRATOR_TASK_TYPES = Enum(
'skipped',
'reboot',
'copy_files',
'role'
'role',
'master_shell',
'move_to_bootstrap',
'erase_node'
)
INTERNAL_TASKS = (ORCHESTRATOR_TASK_TYPES.group,

View File

@ -26,6 +26,7 @@ import sqlalchemy as sa
from oslo_serialization import jsonutils
from nailgun.db.sqlalchemy.models import fields
from nailgun.utils.migration import upgrade_enum
# revision identifiers, used by Alembic.
@ -40,9 +41,11 @@ def upgrade():
upgrade_release_required_component_types()
upgrade_task_model()
upgrade_deployment_graphs_attributes()
upgrade_orchestrator_task_types()
def downgrade():
downgrade_orchestrator_task_types()
downgrade_deployment_graphs_attributes()
downgrade_task_model()
downgrade_release_required_component_types()
@ -369,3 +372,44 @@ def downgrade_deployment_graphs_attributes():
op.drop_column('deployment_graphs', 'on_success')
op.drop_column('deployment_graphs', 'on_error')
op.drop_column('deployment_graphs', 'on_stop')
orchestrator_task_types_old = (
'puppet',
'shell',
'sync',
'upload_file',
'group',
'stage',
'skipped',
'reboot',
'copy_files',
'role'
)
orchestrator_task_types_new = orchestrator_task_types_old + (
'master_shell',
'move_to_bootstrap',
'erase_node'
)
def upgrade_orchestrator_task_types():
upgrade_enum(
'deployment_graph_tasks',
'type',
'deployment_graph_tasks_type',
orchestrator_task_types_old,
orchestrator_task_types_new
)
def downgrade_orchestrator_task_types():
upgrade_enum(
'deployment_graph_tasks',
'type',
'deployment_graph_tasks_type',
orchestrator_task_types_new,
orchestrator_task_types_old
)

View File

@ -20,7 +20,6 @@ import re
import six
from nailgun import consts
from nailgun import errors
from nailgun.expression import Expression
from nailgun.logger import logger
from nailgun.settings import settings
@ -214,23 +213,10 @@ class DefaultTaskSerializer(NoopTaskSerializer):
return task
def handle_unsupported(_, task_template):
raise errors.SerializerNotSupported(
'The task with type {0} is not supported.'
.format(task_template['type'])
)
class TasksSerializersFactory(object):
known_types = {
consts.ORCHESTRATOR_TASK_TYPES.skipped: NoopTaskSerializer,
consts.ORCHESTRATOR_TASK_TYPES.stage: NoopTaskSerializer,
consts.ORCHESTRATOR_TASK_TYPES.copy_files: DefaultTaskSerializer,
consts.ORCHESTRATOR_TASK_TYPES.puppet: DefaultTaskSerializer,
consts.ORCHESTRATOR_TASK_TYPES.reboot: DefaultTaskSerializer,
consts.ORCHESTRATOR_TASK_TYPES.shell: DefaultTaskSerializer,
consts.ORCHESTRATOR_TASK_TYPES.sync: DefaultTaskSerializer,
consts.ORCHESTRATOR_TASK_TYPES.upload_file: DefaultTaskSerializer,
}
def __init__(self, transaction):
@ -238,6 +224,6 @@ class TasksSerializersFactory(object):
def create_serializer(self, task_template):
serializer_class = self.known_types.get(
task_template['type'], handle_unsupported
task_template['type'], DefaultTaskSerializer
)
return serializer_class(self.context, task_template)

View File

@ -148,3 +148,20 @@ class TestDeploymentGraphsDowngrade(base.BaseAlembicMigrationTest):
self.assertNotIn('on_success', graphs_table.c)
self.assertNotIn('on_error', graphs_table.c)
self.assertNotIn('on_stop', graphs_table.c)
class TestOrchestratorTaskTypesDowngrade(base.BaseAlembicMigrationTest):
def test_enum_does_not_have_new_values(self):
expected_values = {
'master_shell',
'move_to_bootstrap',
'erase_node',
}
result = db.execute(sa.text(
'select unnest(enum_range(NULL::deployment_graph_tasks_type))'
)).fetchall()
self.assertFalse(
expected_values.intersection((x[0] for x in result))
)

View File

@ -14,7 +14,6 @@
# under the License.
from nailgun import consts
from nailgun import errors
from nailgun.lcm.context import TransactionContext
from nailgun.lcm import task_serializer
from nailgun.settings import settings
@ -302,14 +301,3 @@ class TestTasksSerializersFactory(BaseUnitTest):
factory.create_serializer(task),
task_serializer.NoopTaskSerializer
)
def test_create_raise_error_if_unknown_type(self):
unsupported_task_types = [
consts.ORCHESTRATOR_TASK_TYPES.group,
consts.ORCHESTRATOR_TASK_TYPES.role
]
factory = self.factory_class(TransactionContext({}))
for task_type in unsupported_task_types:
task = {'id': 'test', 'type': task_type}
with self.assertRaises(errors.SerializerNotSupported):
factory.create_serializer(task)

View File

@ -597,3 +597,18 @@ class TestDeploymentGraphsMigration(base.BaseAlembicMigrationTest):
'{"node_attributes": {"status": "error"}}', result['on_error']
)
self.assertEqual('{}', result['on_stop'])
class TestOrchestratorTaskTypesMigration(base.BaseAlembicMigrationTest):
def test_enum_has_new_values(self):
expected_values = {
'master_shell',
'move_to_bootstrap',
'erase_node',
}
result = db.execute(sa.text(
'select unnest(enum_range(NULL::deployment_graph_tasks_type))'
)).fetchall()
self.assertTrue(expected_values.issubset((x[0] for x in result)))