Support for Ocata-Pike live-migration over ssh
authorOliver Walsh <owalsh@redhat.com>
Wed, 6 Sep 2017 10:35:07 +0000 (11:35 +0100)
committerEmilien Macchi <emilien@redhat.com>
Sat, 7 Oct 2017 01:00:27 +0000 (01:00 +0000)
In Ocata all live-migration over ssh is performed on the default ssh port (22).
In Pike the containerized live-migration over ssh is on port 2022 as the
docker host's sshd is using port 22.

To allow live migration during upgrade we need to temporarily pin the Pike
computes to port 22 and in the final converge we can switch over to port 2022.

This also changes the default port to 2022 for baremetal computes in Pike to
enable live-migration between baremetal and containerized computes.

Change-Id: Icb9bfdd9a99dc1dce28eb95c50a9a36bffa621b1
Depends-On: I0b80b81711f683be539939e7d084365ff63546d3
Closes-Bug: 1714171
(cherry picked from commit 17fd16b9f266e1aa67bf03ebdf309e89d668ada2)

14 files changed:
docker/services/nova-compute.yaml
docker/services/nova-libvirt.yaml
docker/services/nova-migration-target.yaml
docker/services/sshd.yaml [new file with mode: 0644]
environments/docker-services-tls-everywhere.yaml
environments/docker.yaml
environments/major-upgrade-composable-steps-docker.yaml
environments/major-upgrade-composable-steps.yaml
environments/major-upgrade-converge-docker.yaml
environments/major-upgrade-converge.yaml
puppet/services/nova-compute.yaml
puppet/services/nova-libvirt.yaml
puppet/services/nova-migration-target.yaml
tools/yaml-validate.py

index bf7841b..34f56cd 100644 (file)
@@ -63,7 +63,6 @@ resources:
       DefaultPasswords: {get_param: DefaultPasswords}
       RoleName: {get_param: RoleName}
       RoleParameters: {get_param: RoleParameters}
-      MigrationSshPort: {get_param: DockerNovaMigrationSshdPort}
 
 outputs:
   role_data:
index d20c093..c059cfa 100644 (file)
@@ -105,7 +105,6 @@ resources:
       DefaultPasswords: {get_param: DefaultPasswords}
       RoleName: {get_param: RoleName}
       RoleParameters: {get_param: RoleParameters}
-      MigrationSshPort: {get_param: DockerNovaMigrationSshdPort}
 
 outputs:
   role_data:
index 385343a..904a042 100644 (file)
@@ -41,6 +41,29 @@ parameters:
     description: Port that dockerized nova migration target sshd service
                  binds to.
     type: number
+  MigrationSshKey:
+    type: json
+    description: >
+      SSH key for migration.
+      Expects a dictionary with keys 'public_key' and 'private_key'.
+      Values should be identical to SSH public/private key files.
+    default:
+      public_key: ''
+      private_key: ''
+  MigrationSshPort:
+    default: 2022
+    description: Target port for migration over ssh
+    type: number
+
+conditions:
+
+  # During Ocata->Pike upgrade initially configure the ssh service on port 22
+  # to proxy migration commands to the containerized sshd on port 2022.
+  # When the upgrade converges we can switch migrations over to port 2022.
+  enable_migration_proxy:
+    equals:
+      - {get_param: MigrationSshPort}
+      - 22
 
 resources:
 
@@ -74,10 +97,15 @@ outputs:
         map_merge:
           - get_attr: [SshdBase, role_data, config_settings]
           - get_attr: [NovaMigrationTargetBase, role_data, config_settings]
-          - tripleo.nova_migration_target.firewall_rules:
-              '113 nova_migration_target':
-                dport:
-                  - {get_param: DockerNovaMigrationSshdPort}
+          # NB this prevents the baremetal ssh from listening on port 2022
+          # It doesn't affect the sshd port in the container as we override it below on the sshd cli
+          - tripleo::profile::base::sshd::port: 22
+          - if:
+            - enable_migration_proxy
+            - tripleo::profile::base::nova::migration::proxy::ssh_private_key: {get_param: [ MigrationSshKey, private_key ]}
+              tripleo::profile::base::nova::migration::proxy::target_port: {get_param: DockerNovaMigrationSshdPort}
+              tripleo::profile::base::nova::migration::proxy::target_host: "%{hiera('live_migration_ssh_inbound_addr')}"
+            - {}
       step_config: &step_config
         list_join:
           - "\n"
diff --git a/docker/services/sshd.yaml b/docker/services/sshd.yaml
new file mode 100644 (file)
index 0000000..6f57f13
--- /dev/null
@@ -0,0 +1,72 @@
+heat_template_version: pike
+
+description: >
+  Configure sshd_config
+
+parameters:
+  ServiceData:
+    default: {}
+    description: Dictionary packing service data
+    type: json
+  ServiceNetMap:
+    default: {}
+    description: Mapping of service_name -> network name. Typically set
+                 via parameter_defaults in the resource registry.  This
+                 mapping overrides those in ServiceNetMapDefaults.
+    type: json
+  DefaultPasswords:
+    default: {}
+    type: json
+  RoleName:
+    default: ''
+    description: Role name on which the service is applied
+    type: string
+  RoleParameters:
+    default: {}
+    description: Parameters specific to the role
+    type: json
+  EndpointMap:
+    default: {}
+    description: Mapping of service endpoint -> protocol. Typically set
+                 via parameter_defaults in the resource registry.
+    type: json
+  MigrationSshPort:
+    default: 2022
+    description: Target port for migration over ssh
+    type: number
+
+conditions:
+
+  # During Ocata->Pike upgrade initially configure the ssh service on port 22
+  # to proxy migration commands to the containerized sshd on port 2022.
+  # When the upgrade converges we can switch migrations over to port 2022.
+  enable_migration_proxy:
+    equals:
+      - {get_param: MigrationSshPort}
+      - 22
+
+resources:
+   SshdBase:
+    type: ../../puppet/services/sshd.yaml
+    properties:
+      EndpointMap: {get_param: EndpointMap}
+      ServiceNetMap: {get_param: ServiceNetMap}
+      DefaultPasswords: {get_param: DefaultPasswords}
+      RoleName: {get_param: RoleName}
+      RoleParameters: {get_param: RoleParameters}
+
+outputs:
+  role_data:
+    description: Role data for the ssh
+    value:
+      service_name: sshd
+      config_settings: {get_attr: [SshdBase, role_data, config_settings]}
+      step_config:
+        list_join:
+          - "\n"
+          - - get_attr: [SshdBase, role_data, step_config]
+            - if:
+              - enable_migration_proxy
+              - |
+                include tripleo::profile::base::nova::migration::proxy
+              - ''
index ba190e7..342f278 100644 (file)
@@ -49,6 +49,7 @@ resource_registry:
   OS::TripleO::Services::PankoApi: ../docker/services/panko-api.yaml
   OS::TripleO::Services::RabbitMQ: ../docker/services/rabbitmq.yaml
   OS::TripleO::Services::Redis: ../docker/services/database/redis.yaml
+  OS::TripleO::Services::Sshd: ../docker/services/sshd.yaml
   OS::TripleO::Services::SwiftProxy: ../docker/services/swift-proxy.yaml
   OS::TripleO::Services::SwiftRingBuilder: ../docker/services/swift-ringbuilder.yaml
   OS::TripleO::Services::SwiftStorage: ../docker/services/swift-storage.yaml
index 06e3d3a..5737992 100644 (file)
@@ -32,6 +32,7 @@ resource_registry:
   OS::TripleO::Services::RabbitMQ: ../docker/services/rabbitmq.yaml
   OS::TripleO::Services::Redis: ../docker/services/database/redis.yaml
   OS::TripleO::Services::Memcached: ../docker/services/memcached.yaml
+  OS::TripleO::Services::Sshd: ../docker/services/sshd.yaml
   OS::TripleO::Services::SwiftProxy: ../docker/services/swift-proxy.yaml
   OS::TripleO::Services::SwiftStorage: ../docker/services/swift-storage.yaml
   OS::TripleO::Services::SwiftRingBuilder: ../docker/services/swift-ringbuilder.yaml
index 888e270..1b7f17e 100644 (file)
@@ -9,3 +9,4 @@ parameter_defaults:
     set -eu
     # Ocata to Pike, put any needed host-level workarounds here
     yum install -y ansible-pacemaker
+  MigrationSshPort: 22
index db83f90..5433572 100644 (file)
@@ -14,3 +14,4 @@ parameter_defaults:
     rm -f /usr/libexec/os-apply-config/templates/etc/puppet/hiera.yaml
     rm -f /usr/libexec/os-refresh-config/configure.d/40-hiera-datafiles
     rm -f /etc/puppet/hieradata/*.yaml
+  MigrationSshPort: 22
index 668f8a9..3f0a3ec 100644 (file)
@@ -8,3 +8,4 @@ parameter_defaults:
   UpgradeLevelNovaCompute: ''
   UpgradeInitCommonCommand: ''
   UpgradeInitCommand: ''
+  MigrationSshPort: 2022
index 668f8a9..3f0a3ec 100644 (file)
@@ -8,3 +8,4 @@ parameter_defaults:
   UpgradeLevelNovaCompute: ''
   UpgradeInitCommonCommand: ''
   UpgradeInitCommand: ''
+  MigrationSshPort: 2022
index 22a743e..9e5ba12 100644 (file)
@@ -108,7 +108,7 @@ parameters:
       public_key: ''
       private_key: ''
   MigrationSshPort:
-    default: 22
+    default: 2022
     description: Target port for migration over ssh
     type: number
 
index 3f37cd9..ac7cc8f 100644 (file)
@@ -94,7 +94,7 @@ parameters:
       public_key: ''
       private_key: ''
   MigrationSshPort:
-    default: 22
+    default: 2022
     description: Target port for migration over ssh
     type: number
 
index 128abc2..0c2b419 100644 (file)
@@ -39,6 +39,10 @@ parameters:
     default:
       public_key: ''
       private_key: ''
+  MigrationSshPort:
+    default: 2022
+    description: Target port for migration over ssh
+    type: number
 
 outputs:
   role_data:
@@ -53,5 +57,12 @@ outputs:
           - "%{hiera('live_migration_ssh_inbound_addr')}"
         live_migration_ssh_inbound_addr: {get_param: [ServiceNetMap, NovaLibvirtNetwork]}
         cold_migration_ssh_inbound_addr: {get_param: [ServiceNetMap, NovaColdMigrationNetwork]}
+        tripleo::profile::base::sshd::port:
+          - 22
+          - {get_param: MigrationSshPort}
+        tripleo.nova_migration_target.firewall_rules:
+          '113 nova_migration_target':
+            dport:
+              - {get_param: MigrationSshPort}
       step_config: |
         include tripleo::profile::base::nova::migration::target
index f7a45d7..66ac101 100755 (executable)
@@ -116,6 +116,22 @@ PREFERRED_CAMEL_CASE = {
     'haproxy': 'HAProxy',
 }
 
+# Overrides for docker/puppet validation
+# <filename>: True explicitly enables validation
+# <filename>: False explicitly disables validation
+#
+# If a filename is not found in the overrides then the top level directory is
+# used to determine which validation method to use.
+VALIDATE_PUPPET_OVERRIDE = {
+  # docker/service/sshd.yaml is a variation of the puppet sshd service
+  './docker/services/sshd.yaml': True,
+  # qdr aliases rabbitmq service to provide alternative messaging backend
+  './puppet/services/qdr.yaml': False,
+}
+VALIDATE_DOCKER_OVERRIDE = {
+  # docker/service/sshd.yaml is a variation of the puppet sshd service
+  './docker/services/sshd.yaml': False,
+}
 
 def exit_usage():
     print('Usage %s <yaml file or directory>' % sys.argv[0])
@@ -436,12 +452,14 @@ def validate(filename, param_map):
                   % filename)
             return 1
 
-        # qdr aliases rabbitmq service to provide alternative messaging backend
-        if (filename.startswith('./puppet/services/') and
-                filename not in ['./puppet/services/qdr.yaml']):
+        if VALIDATE_PUPPET_OVERRIDE.get(filename, False) or (
+                filename.startswith('./puppet/services/') and
+                VALIDATE_PUPPET_OVERRIDE.get(filename, True)):
             retval = validate_service(filename, tpl)
 
-        if filename.startswith('./docker/services/'):
+        if VALIDATE_DOCKER_OVERRIDE.get(filename, False) or (
+                filename.startswith('./docker/services/') and
+                VALIDATE_DOCKER_OVERRIDE.get(filename, True)):
             retval = validate_docker_service(filename, tpl)
 
         if filename.endswith('hyperconverged-ceph.yaml'):