Basic support for deploying Ironic in overcloud

Note that this change is not enough yet to deploy bare metal instances,
it only deploys Ironic services themselves and makes sure they work.

Also it does not support HA for now.

Co-Authored-By: Dmitry Tantsur <dtansur@redhat.com>
Partially-implements: blueprint ironic-integration
Change-Id: I541be905022264e2d4828e7c46338f2e300df540
This commit is contained in:
Imre Farkas 2016-05-13 14:31:45 +00:00 committed by Dmitry Tantsur
parent e850ed7b83
commit dfbc9380aa
12 changed files with 312 additions and 0 deletions

View File

@ -28,6 +28,9 @@ parameter_defaults:
HeatCfnInternal: {protocol: 'http', port: '8000', host: 'IP_ADDRESS'} HeatCfnInternal: {protocol: 'http', port: '8000', host: 'IP_ADDRESS'}
HeatCfnPublic: {protocol: 'https', port: '13005', host: 'CLOUDNAME'} HeatCfnPublic: {protocol: 'https', port: '13005', host: 'CLOUDNAME'}
HorizonPublic: {protocol: 'https', port: '443', host: 'CLOUDNAME'} HorizonPublic: {protocol: 'https', port: '443', host: 'CLOUDNAME'}
IronicAdmin: {protocol: 'http', port: '6385', host: 'IP_ADDRESS'}
IronicInternal: {protocol: 'http', port: '6385', host: 'IP_ADDRESS'}
IronicPublic: {protocol: 'https', port: '13385', host: 'CLOUDNAME'}
KeystoneAdmin: {protocol: 'http', port: '35357', host: 'IP_ADDRESS'} KeystoneAdmin: {protocol: 'http', port: '35357', host: 'IP_ADDRESS'}
KeystoneInternal: {protocol: 'http', port: '5000', host: 'IP_ADDRESS'} KeystoneInternal: {protocol: 'http', port: '5000', host: 'IP_ADDRESS'}
KeystonePublic: {protocol: 'https', port: '13000', host: 'CLOUDNAME'} KeystonePublic: {protocol: 'https', port: '13000', host: 'CLOUDNAME'}

View File

@ -192,3 +192,18 @@ Sahara:
uri_suffixes: uri_suffixes:
'': /v1.1/%(tenant_id)s '': /v1.1/%(tenant_id)s
port: 8386 port: 8386
Ironic:
Internal:
vip_param: IronicApi
uri_suffixes:
'': /v1
Public:
vip_param: Public
uri_suffixes:
'': /v1
Admin:
vip_param: IronicApi
uri_suffixes:
'': /v1
port: 6385

View File

@ -15,6 +15,7 @@ parameters:
GlanceRegistryVirtualIP: {type: string, default: ''} GlanceRegistryVirtualIP: {type: string, default: ''}
GnocchiApiVirtualIP: {type: string, default: ''} GnocchiApiVirtualIP: {type: string, default: ''}
HeatApiVirtualIP: {type: string, default: ''} HeatApiVirtualIP: {type: string, default: ''}
IronicApiVirtualIP: {type: string, default: ''}
KeystoneAdminApiVirtualIP: {type: string, default: ''} KeystoneAdminApiVirtualIP: {type: string, default: ''}
KeystonePublicApiVirtualIP: {type: string, default: ''} KeystonePublicApiVirtualIP: {type: string, default: ''}
MysqlVirtualIP: {type: string, default: ''} MysqlVirtualIP: {type: string, default: ''}
@ -49,6 +50,9 @@ parameters:
HeatCfnInternal: {protocol: http, port: '8000', host: IP_ADDRESS} HeatCfnInternal: {protocol: http, port: '8000', host: IP_ADDRESS}
HeatCfnPublic: {protocol: http, port: '8000', host: IP_ADDRESS} HeatCfnPublic: {protocol: http, port: '8000', host: IP_ADDRESS}
HorizonPublic: {protocol: http, port: '80', host: IP_ADDRESS} HorizonPublic: {protocol: http, port: '80', host: IP_ADDRESS}
IronicAdmin: {protocol: http, port: '6385', host: IP_ADDRESS}
IronicInternal: {protocol: http, port: '6385', host: IP_ADDRESS}
IronicPublic: {protocol: http, port: '6385', host: IP_ADDRESS}
KeystoneAdmin: {protocol: http, port: '35357', host: IP_ADDRESS} KeystoneAdmin: {protocol: http, port: '35357', host: IP_ADDRESS}
KeystoneInternal: {protocol: http, port: '5000', host: IP_ADDRESS} KeystoneInternal: {protocol: http, port: '5000', host: IP_ADDRESS}
KeystonePublic: {protocol: http, port: '5000', host: IP_ADDRESS} KeystonePublic: {protocol: http, port: '5000', host: IP_ADDRESS}
@ -1076,6 +1080,123 @@ outputs:
IP_ADDRESS: {get_param: PublicVirtualIP} IP_ADDRESS: {get_param: PublicVirtualIP}
- ':' - ':'
- get_param: [EndpointMap, HorizonPublic, port] - get_param: [EndpointMap, HorizonPublic, port]
IronicAdmin:
host:
str_replace:
template:
get_param: [EndpointMap, IronicAdmin, host]
params:
CLOUDNAME: {get_param: CloudName}
IP_ADDRESS: {get_param: IronicApiVirtualIP}
port:
get_param: [EndpointMap, IronicAdmin, port]
protocol:
get_param: [EndpointMap, IronicAdmin, protocol]
uri:
list_join:
- ''
- - get_param: [EndpointMap, IronicAdmin, protocol]
- ://
- str_replace:
template:
get_param: [EndpointMap, IronicAdmin, host]
params:
CLOUDNAME: {get_param: CloudName}
IP_ADDRESS: {get_param: IronicApiVirtualIP}
- ':'
- get_param: [EndpointMap, IronicAdmin, port]
- /v1
uri_no_suffix:
list_join:
- ''
- - get_param: [EndpointMap, IronicAdmin, protocol]
- ://
- str_replace:
template:
get_param: [EndpointMap, IronicAdmin, host]
params:
CLOUDNAME: {get_param: CloudName}
IP_ADDRESS: {get_param: IronicApiVirtualIP}
- ':'
- get_param: [EndpointMap, IronicAdmin, port]
IronicInternal:
host:
str_replace:
template:
get_param: [EndpointMap, IronicInternal, host]
params:
CLOUDNAME: {get_param: CloudName}
IP_ADDRESS: {get_param: IronicApiVirtualIP}
port:
get_param: [EndpointMap, IronicInternal, port]
protocol:
get_param: [EndpointMap, IronicInternal, protocol]
uri:
list_join:
- ''
- - get_param: [EndpointMap, IronicInternal, protocol]
- ://
- str_replace:
template:
get_param: [EndpointMap, IronicInternal, host]
params:
CLOUDNAME: {get_param: CloudName}
IP_ADDRESS: {get_param: IronicApiVirtualIP}
- ':'
- get_param: [EndpointMap, IronicInternal, port]
- /v1
uri_no_suffix:
list_join:
- ''
- - get_param: [EndpointMap, IronicInternal, protocol]
- ://
- str_replace:
template:
get_param: [EndpointMap, IronicInternal, host]
params:
CLOUDNAME: {get_param: CloudName}
IP_ADDRESS: {get_param: IronicApiVirtualIP}
- ':'
- get_param: [EndpointMap, IronicInternal, port]
IronicPublic:
host:
str_replace:
template:
get_param: [EndpointMap, IronicPublic, host]
params:
CLOUDNAME: {get_param: CloudName}
IP_ADDRESS: {get_param: PublicVirtualIP}
port:
get_param: [EndpointMap, IronicPublic, port]
protocol:
get_param: [EndpointMap, IronicPublic, protocol]
uri:
list_join:
- ''
- - get_param: [EndpointMap, IronicPublic, protocol]
- ://
- str_replace:
template:
get_param: [EndpointMap, IronicPublic, host]
params:
CLOUDNAME: {get_param: CloudName}
IP_ADDRESS: {get_param: PublicVirtualIP}
- ':'
- get_param: [EndpointMap, IronicPublic, port]
- /v1
uri_no_suffix:
list_join:
- ''
- - get_param: [EndpointMap, IronicPublic, protocol]
- ://
- str_replace:
template:
get_param: [EndpointMap, IronicPublic, host]
params:
CLOUDNAME: {get_param: CloudName}
IP_ADDRESS: {get_param: PublicVirtualIP}
- ':'
- get_param: [EndpointMap, IronicPublic, port]
KeystoneAdmin: KeystoneAdmin:
host: host:
str_replace: str_replace:

View File

@ -132,6 +132,8 @@ resource_registry:
OS::TripleO::Services::HeatApiCfn: puppet/services/heat-api-cfn.yaml OS::TripleO::Services::HeatApiCfn: puppet/services/heat-api-cfn.yaml
OS::TripleO::Services::HeatApiCloudwatch: puppet/services/heat-api-cloudwatch.yaml OS::TripleO::Services::HeatApiCloudwatch: puppet/services/heat-api-cloudwatch.yaml
OS::TripleO::Services::HeatEngine: puppet/services/heat-engine.yaml OS::TripleO::Services::HeatEngine: puppet/services/heat-engine.yaml
OS::TripleO::Services::IronicApi: puppet/services/ironic-api.yaml
OS::TripleO::Services::IronicConductor: puppet/services/ironic-conductor.yaml
OS::TripleO::Services::NeutronDhcpAgent: puppet/services/neutron-dhcp.yaml OS::TripleO::Services::NeutronDhcpAgent: puppet/services/neutron-dhcp.yaml
OS::TripleO::Services::NeutronL3Agent: puppet/services/neutron-l3.yaml OS::TripleO::Services::NeutronL3Agent: puppet/services/neutron-l3.yaml
OS::TripleO::Services::NeutronMetadataAgent: puppet/services/neutron-metadata.yaml OS::TripleO::Services::NeutronMetadataAgent: puppet/services/neutron-metadata.yaml

View File

@ -538,6 +538,7 @@ parameters:
CinderIscsiNetwork: storage CinderIscsiNetwork: storage
GlanceApiNetwork: storage GlanceApiNetwork: storage
GlanceRegistryNetwork: internal_api GlanceRegistryNetwork: internal_api
IronicApiNetwork: internal_api
KeystoneAdminApiNetwork: ctlplane # allows undercloud to config endpoints KeystoneAdminApiNetwork: ctlplane # allows undercloud to config endpoints
KeystonePublicApiNetwork: internal_api KeystonePublicApiNetwork: internal_api
NeutronApiNetwork: internal_api NeutronApiNetwork: internal_api
@ -795,6 +796,7 @@ resources:
GlanceRegistryVirtualIP: {get_attr: [VipMap, net_ip_uri_map, {get_param: [ServiceNetMap, GlanceRegistryNetwork]}]} GlanceRegistryVirtualIP: {get_attr: [VipMap, net_ip_uri_map, {get_param: [ServiceNetMap, GlanceRegistryNetwork]}]}
GnocchiApiVirtualIP: {get_attr: [VipMap, net_ip_uri_map, {get_param: [ServiceNetMap, GnocchiApiNetwork]}]} GnocchiApiVirtualIP: {get_attr: [VipMap, net_ip_uri_map, {get_param: [ServiceNetMap, GnocchiApiNetwork]}]}
HeatApiVirtualIP: {get_attr: [VipMap, net_ip_uri_map, {get_param: [ServiceNetMap, HeatApiNetwork]}]} HeatApiVirtualIP: {get_attr: [VipMap, net_ip_uri_map, {get_param: [ServiceNetMap, HeatApiNetwork]}]}
IronicApiVirtualIP: {get_attr: [VipMap, net_ip_uri_map, {get_param: [ServiceNetMap, IronicApiNetwork]}]}
KeystoneAdminApiVirtualIP: {get_attr: [VipMap, net_ip_uri_map, {get_param: [ServiceNetMap, KeystoneAdminApiNetwork]}]} KeystoneAdminApiVirtualIP: {get_attr: [VipMap, net_ip_uri_map, {get_param: [ServiceNetMap, KeystoneAdminApiNetwork]}]}
KeystonePublicApiVirtualIP: {get_attr: [VipMap, net_ip_uri_map, {get_param: [ServiceNetMap, KeystonePublicApiNetwork]}]} KeystonePublicApiVirtualIP: {get_attr: [VipMap, net_ip_uri_map, {get_param: [ServiceNetMap, KeystonePublicApiNetwork]}]}
MysqlVirtualIP: {get_attr: [VipMap, net_ip_uri_map, {get_param: [ServiceNetMap, MysqlNetwork]}]} MysqlVirtualIP: {get_attr: [VipMap, net_ip_uri_map, {get_param: [ServiceNetMap, MysqlNetwork]}]}
@ -1151,6 +1153,7 @@ resources:
keystone_public_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, KeystonePublicApiNetwork]}]} keystone_public_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, KeystonePublicApiNetwork]}]}
keystone_admin_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, KeystoneAdminApiNetwork]}]} keystone_admin_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, KeystoneAdminApiNetwork]}]}
sahara_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, SaharaApiNetwork]}]} sahara_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, SaharaApiNetwork]}]}
ironic_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, IronicApiNetwork]}]}
DeployIdentifier: {get_param: DeployIdentifier} DeployIdentifier: {get_param: DeployIdentifier}
UpdateIdentifier: {get_param: UpdateIdentifier} UpdateIdentifier: {get_param: UpdateIdentifier}
@ -1274,6 +1277,7 @@ resources:
public_virtual_ip: {get_attr: [VipMap, net_ip_map, external]} public_virtual_ip: {get_attr: [VipMap, net_ip_map, external]}
internal_api_virtual_ip: {get_attr: [VipMap, net_ip_map, internal_api]} internal_api_virtual_ip: {get_attr: [VipMap, net_ip_map, internal_api]}
sahara_api_vip: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, SaharaApiNetwork]}]} sahara_api_vip: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, SaharaApiNetwork]}]}
ironic_api_vip: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, IronicApiNetwork]}]}
storage_virtual_ip: {get_attr: [VipMap, net_ip_map, storage]} storage_virtual_ip: {get_attr: [VipMap, net_ip_map, storage]}
storage_mgmt_virtual_ip: {get_attr: [VipMap, net_ip_map, storage_mgmt]} storage_mgmt_virtual_ip: {get_attr: [VipMap, net_ip_map, storage_mgmt]}
@ -1545,6 +1549,9 @@ outputs:
HeatInternalVip: HeatInternalVip:
description: VIP for Heat API internal endpoint description: VIP for Heat API internal endpoint
value: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, HeatApiNetwork]}]} value: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, HeatApiNetwork]}]}
IronicInternalVip:
description: VIP for Ironic API internal endpoint
value: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, IronicApiNetwork]}]}
KeystoneInternalVip: KeystoneInternalVip:
description: VIP for Keystone API internal endpoint description: VIP for Keystone API internal endpoint
value: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, KeystonePublicApiNetwork]}]} value: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, KeystonePublicApiNetwork]}]}

View File

@ -56,6 +56,8 @@ parameters:
type: comma_delimited_list type: comma_delimited_list
sahara_api_node_ips: sahara_api_node_ips:
type: comma_delimited_list type: comma_delimited_list
ironic_api_node_ips:
type: comma_delimited_list
DeployIdentifier: DeployIdentifier:
type: string type: string
@ -294,6 +296,14 @@ resources:
list_join: list_join:
- "','" - "','"
- {get_param: sahara_api_node_ips} - {get_param: sahara_api_node_ips}
ironic_api_node_ips:
str_replace:
template: "['SERVERS_LIST']"
params:
SERVERS_LIST:
list_join:
- "','"
- {get_param: ironic_api_node_ips}
# NOTE(gfidente): interpolation with %{} in the # NOTE(gfidente): interpolation with %{} in the
# hieradata file can't be used as it returns string # hieradata file can't be used as it returns string
@ -306,6 +316,7 @@ resources:
nova::rabbit_hosts: *rabbit_nodes_array nova::rabbit_hosts: *rabbit_nodes_array
keystone::rabbit_hosts: *rabbit_nodes_array keystone::rabbit_hosts: *rabbit_nodes_array
sahara::rabbit_hosts: *rabbit_nodes_array sahara::rabbit_hosts: *rabbit_nodes_array
ironic::rabbit_hosts: *rabbit_nodes_array
deploy_identifier: {get_param: DeployIdentifier} deploy_identifier: {get_param: DeployIdentifier}
update_identifier: {get_param: UpdateIdentifier} update_identifier: {get_param: UpdateIdentifier}

View File

@ -793,6 +793,7 @@ resources:
ceph_cluster_network: {get_attr: [NetIpMap, net_ip_subnet_map, {get_param: [ServiceNetMap, CephClusterNetwork]}]} ceph_cluster_network: {get_attr: [NetIpMap, net_ip_subnet_map, {get_param: [ServiceNetMap, CephClusterNetwork]}]}
ceph_public_network: {get_attr: [NetIpMap, net_ip_subnet_map, {get_param: [ServiceNetMap, CephPublicNetwork]}]} ceph_public_network: {get_attr: [NetIpMap, net_ip_subnet_map, {get_param: [ServiceNetMap, CephPublicNetwork]}]}
ceph_public_ip: {get_attr: [NetIpMap, net_ip_map, {get_param: [ServiceNetMap, CephPublicNetwork]}]} ceph_public_ip: {get_attr: [NetIpMap, net_ip_map, {get_param: [ServiceNetMap, CephPublicNetwork]}]}
ironic_api_network: {get_attr: [NetIpMap, net_ip_map, {get_param: [ServiceNetMap, IronicApiNetwork]}]}
# Map heat metadata into hiera datafiles # Map heat metadata into hiera datafiles
ControllerConfig: ControllerConfig:

View File

@ -53,6 +53,14 @@ heat::db::mysql::allowed_hosts:
- '%' - '%'
- "%{hiera('mysql_bind_host')}" - "%{hiera('mysql_bind_host')}"
# Ironic
ironic::db::mysql::user: ironic
ironic::db::mysql::host: "%{hiera('mysql_virtual_ip')}"
ironic::db::mysql::dbname: ironic
ironic::db::mysql::allowed_hosts:
- '%'
- "%{hiera('mysql_bind_host')}"
# Ceilometer # Ceilometer
ceilometer::db::mysql::user: ceilometer ceilometer::db::mysql::user: ceilometer
ceilometer::db::mysql::host: "%{hiera('mysql_virtual_ip')}" ceilometer::db::mysql::host: "%{hiera('mysql_virtual_ip')}"

View File

@ -0,0 +1,43 @@
heat_template_version: 2016-04-08
description: >
OpenStack Ironic API configured with Puppet
parameters:
EndpointMap:
default: {}
description: Mapping of service endpoint -> protocol. Typically set
via parameter_defaults in the resource registry.
type: json
IronicPassword:
description: The password for the Ironic service and db account, used by the Ironic services
type: string
hidden: true
resources:
IronicBase:
type: ./ironic-base.yaml
properties:
EndpointMap: {get_param: EndpointMap}
outputs:
role_data:
description: Role data for the Ironic API role.
value:
config_settings:
map_merge:
- get_attr: [IronicBase, role_data, config_settings]
# NOTE(dtantsur): the my_ip parameter is heavily overloaded in
# ironic. It's used as a default value for e.g. TFTP server IP,
# glance and neutron endpoints, virtual console IP. We override
# the TFTP server IP in ironic-conductor.yaml as it should not be
# the VIP, but rather a real IP of the controller.
- ironic::my_ip: {get_param: [EndpointMap, MysqlInternal, host]}
ironic::api::admin_password: {get_param: IronicPassword}
ironic::keystone::auth::public_url: {get_param: [EndpointMap, IronicPublic, uri]}
ironic::keystone::auth::internal_url: {get_param: [EndpointMap, IronicInternal, uri]}
ironic::keystone::auth::admin_url: {get_param: [EndpointMap, IronicAdmin, uri]}
ironic::keystone::auth::password: {get_param: IronicPassword }
step_config: |
include ::tripleo::profile::base::ironic::api

View File

@ -0,0 +1,64 @@
heat_template_version: 2016-04-08
description: >
OpenStack Ironic services configured with Puppet
parameters:
EndpointMap:
default: {}
description: Mapping of service endpoint -> protocol. Typically set
via parameter_defaults in the resource registry.
type: json
Debug:
default: ''
description: Set to True to enable debugging on all services.
type: string
IronicPassword:
description: The password for the Ironic service and db account, used by the Ironic services
type: string
hidden: true
RabbitUserName:
default: guest
description: The username for RabbitMQ
type: string
RabbitPassword:
description: The password for RabbitMQ
type: string
hidden: true
RabbitClientPort:
default: 5672
description: Set rabbit subscriber port, change this if using SSL
type: number
RabbitClientUseSSL:
default: false
description: >
Rabbit client subscriber parameter to specify
an SSL connection to the RabbitMQ host.
type: string
outputs:
role_data:
description: Role data for the Ironic role.
value:
config_settings:
ironic_dsn: &ironic_dsn
list_join:
- ''
- - {get_param: [EndpointMap, MysqlInternal, protocol]}
- '://ironic:'
- {get_param: IronicPassword}
- '@'
- {get_param: [EndpointMap, MysqlInternal, host]}
- '/ironic'
ironic::admin_tenant_name: 'service'
ironic::database_connection: *ironic_dsn
ironic::debug: {get_param: Debug}
ironic::rabbit_userid: {get_param: RabbitUserName}
ironic::rabbit_password: {get_param: RabbitPassword}
ironic::rabbit_port: {get_param: RabbitClientPort}
ironic::rabbit_use_ssl: {get_param: RabbitClientUseSSL}
ironic::db::mysql::password: {get_param: IronicPassword}
ironic::keystone::auth::tenant: 'service'
step_config: |
include ::tripleo::profile::base::ironic

View File

@ -0,0 +1,36 @@
heat_template_version: 2016-04-08
description: >
OpenStack Ironic conductor configured with Puppet
parameters:
EndpointMap:
default: {}
description: Mapping of service endpoint -> protocol. Typically set
via parameter_defaults in the resource registry.
type: json
IronicEnabledDrivers:
default: ['pxe_ipmitool', 'agent_ipmitool']
description: Enabled Ironic drivers
type: comma_delimited_list
resources:
IronicBase:
type: ./ironic-base.yaml
properties:
EndpointMap: {get_param: EndpointMap}
outputs:
role_data:
description: Role data for the Ironic conductor role.
value:
config_settings:
map_merge:
- get_attr: [IronicBase, role_data, config_settings]
- ironic::enabled_drivers: {get_param: IronicEnabledDrivers}
# Prevent tftp_server from defaulting to my_ip setting, which is
# controller VIP, not a real IP.
ironic::drivers::pxe::tftp_server: {get_input: ironic_api_network}
step_config: |
include ::tripleo::profile::base::ironic::conductor

View File

@ -37,6 +37,7 @@ resources:
internal_api_virtual_ip: {get_input: internal_api_virtual_ip} internal_api_virtual_ip: {get_input: internal_api_virtual_ip}
storage_virtual_ip: {get_input: storage_virtual_ip} storage_virtual_ip: {get_input: storage_virtual_ip}
storage_mgmt_virtual_ip: {get_input: storage_mgmt_virtual_ip} storage_mgmt_virtual_ip: {get_input: storage_mgmt_virtual_ip}
ironic_api_vip: {get_input: ironic_api_vip}
# public_virtual_ip and controller_virtual_ip are needed in # public_virtual_ip and controller_virtual_ip are needed in
# both HAproxy & keepalived. # both HAproxy & keepalived.
tripleo::haproxy::public_virtual_ip: {get_input: public_virtual_ip} tripleo::haproxy::public_virtual_ip: {get_input: public_virtual_ip}