Configure migration SSH tunnel
authorOliver Walsh <owalsh@redhat.com>
Tue, 28 Mar 2017 15:02:18 +0000 (16:02 +0100)
committerOliver Walsh <owalsh@redhat.com>
Fri, 21 Apr 2017 01:02:04 +0000 (01:02 +0000)
This patch configures SSH tunneling for nova cold-migration and reuses the
tunnel for libvirt live-migration unless TLS has been enabled.

Change-Id: I367757cbe8757d11943af7e41af620f9ce919a06
Depends-On: Iac1763761c652bed637cb7cf85bc12347b5fe7ec
(cherry picked from commit ccbcd11276c7bc3ffc8f013d9a5b2d3944bf76cf)

manifests/profile/base/nova.pp
releasenotes/notes/cold_migration_setup-dc4ebd834920c27f.yaml [new file with mode: 0644]
spec/classes/tripleo_profile_base_nova_spec.rb

index cb34521..b4330a9 100644 (file)
 #   (Optional) The current step of the deployment
 #   Defaults to hiera('step')
 #
+# [*migration_ssh_key*]
+#   (Optional) SSH key pair for migration SSH tunnel.
+#   Expects a hash with keys 'private_key' and 'public_key'.
+#   Defaults to {}
+#
+# [*libvirt_tls*]
+#   (Optional) Whether or not libvird TLS service is enabled.
+#   Defaults to false
+
 class tripleo::profile::base::nova (
   $bootstrap_node       = hiera('bootstrap_nodeid', undef),
   $libvirt_enabled      = false,
@@ -74,6 +83,8 @@ class tripleo::profile::base::nova (
   $messaging_use_ssl    = hiera('nova::rabbit_use_ssl', '0'),
   $nova_compute_enabled = false,
   $step                 = hiera('step'),
+  $migration_ssh_key       = {},
+  $libvirt_tls             = false
 ) {
   if $::hostname == downcase($bootstrap_node) {
     $sync_db = true
@@ -89,18 +100,6 @@ class tripleo::profile::base::nova (
 
   if $step >= 4 or ($step >= 3 and $sync_db) {
     $messaging_use_ssl_real = sprintf('%s', bool2num(str2bool($messaging_use_ssl)))
-    # TODO(ccamacho): remove sprintf once we properly type the port, needs
-    # to be a string for the os_transport_url function.
-    class { '::nova' :
-      default_transport_url => os_transport_url({
-        'transport' => $messaging_driver,
-        'hosts'     => $messaging_hosts,
-        'port'      => sprintf('%s', $messaging_port),
-        'username'  => $messaging_username,
-        'password'  => $messaging_password,
-        'ssl'       => $messaging_use_ssl_real,
-      }),
-    }
     include ::nova::config
     class { '::nova::cache':
       enabled          => true,
@@ -108,15 +107,65 @@ class tripleo::profile::base::nova (
       memcache_servers => $memcache_servers,
     }
     include ::nova::placement
-  }
 
-  if $step >= 4 {
-    if $manage_migration {
-      class { '::nova::migration::libvirt':
-        configure_libvirt => $libvirt_enabled,
-        configure_nova    => $nova_compute_enabled,
+    if $step >= 4 and $manage_migration {
+
+      # Libvirt setup (live-migration)
+      if $libvirt_tls {
+        class { '::nova::migration::libvirt':
+          transport         => 'tls',
+          configure_libvirt => $libvirt_enabled,
+          configure_nova    => $nova_compute_enabled,
+        }
+      } else {
+        # Reuse the cold-migration SSH tunnel when TLS is not enabled
+        class { '::nova::migration::libvirt':
+          transport          => 'ssh',
+          configure_libvirt  => $libvirt_enabled,
+          configure_nova     => $nova_compute_enabled,
+          client_user        => 'nova',
+          client_extraparams => {'keyfile' => '/var/lib/nova/.ssh/id_rsa'}
+        }
       }
+
+      if $migration_ssh_key != {} {
+        # Nova SSH tunnel setup (cold-migration)
+
+        #TODO: Remove me when https://review.rdoproject.org/r/#/c/4008 lands
+        user { 'nova':
+          ensure => present,
+          shell  => '/bin/bash',
+        }
+
+        $private_key_parts = split($migration_ssh_key['public_key'], ' ')
+        $nova_public_key = {
+          'type' => $private_key_parts[0],
+          key    => $private_key_parts[1]
+        }
+        $nova_private_key = {
+          'type' => $private_key_parts[0],
+          key    => $migration_ssh_key['private_key']
+        }
+      } else {
+        $nova_public_key = undef
+        $nova_private_key = undef
+      }
+    } else {
+      $nova_public_key = undef
+      $nova_private_key = undef
     }
-  }
 
+    class { '::nova' :
+      default_transport_url => os_transport_url({
+        'transport' => $messaging_driver,
+        'hosts'     => $messaging_hosts,
+        'port'      => sprintf('%s', $messaging_port),
+        'username'  => $messaging_username,
+        'password'  => $messaging_password,
+        'ssl'       => $messaging_use_ssl_real,
+      }),
+      nova_public_key       => $nova_public_key,
+      nova_private_key      => $nova_private_key,
+    }
+  }
 }
diff --git a/releasenotes/notes/cold_migration_setup-dc4ebd834920c27f.yaml b/releasenotes/notes/cold_migration_setup-dc4ebd834920c27f.yaml
new file mode 100644 (file)
index 0000000..00b7799
--- /dev/null
@@ -0,0 +1,4 @@
+---
+features:
+  - Configure ssh tunneling for nova cold-migration. Re-use the tunnel for
+    libvirt live-migration unless TLS is enabled.
index 68b01e9..9056034 100644 (file)
@@ -85,7 +85,12 @@ describe 'tripleo::profile::base::nova' do
 
       it {
         is_expected.to contain_class('tripleo::profile::base::nova')
-        is_expected.to contain_class('nova')
+        is_expected.to contain_class('nova').with(
+          :default_transport_url => /.+/,
+          :notification_transport_url => /.+/,
+          :nova_public_key => nil,
+          :nova_private_key => nil,
+        )
         is_expected.to contain_class('nova::config')
         is_expected.to contain_class('nova::cache')
         is_expected.to contain_class('nova::placement')
@@ -109,11 +114,120 @@ describe 'tripleo::profile::base::nova' do
 
       it {
         is_expected.to contain_class('tripleo::profile::base::nova')
-        is_expected.to contain_class('nova')
+        is_expected.to contain_class('nova').with(
+          :default_transport_url => /.+/,
+          :notification_transport_url => /.+/,
+          :nova_public_key => nil,
+          :nova_private_key => nil,
+        )
+        is_expected.to contain_class('nova::config')
+        is_expected.to contain_class('nova::placement')
+        is_expected.to contain_class('nova::cache')
+        is_expected.to contain_class('nova::migration::libvirt').with(
+          :transport         => 'ssh',
+          :configure_libvirt => params[:libvirt_enabled],
+          :configure_nova    => params[:nova_compute_enabled]
+        )
+      }
+    end
+
+    context 'with step 4 with libvirt TLS' do
+      let(:pre_condition) {
+        'include ::nova::compute::libvirt::services'
+      }
+      let(:params) { {
+        :step           => 4,
+        :libvirt_enabled => true,
+        :manage_migration => true,
+        :nova_compute_enabled => true,
+        :bootstrap_node  => 'node.example.com',
+        :messaging_hosts => [ 'localhost' ],
+        :messaging_password => 'foo',
+        :libvirt_tls => true,
+      } }
+
+      it {
+        is_expected.to contain_class('tripleo::profile::base::nova')
+        is_expected.to contain_class('nova').with(
+          :default_transport_url => /.+/,
+          :notification_transport_url => /.+/,
+          :nova_public_key => nil,
+          :nova_private_key => nil,
+        )
+        is_expected.to contain_class('nova::config')
+        is_expected.to contain_class('nova::placement')
+        is_expected.to contain_class('nova::cache')
+        is_expected.to contain_class('nova::migration::libvirt').with(
+          :transport         => 'tls',
+          :configure_libvirt => params[:libvirt_enabled],
+          :configure_nova    => params[:nova_compute_enabled],
+        )
+      }
+    end
+
+    context 'with step 4 with libvirt and migration ssh key' do
+      let(:pre_condition) {
+        'include ::nova::compute::libvirt::services'
+      }
+      let(:params) { {
+        :step           => 4,
+        :libvirt_enabled => true,
+        :manage_migration => true,
+        :nova_compute_enabled => true,
+        :bootstrap_node  => 'node.example.com',
+        :messaging_hosts => [ 'localhost' ],
+        :messaging_password => 'foo',
+        :migration_ssh_key => { 'private_key' => 'foo', 'public_key' => 'ssh-rsa bar'}
+      } }
+
+      it {
+        is_expected.to contain_class('tripleo::profile::base::nova')
+        is_expected.to contain_class('nova').with(
+          :default_transport_url => /.+/,
+          :notification_transport_url => /.+/,
+          :nova_public_key  => {'key' => 'bar', 'type' => 'ssh-rsa'},
+          :nova_private_key => {'key' => 'foo', 'type' => 'ssh-rsa'}
+        )
+        is_expected.to contain_class('nova::config')
+        is_expected.to contain_class('nova::placement')
+        is_expected.to contain_class('nova::cache')
+        is_expected.to contain_class('nova::migration::libvirt').with(
+          :transport         => 'ssh',
+          :configure_libvirt => params[:libvirt_enabled],
+          :configure_nova    => params[:nova_compute_enabled]
+        )
+      }
+    end
+
+    context 'with step 4 with libvirt TLS and migration ssh key' do
+      let(:pre_condition) {
+        'include ::nova::compute::libvirt::services'
+      }
+      let(:params) { {
+        :step           => 4,
+        :libvirt_enabled => true,
+        :manage_migration => true,
+        :nova_compute_enabled => true,
+        :bootstrap_node  => 'node.example.com',
+        :messaging_hosts => [ 'localhost' ],
+        :messaging_password => 'foo',
+        :libvirt_tls => true,
+        :migration_ssh_key => { 'private_key' => 'foo', 'public_key' => 'ssh-rsa bar'}
+      } }
+
+      it {
+        is_expected.to contain_class('tripleo::profile::base::nova')
+        is_expected.to contain_class('nova').with(
+          :default_transport_url => /.+/,
+          :notification_transport_url => /.+/,
+          :nova_public_key  => {'key' => 'bar', 'type' => 'ssh-rsa'},
+          :nova_private_key => {'key' => 'foo', 'type' => 'ssh-rsa'}
+        )
         is_expected.to contain_class('nova::config')
         is_expected.to contain_class('nova::placement')
         is_expected.to contain_class('nova::cache')
         is_expected.to contain_class('nova::migration::libvirt').with(
+          :transport         => 'tls',
           :configure_libvirt => params[:libvirt_enabled],
           :configure_nova    => params[:nova_compute_enabled]
         )