diff --git a/README.rst b/README.rst index ef3b392e..f269d56f 100644 --- a/README.rst +++ b/README.rst @@ -120,6 +120,12 @@ openstack-compute::serialproxy - Installs and configures the serialproxy service for serial console access to VMs +openstack-compute::spiceproxy +--------------------------- + +- Installs and configures the spicehtml5proxy service for console access + to VMs + openstack-compute::vncproxy --------------------------- diff --git a/attributes/default.rb b/attributes/default.rb index 2cc6bff6..9820d20b 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -16,6 +16,11 @@ default['openstack']['compute']['service_role'] = 'admin' default['openstack']['compute']['user'] = 'nova' default['openstack']['compute']['group'] = 'nova' +# If set to 'spice' or 'vnc' the cookbook will attempt to automatically +# enable the right type; any other type will require appropriate attributes +# to be set by the user. +default['openstack']['compute']['console_type'] = 'vnc' + # Logging stuff default['openstack']['compute']['syslog']['use'] = false default['openstack']['compute']['syslog']['facility'] = 'LOG_LOCAL1' @@ -66,6 +71,8 @@ when 'rhel' # :pragma-foodcritic: ~FC024 - won't fix this 'compute_conductor_service' => 'openstack-nova-conductor', 'compute_vncproxy_packages' => ['openstack-nova-novncproxy'], 'compute_vncproxy_service' => 'openstack-nova-novncproxy', + 'compute_spiceproxy_packages' => %w(openstack-nova-spicehtml5proxy spice-html5), + 'compute_spiceproxy_service' => 'openstack-nova-spicehtml5proxy', 'compute_serialproxy_packages' => ['openstack-nova-serialproxy'], 'compute_serialproxy_service' => 'openstack-nova-serialproxy', 'libvirt_packages' => %w(libvirt device-mapper python-libguestfs), @@ -95,8 +102,20 @@ when 'debian' 'compute_conductor_packages' => %w(python3-nova nova-conductor), 'compute_conductor_service' => 'nova-conductor', # Websockify is needed due to https://bugs.launchpad.net/ubuntu/+source/nova/+bug/1076442 - 'compute_vncproxy_packages' => %w(novnc websockify python3-nova nova-novncproxy), + 'compute_vncproxy_packages' => + if platform?('ubuntu') + %w(novnc websockify python3-nova nova-novncproxy) + else + %w(nova-consoleproxy) + end, 'compute_vncproxy_service' => 'nova-novncproxy', + 'compute_spiceproxy_packages' => + if platform?('ubuntu') + %w(nova-spiceproxy spice-html5) + else + %w(nova-consoleproxy) + end, + 'compute_spiceproxy_service' => platform?('ubuntu') ? 'nova-spiceproxy' : 'nova-spicehtml5proxy', 'compute_serialproxy_packages' => %w(python3-nova nova-serialproxy), 'compute_serialproxy_service' => 'nova-serialproxy', 'libvirt_packages' => %w(libvirt-bin python3-guestfs), @@ -121,6 +140,8 @@ default['openstack']['compute']['misc_paste'] = nil compute-metadata-api compute-novnc compute-vnc + compute-spicehtml5 + compute-spice ).each do |service| default['openstack']['bind_service']['all'][service]['host'] = '127.0.0.1' %w(public internal).each do |type| @@ -135,6 +156,9 @@ end # The OpenStack Compute (Nova) novnc endpoint default['openstack']['endpoints'][type]['compute-novnc']['port'] = '6080' default['openstack']['endpoints'][type]['compute-novnc']['path'] = '/vnc_auto.html' + # The OpenStack Compute (Nova) spicehtml5 endpoint + default['openstack']['endpoints'][type]['compute-spicehtml5']['port'] = '6082' + default['openstack']['endpoints'][type]['compute-spicehtml5']['path'] = '/spice_auto.html' # The OpenStack Compute (Nova) metadata API endpoint default['openstack']['endpoints'][type]['compute-metadata-api']['port'] = '8775' default['openstack']['endpoints'][type]['compute-metadata-api']['path'] = '' @@ -146,10 +170,13 @@ end end default['openstack']['bind_service']['all']['compute-serial-proxy']['host'] = '127.0.0.1' default['openstack']['bind_service']['all']['compute-vnc-proxy']['host'] = '127.0.0.1' +default['openstack']['bind_service']['all']['compute-spice-proxy']['host'] = '127.0.0.1' default['openstack']['bind_service']['all']['compute-serial-console']['host'] = '127.0.0.1' default['openstack']['bind_service']['all']['compute-vnc']['port'] = '6081' +default['openstack']['bind_service']['all']['compute-spice']['port'] = '6081' default['openstack']['bind_service']['all']['compute-serial-proxy']['port'] = '6081' default['openstack']['bind_service']['all']['compute-novnc']['port'] = '6080' +default['openstack']['bind_service']['all']['compute-spicehtml5']['port'] = '6082' default['openstack']['bind_service']['all']['compute-metadata-api']['host'] = '127.0.0.1' default['openstack']['bind_service']['all']['compute-metadata-api']['port'] = '8775' default['openstack']['bind_service']['all']['compute-api']['host'] = '127.0.0.1' diff --git a/recipes/nova-common.rb b/recipes/nova-common.rb index ef597a2d..46fdaaf0 100644 --- a/recipes/nova-common.rb +++ b/recipes/nova-common.rb @@ -104,6 +104,13 @@ vnc_bind = node['openstack']['bind_service']['all']['compute-vnc'] vnc_bind_address = bind_address vnc_bind vnc_proxy_bind = node['openstack']['bind_service']['all']['compute-vnc-proxy'] vnc_proxy_bind_address = bind_address vnc_proxy_bind +spicehtml5_endpoint = public_endpoint 'compute-spicehtml5' +spicehtml5_bind = node['openstack']['bind_service']['all']['compute-spicehtml5'] +spicehtml5_bind_address = bind_address spicehtml5_bind +spice_bind = node['openstack']['bind_service']['all']['compute-spice'] +spice_bind_address = bind_address spice_bind +spice_proxy_bind = node['openstack']['bind_service']['all']['compute-spice-proxy'] +spice_proxy_bind_address = bind_address spice_proxy_bind compute_api_endpoint = internal_endpoint 'compute-api' compute_metadata_api_bind = node['openstack']['bind_service']['all']['compute-metadata-api'] compute_metadata_api_bind_address = bind_address compute_metadata_api_bind @@ -115,6 +122,7 @@ image_endpoint = internal_endpoint 'image_api' Chef::Log.debug("openstack-compute::nova-common:identity_endpoint|#{identity_endpoint}") Chef::Log.debug("openstack-compute::nova-common:novnc_endpoint|#{novnc_endpoint}") +Chef::Log.debug("openstack-compute::nova-common:spicehtml5_endpoint|#{spicehtml5_endpoint}") Chef::Log.debug("openstack-compute::nova-common:compute_api_endpoint|#{compute_api_endpoint}") Chef::Log.debug("openstack-compute::nova-common:network_endpoint|#{network_endpoint}") Chef::Log.debug("openstack-compute::nova-common:image_endpoint|#{image_endpoint}") @@ -148,11 +156,7 @@ node.default['openstack']['compute']['conf'].tap do |conf| conf['DEFAULT']['metadata_listen'] = compute_metadata_api_bind_address conf['DEFAULT']['metadata_listen_port'] = compute_metadata_api_bind['port'] - conf['vnc']['novncproxy_base_url'] = novnc_endpoint.to_s - conf['vnc']['novncproxy_host'] = novnc_bind_address - conf['vnc']['novncproxy_port'] = novnc_bind['port'] - conf['vnc']['server_listen'] = vnc_bind_address - conf['vnc']['server_proxyclient_address'] = vnc_proxy_bind_address + unless memcache_servers.empty? # Need to set the backend explicitly, see LP bug #1572062 conf['cache']['backend'] = 'oslo_cache.memcache_pool' @@ -182,6 +186,29 @@ node.default['openstack']['compute']['conf'].tap do |conf| # [serial_console] section conf['serial_console']['base_url'] = "#{serial_proxy_endpoint.scheme}://#{serial_proxy_endpoint.host}:#{serial_proxy_endpoint.port}" conf['serial_console']['proxyclient_address'] = serial_console_bind_address + + # Non-serial consoles + case node['openstack']['compute']['console_type'] + when 'spice' + conf['vnc']['enabled'] = false + conf['spice']['enabled'] = true + conf['spice']['html5proxy_base_url'] = spicehtml5_endpoint.to_s + conf['spice']['html5proxy_host'] = spicehtml5_bind_address + conf['spice']['html5proxy_port'] = spicehtml5_bind['port'] + conf['spice']['server_listen'] = spice_bind_address + conf['spice']['server_proxyclient_address'] = spice_proxy_bind_address + when 'vnc' + # No need to explicitly disable other types, according to Nova documentation + # VNC takes precedence if enabled. + conf['vnc']['enabled'] = true + conf['vnc']['novncproxy_base_url'] = novnc_endpoint.to_s + conf['vnc']['novncproxy_host'] = novnc_bind_address + conf['vnc']['novncproxy_port'] = novnc_bind['port'] + conf['vnc']['server_listen'] = vnc_bind_address + conf['vnc']['server_proxyclient_address'] = vnc_proxy_bind_address + else + Chef::Log.debug("openstack-compute::nova-common:console_type #{node['openstack']['compute']['console_type']} unknown, no auto-configuration") + end end # merge all config options and secrets to be used in nova.conf diff --git a/recipes/spiceproxy.rb b/recipes/spiceproxy.rb new file mode 100644 index 00000000..d4ccc08e --- /dev/null +++ b/recipes/spiceproxy.rb @@ -0,0 +1,39 @@ +# +# Cookbook:: openstack-compute +# Recipe:: spiceproxy +# +# Copyright:: 2012, Rackspace US, Inc. +# Copyright:: 2013, Craig Tracey +# Copyright:: 2020, Oregon State University +# Copyright:: 2021, Marek Szuba +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'openstack-compute::nova-common' + +platform_options = node['openstack']['compute']['platform'] + +package platform_options['compute_spiceproxy_packages'] do + options platform_options['package_overrides'] + action :upgrade +end + +proxy_service = platform_options['compute_spiceproxy_service'] + +service proxy_service do + service_name proxy_service + supports status: true, restart: true + action [:enable, :start] + subscribes :restart, 'template[/etc/nova/nova.conf]' +end diff --git a/spec/nova-common_spec.rb b/spec/nova-common_spec.rb index a36caca9..31cd2f04 100644 --- a/spec/nova-common_spec.rb +++ b/spec/nova-common_spec.rb @@ -242,6 +242,7 @@ describe 'openstack-compute::nova-common' do it '[vnc]' do [ + /^enabled = true$/, %r{^novncproxy_base_url = http://127.0.0.1:6080/vnc_auto.html$}, /^novncproxy_host = 127.0.0.1$/, /^novncproxy_port = 6080$/, @@ -252,6 +253,35 @@ describe 'openstack-compute::nova-common' do end end + it '[spice]' do + expect(chef_run).not_to render_config_file(file.name).with_section_content('spice', /^enabled = true$/) + end + + context 'with SPICE consoles' do + cached(:chef_run) do + node.override['openstack']['compute']['console_type'] = 'spice' + runner.converge(described_recipe) + end + + it 'disables VNC support' do + expect(chef_run).to render_config_file(file.name) + .with_section_content('vnc', /^enabled = false$/) + end + + it 'sets SPICE options correctly' do + [ + /^enabled = true$/, + %r{^html5proxy_base_url = http://127.0.0.1:6082/spice_auto.html$}, + /^html5proxy_host = 127.0.0.1$/, + /^html5proxy_port = 6082$/, + /^server_listen = 127.0.0.1$/, + /^server_proxyclient_address = 127.0.0.1$/, + ].each do |line| + expect(chef_run).to render_config_file(file.name).with_section_content('spice', line) + end + end + end + context 'has a os_region_name setting' do cached(:chef_run) do node.override['openstack']['node'] = 'RegionOne' diff --git a/spec/spiceproxy-redhat_spec.rb b/spec/spiceproxy-redhat_spec.rb new file mode 100644 index 00000000..a1f67095 --- /dev/null +++ b/spec/spiceproxy-redhat_spec.rb @@ -0,0 +1,26 @@ +require_relative 'spec_helper' + +describe 'openstack-compute::spiceproxy' do + describe 'redhat' do + let(:runner) { ChefSpec::SoloRunner.new(REDHAT_OPTS) } + let(:node) { runner.node } + cached(:chef_run) { runner.converge(described_recipe) } + + include_context 'compute_stubs' + include_examples 'expect_runs_nova_common_recipe' + include_examples 'expect_creates_nova_state_dir' + include_examples 'expect_creates_nova_lock_dir' + + it do + expect(chef_run).to upgrade_package %w(openstack-nova-spicehtml5proxy spice-html5) + end + + it 'starts nova spicehtml5proxy' do + expect(chef_run).to start_service('openstack-nova-spicehtml5proxy') + end + + it 'starts nova spicehtml5proxy on boot' do + expect(chef_run).to enable_service('openstack-nova-spicehtml5proxy') + end + end +end diff --git a/spec/spiceproxy_spec.rb b/spec/spiceproxy_spec.rb new file mode 100644 index 00000000..d099ba89 --- /dev/null +++ b/spec/spiceproxy_spec.rb @@ -0,0 +1,26 @@ +require_relative 'spec_helper' + +describe 'openstack-compute::spiceproxy' do + describe 'ubuntu' do + let(:runner) { ChefSpec::SoloRunner.new(UBUNTU_OPTS) } + let(:node) { runner.node } + cached(:chef_run) { runner.converge(described_recipe) } + + include_context 'compute_stubs' + include_examples 'expect_runs_nova_common_recipe' + include_examples 'expect_creates_nova_state_dir' + include_examples 'expect_creates_nova_lock_dir' + + it do + expect(chef_run).to upgrade_package %w(nova-spiceproxy spice-html5) + end + + it 'starts nova spiceproxy' do + expect(chef_run).to start_service('nova-spiceproxy') + end + + it 'starts nova spiceproxy on boot' do + expect(chef_run).to enable_service('nova-spiceproxy') + end + end +end