Add a test for introspection abort action verification.

Change-Id: Ia2c371a862a800220323e81545e6a8693dac51f0
diff --git a/ironic_tempest_plugin/services/introspection_client.py b/ironic_tempest_plugin/services/introspection_client.py
index cce5213..2934e54 100644
--- a/ironic_tempest_plugin/services/introspection_client.py
+++ b/ironic_tempest_plugin/services/introspection_client.py
@@ -73,3 +73,13 @@
         self.expected_success(202, resp.status)
 
         return resp
+
+    @base.handle_errors
+    def abort_introspection(self, uuid):
+        """Abort introspection for a node."""
+        resp, _body = self.post(url=('/%s/introspection/%s/abort' %
+                                     (self.uri_prefix, uuid)),
+                                body=None)
+        self.expected_success(202, resp.status)
+
+        return resp
diff --git a/ironic_tempest_plugin/tests/manager.py b/ironic_tempest_plugin/tests/manager.py
index 445a15e..961b284 100644
--- a/ironic_tempest_plugin/tests/manager.py
+++ b/ironic_tempest_plugin/tests/manager.py
@@ -121,6 +121,9 @@
     def introspection_start(self, uuid):
         return self.introspection_client.start_introspection(uuid)
 
+    def introspection_abort(self, uuid):
+        return self.introspection_client.abort_introspection(uuid)
+
     def baremetal_flavor(self):
         flavor_id = CONF.compute.flavor_ref
         flavor = self.flavors_client.show_flavor(flavor_id)['flavor']
@@ -210,6 +213,11 @@
         if (self.node_show(node_id)['provision_state'] ==
            BaremetalProvisionStates.AVAILABLE):
             return
+        # in case when introspection failed we need set provision state
+        # to 'manage' to make it possible transit into 'provide' state
+        if self.node_show(node_id)['provision_state'] == 'inspect failed':
+            self.baremetal_client.set_node_provision_state(node_id, 'manage')
+
         try:
             self.baremetal_client.set_node_provision_state(node_id, 'provide')
         except tempest.lib.exceptions.RestClientException:
@@ -222,13 +230,14 @@
             timeout=CONF.baremetal.unprovision_timeout,
             interval=self.wait_provisioning_state_interval)
 
-    def introspect_node(self, node_id):
-        # in case there are properties remove those
-        patch = {('properties/%s' % key): None for key in
-                 self.node_show(node_id)['properties']}
-        # reset any previous rule result
-        patch['extra/rule_success'] = None
-        self.node_update(node_id, patch)
+    def introspect_node(self, node_id, remove_props=True):
+        if remove_props:
+            # in case there are properties remove those
+            patch = {('properties/%s' % key): None for key in
+                     self.node_show(node_id)['properties']}
+            # reset any previous rule result
+            patch['extra/rule_success'] = None
+            self.node_update(node_id, patch)
 
         self.baremetal_client.set_node_provision_state(node_id, 'manage')
         self.baremetal_client.set_node_provision_state(node_id, 'inspect')
diff --git a/ironic_tempest_plugin/tests/test_basic.py b/ironic_tempest_plugin/tests/test_basic.py
index 6ef2266..dd099c0 100644
--- a/ironic_tempest_plugin/tests/test_basic.py
+++ b/ironic_tempest_plugin/tests/test_basic.py
@@ -14,8 +14,7 @@
 from tempest import test  # noqa
 
 from ironic_inspector.test.inspector_tempest_plugin.tests import manager
-from ironic_tempest_plugin.tests.scenario.baremetal_manager import \
-    BaremetalProvisionStates
+from ironic_tempest_plugin.tests.scenario import baremetal_manager
 
 
 class InspectorBasicTest(manager.InspectorScenarioTest):
@@ -46,6 +45,17 @@
         self.assertEqual(expected_cpu_arch,
                          node['properties']['cpu_arch'])
 
+    def verify_introspection_aborted(self, uuid):
+        status = self.introspection_status(uuid)
+
+        self.assertEqual('Canceled by operator', status['error'])
+        self.assertTrue(status['finished'])
+
+        self.wait_provisioning_state(
+            uuid, 'inspect failed',
+            timeout=CONF.baremetal.active_timeout,
+            interval=self.wait_provisioning_state_interval)
+
     @test.idempotent_id('03bf7990-bee0-4dd7-bf74-b97ad7b52a4b')
     @test.services('baremetal', 'compute', 'image',
                    'network', 'object_storage')
@@ -91,7 +101,7 @@
 
         for node_id in self.node_ids:
             self.wait_provisioning_state(
-                node_id, BaremetalProvisionStates.AVAILABLE,
+                node_id, baremetal_manager.BaremetalProvisionStates.AVAILABLE,
                 timeout=CONF.baremetal.active_timeout,
                 interval=self.wait_provisioning_state_interval)
 
@@ -100,6 +110,41 @@
         ins, _node = self.boot_instance()
         self.terminate_instance(ins)
 
+    @test.idempotent_id('70ca3070-184b-4b7d-8892-e977d2bc2870')
+    @test.services('baremetal')
+    def test_introspection_abort(self):
+        """This smoke test case follows this very basic set of operations:
+
+            * Start nodes introspection
+            * Wait until nodes power on
+            * Abort introspection
+            * Verifies nodes status and power state
+
+        """
+        # start nodes introspection
+        for node_id in self.node_ids:
+            self.introspect_node(node_id, remove_props=False)
+
+        # wait for nodes power on
+        for node_id in self.node_ids:
+            self.wait_power_state(
+                node_id,
+                baremetal_manager.BaremetalPowerStates.POWER_ON)
+
+        # abort introspection
+        for node_id in self.node_ids:
+            self.introspection_abort(node_id)
+
+        # wait for nodes power off
+        for node_id in self.node_ids:
+            self.wait_power_state(
+                node_id,
+                baremetal_manager.BaremetalPowerStates.POWER_OFF)
+
+        # verify nodes status and provision state
+        for node_id in self.node_ids:
+            self.verify_introspection_aborted(node_id)
+
 
 class InspectorSmokeTest(manager.InspectorScenarioTest):