Merge "Stop nova-api before upgrading package"
[apex-tripleo-heat-templates.git] / overcloud.j2.yaml
index fa160e4..e9447b9 100644 (file)
@@ -1,4 +1,5 @@
-heat_template_version: 2016-10-14
+{% set primary_role_name = roles[0].name -%}
+heat_template_version: ocata
 
 description: >
   Deploy an OpenStack environment, consisting of several node types (roles),
@@ -121,16 +122,11 @@ parameters:
                  resource_registry) which represent nested stacks
                  for each service that should get installed on the {{role.name}} role.
     type: comma_delimited_list
-  {% if role.ServicesDefault %}
-    default: {{role.ServicesDefault}}
-  {% endif %}
 
   {{role.name}}Count:
     description: Number of {{role.name}} nodes to deploy
     type: number
-  {% if role.CountDefault %}
-    default: {{role.CountDefault}}
-  {% endif %}
+    default: {{role.CountDefault|default(0)}}
 
   {{role.name}}HostnameFormat:
     type: string
@@ -140,6 +136,8 @@ parameters:
       and %stackname% is replaced with the stack name e.g overcloud
   {% if role.HostnameFormatDefault %}
     default: "{{role.HostnameFormatDefault}}"
+  {% else %}
+    default: "%stackname%-{{role.name.lower()}}-%index%"
   {% endif %}
 
   {{role.name}}RemovalPolicies:
@@ -149,6 +147,15 @@ parameters:
       List of resources to be removed from {{role.name}} ResourceGroup when
       doing an update which requires removal of specific resources.
       Example format ComputeRemovalPolicies: [{'resource_list': ['0']}]
+
+{% if role.name != 'Compute' %}
+  {{role.name}}SchedulerHints:
+{% else %}
+  NovaComputeSchedulerHints:
+{% endif %}
+    type: json
+    description: Optional scheduler hints to pass to nova
+    default: {}
 {% endfor %}
 
   # Identifiers to trigger tasks on nodes
@@ -164,9 +171,50 @@ parameters:
     description: >
       Setting this to a unique value will re-run any deployment tasks which
       perform configuration on a Heat stack-update.
+  AddVipsToEtcHosts:
+    default: True
+    type: boolean
+    description: >
+      Set to true to append per network Vips to /etc/hosts on each node.
+
+conditions:
+  add_vips_to_etc_hosts: {equals : [{get_param: AddVipsToEtcHosts}, True]}
 
 resources:
 
+  VipHosts:
+    type: OS::Heat::Value
+    properties:
+      type: string
+      value:
+        list_join:
+        - "\n"
+        - - str_replace:
+              template: IP  HOST
+              params:
+                IP: {get_attr: [VipMap, net_ip_map, external]}
+                HOST: {get_param: CloudName}
+          - str_replace:
+              template: IP  HOST
+              params:
+                IP: {get_attr: [VipMap, net_ip_map, ctlplane]}
+                HOST: {get_param: CloudNameCtlplane}
+          - str_replace:
+              template: IP  HOST
+              params:
+                IP: {get_attr: [VipMap, net_ip_map, internal_api]}
+                HOST: {get_param: CloudNameInternal}
+          - str_replace:
+              template: IP  HOST
+              params:
+                IP: {get_attr: [VipMap, net_ip_map, storage]}
+                HOST: {get_param: CloudNameStorage}
+          - str_replace:
+              template: IP  HOST
+              params:
+                IP: {get_attr: [VipMap, net_ip_map, storage_mgmt]}
+                HOST: {get_param: CloudNameStorageManagement}
+
   HeatAuthEncryptionKey:
     type: OS::Heat::RandomString
 
@@ -207,15 +255,49 @@ resources:
       EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
       DefaultPasswords: {get_attr: [DefaultPasswords, passwords]}
 
+  # Filter any null/None service_names which may be present due to mapping
+  # of services to OS::Heat::None
+  {{role.name}}ServiceNames:
+    type: OS::Heat::Value
+    depends_on: {{role.name}}ServiceChain
+    properties:
+      type: comma_delimited_list
+      value:
+        yaql:
+          expression: coalesce($.data, []).where($ != null)
+          data: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
+
+  {{role.name}}HostsDeployment:
+    type: OS::Heat::StructuredDeployments
+    properties:
+      name: {{role.name}}HostsDeployment
+      config: {get_attr: [hostsConfig, config_id]}
+      servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
+
   {{role.name}}AllNodesDeployment:
     type: OS::Heat::StructuredDeployments
+    depends_on:
+{% for role_inner in roles %}
+      - {{role_inner.name}}HostsDeployment
+{% endfor %}
     properties:
       name: {{role.name}}AllNodesDeployment
       config: {get_attr: [allNodesConfig, config_id]}
       servers: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
       input_values:
-        bootstrap_nodeid: {get_attr: [{{role.name}}, resource.0.hostname]}
-        bootstrap_nodeid_ip: {get_attr: [{{role.name}}, resource.0.ip_address]}
+        # Note we have to use yaql to look up the first hostname/ip in the
+        # list because heat path based attributes operate on the attribute
+        # inside the ResourceGroup, not the exposed list ref discussion in
+        # https://bugs.launchpad.net/heat/+bug/1640488
+        # The coalesce is needed because $.data is None during heat validation
+        bootstrap_nodeid:
+          yaql:
+            expression: coalesce($.data, []).first(null)
+            data: {get_attr: [{{role.name}}, hostname]}
+        bootstrap_nodeid_ip:
+          yaql:
+            expression: coalesce($.data, []).first(null)
+            data: {get_attr: [{{role.name}}, ip_address]}
 
   {{role.name}}AllNodesValidationDeployment:
     type: OS::Heat::StructuredDeployments
@@ -235,9 +317,18 @@ resources:
       StorageMgmtIpList: {get_attr: [{{role.name}}, storage_mgmt_ip_address]}
       TenantIpList: {get_attr: [{{role.name}}, tenant_ip_address]}
       ManagementIpList: {get_attr: [{{role.name}}, management_ip_address]}
-      EnabledServices: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
+      EnabledServices: {get_attr: [{{role.name}}ServiceNames, value]}
       ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
       ServiceHostnameList: {get_attr: [{{role.name}}, hostname]}
+      NetworkHostnameMap:
+        # Note (shardy) this somewhat complex yaql may be replaced
+        # with a map_deep_merge function in ocata.  It merges the
+        # list of maps, but appends to colliding lists so we can
+        # create a map of lists for all nodes for each network
+        yaql:
+          expression: dict($.data.where($ != null).flatten().selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
+          data:
+            - {get_attr: [{{role.name}}, hostname_map]}
 
   {{role.name}}:
     type: OS::Heat::ResourceGroup
@@ -257,14 +348,52 @@ resources:
               params:
                 '%stackname%': {get_param: 'OS::stack_name'}
           NodeIndex: '%index%'
+  {% if role.name != 'Compute' %}
+          {{role.name}}SchedulerHints: {get_param: {{role.name}}SchedulerHints}
+  {% else %}
+          NovaComputeSchedulerHints: {get_param: NovaComputeSchedulerHints}
+  {% endif %}
           ServiceConfigSettings:
             map_merge:
               -  get_attr: [{{role.name}}ServiceChain, role_data, config_settings]
           {% for r in roles %}
               - get_attr: [{{r.name}}ServiceChain, role_data, global_config_settings]
           {% endfor %}
-          ServiceNames: {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
+              # This next step combines two yaql passes:
+              # - The inner one does a deep merge on the service_config_settings for all roles
+              # - The outer one filters the map based on the services enabled for the role
+              #   then merges the result into one map.
+              - yaql:
+                  expression: let(root => $) -> $.data.map.items().where($[0] in coalesce($root.data.services, [])).select($[1]).reduce($1.mergeWith($2), {})
+                  data:
+                    map:
+                      yaql:
+                        expression: $.data.where($ != null).reduce($1.mergeWith($2), {})
+                        data:
+                        {% for r in roles %}
+                          - get_attr: [{{r.name}}ServiceChain, role_data, service_config_settings]
+                        {% endfor %}
+                    services: {get_attr: [{{role.name}}ServiceNames, value]}
+          ServiceNames: {get_attr: [{{role.name}}ServiceNames, value]}
           MonitoringSubscriptions: {get_attr: [{{role.name}}ServiceChain, role_data, monitoring_subscriptions]}
+          ServiceMetadataSettings: {get_attr: [{{role.name}}ServiceChain, role_data, service_metadata_settings]}
+{% endfor %}
+
+  hostsConfig:
+    type: OS::TripleO::Hosts::SoftwareConfig
+    properties:
+      hosts:
+        list_join:
+        - "\n"
+        - - if:
+            - add_vips_to_etc_hosts
+            - {get_attr: [VipHosts, value]}
+            - ''
+        -
+{% for role in roles %}
+          - list_join:
+            - "\n"
+            - {get_attr: [{{role.name}}, hosts_entry]}
 {% endfor %}
 
   allNodesConfig:
@@ -275,20 +404,32 @@ resources:
       cloud_name_storage: {get_param: CloudNameStorage}
       cloud_name_storage_mgmt: {get_param: CloudNameStorageManagement}
       cloud_name_ctlplane: {get_param: CloudNameCtlplane}
-      hosts:
-{% for role in roles %}
-        - list_join:
-            - '\n'
-            - {get_attr: [{{role.name}}, hosts_entry]}
-{% endfor %}
       enabled_services:
         list_join:
           - ','
 {% for role in roles %}
-          - {get_attr: [{{role.name}}ServiceChain, role_data, service_names]}
+          - {get_attr: [{{role.name}}ServiceNames, value]}
+{% endfor %}
+      logging_groups:
+        yaql:
+          expression: >
+            $.data.groups.flatten()
+          data:
+            groups:
+{% for role in roles %}
+              - {get_attr: [{{role.name}}ServiceChain, role_data, logging_groups]}
+{% endfor %}
+      logging_sources:
+        yaql:
+          expression: >
+            $.data.sources.flatten()
+          data:
+            sources:
+{% for role in roles %}
+              - {get_attr: [{{role.name}}ServiceChain, role_data, logging_sources]}
 {% endfor %}
-      controller_ips: {get_attr: [Controller, ip_address]}
-      controller_names: {get_attr: [Controller, hostname]}
+      controller_ips: {get_attr: [{{primary_role_name}}, ip_address]}
+      controller_names: {get_attr: [{{primary_role_name}}, hostname]}
       service_ips:
         # Note (shardy) this somewhat complex yaql may be replaced
         # with a map_deep_merge function in ocata.  It merges the
@@ -308,11 +449,25 @@ resources:
             l:
 {% for role in roles %}
               - {get_attr: [{{role.name}}IpListMap, service_hostnames]}
+{% endfor %}
+      short_service_node_names:
+        yaql:
+          expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten()]))
+          data:
+            l:
+{% for role in roles %}
+              - {get_attr: [{{role.name}}IpListMap, short_service_hostnames]}
+{% endfor %}
+      short_service_bootstrap_node:
+        yaql:
+          expression: dict($.data.l.where($ != null).selectMany($.items()).groupBy($[0], $[1], [$[0], $[1].flatten().first()]))
+          data:
+            l:
+{% for role in roles %}
+              - {get_attr: [{{role.name}}IpListMap, short_service_bootstrap_hostnames]}
 {% endfor %}
       # FIXME(shardy): These require further work to move into service_ips
-      memcache_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, MemcachedNetwork]}]}
-      keystone_public_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystonePublicApiNetwork]}]}
-      keystone_admin_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystoneAdminApiNetwork]}]}
+      memcache_node_ips: {get_attr: [{{primary_role_name}}IpListMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, MemcachedNetwork]}]}
       NetVipMap: {get_attr: [VipMap, net_ip_map]}
       RedisVirtualIP: {get_attr: [RedisVirtualIP, ip_address]}
       ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
@@ -344,7 +499,7 @@ resources:
     type: OS::TripleO::Network
 
   ControlVirtualIP:
-    type: OS::Neutron::Port
+    type: OS::TripleO::Network::Ports::ControlPlaneVipPort
     depends_on: Networks
     properties:
       name: control_virtual_ip
@@ -418,21 +573,24 @@ resources:
       PingTestIps:
         list_join:
         - ' '
-        - - {get_attr: [Controller, resource.0.external_ip_address]}
-          - {get_attr: [Controller, resource.0.internal_api_ip_address]}
-          - {get_attr: [Controller, resource.0.storage_ip_address]}
-          - {get_attr: [Controller, resource.0.storage_mgmt_ip_address]}
-          - {get_attr: [Controller, resource.0.tenant_ip_address]}
-          - {get_attr: [Controller, resource.0.management_ip_address]}
+        - - {get_attr: [{{primary_role_name}}, resource.0.external_ip_address]}
+          - {get_attr: [{{primary_role_name}}, resource.0.internal_api_ip_address]}
+          - {get_attr: [{{primary_role_name}}, resource.0.storage_ip_address]}
+          - {get_attr: [{{primary_role_name}}, resource.0.storage_mgmt_ip_address]}
+          - {get_attr: [{{primary_role_name}}, resource.0.tenant_ip_address]}
+          - {get_attr: [{{primary_role_name}}, resource.0.management_ip_address]}
 
   UpdateWorkflow:
     type: OS::TripleO::Tasks::UpdateWorkflow
+    depends_on:
+{% for role in roles %}
+      - {{role.name}}AllNodesDeployment
+{% endfor %}
     properties:
-      controller_servers: {get_attr: [Controller, attributes, nova_server_resource]}
-      compute_servers: {get_attr: [Compute, attributes, nova_server_resource]}
-      blockstorage_servers: {get_attr: [BlockStorage, attributes, nova_server_resource]}
-      objectstorage_servers: {get_attr: [ObjectStorage, attributes, nova_server_resource]}
-      cephstorage_servers: {get_attr: [CephStorage, attributes, nova_server_resource]}
+      servers:
+{% for role in roles %}
+        {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
+{% endfor %}
       input_values:
         deploy_identifier: {get_param: DeployIdentifier}
         update_identifier: {get_param: UpdateIdentifier}
@@ -443,34 +601,32 @@ resources:
     type: OS::TripleO::AllNodesExtraConfig
     depends_on:
       - UpdateWorkflow
-      - ComputeAllNodesValidationDeployment
-      - BlockStorageAllNodesValidationDeployment
-      - ObjectStorageAllNodesValidationDeployment
-      - CephStorageAllNodesValidationDeployment
-      - ControllerAllNodesValidationDeployment
+{% for role in roles %}
+      - {{role.name}}AllNodesValidationDeployment
+{% endfor %}
     properties:
-      controller_servers: {get_attr: [Controller, attributes, nova_server_resource]}
-      compute_servers: {get_attr: [Compute, attributes, nova_server_resource]}
-      blockstorage_servers: {get_attr: [BlockStorage, attributes, nova_server_resource]}
-      objectstorage_servers: {get_attr: [ObjectStorage, attributes, nova_server_resource]}
-      cephstorage_servers: {get_attr: [CephStorage, attributes, nova_server_resource]}
+      servers:
+{% for role in roles %}
+        {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
+{% endfor %}
 
   # Post deployment steps for all roles
   AllNodesDeploySteps:
     type: OS::TripleO::PostDeploySteps
+    depends_on:
+{% for role in roles %}
+      - {{role.name}}AllNodesDeployment
+{% endfor %}
     properties:
       servers:
-        Controller: {get_attr: [Controller, attributes, nova_server_resource]}
-        Compute: {get_attr: [Compute, attributes, nova_server_resource]}
-        BlockStorage: {get_attr: [BlockStorage, attributes, nova_server_resource]}
-        ObjectStorage: {get_attr: [ObjectStorage, attributes, nova_server_resource]}
-        CephStorage: {get_attr: [CephStorage, attributes, nova_server_resource]}
+{% for role in roles %}
+        {{role.name}}: {get_attr: [{{role.name}}, attributes, nova_server_resource]}
+{% endfor %}
+      EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
       role_data:
-        Controller: {get_attr: [ControllerServiceChain, role_data]}
-        Compute: {get_attr: [ComputeServiceChain, role_data]}
-        BlockStorage: {get_attr: [BlockStorageServiceChain, role_data]}
-        ObjectStorage: {get_attr: [ObjectStorageServiceChain, role_data]}
-        CephStorage: {get_attr: [CephStorageServiceChain, role_data]}
+{% for role in roles %}
+        {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data]}
+{% endfor %}
 
 outputs:
   ManagedEndpoints:
@@ -482,54 +638,6 @@ outputs:
   KeystoneAdminVip:
     description: Keystone Admin VIP endpoint
     value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystoneAdminApiNetwork]}]}
-  PublicVip:
-    description: Controller VIP for public API endpoints
-    value: {get_attr: [VipMap, net_ip_map, external]}
-  AodhInternalVip:
-    description: VIP for Aodh API internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, AodhApiNetwork]}]}
-  CeilometerInternalVip:
-    description: VIP for Ceilometer API internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, CeilometerApiNetwork]}]}
-  CephRgwInternalVip:
-    description: VIP for Ceph RGW internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, CephRgwNetwork]}]}
-  CinderInternalVip:
-    description: VIP for Cinder API internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, CinderApiNetwork]}]}
-  GlanceInternalVip:
-    description: VIP for Glance API internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, GlanceApiNetwork]}]}
-  GnocchiInternalVip:
-    description: VIP for Gnocchi API internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, GnocchiApiNetwork]}]}
-  HeatInternalVip:
-    description: VIP for Heat API internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, HeatApiNetwork]}]}
-  IronicInternalVip:
-    description: VIP for Ironic API internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, IronicApiNetwork]}]}
-  KeystoneInternalVip:
-    description: VIP for Keystone API internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, KeystonePublicApiNetwork]}]}
-  ManilaInternalVip:
-    description: VIP for Manila API internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, ManilaApiNetwork]}]}
-  NeutronInternalVip:
-    description: VIP for Neutron API internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, NeutronApiNetwork]}]}
-  NovaInternalVip:
-    description: VIP for Nova API internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, NovaApiNetwork]}]}
-  OpenDaylightInternalVip:
-    description: VIP for OpenDaylight API internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, OpenDaylightApiNetwork]}]}
-  SaharaInternalVip:
-    description: VIP for Sahara API internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, SaharaApiNetwork]}]}
-  SwiftInternalVip:
-    description: VIP for Swift Proxy internal endpoint
-    value: {get_attr: [VipMap, net_ip_map, {get_attr: [ServiceNetMap, service_net_map, SwiftProxyNetwork]}]}
   EndpointMap:
     description: |
       Mapping of the resources with the needed info for their endpoints.
@@ -541,12 +649,20 @@ outputs:
       The content that should be appended to your /etc/hosts if you want to get
       hostname-based access to the deployed nodes (useful for testing without
       setting up a DNS).
-    value: {get_attr: [allNodesConfig, hosts_entries]}
+    value:
+      list_join:
+      - "\n"
+      - - {get_attr: [hostsConfig, hosts_entries]}
+      - - {get_attr: [VipHosts, value]}
   EnabledServices:
     description: The services enabled on each role
     value:
-      Controller: {get_attr: [ControllerServiceChain, role_data, service_names]}
-      Compute: {get_attr: [ComputeServiceChain, role_data, service_names]}
-      BlockStorage: {get_attr: [BlockStorageServiceChain, role_data, service_names]}
-      ObjectStorage: {get_attr: [ObjectStorageServiceChain, role_data, service_names]}
-      CephStorage: {get_attr: [CephStorageServiceChain, role_data, service_names]}
+{% for role in roles %}
+      {{role.name}}: {get_attr: [{{role.name}}ServiceNames, value]}
+{% endfor %}
+  RoleData:
+    description: The configuration data associated with each role
+    value:
+{% for role in roles %}
+      {{role.name}}: {get_attr: [{{role.name}}ServiceChain, role_data]}
+{% endfor %}