From cb9a1957560798f97040723a6a04b19a7f1cf09f Mon Sep 17 00:00:00 2001 From: James Page Date: Thu, 15 Sep 2016 12:02:35 +0100 Subject: [PATCH] Add support for serial console access Enable instance serial console based on flags provided from nova-cloud-controller charm. This is only supported in OpenStack Juno or later, and replaces the standard output to the nova console-log. Change-Id: I147166d9b273964d34ba81724b0311f269b9fea0 Depends-On: I3bfcca88bd6147be337e6d770db7348170b914e6 --- hooks/nova_compute_context.py | 28 +++++++++++++++++++++ hooks/nova_compute_utils.py | 4 ++- templates/juno/nova.conf | 2 ++ templates/kilo/nova.conf | 2 ++ templates/liberty/nova.conf | 2 ++ templates/mitaka/nova.conf | 2 ++ templates/parts/section-serial-console | 4 +++ unit_tests/test_nova_compute_contexts.py | 31 ++++++++++++++++++++++++ 8 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 templates/parts/section-serial-console diff --git a/hooks/nova_compute_context.py b/hooks/nova_compute_context.py index b133aa82..00b38457 100644 --- a/hooks/nova_compute_context.py +++ b/hooks/nova_compute_context.py @@ -281,6 +281,34 @@ class NovaComputeCephContext(context.CephContext): return ctxt +class SerialConsoleContext(context.OSContextGenerator): + + @property + def enable_serial_console(self): + for rid in relation_ids('cloud-compute'): + for unit in related_units(rid): + if bool(relation_get('enable_serial_console', + rid=rid, unit=unit)) is True: + return 'true' + return 'false' + + @property + def serial_console_base_url(self): + for rid in relation_ids('cloud-compute'): + for unit in related_units(rid): + base_url = relation_get('serial_console_base_url', + rid=rid, unit=unit) + if base_url is not None: + return base_url + return 'ws://127.0.0.1:6083/' + + def __call__(self): + return { + 'enable_serial_console': self.enable_serial_console, + 'serial_console_base_url': self.serial_console_base_url, + } + + class CloudComputeContext(context.OSContextGenerator): ''' diff --git a/hooks/nova_compute_utils.py b/hooks/nova_compute_utils.py index e25bbbb0..9afe1fb8 100644 --- a/hooks/nova_compute_utils.py +++ b/hooks/nova_compute_utils.py @@ -108,6 +108,7 @@ from nova_compute_context import ( NovaAPIAppArmorContext, NovaComputeAppArmorContext, NovaNetworkAppArmorContext, + SerialConsoleContext, ) CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt' @@ -222,7 +223,8 @@ BASE_RESOURCE_MAP = { DesignateContext(), NovaComputeVirtContext(), context.LogLevelContext(), - context.InternalEndpointContext()], + context.InternalEndpointContext(), + SerialConsoleContext()], }, NOVA_API_AA_PROFILE_PATH: { 'services': ['nova-api'], diff --git a/templates/juno/nova.conf b/templates/juno/nova.conf index aaa6d655..3f0c3280 100644 --- a/templates/juno/nova.conf +++ b/templates/juno/nova.conf @@ -170,3 +170,5 @@ disk_cachemodes = {{ disk_cachemodes }} {% include "parts/section-cinder" %} {% include "parts/section-ephemeral" %} + +{% include "parts/section-serial-console" %} diff --git a/templates/kilo/nova.conf b/templates/kilo/nova.conf index f7fd2d05..87446c20 100644 --- a/templates/kilo/nova.conf +++ b/templates/kilo/nova.conf @@ -197,3 +197,5 @@ lock_path=/var/lock/nova disable_libvirt_livesnapshot = False {% include "parts/section-ephemeral" %} + +{% include "parts/section-serial-console" %} diff --git a/templates/liberty/nova.conf b/templates/liberty/nova.conf index 92d1926d..a27c296b 100644 --- a/templates/liberty/nova.conf +++ b/templates/liberty/nova.conf @@ -203,3 +203,5 @@ lock_path=/var/lock/nova disable_libvirt_livesnapshot = False {% include "parts/section-ephemeral" %} + +{% include "parts/section-serial-console" %} diff --git a/templates/mitaka/nova.conf b/templates/mitaka/nova.conf index 7cc19a14..5c796975 100644 --- a/templates/mitaka/nova.conf +++ b/templates/mitaka/nova.conf @@ -219,3 +219,5 @@ lock_path=/var/lock/nova disable_libvirt_livesnapshot = False {% include "parts/section-ephemeral" %} + +{% include "parts/section-serial-console" %} \ No newline at end of file diff --git a/templates/parts/section-serial-console b/templates/parts/section-serial-console new file mode 100644 index 00000000..396ebd12 --- /dev/null +++ b/templates/parts/section-serial-console @@ -0,0 +1,4 @@ +[serial_console] +enabled = {{ enable_serial_console }} +proxyclient_address = {{ console_listen_addr }} +base_url = {{ serial_console_base_url }} \ No newline at end of file diff --git a/unit_tests/test_nova_compute_contexts.py b/unit_tests/test_nova_compute_contexts.py index 19eb7c53..b1f31d94 100644 --- a/unit_tests/test_nova_compute_contexts.py +++ b/unit_tests/test_nova_compute_contexts.py @@ -404,3 +404,34 @@ class DesignateContextTests(CharmTestCase): self.assertEqual(designatectxt(), { 'enable_designate': False, }) + + +class SerialConsoleContextTests(CharmTestCase): + + def setUp(self): + super(SerialConsoleContextTests, self).setUp(context, TO_PATCH) + self.relation_get.side_effect = self.test_relation.get + self.config.side_effect = self.test_config.get + self.host_uuid = 'e46e530d-18ae-4a67-9ff0-e6e2ba7c60a7' + + def test_serial_console_not_provided(self): + self.relation_ids.return_value = ['cloud-compute:0'] + self.related_units.return_value = 'nova-cloud-controller/0' + self.assertEqual( + context.SerialConsoleContext()(), + {'enable_serial_console': 'false', + 'serial_console_base_url': 'ws://127.0.0.1:6083/'} + ) + + def test_serial_console_provided(self): + self.relation_ids.return_value = ['cloud-compute:0'] + self.related_units.return_value = 'nova-cloud-controller/0' + self.test_relation.set({ + 'enable_serial_console': 'true', + 'serial_console_base_url': 'ws://10.10.10.1:6083/' + }) + self.assertEqual( + context.SerialConsoleContext()(), + {'enable_serial_console': 'true', + 'serial_console_base_url': 'ws://10.10.10.1:6083/'} + )