Browse Source

Merge "New command "openstack overcloud node unprovision""

tags/12.2.0
Zuul 2 weeks ago
parent
commit
68b56c694b

+ 10
- 0
releasenotes/notes/node-unprovision-dd400e58f2f479a2.yaml View File

@@ -0,0 +1,10 @@
1
+features:
2
+  - |
3
+    New command "openstack overcloud node unprovision"
4
+
5
+    This is a companion command to "openstack overcloud node provision"
6
+    which is required for scale-down and should be run after "openstack
7
+    overcloud deploy".
8
+
9
+    It will undeploy any instance which has provisioned=False in the
10
+    supplied roles yaml.

+ 1
- 0
setup.cfg View File

@@ -76,6 +76,7 @@ openstack.tripleoclient.v1 =
76 76
     overcloud_node_bios_configure = tripleoclient.v1.overcloud_bios:ConfigureBIOS
77 77
     overcloud_node_bios_reset = tripleoclient.v1.overcloud_bios:ResetBIOS
78 78
     overcloud_node_provision = tripleoclient.v1.overcloud_node:ProvisionNode
79
+    overcloud_node_unprovision = tripleoclient.v1.overcloud_node:UnprovisionNode
79 80
     overcloud_parameters_set = tripleoclient.v1.overcloud_parameters:SetParameters
80 81
     overcloud_plan_create = tripleoclient.v1.overcloud_plan:CreatePlan
81 82
     overcloud_plan_delete = tripleoclient.v1.overcloud_plan:DeletePlan

+ 38
- 0
tripleoclient/tests/v1/overcloud_node/test_overcloud_node.py View File

@@ -1099,3 +1099,41 @@ class TestProvisionNode(fakes.TestOvercloudNode):
1099 1099
                             'ssh_keys': ['I am a key'],
1100 1100
                             'ssh_user_name': 'heat-admin'}
1101 1101
         )
1102
+
1103
+
1104
+class TestUnprovisionNode(fakes.TestOvercloudNode):
1105
+
1106
+    def setUp(self):
1107
+        super(TestUnprovisionNode, self).setUp()
1108
+
1109
+        self.workflow = self.app.client_manager.workflow_engine
1110
+        execution = mock.Mock()
1111
+        execution.id = "IDID"
1112
+        self.workflow.executions.create.return_value = execution
1113
+        client = self.app.client_manager.tripleoclient
1114
+        self.websocket = client.messaging_websocket()
1115
+        self.websocket.wait_for_messages.return_value = [{
1116
+            "status": "SUCCESS",
1117
+            "message": "Success",
1118
+            "environment": {"cat": "meow"},
1119
+            "execution": {"id": "IDID"}
1120
+        }]
1121
+
1122
+        self.cmd = overcloud_node.UnprovisionNode(self.app, None)
1123
+
1124
+    def test_ok(self):
1125
+        with tempfile.NamedTemporaryFile() as inp:
1126
+            inp.write(b'- name: Compute\n- name: Controller\n')
1127
+            inp.flush()
1128
+            argslist = [inp.name]
1129
+            verifylist = [('input', inp.name)]
1130
+
1131
+            parsed_args = self.check_parser(self.cmd,
1132
+                                            argslist, verifylist)
1133
+            self.cmd.take_action(parsed_args)
1134
+
1135
+        self.workflow.executions.create.assert_called_once_with(
1136
+            'tripleo.baremetal_deploy.v1.undeploy_roles',
1137
+            workflow_input={'roles': [{'name': 'Compute'},
1138
+                                      {'name': 'Controller'}]}
1139
+        )

+ 30
- 2
tripleoclient/v1/overcloud_node.py View File

@@ -485,9 +485,9 @@ class DiscoverNode(command.Command):
485 485
 
486 486
 
487 487
 class ProvisionNode(command.Command):
488
-    """Provision a new node using Ironic."""
488
+    """Provision new nodes using Ironic."""
489 489
 
490
-    log = logging.getLogger(__name__ + ".DiscoverNode")
490
+    log = logging.getLogger(__name__ + ".ProvisionNode")
491 491
 
492 492
     def get_parser(self, prog_name):
493 493
         parser = super(ProvisionNode, self).get_parser(prog_name)
@@ -534,3 +534,31 @@ class ProvisionNode(command.Command):
534 534
 
535 535
         print('Nodes deployed successfully, add %s to your deployment '
536 536
               'environment' % parsed_args.output)
537
+
538
+
539
+class UnprovisionNode(command.Command):
540
+    """Unprovisions nodes using Ironic."""
541
+
542
+    log = logging.getLogger(__name__ + ".UnprovisionNode")
543
+
544
+    def get_parser(self, prog_name):
545
+        parser = super(UnprovisionNode, self).get_parser(prog_name)
546
+        parser.add_argument('input',
547
+                            metavar='<baremetal_deployment.yaml>',
548
+                            help=_('Configuration file describing the '
549
+                                   'baremetal deployment'))
550
+        return parser
551
+
552
+    def take_action(self, parsed_args):
553
+        self.log.debug("take_action(%s)" % parsed_args)
554
+
555
+        with open(parsed_args.input, 'r') as fp:
556
+            roles = yaml.safe_load(fp)
557
+
558
+        # TODO(sbaker) call ExpandRolesAction to get a list of
559
+        # instances being unprovisioned to prompt for confirmation
560
+        baremetal.undeploy_roles(
561
+            self.app.client_manager,
562
+            roles=roles)
563
+
564
+        print('Unprovision complete')

+ 27
- 0
tripleoclient/workflows/baremetal.py View File

@@ -541,3 +541,30 @@ def deploy_roles(clients, **workflow_input):
541 541
             'Error deploying nodes: {}'.format(payload['message']))
542 542
 
543 543
     return payload
544
+
545
+
546
+def undeploy_roles(clients, **workflow_input):
547
+    """Undeploy provided roles using Ironic.
548
+
549
+    Run the tripleo.baremetal_deploy.v1.undeploy_roles Mistral workflow.
550
+    """
551
+
552
+    workflow_client = clients.workflow_engine
553
+    tripleoclients = clients.tripleoclient
554
+
555
+    with tripleoclients.messaging_websocket() as ws:
556
+        execution = base.start_workflow(
557
+            workflow_client,
558
+            'tripleo.baremetal_deploy.v1.undeploy_roles',
559
+            workflow_input=workflow_input
560
+        )
561
+
562
+        for payload in base.wait_for_messages(workflow_client, ws, execution):
563
+            if payload.get('message'):
564
+                print(payload['message'])
565
+
566
+    if payload['status'] != 'SUCCESS':
567
+        raise exceptions.NodeConfigurationError(
568
+            'Error undeploying nodes: {}'.format(payload['message']))
569
+
570
+    return payload

Loading…
Cancel
Save