Merge lp:~xianghui/charms/trusty/nova-cloud-controller/lp1476455 into lp:~openstack-charmers-archive/charms/trusty/nova-cloud-controller/next

Proposed by Xiang Hui
Status: Merged
Approved by: Edward Hope-Morley
Approved revision: 187
Merged at revision: 178
Proposed branch: lp:~xianghui/charms/trusty/nova-cloud-controller/lp1476455
Merge into: lp:~openstack-charmers-archive/charms/trusty/nova-cloud-controller/next
Diff against target: 442 lines (+278/-10)
11 files modified
config.yaml (+14/-0)
hooks/nova_cc_context.py (+56/-0)
hooks/nova_cc_hooks.py (+23/-4)
hooks/nova_cc_utils.py (+2/-1)
templates/icehouse/nova.conf (+2/-0)
templates/juno/nova.conf (+2/-0)
templates/kilo/nova.conf (+2/-0)
templates/parts/novnc (+3/-0)
templates/parts/spice (+4/-0)
unit_tests/test_nova_cc_contexts.py (+148/-0)
unit_tests/test_nova_cc_hooks.py (+22/-5)
To merge this branch: bzr merge lp:~xianghui/charms/trusty/nova-cloud-controller/lp1476455
Reviewer Review Type Date Requested Status
OpenStack Charmers Pending
Edward Hope-Morley Pending
Review via email: mp+265759@code.launchpad.net

This proposal supersedes a proposal from 2015-07-22.

Description of the change

Support nova console session to be encrypted without nova API SSL.

To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal

charm_lint_check #6615 nova-cloud-controller-next for xianghui mp265496
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/6615/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal

charm_unit_test #6247 nova-cloud-controller-next for xianghui mp265496
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/6247/

Revision history for this message
Edward Hope-Morley (hopem) wrote : Posted in a previous version of this proposal

See inline

review: Needs Fixing
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal

charm_lint_check #6618 nova-cloud-controller-next for xianghui mp265496
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/6618/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal

charm_unit_test #6250 nova-cloud-controller-next for xianghui mp265496
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/6250/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal

charm_lint_check #6626 nova-cloud-controller-next for xianghui mp265496
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/6626/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal

charm_unit_test #6253 nova-cloud-controller-next for xianghui mp265496
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/6253/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal

charm_amulet_test #5255 nova-cloud-controller-next for xianghui mp265496
    AMULET FAIL: amulet-test failed

AMULET Results (max last 2 lines):
make: *** [test] Error 1
ERROR:root:Make target returned non-zero.

Full amulet test output: http://paste.ubuntu.com/11921798/
Build: http://10.245.162.77:8080/job/charm_amulet_test/5255/

Revision history for this message
Edward Hope-Morley (hopem) wrote : Posted in a previous version of this proposal

This all lgtm apart from one small comment. I'm gonna have a go at deploying it with your bundle before I +1 it tho. I also see that amulet failed but not sure if that is related.

Revision history for this message
Xiang Hui (xianghui) : Posted in a previous version of this proposal
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #6781 nova-cloud-controller-next for xianghui mp265759
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/6781/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #6408 nova-cloud-controller-next for xianghui mp265759
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/6408/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #5278 nova-cloud-controller-next for xianghui mp265759
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/5278/

Revision history for this message
Edward Hope-Morley (hopem) : Posted in a previous version of this proposal
187. By Xiang Hui

decode before write file

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #6886 nova-cloud-controller-next for xianghui mp265759
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/6886/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #6413 nova-cloud-controller-next for xianghui mp265759
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/6413/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #5328 nova-cloud-controller-next for xianghui mp265759
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/5328/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'config.yaml'
2--- config.yaml 2015-07-10 14:14:23 +0000
3+++ config.yaml 2015-07-24 10:07:27 +0000
4@@ -381,3 +381,17 @@
5
6 If memcached is being used to store the tokens, then it's recommended to
7 change this configuration to False.
8+ console-access-ssl-cert:
9+ type: string
10+ default:
11+ description: |
12+ Used for encrypting console connections. This differs from the SSL certificate
13+ used for API endpoints and is used for console access session only. Setting
14+ this value along with console-access-ssl-key will enable encrypted console
15+ sessions. This has nothing to do with Nova API SSL and can be used
16+ independently. This can be used in conjunction with console-access-protocol
17+ set to 'novnc' or 'spice'.
18+ console-access-ssl-key:
19+ type: string
20+ default:
21+ description: SSL key to use with certificate specified as console-access-ssl-cert.
22
23=== modified file 'hooks/nova_cc_context.py'
24--- hooks/nova_cc_context.py 2015-04-08 12:10:09 +0000
25+++ hooks/nova_cc_context.py 2015-07-24 10:07:27 +0000
26@@ -1,5 +1,6 @@
27 import os
28
29+from base64 import b64decode
30 from charmhelpers.core.hookenv import (
31 config,
32 relation_ids,
33@@ -9,6 +10,8 @@
34 related_units,
35 relations_for_id,
36 relation_get,
37+ DEBUG,
38+ unit_get,
39 )
40 from charmhelpers.fetch import (
41 apt_install,
42@@ -23,6 +26,7 @@
43 determine_apache_port,
44 determine_api_port,
45 https,
46+ is_clustered,
47 )
48 from charmhelpers.contrib.network.ip import (
49 format_ipv6_addr,
50@@ -30,6 +34,7 @@
51 from charmhelpers.contrib.openstack.ip import (
52 resolve_address,
53 INTERNAL,
54+ PUBLIC,
55 )
56
57
58@@ -350,3 +355,54 @@
59 ctxt['ssl_key'] = key
60
61 return ctxt
62+
63+
64+class ConsoleSSLContext(context.OSContextGenerator):
65+ interfaces = []
66+
67+ def __call__(self):
68+ ctxt = {}
69+ from nova_cc_utils import console_attributes
70+
71+ if config('console-access-ssl-cert') \
72+ and config('console-access-ssl-key') \
73+ and config('console-access-protocol'):
74+ ssl_dir = '/etc/nova/ssl/'
75+ if not os.path.exists(ssl_dir):
76+ log('Creating %s.' % ssl_dir, level=DEBUG)
77+ os.mkdir(ssl_dir)
78+
79+ cert_path = os.path.join(ssl_dir, 'nova_cert.pem')
80+ decode_ssl_cert = b64decode(config('console-access-ssl-cert'))
81+
82+ key_path = os.path.join(ssl_dir, 'nova_key.pem')
83+ decode_ssl_key = b64decode(config('console-access-ssl-key'))
84+
85+ with open(cert_path, 'w') as fh:
86+ fh.write(decode_ssl_cert)
87+ with open(key_path, 'w') as fh:
88+ fh.write(decode_ssl_key)
89+
90+ ctxt['ssl_only'] = True
91+ ctxt['ssl_cert'] = cert_path
92+ ctxt['ssl_key'] = key_path
93+
94+ if is_clustered():
95+ ip_addr = resolve_address(endpoint_type=PUBLIC)
96+ else:
97+ ip_addr = unit_get('private-address')
98+
99+ ip_addr = format_ipv6_addr(ip_addr) or ip_addr
100+
101+ _proto = config('console-access-protocol')
102+ url = "https://%s:%s%s" % (
103+ ip_addr,
104+ console_attributes('proxy-port', proto=_proto),
105+ console_attributes('proxy-page', proto=_proto))
106+
107+ if _proto == 'novnc':
108+ ctxt['novncproxy_base_url'] = url
109+ elif _proto == 'spice':
110+ ctxt['html5proxy_base_url'] = url
111+
112+ return ctxt
113
114=== modified file 'hooks/nova_cc_hooks.py'
115--- hooks/nova_cc_hooks.py 2015-06-12 13:03:50 +0000
116+++ hooks/nova_cc_hooks.py 2015-07-24 10:07:27 +0000
117@@ -106,13 +106,15 @@
118 from charmhelpers.contrib.hahelpers.cluster import (
119 is_elected_leader,
120 get_hacluster_config,
121+ https,
122 )
123
124 from charmhelpers.payload.execd import execd_preinstall
125
126 from charmhelpers.contrib.openstack.ip import (
127 canonical_url,
128- PUBLIC, INTERNAL, ADMIN
129+ PUBLIC, INTERNAL, ADMIN,
130+ resolve_address,
131 )
132
133 from charmhelpers.contrib.network.ip import (
134@@ -120,7 +122,8 @@
135 get_netmask_for_address,
136 get_address_in_network,
137 get_ipv6_addr,
138- is_ipv6
139+ is_ipv6,
140+ format_ipv6_addr,
141 )
142
143 from charmhelpers.contrib.openstack.context import ADDRESS_TYPES
144@@ -511,10 +514,26 @@
145 return {}
146 rel_settings['console_keymap'] = config('console-keymap')
147 rel_settings['console_access_protocol'] = proto
148+
149+ console_ssl = False
150+ if config('console-access-ssl-cert') and config('console-access-ssl-key'):
151+ console_ssl = True
152+
153 if config('console-proxy-ip') == 'local':
154- proxy_base_addr = canonical_url(CONFIGS, PUBLIC)
155+ if console_ssl:
156+ address = resolve_address(endpoint_type=PUBLIC)
157+ address = format_ipv6_addr(address) or address
158+ proxy_base_addr = 'https://%s' % address
159+ else:
160+ # canonical_url will only return 'https:' if API SSL are enabled.
161+ proxy_base_addr = canonical_url(CONFIGS, PUBLIC)
162 else:
163- proxy_base_addr = "http://" + config('console-proxy-ip')
164+ if console_ssl or https():
165+ schema = "https"
166+ else:
167+ schema = "http"
168+ proxy_base_addr = "%s://%s" % (schema, config('console-proxy-ip'))
169+
170 if proto == 'vnc':
171 protocols = ['novnc', 'xvpvnc']
172 else:
173
174=== modified file 'hooks/nova_cc_utils.py'
175--- hooks/nova_cc_utils.py 2015-07-16 20:51:15 +0000
176+++ hooks/nova_cc_utils.py 2015-07-24 10:07:27 +0000
177@@ -194,7 +194,8 @@
178 nova_cc_context.NovaIPv6Context(),
179 nova_cc_context.NeutronCCContext(),
180 nova_cc_context.NovaConfigContext(),
181- nova_cc_context.InstanceConsoleContext()],
182+ nova_cc_context.InstanceConsoleContext(),
183+ nova_cc_context.ConsoleSSLContext()],
184 }),
185 (NOVA_API_PASTE, {
186 'services': [s for s in BASE_SERVICES if 'api' in s],
187
188=== modified file 'templates/icehouse/nova.conf'
189--- templates/icehouse/nova.conf 2015-04-10 02:39:10 +0000
190+++ templates/icehouse/nova.conf 2015-07-24 10:07:27 +0000
191@@ -165,3 +165,5 @@
192
193 [conductor]
194 workers = {{ workers }}
195+
196+{% include "parts/spice" %}
197
198=== modified file 'templates/juno/nova.conf'
199--- templates/juno/nova.conf 2015-04-13 08:49:59 +0000
200+++ templates/juno/nova.conf 2015-07-24 10:07:27 +0000
201@@ -160,3 +160,5 @@
202
203 [conductor]
204 workers = {{ workers }}
205+
206+{% include "parts/spice" %}
207
208=== modified file 'templates/kilo/nova.conf'
209--- templates/kilo/nova.conf 2015-04-13 08:49:59 +0000
210+++ templates/kilo/nova.conf 2015-07-24 10:07:27 +0000
211@@ -155,3 +155,5 @@
212
213 [oslo_concurrency]
214 lock_path=/var/lock/nova
215+
216+{% include "parts/spice" %}
217
218=== modified file 'templates/parts/novnc'
219--- templates/parts/novnc 2015-04-08 12:10:09 +0000
220+++ templates/parts/novnc 2015-07-24 10:07:27 +0000
221@@ -7,3 +7,6 @@
222 {% if ssl_key -%}
223 key={{ ssl_key }}
224 {% endif %}
225+{% if novncproxy_base_url -%}
226+novncproxy_base_url={{ novncproxy_base_url }}
227+{% endif %}
228
229=== added file 'templates/parts/spice'
230--- templates/parts/spice 1970-01-01 00:00:00 +0000
231+++ templates/parts/spice 2015-07-24 10:07:27 +0000
232@@ -0,0 +1,4 @@
233+[spice]
234+{% if html5proxy_base_url -%}
235+html5proxy_base_url = {{ html5proxy_base_url }}
236+{% endif -%}
237
238=== modified file 'unit_tests/test_nova_cc_contexts.py'
239--- unit_tests/test_nova_cc_contexts.py 2015-06-11 13:33:42 +0000
240+++ unit_tests/test_nova_cc_contexts.py 2015-07-24 10:07:27 +0000
241@@ -148,3 +148,151 @@
242 self.assertTrue(context.use_local_neutron_api())
243 self.related_units.return_value = ['unit/0']
244 self.assertFalse(context.use_local_neutron_api())
245+
246+ @mock.patch.object(context, 'config')
247+ def test_console_access_ssl_disabled(self, mock_config):
248+ config = {'console-access-ssl_cert': 'LS0tLS1CRUdJTiBDRV',
249+ 'console-access-ssl_key': 'LS0tLS1CRUdJTiBQUk'}
250+ mock_config.side_effect = lambda key: config.get(key)
251+
252+ ctxt = context.ConsoleSSLContext()()
253+ self.assertEqual(ctxt, None)
254+
255+ config = {'console-access-ssl_cert': None,
256+ 'console-access-ssl_key': None}
257+ mock_config.side_effect = lambda key: config.get(key)
258+
259+ ctxt = context.ConsoleSSLContext()()
260+ self.assertEqual(ctxt, None)
261+
262+ config = {'console-access-protocol': 'novnc',
263+ 'console-access-ssl_cert': None,
264+ 'console-access-ssl_key': None}
265+ mock_config.side_effect = lambda key: config.get(key)
266+
267+ ctxt = context.ConsoleSSLContext()()
268+ self.assertEqual(ctxt, None)
269+
270+ @mock.patch('__builtin__.open')
271+ @mock.patch('os.path.exists')
272+ @mock.patch.object(context, 'config')
273+ @mock.patch.object(context, 'unit_get')
274+ @mock.patch.object(context, 'is_clustered')
275+ @mock.patch.object(context, 'resolve_address')
276+ @mock.patch.object(context, 'b64decode')
277+ def test_noVNC_ssl_enabled(self, mock_b64decode,
278+ mock_resolve_address,
279+ mock_is_clustered, mock_unit_get,
280+ mock_config, mock_exists, mock_open):
281+ config = {'console-access-ssl-cert': 'LS0tLS1CRUdJTiBDRV',
282+ 'console-access-ssl-key': 'LS0tLS1CRUdJTiBQUk',
283+ 'console-access-protocol': 'novnc'}
284+ mock_config.side_effect = lambda key: config.get(key)
285+ mock_exists.return_value = True
286+ mock_unit_get.return_value = '127.0.0.1'
287+ mock_is_clustered.return_value = True
288+ mock_resolve_address.return_value = '10.5.100.1'
289+ mock_b64decode.return_value = 'decode_success'
290+
291+ mock_open.return_value.__enter__ = lambda s: s
292+ mock_open.return_value.__exit__ = mock.Mock()
293+
294+ ctxt = context.ConsoleSSLContext()()
295+ self.assertTrue(ctxt['ssl_only'])
296+ self.assertEqual(ctxt['ssl_cert'], '/etc/nova/ssl/nova_cert.pem')
297+ self.assertEqual(ctxt['ssl_key'], '/etc/nova/ssl/nova_key.pem')
298+ self.assertEqual(ctxt['novncproxy_base_url'],
299+ 'https://10.5.100.1:6080/vnc_auto.html')
300+
301+ @mock.patch('__builtin__.open')
302+ @mock.patch('os.path.exists')
303+ @mock.patch.object(context, 'config')
304+ @mock.patch.object(context, 'unit_get')
305+ @mock.patch.object(context, 'is_clustered')
306+ @mock.patch.object(context, 'resolve_address')
307+ @mock.patch.object(context, 'b64decode')
308+ def test_noVNC_ssl_enabled_no_cluster(self, mock_b64decode,
309+ mock_resolve_address,
310+ mock_is_clustered, mock_unit_get,
311+ mock_config, mock_exists, mock_open):
312+ config = {'console-access-ssl-cert': 'LS0tLS1CRUdJTiBDRV',
313+ 'console-access-ssl-key': 'LS0tLS1CRUdJTiBQUk',
314+ 'console-access-protocol': 'novnc'}
315+ mock_config.side_effect = lambda key: config.get(key)
316+ mock_exists.return_value = True
317+ mock_unit_get.return_value = '10.5.0.1'
318+ mock_is_clustered.return_value = False
319+ mock_b64decode.return_value = 'decode_success'
320+
321+ mock_open.return_value.__enter__ = lambda s: s
322+ mock_open.return_value.__exit__ = mock.Mock()
323+
324+ ctxt = context.ConsoleSSLContext()()
325+ self.assertTrue(ctxt['ssl_only'])
326+ self.assertEqual(ctxt['ssl_cert'], '/etc/nova/ssl/nova_cert.pem')
327+ self.assertEqual(ctxt['ssl_key'], '/etc/nova/ssl/nova_key.pem')
328+ self.assertEqual(ctxt['novncproxy_base_url'],
329+ 'https://10.5.0.1:6080/vnc_auto.html')
330+
331+ @mock.patch('__builtin__.open')
332+ @mock.patch('os.path.exists')
333+ @mock.patch.object(context, 'config')
334+ @mock.patch.object(context, 'unit_get')
335+ @mock.patch.object(context, 'is_clustered')
336+ @mock.patch.object(context, 'resolve_address')
337+ @mock.patch.object(context, 'b64decode')
338+ def test_spice_html5_ssl_enabled(self, mock_b64decode,
339+ mock_resolve_address,
340+ mock_is_clustered, mock_unit_get,
341+ mock_config, mock_exists, mock_open):
342+ config = {'console-access-ssl-cert': 'LS0tLS1CRUdJTiBDRV',
343+ 'console-access-ssl-key': 'LS0tLS1CRUdJTiBQUk',
344+ 'console-access-protocol': 'spice'}
345+ mock_config.side_effect = lambda key: config.get(key)
346+ mock_exists.return_value = True
347+ mock_unit_get.return_value = '127.0.0.1'
348+ mock_is_clustered.return_value = True
349+ mock_resolve_address.return_value = '10.5.100.1'
350+ mock_b64decode.return_value = 'decode_success'
351+
352+ mock_open.return_value.__enter__ = lambda s: s
353+ mock_open.return_value.__exit__ = mock.Mock()
354+
355+ ctxt = context.ConsoleSSLContext()()
356+ self.assertTrue(ctxt['ssl_only'])
357+ self.assertEqual(ctxt['ssl_cert'], '/etc/nova/ssl/nova_cert.pem')
358+ self.assertEqual(ctxt['ssl_key'], '/etc/nova/ssl/nova_key.pem')
359+ self.assertEqual(ctxt['html5proxy_base_url'],
360+ 'https://10.5.100.1:6082/spice_auto.html')
361+
362+ @mock.patch('__builtin__.open')
363+ @mock.patch('os.path.exists')
364+ @mock.patch.object(context, 'config')
365+ @mock.patch.object(context, 'unit_get')
366+ @mock.patch.object(context, 'is_clustered')
367+ @mock.patch.object(context, 'resolve_address')
368+ @mock.patch.object(context, 'b64decode')
369+ def test_spice_html5_ssl_enabled_no_cluster(self, mock_b64decode,
370+ mock_resolve_address,
371+ mock_is_clustered,
372+ mock_unit_get,
373+ mock_config, mock_exists,
374+ mock_open):
375+ config = {'console-access-ssl-cert': 'LS0tLS1CRUdJTiBDRV',
376+ 'console-access-ssl-key': 'LS0tLS1CRUdJTiBQUk',
377+ 'console-access-protocol': 'spice'}
378+ mock_config.side_effect = lambda key: config.get(key)
379+ mock_exists.return_value = True
380+ mock_unit_get.return_value = '10.5.0.1'
381+ mock_is_clustered.return_value = False
382+ mock_b64decode.return_value = 'decode_success'
383+
384+ mock_open.return_value.__enter__ = lambda s: s
385+ mock_open.return_value.__exit__ = mock.Mock()
386+
387+ ctxt = context.ConsoleSSLContext()()
388+ self.assertTrue(ctxt['ssl_only'])
389+ self.assertEqual(ctxt['ssl_cert'], '/etc/nova/ssl/nova_cert.pem')
390+ self.assertEqual(ctxt['ssl_key'], '/etc/nova/ssl/nova_key.pem')
391+ self.assertEqual(ctxt['html5proxy_base_url'],
392+ 'https://10.5.0.1:6082/spice_auto.html')
393
394=== modified file 'unit_tests/test_nova_cc_hooks.py'
395--- unit_tests/test_nova_cc_hooks.py 2015-06-12 13:03:50 +0000
396+++ unit_tests/test_nova_cc_hooks.py 2015-07-24 10:07:27 +0000
397@@ -681,16 +681,14 @@
398 }
399 self.assertEqual(_con_sets, console_settings)
400
401- @patch.object(hooks, 'canonical_url')
402+ @patch.object(hooks, 'https')
403 @patch.object(utils, 'config')
404- def test_console_settings_explicit_ip(self, _utils_config,
405- _canonical_url):
406+ def test_console_settings_explicit_ip(self, _utils_config, _https):
407 _utils_config.return_value = 'spice'
408+ _https.return_value = False
409 _cc_public_host = "public-host"
410- _cc_private_host = "private-host"
411 self.test_config.set('console-proxy-ip', _cc_public_host)
412 _con_sets = hooks.console_settings()
413- _canonical_url.return_value = 'http://' + _cc_private_host
414 console_settings = {
415 'console_proxy_spice_address': 'http://%s:6082/spice_auto.html' %
416 (_cc_public_host),
417@@ -701,6 +699,25 @@
418 }
419 self.assertEqual(_con_sets, console_settings)
420
421+ @patch.object(hooks, 'https')
422+ @patch.object(utils, 'config')
423+ def test_console_settings_explicit_ip_with_https(self, _utils_config,
424+ _https):
425+ _utils_config.return_value = 'spice'
426+ _https.return_value = True
427+ _cc_public_host = "public-host"
428+ self.test_config.set('console-proxy-ip', _cc_public_host)
429+ _con_sets = hooks.console_settings()
430+ console_settings = {
431+ 'console_proxy_spice_address': 'https://%s:6082/spice_auto.html' %
432+ (_cc_public_host),
433+ 'console_proxy_spice_host': _cc_public_host,
434+ 'console_proxy_spice_port': 6082,
435+ 'console_access_protocol': 'spice',
436+ 'console_keymap': 'en-us'
437+ }
438+ self.assertEqual(_con_sets, console_settings)
439+
440 def test_conditional_neutron_migration(self):
441 self.os_release.return_value = 'juno'
442 self.services.return_value = ['neutron-server']

Subscribers

People subscribed via source and target branches