diff --git a/mogan/tests/tempest/api/base.py b/mogan/tests/tempest/api/base.py index 3b223f25..63c92380 100644 --- a/mogan/tests/tempest/api/base.py +++ b/mogan/tests/tempest/api/base.py @@ -47,6 +47,7 @@ class BaseBaremetalComputeTest(tempest.test.BaseTestCase): super(BaseBaremetalComputeTest, cls).setup_clients() cls.baremetal_compute_client = cls.os_admin.baremetal_compute_client cls.compute_networks_client = cls.os_admin.compute_networks_client + cls.baremetal_node_client = cls.os_admin.baremetal_node_client @classmethod def _get_small_flavor(cls): diff --git a/mogan/tests/tempest/api/test_servers.py b/mogan/tests/tempest/api/test_servers.py index 4889caf3..658ba09f 100644 --- a/mogan/tests/tempest/api/test_servers.py +++ b/mogan/tests/tempest/api/test_servers.py @@ -12,7 +12,10 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. +import time + from tempest.lib import decorators +from tempest.lib import exceptions as lib_exc from mogan.tests.tempest.api import base @@ -124,3 +127,28 @@ class BaremetalComputeAPIServersTest(base.BaseBaremetalComputeTest): self.server_ids[0], 'rebuild') self._wait_for_servers_status(self.server_ids[0], 15, 900, 'active', 'power on') + + def _wait_for_console(self, node, console_enabled): + enabled = None + wait_interval = 3 + wait_timeout = 0 + while enabled != console_enabled: + time.sleep(wait_interval) + console = self.baremetal_node_client.get_node_console(node) + enabled = console['console_enabled'] + wait_timeout += wait_interval + if wait_timeout >= 30: + raise lib_exc.TimeoutException( + 'Failed to acquire console information for node: %s' % + node) + + def test_server_get_console(self): + self._ensure_states_before_test() + node = self.baremetal_node_client.show_bm_node( + service_id=self.server_ids[0]) + self.baremetal_node_client.bm_node_set_console_port(node['uuid'], 4321) + self.baremetal_node_client.set_node_console_state(node['uuid'], True) + self._wait_for_console(node['uuid'], True) + console = self.baremetal_compute_client.server_get_serial_console( + self.server_ids[0]) + self.assertIn('url', console) diff --git a/mogan/tests/tempest/config.py b/mogan/tests/tempest/config.py index f67208cf..65fabdcf 100644 --- a/mogan/tests/tempest/config.py +++ b/mogan/tests/tempest/config.py @@ -22,6 +22,9 @@ ServiceAvailableGroup = [ cfg.BoolOpt("mogan_plugin", default=True, help="Whether or not Mogan is expected to be available"), + cfg.BoolOpt("ironic_plugin", + default=True, + help="Whether or not Ironic is expected to be available") ] baremetal_compute_group = cfg.OptGroup( @@ -38,3 +41,17 @@ BaremetalComputeGroup = [ help="The endpoint type to use for the baremetal_compute" " service."), ] + +baremetal_node_group = cfg.OptGroup( + name='baremetal_node_plugin', title='Baremetal Service Options') + +BaremetalNodeGroup = [ + cfg.StrOpt('catalog_type', + default='baremetal', + help="Catalog type of the baremetal service."), + cfg.StrOpt('endpoint_type', + default='publicURL', + choices=['public', 'admin', 'internal', + 'publicURL', 'adminURL', 'internalURL'], + help="The endpoint type to use for the baremetal service."), +] diff --git a/mogan/tests/tempest/plugin.py b/mogan/tests/tempest/plugin.py index c4f2358f..6b996daf 100644 --- a/mogan/tests/tempest/plugin.py +++ b/mogan/tests/tempest/plugin.py @@ -38,6 +38,12 @@ class MoganTempestPlugin(plugins.TempestPlugin): tempest_config.baremetal_compute_group, tempest_config.BaremetalComputeGroup) + config.register_opt_group(conf, + tempest_config.baremetal_node_group, + tempest_config.BaremetalNodeGroup) + def get_opt_lists(self): return [(tempest_config.baremetal_compute_group.name, - tempest_config.BaremetalComputeGroup)] + tempest_config.BaremetalComputeGroup), + (tempest_config.baremetal_node_group.name, + tempest_config.BaremetalNodeGroup)] diff --git a/mogan/tests/tempest/service/client.py b/mogan/tests/tempest/service/client.py index bc7ae9ba..fe3cf30e 100644 --- a/mogan/tests/tempest/service/client.py +++ b/mogan/tests/tempest/service/client.py @@ -176,6 +176,75 @@ class BaremetalComputeClient(rest_client.RestClient): body = self.deserialize(body)['nodes'] return rest_client.ResponseBodyList(resp, body) + def server_get_serial_console(self, server_id): + uri = '%s/servers/%s/serial_console' % (self.uri_prefix, server_id) + resp, body = self.get(uri) + self.expected_success(200, resp.status) + body = self.deserialize(body)['console'] + return rest_client.ResponseBody(resp, body) + + +class BaremetalNodeClient(rest_client.RestClient): + version = '1' + uri_prefix = "v1" + + def deserialize(self, body): + return json.loads(body.replace("\n", "")) + + def serialize(self, body): + return json.dumps(body) + + def list_bm_nodes(self): + uri = '%s/nodes' % self.uri_prefix + resp, body = self.get(uri) + self.expected_success(200, resp.status) + body = self.deserialize(body)['nodes'] + return rest_client.ResponseBodyList(resp, body) + + def show_bm_node(self, node_uuid=None, service_id=None): + if service_id: + uri = '%s/nodes/detail?instance_uuid=%s' % (self.uri_prefix, + service_id) + else: + uri = '%s/nodes/%s' % (self.uri_prefix, node_uuid) + resp, body = self.get(uri) + self.expected_success(200, resp.status) + body = self.deserialize(body) + if service_id: + body = body['nodes'][0] + return rest_client.ResponseBody(resp, body) + + def set_node_console_state(self, node_id, enabled): + uri = '%s/nodes/%s/states/console' % (self.uri_prefix, node_id) + target_body = {'enabled': enabled} + target_body = self.serialize(target_body) + resp, body = self.put(uri, target_body) + self.expected_success(202, resp.status) + if body: + body = self.deserialize(body) + return rest_client.ResponseBody(resp, body) + + def get_node_console(self, node_id): + uri = '%s/nodes/%s/states/console' % (self.uri_prefix, node_id) + resp, body = self.get(uri) + self.expected_success(200, resp.status) + body = self.deserialize(body) + return rest_client.ResponseBody(resp, body) + + def update_bm_node(self, node_id, updates): + uri = '%s/nodes/%s' % (self.uri_prefix, node_id) + target_body = self.serialize(updates) + resp, body = self.patch(uri, target_body) + self.expected_success(200, resp.status) + if body: + body = self.deserialize(body) + return rest_client.ResponseBody(resp, body) + + def bm_node_set_console_port(self, node_id, port): + updates = [{"path": "/driver_info/ipmi_terminal_port", + "value": port, "op": "add"}] + self.update_bm_node(node_id, updates) + class Manager(manager.Manager): @@ -183,6 +252,7 @@ class Manager(manager.Manager): 'baremetal_compute_client', 'compute_networks_client', 'image_client_v2', + 'baremetal_node_client' ] default_params = { @@ -217,6 +287,13 @@ class Manager(manager.Manager): } image_params.update(default_params) + baremetal_node_params = { + 'service': CONF.baremetal_node_plugin.catalog_type, + 'region': CONF.identity.region, + 'endpoint_type': CONF.baremetal_node_plugin.endpoint_type, + } + baremetal_node_params.update(default_params) + def __init__(self, credentials=None, service=None): super(Manager, self).__init__(credentials) for client in self.load_clients: @@ -235,3 +312,8 @@ class Manager(manager.Manager): self.image_client_v2 = image_cli.ImagesClient( self.auth_provider, **self.image_params) + + def set_baremetal_node_client(self): + self.baremetal_node_client = BaremetalNodeClient( + self.auth_provider, + **self.baremetal_node_params)