Render VIPs dynamically based on network_data.yaml
authorDan Sneddon <dsneddon@redhat.com>
Fri, 21 Jul 2017 21:33:33 +0000 (14:33 -0700)
committerBob Fournier <bfournie@redhat.com>
Fri, 4 Aug 2017 13:44:31 +0000 (09:44 -0400)
This change modifies the templates to dynamically define the VIPs
based on network_data.yaml. If a network is defined and marked
with "vip: true" in network_data.yaml, it will be included in the
overcloud.yaml which defines the deployment-level resources.

This should make it possible to create custom networks and
use them for services which use high-availability through VIPs.

Also, extraconfig/nova_metadata/krb-service-pricipals.yaml
was modified to dynamically produce the FQDN map for VIPs on
isolated networks, to match overcloud.j2.yaml.

Depends-On: If074f87494a46305c990a0ea332c7b576d3c6ed8
Depends-On: Iab8aca2f1fcaba0c8f109717a4b3068f629c9aab
Partially-implements: blueprint composable-networks
Closes-bug: 1667104
Change-Id: I71339a6ac41133e95dbc3f93abb7a9fdeb0f2da0

extraconfig/nova_metadata/krb-service-principals.j2.yaml [moved from extraconfig/nova_metadata/krb-service-principals.yaml with 65% similarity]
network/ports/net_vip_map_external.j2.yaml [new file with mode: 0644]
network/ports/net_vip_map_external.yaml [deleted file]
network/ports/net_vip_map_external_v6.j2.yaml [new file with mode: 0644]
network/ports/net_vip_map_external_v6.yaml [deleted file]
overcloud.j2.yaml

@@ -5,30 +5,38 @@ parameters:
   RoleData:
      type: json
      description: the list containing the 'role_data' output for the ServiceChain
-
-  # Coming from parameter_defaults
+{%- for network in networks if network.vip|default(false) %}
+{%- if network.name == 'External' %}
+  # Special case the External hostname param, which is CloudName
   CloudName:
     default: overcloud.localdomain
     description: The DNS name of this cloud. E.g. ci-overcloud.tripleo.org
     type: string
+{%- elif network.name == 'InternalApi' %}
+  # Special case the Internal API hostname param, which is CloudNameInternal
   CloudNameInternal:
-    default: overcloud.internalapi.localdomain
+    default: overcloud.{{network.name.lower()}}.localdomain
     description: >
-      The DNS name of this cloud's internal API endpoint. E.g.
-      'ci-overcloud.internalapi.tripleo.org'.
+      The DNS name of this cloud's {{network.name_lower}} endpoint. E.g.
+      'ci-overcloud.{{network.name.lower()}}.tripleo.org'.
     type: string
-  CloudNameStorage:
-    default: overcloud.storage.localdomain
+{%- elif network.name == 'StorageMgmt' %}
+  # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
+  CloudNameStorageManagement:
+    default: overcloud.{{network.name.lower()}}.localdomain
     description: >
-      The DNS name of this cloud's storage endpoint. E.g.
-      'ci-overcloud.storage.tripleo.org'.
+      The DNS name of this cloud's {{network.name_lower}} endpoint. E.g.
+      'ci-overcloud.{{network.name.lower()}}.tripleo.org'.
     type: string
-  CloudNameStorageManagement:
-    default: overcloud.storagemgmt.localdomain
+{%- else %}
+  CloudName{{network.name}}:
+    default: overcloud.{{network.name.lower()}}.localdomain
     description: >
-      The DNS name of this cloud's storage management endpoint. E.g.
-      'ci-overcloud.storagemgmt.tripleo.org'.
+      The DNS name of this cloud's {{network.name_lower}} endpoint. E.g.
+      'ci-overcloud.{{network.name.lower()}}.tripleo.org'.
     type: string
+{%- endif %}
+{%- endfor %}
   CloudNameCtlplane:
     default: overcloud.ctlplane.localdomain
     description: >
@@ -61,10 +69,17 @@ resources:
           data:
             metadata: {get_attr: [IncomingMetadataSettings, value]}
             fqdns:
+{%- for network in networks if network.vip|default(false) %}
+{%- if network.name == 'External' %}
               external: {get_param: CloudName}
+{%- elif network.name == 'InternalApi' %}
               internal_api: {get_param: CloudNameInternal}
-              storage: {get_param: CloudNameStorage}
+{%- elif network.name == 'StorageMgmt' %}
               storage_mgmt: {get_param: CloudNameStorageManagement}
+{%- else %}
+              {{network.name_lower}}: {get_param: CloudName{{network.name}}}
+{%- endif %}
+{%- endfor %}
               ctlplane: {get_param: CloudNameCtlplane}
 
   CompactServices:
@@ -82,3 +97,4 @@ outputs:
       map_merge:
         - {get_attr: [IndividualServices, value]}
         - compact_services: {get_attr: [CompactServices, value]}
+
diff --git a/network/ports/net_vip_map_external.j2.yaml b/network/ports/net_vip_map_external.j2.yaml
new file mode 100644 (file)
index 0000000..b17f48b
--- /dev/null
@@ -0,0 +1,40 @@
+heat_template_version: pike
+
+parameters:
+  # Set these via parameter defaults to configure external VIPs
+  ControlPlaneIP:
+    default: ''
+    type: string
+{%- for network in networks if network.vip|default(false) %}
+  {{network.name}}NetworkVip:
+    default: ''
+    type: string
+{%- endfor %}
+  # The following are unused in this template
+  ControlPlaneIp:
+    default: ''
+    type: string
+{%- for network in networks if network.vip|default(false) %}
+  {{network.name}}Ip:
+    default: ''
+    type: string
+  {{network.name}}IpUri:
+    default: ''
+    type: string
+    description: IP address with brackets in case of IPv6
+{%- endfor %}
+
+outputs:
+  net_ip_map:
+    description: >
+      A Hash containing a mapping of network names to assigned IPs
+      for a specific machine.
+    value:
+      ctlplane: {get_param: ControlPlaneIP}
+{%- for network in networks if network.vip|default(false) %}
+      {{network.name_lower}}: {get_param: {{network.name}}NetworkVip}
+{%- endfor %}
+      ctlplane_uri: {get_param: ControlPlaneIP}
+{%- for network in networks if network.vip|default(false) %}
+      {{network.name_lower}}_uri: {get_param: {{network.name}}NetworkVip}
+{%- endfor %}
diff --git a/network/ports/net_vip_map_external.yaml b/network/ports/net_vip_map_external.yaml
deleted file mode 100644 (file)
index d084788..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-heat_template_version: pike
-
-parameters:
-  # Set these via parameter defaults to configure external VIPs
-  ControlPlaneIP:
-    default: ''
-    type: string
-  ExternalNetworkVip:
-    default: ''
-    type: string
-  InternalApiNetworkVip:
-    default: ''
-    type: string
-  StorageNetworkVip:
-    default: ''
-    type: string
-  StorageMgmtNetworkVip:
-    default: ''
-    type: string
-  # The following are unused in this template
-  ControlPlaneIp:
-    default: ''
-    type: string
-  ExternalIp:
-    default: ''
-    type: string
-  ExternalIpUri:
-    default: ''
-    type: string
-    description: IP address with brackets in case of IPv6
-  InternalApiIp:
-    default: ''
-    type: string
-  InternalApiIpUri:
-    default: ''
-    type: string
-    description: IP address with brackets in case of IPv6
-  StorageIp:
-    default: ''
-    type: string
-  StorageIpUri:
-    default: ''
-    type: string
-    description: IP address with brackets in case of IPv6
-  StorageMgmtIp:
-    default: ''
-    type: string
-  StorageMgmtIpUri:
-    default: ''
-    type: string
-    description: IP address with brackets in case of IPv6
-
-outputs:
-  net_ip_map:
-    description: >
-      A Hash containing a mapping of network names to assigned IPs
-      for a specific machine.
-    value:
-      ctlplane: {get_param: ControlPlaneIP}
-      external: {get_param: ExternalNetworkVip}
-      internal_api: {get_param: InternalApiNetworkVip}
-      storage: {get_param: StorageNetworkVip}
-      storage_mgmt: {get_param: StorageMgmtNetworkVip}
-      ctlplane_uri: {get_param: ControlPlaneIP}
-      external_uri: {get_param: ExternalNetworkVip}
-      internal_api_uri: {get_param: InternalApiNetworkVip}
-      storage_uri: {get_param: StorageNetworkVip}
-      storage_mgmt_uri: {get_param: StorageMgmtNetworkVip}
diff --git a/network/ports/net_vip_map_external_v6.j2.yaml b/network/ports/net_vip_map_external_v6.j2.yaml
new file mode 100644 (file)
index 0000000..5eff73c
--- /dev/null
@@ -0,0 +1,45 @@
+heat_template_version: pike
+
+parameters:
+  # Set these via parameter defaults to configure external VIPs
+  ControlPlaneIP:
+    default: ''
+    type: string
+{%- for network in networks if network.vip|default(false) %}
+  {{network.name}}NetworkVip:
+    default: ''
+    type: string
+{%- endfor %}
+  # The following are unused in this template
+  ControlPlaneIp:
+    default: ''
+    type: string
+{%- for network in networks if network.vip|default(false) %}
+  {{network.name}}Ip:
+    default: ''
+    type: string
+  {{network.name}}IpUri:
+    default: ''
+    type: string
+    description: IP address with brackets in case of IPv6
+{%- endfor %}
+
+outputs:
+  net_ip_map:
+    description: >
+      A Hash containing a mapping of network names to assigned IPs
+      for a specific machine.
+    value:
+      ctlplane: {get_param: ControlPlaneIP}
+{%- for network in networks if network.vip|default(false) %}
+      {{network.name_lower}}: {get_param: {{network.name}}NetworkVip}
+{%- endfor %}
+      ctlplane_uri: {get_param: ControlPlaneIP}
+{%- for network in networks if network.vip|default(false) %}
+      {{network.name_lower}}_uri:
+        list_join:
+          - ''
+          - - '['
+            - {get_param: {{network.name}}NetworkVip}
+            - ']'
+{%- endfor %}
diff --git a/network/ports/net_vip_map_external_v6.yaml b/network/ports/net_vip_map_external_v6.yaml
deleted file mode 100644 (file)
index 72e60cb..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-heat_template_version: pike
-
-parameters:
-  # Set these via parameter defaults to configure external VIPs
-  ControlPlaneIP:
-    default: ''
-    type: string
-  ExternalNetworkVip:
-    default: ''
-    type: string
-  InternalApiNetworkVip:
-    default: ''
-    type: string
-  StorageNetworkVip:
-    default: ''
-    type: string
-  StorageMgmtNetworkVip:
-    default: ''
-    type: string
-  # The following are unused in this template
-  ControlPlaneIp:
-    default: ''
-    type: string
-  ExternalIp:
-    default: ''
-    type: string
-  ExternalIpUri:
-    default: ''
-    type: string
-    description: IP address with brackets in case of IPv6
-  InternalApiIp:
-    default: ''
-    type: string
-  InternalApiIpUri:
-    default: ''
-    type: string
-    description: IP address with brackets in case of IPv6
-  StorageIp:
-    default: ''
-    type: string
-  StorageIpUri:
-    default: ''
-    type: string
-    description: IP address with brackets in case of IPv6
-  StorageMgmtIp:
-    default: ''
-    type: string
-  StorageMgmtIpUri:
-    default: ''
-    type: string
-    description: IP address with brackets in case of IPv6
-
-outputs:
-  net_ip_map:
-    description: >
-      A Hash containing a mapping of network names to assigned IPs
-      for a specific machine.
-    value:
-      ctlplane: {get_param: ControlPlaneIP}
-      external: {get_param: ExternalNetworkVip}
-      internal_api: {get_param: InternalApiNetworkVip}
-      storage: {get_param: StorageNetworkVip}
-      storage_mgmt: {get_param: StorageMgmtNetworkVip}
-      ctlplane_uri: {get_param: ControlPlaneIP}
-      external_uri:
-        list_join:
-          - ''
-          - - '['
-            - {get_param: ExternalNetworkVip}
-            - ']'
-      internal_api_uri:
-        list_join:
-          - ''
-          - - '['
-            - {get_param: InternalApiNetworkVip}
-            - ']'
-      storage_uri:
-        list_join:
-          - ''
-          - - '['
-            - {get_param: StorageNetworkVip}
-            - ']'
-      storage_mgmt_uri:
-        list_join:
-          - ''
-          - - '['
-            - {get_param: StorageMgmtNetworkVip}
-            - ']'
index 2bfdf50..c397da0 100644 (file)
@@ -21,40 +21,44 @@ description: >
 parameters:
 
   # Common parameters (not specific to a role)
+{%- for network in networks if network.vip|default(false) %}
+{%- if network.name == 'External' %}
+  # Special case the External hostname param, which is CloudName
   CloudName:
     default: overcloud.localdomain
     description: The DNS name of this cloud. E.g. ci-overcloud.tripleo.org
     type: string
+{%- elif network.name == 'InternalApi' %}
+  # Special case the Internal API hostname param, which is CloudNameInternal
   CloudNameInternal:
-    default: overcloud.internalapi.localdomain
+    default: overcloud.{{network.name.lower()}}.localdomain
     description: >
-      The DNS name of this cloud's internal API endpoint. E.g.
-      'ci-overcloud.internalapi.tripleo.org'.
+      The DNS name of this cloud's {{network.name_lower}} endpoint. E.g.
+      'ci-overcloud.{{network.name.lower()}}.tripleo.org'.
     type: string
-  CloudNameStorage:
-    default: overcloud.storage.localdomain
+{%- elif network.name == 'StorageMgmt' %}
+  # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
+  CloudNameStorageManagement:
+    default: overcloud.{{network.name.lower()}}.localdomain
     description: >
-      The DNS name of this cloud's storage endpoint. E.g.
-      'ci-overcloud.storage.tripleo.org'.
+      The DNS name of this cloud's {{network.name_lower}} endpoint. E.g.
+      'ci-overcloud.{{network.name.lower()}}.tripleo.org'.
     type: string
-  CloudNameStorageManagement:
-    default: overcloud.storagemgmt.localdomain
+{%- else %}
+  CloudName{{network.name}}:
+    default: overcloud.{{network.name.lower()}}.localdomain
     description: >
-      The DNS name of this cloud's storage management endpoint. E.g.
-      'ci-overcloud.storagemgmt.tripleo.org'.
+      The DNS name of this cloud's {{network.name_lower}} endpoint. E.g.
+      'ci-overcloud.{{network.name.lower()}}.tripleo.org'.
     type: string
+{%- endif %}
+{%- endfor %}
   CloudNameCtlplane:
     default: overcloud.ctlplane.localdomain
     description: >
       The DNS name of this cloud's provisioning network endpoint. E.g.
       'ci-overcloud.ctlplane.tripleo.org'.
     type: string
-  ControlFixedIPs:
-    default: []
-    description: >
-        Control the IP allocation for the ControlVirtualIP port. E.g.
-        [{'ip_address':'1.2.3.4'}]
-    type: json
   ExtraConfig:
     default: {}
     description: |
@@ -77,12 +81,6 @@ parameters:
     description: |
       DEPRECATED use ComputeExtraConfig instead
     type: json
-  InternalApiVirtualFixedIPs:
-    default: []
-    description: >
-        Control the IP allocation for the InternalApiVirtualInterface port. E.g.
-        [{'ip_address':'1.2.3.4'}]
-    type: json
   NeutronControlPlaneID:
     default: 'ctlplane'
     type: string
@@ -91,28 +89,34 @@ parameters:
     default: nic1
     description: Which interface to add to the NeutronPhysicalBridge.
     type: string
-  PublicVirtualFixedIPs:
+  ControlFixedIPs:
     default: []
     description: >
-        Control the IP allocation for the PublicVirtualInterface port. E.g.
+        Control the IP allocation for the ControlVirtualIP port. E.g.
         [{'ip_address':'1.2.3.4'}]
     type: json
-  RabbitCookieSalt:
-    type: string
-    default: unset
-    description: Salt for the rabbit cookie, change this to force the randomly generated rabbit cookie to change.
-  StorageVirtualFixedIPs:
+{%- for network in networks if network.vip|default(false) %}
+{%- if network.name == 'External' %}
+  # TODO (dsneddon) Legacy name, eventually refactor to match network name
+  PublicVirtualFixedIPs:
     default: []
     description: >
-        Control the IP allocation for the StorageVirtualInterface port. E.g.
+        Control the IP allocation for the PublicVirtualInterface port. E.g.
         [{'ip_address':'1.2.3.4'}]
     type: json
-  StorageMgmtVirtualFixedIPs:
+{%- else %}
+  {{network.name}}VirtualFixedIPs:
     default: []
     description: >
-        Control the IP allocation for the StorageMgmgVirtualInterface port. E.g.
+        Control the IP allocation for the {{network.name}}VirtualInterface port. E.g.
         [{'ip_address':'1.2.3.4'}]
     type: json
+{%- endif %}
+{%- endfor %}
+  RabbitCookieSalt:
+    type: string
+    default: unset
+    description: Salt for the rabbit cookie, change this to force the randomly generated rabbit cookie to change.
   RedisVirtualFixedIPs:
     default: []
     description: >
@@ -246,28 +250,38 @@ resources:
         - - str_replace:
               template: IP  HOST
               params:
-                IP: {get_attr: [VipMap, net_ip_map, external]}
-                HOST: {get_param: CloudName}
+                IP: {get_attr: [VipMap, net_ip_map, ctlplane]}
+                HOST: {get_param: CloudNameCtlplane}
+{%- for network in networks if network.vip|default(false) %}
+{%- if network.name == 'External' %}
+  # Special case the External hostname param, which is CloudName
           - str_replace:
               template: IP  HOST
               params:
-                IP: {get_attr: [VipMap, net_ip_map, ctlplane]}
-                HOST: {get_param: CloudNameCtlplane}
+                IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
+                HOST: {get_param: CloudName}
+{%- elif network.name == 'InternalApi' %}
+  # Special case the Internal API hostname param, which is CloudNameInternal
           - str_replace:
               template: IP  HOST
               params:
-                IP: {get_attr: [VipMap, net_ip_map, internal_api]}
+                IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
                 HOST: {get_param: CloudNameInternal}
+{%- elif network.name == 'StorageMgmt' %}
+  # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
           - str_replace:
               template: IP  HOST
               params:
-                IP: {get_attr: [VipMap, net_ip_map, storage]}
-                HOST: {get_param: CloudNameStorage}
+                IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
+                HOST: {get_param: CloudNameStorageManagement}
+{%- else %}
           - str_replace:
               template: IP  HOST
               params:
-                IP: {get_attr: [VipMap, net_ip_map, storage_mgmt]}
-                HOST: {get_param: CloudNameStorageManagement}
+                IP: {get_attr: [VipMap, net_ip_map, {{network.name_lower}}]}
+                HOST: {get_param: CloudName{{network.name}}}
+{%- endif %}
+{%- endfor %}
 
   HeatAuthEncryptionKey:
     type: OS::TripleO::RandomString
@@ -303,11 +317,21 @@ resources:
     type: OS::TripleO::EndpointMap
     properties:
       CloudEndpoints:
-        external: {get_param: CloudName}
-        internal_api: {get_param: CloudNameInternal}
-        storage: {get_param: CloudNameStorage}
-        storage_mgmt: {get_param: CloudNameStorageManagement}
         ctlplane: {get_param: CloudNameCtlplane}
+{%- for network in networks if network.vip|default(false) %}
+{%- if network.name == 'External' %}
+  # Special case the External hostname param, which is CloudName
+        {{network.name_lower}}: {get_param: CloudName}
+{%- elif network.name == 'InternalApi' %}
+  # Special case the Internal API hostname param, which is CloudNameInternal
+        {{network.name_lower}}: {get_param: CloudNameInternal}
+{%- elif network.name == 'StorageMgmt' %}
+  # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
+        {{network.name_lower}}: {get_param: CloudNameStorageManagement}
+{%- else %}
+        {{network.name_lower}}: {get_param: CloudName{{network.name}}}
+{%- endif %}
+{%- endfor %}
       NetIpMap: {get_attr: [VipMap, net_ip_map]}
       ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map]}
 
@@ -464,12 +488,9 @@ resources:
     type: OS::TripleO::Network::Ports::NetIpListMap
     properties:
       ControlPlaneIpList: {get_attr: [{{role.name}}, ip_address]}
-      ExternalIpList: {get_attr: [{{role.name}}, external_ip_address]}
-      InternalApiIpList: {get_attr: [{{role.name}}, internal_api_ip_address]}
-      StorageIpList: {get_attr: [{{role.name}}, storage_ip_address]}
-      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]}
+{%- for network in networks if network.enabled|default(true) %}
+      {{network.name}}IpList: {get_attr: [{{role.name}}, {{network.name_lower}}_ip_address]}
+{%- endfor %}
       EnabledServices: {get_attr: [{{role.name}}ServiceNames, value]}
       ServiceNetMap: {get_attr: [ServiceNetMap, service_net_map_lower]}
       ServiceHostnameList: {get_attr: [{{role.name}}, hostname]}
@@ -588,10 +609,20 @@ resources:
   allNodesConfig:
     type: OS::TripleO::AllNodes::SoftwareConfig
     properties:
-      cloud_name_external: {get_param: CloudName}
-      cloud_name_internal_api: {get_param: CloudNameInternal}
-      cloud_name_storage: {get_param: CloudNameStorage}
-      cloud_name_storage_mgmt: {get_param: CloudNameStorageManagement}
+{%- for network in networks if network.vip|default(false) %}
+{%- if network.name == 'External' %}
+  # Special case the External hostname param, which is CloudName
+      cloud_name_{{network.name_lower}}: {get_param: CloudName}
+{%- elif network.name == 'InternalApi' %}
+  # Special case the Internal API hostname param, which is CloudNameInternal
+      cloud_name_{{network.name_lower}}: {get_param: CloudNameInternal}
+{%- elif network.name == 'StorageMgmt' %}
+  # Special case StorageMgmt hostname param, which is CloudNameStorageManagement
+      cloud_name_{{network.name_lower}}: {get_param: CloudNameStorageManagement}
+{%- else %}
+      cloud_name_{{network.name_lower}}: {get_param: CloudName{{network.name}}}
+{%- endif %}
+{%- endfor %}
       cloud_name_ctlplane: {get_param: CloudNameCtlplane}
       enabled_services:
         list_join:
@@ -705,6 +736,8 @@ resources:
       ServiceName: redis
       FixedIPs: {get_param: RedisVirtualFixedIPs}
 
+{%- for network in networks if network.vip|default(false) %}
+{%- if network.name == 'External' %}
   # The public VIP is on the External net, falls back to ctlplane
   PublicVirtualIP:
     depends_on: Networks
@@ -714,43 +747,38 @@ resources:
       ControlPlaneNetwork: {get_param: NeutronControlPlaneID}
       PortName: public_virtual_ip
       FixedIPs: {get_param: PublicVirtualFixedIPs}
-
-  InternalApiVirtualIP:
+{%- elif network.name == 'StorageMgmt' %}
+  {{network.name}}VirtualIP:
     depends_on: Networks
-    type: OS::TripleO::Network::Ports::InternalApiVipPort
+    type: OS::TripleO::Network::Ports::{{network.name}}VipPort
     properties:
       ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
-      PortName: internal_api_virtual_ip
-      FixedIPs: {get_param: InternalApiVirtualFixedIPs}
-
-  StorageVirtualIP:
-    depends_on: Networks
-    type: OS::TripleO::Network::Ports::StorageVipPort
-    properties:
-      ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
-      PortName: storage_virtual_ip
-      FixedIPs: {get_param: StorageVirtualFixedIPs}
-
-  StorageMgmtVirtualIP:
+      PortName: storage_management_virtual_ip
+      FixedIPs: {get_param: {{network.name}}VirtualFixedIPs}
+{%- else %}
+  {{network.name}}VirtualIP:
     depends_on: Networks
-    type: OS::TripleO::Network::Ports::StorageMgmtVipPort
+    type: OS::TripleO::Network::Ports::{{network.name}}VipPort
     properties:
       ControlPlaneIP: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
-      PortName: storage_management_virtual_ip
-      FixedIPs: {get_param: StorageMgmtVirtualFixedIPs}
+      PortName: {{network.name_lower}}_virtual_ip
+      FixedIPs: {get_param: {{network.name}}VirtualFixedIPs}
+{%- endif %}
+{%- endfor %}
 
   VipMap:
     type: OS::TripleO::Network::Ports::NetVipMap
     properties:
       ControlPlaneIp: {get_attr: [ControlVirtualIP, fixed_ips, 0, ip_address]}
+{%- for network in networks if network.vip|default(false) %}
+{%- if network.name == 'External' %}
       ExternalIp: {get_attr: [PublicVirtualIP, ip_address]}
       ExternalIpUri: {get_attr: [PublicVirtualIP, ip_address_uri]}
-      InternalApiIp: {get_attr: [InternalApiVirtualIP, ip_address]}
-      InternalApiIpUri: {get_attr: [InternalApiVirtualIP, ip_address_uri]}
-      StorageIp: {get_attr: [StorageVirtualIP, ip_address]}
-      StorageIpUri: {get_attr: [StorageVirtualIP, ip_address_uri]}
-      StorageMgmtIp: {get_attr: [StorageMgmtVirtualIP, ip_address]}
-      StorageMgmtIpUri: {get_attr: [StorageMgmtVirtualIP, ip_address_uri]}
+{%- else %}
+      {{network.name}}Ip: {get_attr: [{{network.name}}VirtualIP, ip_address]}
+      {{network.name}}IpUri: {get_attr: [{{network.name}}VirtualIP, ip_address_uri]}
+{%- endif %}
+{%- endfor %}
       # No tenant or management VIP required
     # Because of nested get_attr functions in the KeystoneAdminVip output, we
     # can't determine which attributes of VipMap are used until after
@@ -764,24 +792,12 @@ resources:
       PingTestIps:
         list_join:
         - ' '
-        - - yaql:
-              expression: coalesce($.data, []).first(null)
-              data: {get_attr: [{{primary_role_name}}, external_ip_address]}
-          - yaql:
-              expression: coalesce($.data, []).first(null)
-              data: {get_attr: [{{primary_role_name}}, internal_api_ip_address]}
-          - yaql:
-              expression: coalesce($.data, []).first(null)
-              data: {get_attr: [{{primary_role_name}}, storage_ip_address]}
-          - yaql:
-              expression: coalesce($.data, []).first(null)
-              data: {get_attr: [{{primary_role_name}}, storage_mgmt_ip_address]}
-          - yaql:
-              expression: coalesce($.data, []).first(null)
-              data: {get_attr: [{{primary_role_name}}, tenant_ip_address]}
+        -
+{%- for network in networks if network.enabled|default(true) %}
           - yaql:
               expression: coalesce($.data, []).first(null)
-              data: {get_attr: [{{primary_role_name}}, management_ip_address]}
+              data: {get_attr: [{{primary_role_name}}, {{network.name_lower}}_ip_address]}
+{%- endfor %}
 
   UpdateWorkflow:
     type: OS::TripleO::Tasks::UpdateWorkflow