Add new interface 'dashboard'
This new interface consumes information exposed by openstack-dashboard to correctly configure nova-serialproxy and allow requests coming from the web browser that tries to load the serial console. Change-Id: I2d82abffb9649f16a792f180806cea36cc5e25df Closes-Bug: #2030094
This commit is contained in:
parent
b58f88263f
commit
816ee80cd0
1
hooks/dashboard-relation-changed
Symbolic link
1
hooks/dashboard-relation-changed
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
nova_cc_hooks.py
|
1
hooks/dashboard-relation-joined
Symbolic link
1
hooks/dashboard-relation-joined
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
nova_cc_hooks.py
|
@ -587,8 +587,33 @@ class SerialConsoleContext(ch_context.OSContextGenerator):
|
|||||||
ctxt = {
|
ctxt = {
|
||||||
'enable_serial_console':
|
'enable_serial_console':
|
||||||
str(hookenv.config('enable-serial-console')).lower(),
|
str(hookenv.config('enable-serial-console')).lower(),
|
||||||
'serial_console_base_url': 'ws://{}:6083/'.format(ip_addr)
|
'serial_console_base_url': 'ws://{}:6083/'.format(ip_addr),
|
||||||
}
|
}
|
||||||
|
if hookenv.config('enable-serial-console'):
|
||||||
|
for rel_id in hookenv.relation_ids('dashboard'):
|
||||||
|
ctxt['console_allowed_origins'] = []
|
||||||
|
rel_units = hookenv.related_units(rel_id)
|
||||||
|
if not rel_units:
|
||||||
|
continue
|
||||||
|
|
||||||
|
os_public_hostname = hookenv.relation_get('os-public-hostname',
|
||||||
|
rid=rel_id,
|
||||||
|
app=rel_units[0])
|
||||||
|
if os_public_hostname:
|
||||||
|
ctxt['console_allowed_origins'].append(os_public_hostname)
|
||||||
|
|
||||||
|
vip = hookenv.relation_get('vip',
|
||||||
|
rid=rel_id,
|
||||||
|
app=rel_units[0])
|
||||||
|
if vip:
|
||||||
|
ip_addresses = [ip.strip() for ip in vip.split(' ')]
|
||||||
|
ctxt['console_allowed_origins'] += ip_addresses
|
||||||
|
|
||||||
|
for unit in rel_units:
|
||||||
|
ingress_address = hookenv.ingress_address(rel_id, unit)
|
||||||
|
if ingress_address:
|
||||||
|
ctxt['console_allowed_origins'].append(ingress_address)
|
||||||
|
|
||||||
return ctxt
|
return ctxt
|
||||||
|
|
||||||
|
|
||||||
|
@ -1403,6 +1403,15 @@ def placement_relation_changed(rid=None, unit=None):
|
|||||||
ch_host.service_restart(s)
|
ch_host.service_restart(s)
|
||||||
|
|
||||||
|
|
||||||
|
@hooks.hook('dashboard-relation-joined',
|
||||||
|
'dashboard-relation-changed')
|
||||||
|
def dashboard_relation_changed():
|
||||||
|
"""
|
||||||
|
Gather information from the related openstack-dashboard units
|
||||||
|
"""
|
||||||
|
CONFIGS.write_all()
|
||||||
|
|
||||||
|
|
||||||
@hooks.hook('update-status')
|
@hooks.hook('update-status')
|
||||||
@ch_harden.harden()
|
@ch_harden.harden()
|
||||||
def update_status():
|
def update_status():
|
||||||
|
@ -1763,7 +1763,9 @@ def check_optional_relations(configs):
|
|||||||
if hookenv.relation_ids('ha'):
|
if hookenv.relation_ids('ha'):
|
||||||
try:
|
try:
|
||||||
ch_cluster.get_hacluster_config()
|
ch_cluster.get_hacluster_config()
|
||||||
except Exception:
|
except Exception as ex:
|
||||||
|
hookenv.log("get_hacluster_config exception: %s" % str(ex),
|
||||||
|
hookenv.DEBUG)
|
||||||
return ('blocked',
|
return ('blocked',
|
||||||
'hacluster missing configuration: '
|
'hacluster missing configuration: '
|
||||||
'vip, vip_iface, vip_cidr')
|
'vip, vip_iface, vip_cidr')
|
||||||
@ -1780,6 +1782,12 @@ def check_optional_relations(configs):
|
|||||||
'false, this configuration is only availabe for releases>=Train'
|
'false, this configuration is only availabe for releases>=Train'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if hookenv.config('enable-serial-console'):
|
||||||
|
if not hookenv.relation_ids('dashboard'):
|
||||||
|
return ('blocked',
|
||||||
|
("Required relation 'dashboard' needed when "
|
||||||
|
"enable-serial-console is set to True"))
|
||||||
|
|
||||||
# return 'unknown' as the lowest priority to not clobber an existing
|
# return 'unknown' as the lowest priority to not clobber an existing
|
||||||
# status.
|
# status.
|
||||||
return "unknown", None
|
return "unknown", None
|
||||||
|
@ -45,6 +45,8 @@ requires:
|
|||||||
interface: nova-compute
|
interface: nova-compute
|
||||||
cinder-volume-service:
|
cinder-volume-service:
|
||||||
interface: cinder
|
interface: cinder
|
||||||
|
dashboard:
|
||||||
|
interface: dashboard
|
||||||
quantum-network-service:
|
quantum-network-service:
|
||||||
interface: quantum
|
interface: quantum
|
||||||
neutron-api:
|
neutron-api:
|
||||||
|
6
templates/parts/section-console
Normal file
6
templates/parts/section-console
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{% if console_allowed_origins -%}
|
||||||
|
[console]
|
||||||
|
# List of allowed origins to the console websocket proxy to allow connections
|
||||||
|
# from other origin hostnames.
|
||||||
|
allowed_origins = {{ console_allowed_origins|join(',') }}
|
||||||
|
{% endif -%}
|
@ -193,6 +193,8 @@ html5proxy_port = {{ console_access_port }}
|
|||||||
|
|
||||||
{% include "parts/section-serial-console" %}
|
{% include "parts/section-serial-console" %}
|
||||||
|
|
||||||
|
{% include "parts/section-console" %}
|
||||||
|
|
||||||
{% if memcached_servers %}
|
{% if memcached_servers %}
|
||||||
[cache]
|
[cache]
|
||||||
enabled = true
|
enabled = true
|
||||||
|
@ -517,6 +517,8 @@ class NovaComputeContextTests(CharmTestCase):
|
|||||||
self.test_config.set('enable-serial-console', True)
|
self.test_config.set('enable-serial-console', True)
|
||||||
mock_format_ipv6_address.return_value = None
|
mock_format_ipv6_address.return_value = None
|
||||||
mock_resolve_address.return_value = '10.10.10.1'
|
mock_resolve_address.return_value = '10.10.10.1'
|
||||||
|
|
||||||
|
# no relation to openstack-dashboard:dashboard
|
||||||
ctxt = context.SerialConsoleContext()()
|
ctxt = context.SerialConsoleContext()()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
ctxt,
|
ctxt,
|
||||||
@ -526,6 +528,40 @@ class NovaComputeContextTests(CharmTestCase):
|
|||||||
mock_resolve_address.assert_called_with(
|
mock_resolve_address.assert_called_with(
|
||||||
endpoint_type=context.ch_ip.PUBLIC)
|
endpoint_type=context.ch_ip.PUBLIC)
|
||||||
|
|
||||||
|
# generated context when related to openstack-dashboard:dashboard
|
||||||
|
fake_relation_ids = {
|
||||||
|
'dashboard': ['dashboard:1'],
|
||||||
|
}
|
||||||
|
self.relation_ids.side_effect = fake_relation_ids.get
|
||||||
|
fake_related_units = {'dashboard:1': ['openstack-dashboard/0']}
|
||||||
|
self.related_units.side_effect = fake_related_units.get
|
||||||
|
|
||||||
|
def fake_relation_get(attribute=None, rid=None, unit=None, app=None):
|
||||||
|
data = {
|
||||||
|
'dashboard:1': {
|
||||||
|
'openstack-dashboard/0': {
|
||||||
|
'os-public-hostname': 'myhostname',
|
||||||
|
'vip': '1.2.3.4',
|
||||||
|
'ingress-address': '10.20.30.40',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if attribute:
|
||||||
|
return data[rid][unit or app][attribute]
|
||||||
|
else:
|
||||||
|
return data[rid][unit or app]
|
||||||
|
|
||||||
|
self.relation_get.side_effect = fake_relation_get
|
||||||
|
|
||||||
|
ctxt = context.SerialConsoleContext()()
|
||||||
|
self.assertEqual(
|
||||||
|
ctxt,
|
||||||
|
{'serial_console_base_url': 'ws://10.10.10.1:6083/',
|
||||||
|
'enable_serial_console': 'true',
|
||||||
|
'console_allowed_origins': ['myhostname', '1.2.3.4',
|
||||||
|
'10.20.30.40']}
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(context, 'ch_cluster')
|
@mock.patch.object(context, 'ch_cluster')
|
||||||
@mock.patch('os.path.exists')
|
@mock.patch('os.path.exists')
|
||||||
@mock.patch('charmhelpers.contrib.openstack.ip.resolve_address')
|
@mock.patch('charmhelpers.contrib.openstack.ip.resolve_address')
|
||||||
|
@ -1947,3 +1947,31 @@ class NovaCCUtilsTests(CharmTestCase):
|
|||||||
call(['nova-manage', 'cell_v2', 'update_cell',
|
call(['nova-manage', 'cell_v2', 'update_cell',
|
||||||
'--cell_uuid', 'cell1uuid']),
|
'--cell_uuid', 'cell1uuid']),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@patch('charmhelpers.core.hookenv.relation_ids')
|
||||||
|
def test_check_optional_relations(self, relation_ids):
|
||||||
|
self.get_os_codename_install_source.return_value = 'ussuri'
|
||||||
|
self.os_release.return_value = 'ussuri'
|
||||||
|
|
||||||
|
fake_relation_ids = {'placement': ['placement:0'],
|
||||||
|
'ha': ['ha:1'],
|
||||||
|
'dashboard': []}
|
||||||
|
relation_ids.side_effect = fake_relation_ids.get
|
||||||
|
self.test_config.set('enable-serial-console', True)
|
||||||
|
(status, workload_msg) = utils.check_optional_relations(None)
|
||||||
|
|
||||||
|
self.assertEqual('blocked', status)
|
||||||
|
self.assertEqual(('hacluster missing configuration: vip, vip_iface, '
|
||||||
|
'vip_cidr'),
|
||||||
|
workload_msg)
|
||||||
|
with patch.object(utils.ch_cluster,
|
||||||
|
'get_hacluster_config') as get_hacluster_config: # noqa
|
||||||
|
(status, workload_msg) = utils.check_optional_relations(None)
|
||||||
|
self.assertEqual('blocked', status)
|
||||||
|
self.assertEqual(("Required relation 'dashboard' needed when "
|
||||||
|
"enable-serial-console is set to True"),
|
||||||
|
workload_msg)
|
||||||
|
fake_relation_ids['dashboard'] = ['dashboard:2']
|
||||||
|
(status, workload_msg) = utils.check_optional_relations(None)
|
||||||
|
self.assertEqual('unknown', status)
|
||||||
|
self.assertEqual(None, workload_msg)
|
||||||
|
Loading…
Reference in New Issue
Block a user