Adds OpenDaylight HA (OVSDB Clustering)
[apex.git] / build / opnfv-tripleo-heat-templates.patch
1 From 516a741efddd1276d2b02010a7095737b6ce49cf Mon Sep 17 00:00:00 2001
2 From: Tim Rozet <tdrozet@gmail.com>
3 Date: Tue, 12 Jan 2016 16:49:57 -0500
4 Subject: [PATCH] Adds current opnfv patch with ODL and ONOS support
5
6 ---
7  environments/onos.yaml                             |   8 +
8  environments/opendaylight-external.yaml            |  25 ++
9  environments/opendaylight.yaml                     |  26 ++
10  environments/opendaylight_l3.yaml                  |   9 +
11  environments/opendaylight_sdnvpn.yaml              |  29 ++
12  environments/opendaylight_sfc.yaml                 |  28 ++
13  network/endpoints/endpoint_map.yaml                |  31 ++
14  overcloud-resource-registry-puppet.yaml            |   3 +
15  overcloud-without-mergepy.yaml                     | 103 +++++
16  puppet/all-nodes-config.yaml                       |  27 ++
17  puppet/compute.yaml                                |  41 ++
18  puppet/controller.yaml                             | 104 ++++-
19  puppet/hieradata/common.yaml                       |   1 +
20  puppet/hieradata/controller.yaml                   |   5 +-
21  puppet/manifests/overcloud_compute.pp              |  49 ++-
22  puppet/manifests/overcloud_controller.pp           | 130 +++++-
23  puppet/manifests/overcloud_controller_pacemaker.pp | 482 ++++++++++++++-------
24  puppet/manifests/overcloud_opendaylight.pp         |  27 ++
25  puppet/opendaylight-puppet.yaml                    | 223 ++++++++++
26  puppet/vip-config.yaml                             |   1 +
27  20 files changed, 1190 insertions(+), 162 deletions(-)
28  create mode 100644 environments/onos.yaml
29  create mode 100644 environments/opendaylight-external.yaml
30  create mode 100644 environments/opendaylight.yaml
31  create mode 100644 environments/opendaylight_l3.yaml
32  create mode 100644 environments/opendaylight_sdnvpn.yaml
33  create mode 100644 environments/opendaylight_sfc.yaml
34  create mode 100644 puppet/manifests/overcloud_opendaylight.pp
35  create mode 100644 puppet/opendaylight-puppet.yaml
36
37 diff --git a/environments/onos.yaml b/environments/onos.yaml
38 new file mode 100644
39 index 0000000..510aca9
40 --- /dev/null
41 +++ b/environments/onos.yaml
42 @@ -0,0 +1,8 @@
43 +parameters:
44 +    #This a bug for odl deployment. Once bug fixed OpenDaylightCount can be remove.
45 +    OpenDaylightCount: 0
46 +    NeutronL3HA: false
47 +    ExtraConfig:
48 +      neutron_service_plugins: ['onos_router']
49 +      neutron_mechanism_drivers: ['onos_ml2']
50 +      neutron_tenant_network_type: vxlan
51 diff --git a/environments/opendaylight-external.yaml b/environments/opendaylight-external.yaml
52 new file mode 100644
53 index 0000000..411df21
54 --- /dev/null
55 +++ b/environments/opendaylight-external.yaml
56 @@ -0,0 +1,25 @@
57 +# Environment file used to enable OpenDaylight
58 +# Currently uses overcloud image that is assumed
59 +# to be virt-customized with ODL RPM already on it
60 +
61 +# These parameters customize the OpenDaylight Node
62 +# The user name and password are for the ODL service
63 +# Defaults are included here for reference
64 +#parameter_defaults:
65 +#  OpenDaylightFlavor: baremetal
66 +#  OpenDaylightHostname: opendaylight-server
67 +#  OpenDaylightImage: overcloud-full
68 +#  OpenDaylightUsername: admin
69 +#  OpenDaylightPassword: admin
70 +
71 +parameters:
72 +    # increase this if you need more ODL nodes
73 +    OpenDaylightCount: 1
74 +    NeutronL3HA: false
75 +    ExtraConfig:
76 +      neutron_mechanism_drivers: ['opendaylight']
77 +      neutron_tenant_network_type: vxlan
78 +      # Enable this if you want OpenDaylight on the contollers
79 +      # reduce OpenDaylightCount to 0 if you don't want any
80 +      # OpenDaylight only nodes
81 +      #opendaylight_install: true
82 diff --git a/environments/opendaylight.yaml b/environments/opendaylight.yaml
83 new file mode 100644
84 index 0000000..cfa4ad3
85 --- /dev/null
86 +++ b/environments/opendaylight.yaml
87 @@ -0,0 +1,26 @@
88 +# Environment file used to enable OpenDaylight
89 +# Currently uses overcloud image that is assumed
90 +# to be virt-customized with ODL RPM already on it
91 +
92 +# These parameters customize the OpenDaylight Node
93 +# The user name and password are for the ODL service
94 +# Defaults are included here for reference
95 +#parameter_defaults:
96 +#  OpenDaylightFlavor: baremetal
97 +#  OpenDaylightHostname: opendaylight-server
98 +#  OpenDaylightImage: overcloud-full
99 +#  OpenDaylightUsername: admin
100 +#  OpenDaylightPassword: admin
101 +
102 +parameters:
103 +    # increase this if you need more ODL nodes
104 +    # OpenDaylightCount: 1
105 +    NeutronL3HA: false
106 +    OpenDaylightEnableHA: true
107 +    ExtraConfig:
108 +      neutron_mechanism_drivers: ['opendaylight']
109 +      neutron_tenant_network_type: vxlan
110 +      # Enable this if you want OpenDaylight on the contollers
111 +      # reduce OpenDaylightCount to 0 if you don't want any
112 +      # OpenDaylight only nodes
113 +      opendaylight_install: true
114 diff --git a/environments/opendaylight_l3.yaml b/environments/opendaylight_l3.yaml
115 new file mode 100644
116 index 0000000..05c0aff
117 --- /dev/null
118 +++ b/environments/opendaylight_l3.yaml
119 @@ -0,0 +1,9 @@
120 +parameters:
121 +    #NeutronEnableL3Agent: false
122 +    NeutronEnableForceMetadata: true
123 +    OpenDaylightEnableL3: "'yes'"
124 +    NeutronServicePlugins: "networking_odl.l3.l3_odl.OpenDaylightL3RouterPlugin"
125 +    ExtraConfig:
126 +      neutron_mechanism_drivers: ['opendaylight']
127 +      neutron_tenant_network_type: vxlan
128 +      opendaylight_install: true
129 diff --git a/environments/opendaylight_sdnvpn.yaml b/environments/opendaylight_sdnvpn.yaml
130 new file mode 100644
131 index 0000000..3a14975
132 --- /dev/null
133 +++ b/environments/opendaylight_sdnvpn.yaml
134 @@ -0,0 +1,29 @@
135 +# Environment file used to enable OpenDaylight
136 +# Currently uses overcloud image that is assumed
137 +# to be virt-customized with ODL RPM already on it
138 +
139 +# These parameters customize the OpenDaylight Node
140 +# The user name and password are for the ODL service
141 +# Defaults are included here for reference
142 +#parameter_defaults:
143 +#  OpenDaylightFlavor: baremetal
144 +#  OpenDaylightHostname: opendaylight-server
145 +#  OpenDaylightImage: overcloud-full
146 +#  OpenDaylightUsername: admin
147 +#  OpenDaylightPassword: admin
148 +
149 +parameters:
150 +    # increase this if you need more ODL nodes
151 +    # OpenDaylightCount: 1
152 +    ControllerEnableSwiftStorage: false
153 +    OpenDaylightFeatures: "odl-ovsdb-openstack,odl-vpnservice-api,odl-vpnservice-impl,odl-vpnservice-impl-rest,odl-vpnservice-impl-ui,odl-vpnservice-core"
154 +    NeutronL3HA: false
155 +    NeutronServicePlugins: "router,qos,networking_bgpvpn.neutron.services.plugin.BGPVPNPlugin"
156 +    ExtraConfig:
157 +      tripleo::ringbuilder::build_ring: False
158 +      neutron_mechanism_drivers: ['opendaylight']
159 +      neutron_tenant_network_type: vxlan
160 +      # Enable this if you want OpenDaylight on the contollers
161 +      # reduce OpenDaylightCount to 0 if you don't want any
162 +      # OpenDaylight only nodes
163 +      opendaylight_install: true
164 diff --git a/environments/opendaylight_sfc.yaml b/environments/opendaylight_sfc.yaml
165 new file mode 100644
166 index 0000000..3dd1e13
167 --- /dev/null
168 +++ b/environments/opendaylight_sfc.yaml
169 @@ -0,0 +1,28 @@
170 +# Environment file used to enable OpenDaylight
171 +# Currently uses overcloud image that is assumed
172 +# to be virt-customized with ODL RPM already on it
173 +
174 +# These parameters customize the OpenDaylight Node
175 +# The user name and password are for the ODL service
176 +# Defaults are included here for reference
177 +#parameter_defaults:
178 +#  OpenDaylightFlavor: baremetal
179 +#  OpenDaylightHostname: opendaylight-server
180 +#  OpenDaylightImage: overcloud-full
181 +#  OpenDaylightUsername: admin
182 +#  OpenDaylightPassword: admin
183 +
184 +parameters:
185 +    # increase this if you need more ODL nodes
186 +    # OpenDaylightCount: 1
187 +    ControllerEnableSwiftStorage: false
188 +    OpenDaylightFeatures: "odl-ovsdb-sfc-rest"
189 +    NeutronL3HA: false
190 +    ExtraConfig:
191 +      tripleo::ringbuilder::build_ring: False
192 +      neutron_mechanism_drivers: ['opendaylight']
193 +      neutron_tenant_network_type: vxlan
194 +      # Enable this if you want OpenDaylight on the contollers
195 +      # reduce OpenDaylightCount to 0 if you don't want any
196 +      # OpenDaylight only nodes
197 +      opendaylight_install: true
198 diff --git a/network/endpoints/endpoint_map.yaml b/network/endpoints/endpoint_map.yaml
199 index 0521401..7caa91b 100644
200 --- a/network/endpoints/endpoint_map.yaml
201 +++ b/network/endpoints/endpoint_map.yaml
202 @@ -4,6 +4,9 @@ description: >
203    A Map of OpenStack Endpoints
204  
205  parameters:
206 +  AodhApiVirtualIP:
207 +    type: string
208 +    default: ''
209    CeilometerApiVirtualIP:
210      type: string
211      default: ''
212 @@ -43,6 +46,9 @@ parameters:
213    EndpointMap:
214      type: json
215      default:
216 +      AodhAdmin: {protocol: 'http', port: '8042', host: 'IP_ADDRESS'}
217 +      AodhInternal: {protocol: 'http', port: '8042', host: 'IP_ADDRESS'}
218 +      AodhPublic: {protocol: 'http', port: '8042', host: 'IP_ADDRESS'}
219        CeilometerAdmin: {protocol: 'http', port: '8777', host: 'IP_ADDRESS'}
220        CeilometerInternal: {protocol: 'http', port: '8777', host: 'IP_ADDRESS'}
221        CeilometerPublic: {protocol: 'http', port: '8777', host: 'IP_ADDRESS'}
222 @@ -83,6 +89,28 @@ parameters:
223  
224  resources:
225  
226 +  AodhInternal:
227 +    type: OS::TripleO::Endpoint
228 +    properties:
229 +      EndpointName: AodhInternal
230 +      EndpointMap: { get_param: EndpointMap }
231 +      CloudName: {get_param: CloudName}
232 +      IP: {get_param: AodhApiVirtualIP}
233 +  AodhPublic:
234 +    type: OS::TripleO::Endpoint
235 +    properties:
236 +      EndpointName: AodhPublic
237 +      EndpointMap: { get_param: EndpointMap }
238 +      CloudName: {get_param: CloudName}
239 +      IP: {get_param: PublicVirtualIP}
240 +  AodhAdmin:
241 +    type: OS::TripleO::Endpoint
242 +    properties:
243 +      EndpointName: AodhAdmin
244 +      EndpointMap: { get_param: EndpointMap }
245 +      CloudName: {get_param: CloudName}
246 +      IP: {get_param: AodhApiVirtualIP}
247 +
248    CeilometerInternal:
249      type: OS::TripleO::Endpoint
250      properties:
251 @@ -407,6 +435,9 @@ resources:
252  outputs:
253    endpoint_map:
254      value:
255 +      AodhInternal: {get_attr: [ AodhInternal, endpoint] }
256 +      AodhPublic: {get_attr: [ AodhPublic, endpoint] }
257 +      AodhAdmin: {get_attr: [ AodhAdmin, endpoint] }
258        CeilometerInternal: {get_attr: [ CeilometerInternal, endpoint] }
259        CeilometerPublic: {get_attr: [ CeilometerPublic, endpoint] }
260        CeilometerAdmin: {get_attr: [ CeilometerAdmin, endpoint] }
261 diff --git a/overcloud-resource-registry-puppet.yaml b/overcloud-resource-registry-puppet.yaml
262 index 4cfed6b..adecc79 100644
263 --- a/overcloud-resource-registry-puppet.yaml
264 +++ b/overcloud-resource-registry-puppet.yaml
265 @@ -27,6 +27,9 @@ resource_registry:
266    # To disable, replace with firstboot/userdata_default.yaml
267    OS::TripleO::NodeAdminUserData: firstboot/userdata_heat_admin.yaml
268  
269 +  # This configures OpenDaylight to drive the network
270 +  OS::TripleO::OpenDaylightNode: puppet/opendaylight-puppet.yaml
271 +
272    # Hooks for operator extra config
273    # NodeUserData == Cloud-init additional user-data, e.g cloud-config
274    # ControllerExtraConfigPre == Controller configuration pre service deployment
275 diff --git a/overcloud-without-mergepy.yaml b/overcloud-without-mergepy.yaml
276 index a532c2f..9c6e3cd 100644
277 --- a/overcloud-without-mergepy.yaml
278 +++ b/overcloud-without-mergepy.yaml
279 @@ -15,6 +15,11 @@ parameters:
280      description: The password for the keystone admin account, used for monitoring, querying neutron etc.
281      type: string
282      hidden: true
283 +  AodhPassword:
284 +    default: unset
285 +    description: The password for the aodh services
286 +    type: string
287 +    hidden: true
288    CeilometerBackend:
289      default: 'mongodb'
290      description: The ceilometer backend type.
291 @@ -113,6 +118,10 @@ parameters:
292      default: ''
293      type: string
294      description: Neutron ID for ctlplane network.
295 +  NeutronEnableForceMetadata:
296 +    default: 'False'
297 +    description: If True, DHCP always provides metadata route to VM.
298 +    type: string
299    NeutronEnableTunnelling:
300      type: string
301      default: "True"
302 @@ -227,6 +236,35 @@ parameters:
303      default: false
304      description: Should MongoDb journaling be disabled
305      type: boolean
306 +  OpenDaylightPort:
307 +    default: 8081
308 +    description: Set opendaylight service port
309 +    type: number
310 +  OpenDaylightEnableL3:
311 +    description: Knob to enable/disable ODL L3
312 +    type: string
313 +    default: 'no'
314 +  OpenDaylightEnableHA:
315 +    description: Knob to enable/disable ODL HA
316 +    type: boolean
317 +    default: false
318 +  OpenDaylightFeatures:
319 +    description: List of features to install with ODL
320 +    type: comma_delimited_list
321 +    default: "odl-ovsdb-openstack"
322 +  OpenDaylightInstall:
323 +    default: false
324 +    description: Whether to install OpenDaylight on the control nodes.
325 +    type: boolean
326 +  OpenDaylightUsername:
327 +    default: 'admin'
328 +    description: The username for the opendaylight server.
329 +    type: string
330 +  OpenDaylightPassword:
331 +    default: 'admin'
332 +    type: string
333 +    description: The password for the opendaylight server.
334 +    hidden: true
335    PublicVirtualFixedIPs:
336      default: []
337      description: >
338 @@ -575,6 +613,8 @@ parameters:
339      default:
340        NeutronTenantNetwork: tenant
341        CeilometerApiNetwork: internal_api
342 +      AodhApiNetwork: internal_api
343 +      OpenDaylightNetwork: internal_api
344        MongoDbNetwork: internal_api
345        CinderApiNetwork: internal_api
346        CinderIscsiNetwork: storage
347 @@ -664,6 +704,18 @@ parameters:
348        structure as ExtraConfig.
349      type: json
350  
351 +# OpenDaylight specific parameters
352 +  OpenDaylightCount:
353 +    type: number
354 +    default: 0
355 +  OpenDaylightImage:
356 +    default: overcloud-full
357 +    type: string
358 +  OpenDaylightFlavor:
359 +    default: baremetal
360 +    description: Flavor for OpenDaylight node
361 +    type: string
362 +
363    # Hostname format for each role
364    # Note %index% is translated into the index of the node, e.g 0/1/2 etc
365    # and %stackname% is replaced with OS::stack_name in the template below.
366 @@ -688,6 +740,10 @@ parameters:
367      type: string
368      description: Format for CephStorage node hostnames
369      default: '%stackname%-cephstorage-%index%'
370 +  OpenDaylightHostnameFormat:
371 +    type: string
372 +    description: Format for OpenDaylight node hostnames
373 +    default: '%stackname%-opendaylight-%index%'
374  
375    # Identifiers to trigger tasks on nodes
376    UpdateIdentifier:
377 @@ -758,6 +814,7 @@ resources:
378      properties:
379        CloudName: {get_param: CloudName}
380        CeilometerApiVirtualIP: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, CeilometerApiNetwork]}]}
381 +      AodhApiVirtualIP: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, AodhApiNetwork]}]}
382        CinderApiVirtualIP: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, CinderApiNetwork]}]}
383        GlanceApiVirtualIP: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, GlanceApiNetwork]}]}
384        GlanceRegistryVirtualIP: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, GlanceRegistryNetwork]}]}
385 @@ -770,6 +827,29 @@ resources:
386        SwiftProxyVirtualIP: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, SwiftProxyNetwork]}]}
387        PublicVirtualIP: {get_attr: [VipMap, net_ip_map, external]}
388  
389 +  OpenDaylightNode:
390 +    type: OS::Heat::ResourceGroup
391 +    depends_on: Networks
392 +    properties:
393 +      count: {get_param: OpenDaylightCount}
394 +      removal_policies: {get_param: ComputeRemovalPolicies}
395 +      resource_def:
396 +        type: OS::TripleO::OpenDaylightNode
397 +        properties:
398 +          UpdateIdentifier: {get_param: UpdateIdentifier}
399 +          OpenDaylightFlavor: {get_param: OpenDaylightFlavor}
400 +          OpenDaylightImage: {get_param: OpenDaylightImage}
401 +          OpenDaylightPort: {get_param: OpenDaylightPort}
402 +          OpenDaylightUsername: {get_param: OpenDaylightUsername}
403 +          OpenDaylightFeatures: {get_param: OpenDaylightFeatures}
404 +          OpenDaylightPassword: {get_param: OpenDaylightPassword}
405 +          OpenDaylightEnableL3: {get_param: OpenDaylightEnableL3}
406 +          OpenDaylightHostname:
407 +            str_replace:
408 +              template: {get_param: OpenDaylightHostnameFormat}
409 +              params:
410 +                '%stackname%': {get_param: 'OS::stack_name'}
411 +
412    Controller:
413      type: OS::Heat::ResourceGroup
414      depends_on: Networks
415 @@ -781,6 +861,7 @@ resources:
416          properties:
417            AdminPassword: {get_param: AdminPassword}
418            AdminToken: {get_param: AdminToken}
419 +          AodhPassword: {get_param: AodhPassword}
420            CeilometerBackend: {get_param: CeilometerBackend}
421            CeilometerMeteringSecret: {get_param: CeilometerMeteringSecret}
422            CeilometerPassword: {get_param: CeilometerPassword}
423 @@ -832,6 +913,7 @@ resources:
424            NeutronBridgeMappings: {get_param: NeutronBridgeMappings}
425            NeutronExternalNetworkBridge: {get_param: NeutronExternalNetworkBridge}
426            NeutronEnableTunnelling: {get_param: NeutronEnableTunnelling}
427 +          NeutronEnableForceMetadata: {get_param: NeutronEnableForceMetadata}
428            NeutronNetworkVLANRanges: {get_param: NeutronNetworkVLANRanges}
429            NeutronPublicInterface: {get_param: NeutronPublicInterface}
430            NeutronPublicInterfaceDefaultRoute: {get_param: NeutronPublicInterfaceDefaultRoute}
431 @@ -853,6 +935,13 @@ resources:
432            NovaPassword: {get_param: NovaPassword}
433            NtpServer: {get_param: NtpServer}
434            MongoDbNoJournal: {get_param: MongoDbNoJournal}
435 +          OpenDaylightPort: {get_param: OpenDaylightPort}
436 +          OpenDaylightInstall: {get_param: OpenDaylightInstall}
437 +          OpenDaylightUsername: {get_param: OpenDaylightUsername}
438 +          OpenDaylightFeatures: {get_param: OpenDaylightFeatures}
439 +          OpenDaylightPassword: {get_param: OpenDaylightPassword}
440 +          OpenDaylightEnableL3: {get_param: OpenDaylightEnableL3}
441 +          OpenDaylightEnableHA: {get_param: OpenDaylightEnableHA}
442            PcsdPassword: {get_resource: PcsdPassword}
443            PublicVirtualInterface: {get_param: PublicVirtualInterface}
444            RabbitPassword: {get_param: RabbitPassword}
445 @@ -878,6 +967,8 @@ resources:
446            ServiceNetMap: {get_param: ServiceNetMap}
447            EndpointMap: {get_attr: [EndpointMap, endpoint_map]}
448            CeilometerApiVirtualIP: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, CeilometerApiNetwork]}]}
449 +          AodhApiVirtualIP: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, AodhApiNetwork]}]}
450 +          OpenDaylightApiVirtualIP: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, OpenDaylightApiNetwork]}]}
451            CinderApiVirtualIP: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, CinderApiNetwork]}]}
452            HeatApiVirtualIP: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, HeatApiNetwork]}]}
453            GlanceApiVirtualIP: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, GlanceApiNetwork]}]}
454 @@ -948,6 +1039,10 @@ resources:
455            NovaPublicIP: {get_attr: [PublicVirtualIP, ip_address]}
456            NovaPassword: {get_param: NovaPassword}
457            NtpServer: {get_param: NtpServer}
458 +          OpenDaylightPort: {get_param: OpenDaylightPort}
459 +          OpenDaylightUsername: {get_param: OpenDaylightUsername}
460 +          OpenDaylightPassword: {get_param: OpenDaylightPassword}
461 +          OpenDaylightEnableHA: {get_param: OpenDaylightEnableHA}
462            RabbitHost: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, RabbitMqNetwork]}]}
463            RabbitPassword: {get_param: RabbitPassword}
464            RabbitUserName: {get_param: RabbitUserName}
465 @@ -1068,6 +1163,7 @@ resources:
466        compute_hosts: {get_attr: [Compute, hosts_entry]}
467        controller_hosts: {get_attr: [Controller, hosts_entry]}
468        controller_ips: {get_attr: [Controller, ip_address]}
469 +      opendaylight_ip: {get_attr: [OpenDaylightNode, ip_address]}
470        block_storage_hosts: {get_attr: [BlockStorage, hosts_entry]}
471        object_storage_hosts: {get_attr: [ObjectStorage, hosts_entry]}
472        ceph_storage_hosts: {get_attr: [CephStorage, hosts_entry]}
473 @@ -1081,6 +1177,8 @@ resources:
474        heat_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, HeatApiNetwork]}]}
475        swift_proxy_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, SwiftProxyNetwork]}]}
476        ceilometer_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, CeilometerApiNetwork]}]}
477 +      aodh_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, AodhApiNetwork]}]}
478 +      opendaylight_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, OpenDaylightApiNetwork]}]}
479        nova_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, NovaApiNetwork]}]}
480        nova_metadata_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, NovaMetadataNetwork]}]}
481        glance_api_node_ips: {get_attr: [ControllerIpListMap, net_ip_map, {get_param: [ServiceNetMap, GlanceApiNetwork]}]}
482 @@ -1189,6 +1287,8 @@ resources:
483          nova_api_vip: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, NovaApiNetwork]}]}
484          nova_metadata_vip: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, NovaMetadataNetwork]}]}
485          ceilometer_api_vip: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, CeilometerApiNetwork]}]}
486 +        aodh_api_vip: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, AodhApiNetwork]}]}
487 +        opendaylight_api_vip: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, OpenDaylightApiNetwork]}]}
488          heat_api_vip: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, HeatApiNetwork]}]}
489          horizon_vip: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, HorizonNetwork]}]}
490          redis_vip: {get_attr: [RedisVirtualIP, ip_address]}
491 @@ -1434,6 +1534,9 @@ outputs:
492    PublicVip:
493      description: Controller VIP for public API endpoints
494      value: {get_attr: [PublicVirtualIP, ip_address]}
495 +  AodhInternalVip:
496 +    description: VIP for Aodh API internal endpoint
497 +    value: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, AodhApiNetwork]}]}
498    CeilometerInternalVip:
499      description: VIP for Ceilometer API internal endpoint
500      value: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, CeilometerApiNetwork]}]}
501 diff --git a/puppet/all-nodes-config.yaml b/puppet/all-nodes-config.yaml
502 index 2bc519b..1ebaff5 100644
503 --- a/puppet/all-nodes-config.yaml
504 +++ b/puppet/all-nodes-config.yaml
505 @@ -8,6 +8,8 @@ parameters:
506      type: comma_delimited_list
507    controller_ips:
508      type: comma_delimited_list
509 +  opendaylight_ip:
510 +    type: comma_delimited_list
511    block_storage_hosts:
512      type: comma_delimited_list
513    object_storage_hosts:
514 @@ -34,6 +36,10 @@ parameters:
515      type: comma_delimited_list
516    ceilometer_api_node_ips:
517      type: comma_delimited_list
518 +  aodh_api_node_ips:
519 +    type: comma_delimited_list
520 +  opendaylight_api_node_ips:
521 +    type: comma_delimited_list
522    nova_api_node_ips:
523      type: comma_delimited_list
524    nova_metadata_node_ips:
525 @@ -82,6 +88,10 @@ resources:
526                raw_data: {get_file: hieradata/RedHat.yaml}
527              all_nodes:
528                mapped_data:
529 +                opendaylight_controller_ip:
530 +                  list_join:
531 +                  - ','
532 +                  - {get_param: opendaylight_ip}
533                  controller_node_ips:
534                    list_join:
535                    - ','
536 @@ -166,6 +176,22 @@ resources:
537                          list_join:
538                          - "','"
539                          - {get_param: ceilometer_api_node_ips}
540 +                aodh_api_node_ips:
541 +                  str_replace:
542 +                    template: "['SERVERS_LIST']"
543 +                    params:
544 +                      SERVERS_LIST:
545 +                        list_join:
546 +                        - "','"
547 +                        - {get_param: aodh_api_node_ips}
548 +                opendaylight_api_node_ips:
549 +                  str_replace:
550 +                    template: "['SERVERS_LIST']"
551 +                    params:
552 +                      SERVERS_LIST:
553 +                        list_join:
554 +                        - "','"
555 +                        - {get_param: opendaylight_api_node_ips}
556                  nova_api_node_ips:
557                    str_replace:
558                      template: "['SERVERS_LIST']"
559 @@ -239,6 +265,7 @@ resources:
560                  neutron::rabbit_hosts: *rabbit_nodes_array
561                  nova::rabbit_hosts: *rabbit_nodes_array
562                  keystone::rabbit_hosts: *rabbit_nodes_array
563 +                aodh::rabbit_hosts: *rabbit_nodes_array
564  
565  outputs:
566    config_id:
567 diff --git a/puppet/compute.yaml b/puppet/compute.yaml
568 index 70c7403..ba7cbfd 100644
569 --- a/puppet/compute.yaml
570 +++ b/puppet/compute.yaml
571 @@ -213,6 +213,27 @@ parameters:
572    NtpServer:
573      type: string
574      default: ''
575 +  OpenDaylightPort:
576 +    default: 8081
577 +    description: Set opendaylight service port
578 +    type: number
579 +  OpenDaylightUsername:
580 +    default: 'admin'
581 +    description: The username for the opendaylight server.
582 +    type: string
583 +  OpenDaylightPassword:
584 +    default: 'admin'
585 +    type: string
586 +    description: The password for the opendaylight server.
587 +    hidden: true
588 +  OpenDaylightEnableHA:
589 +    description: Knob to enable/disable ODL HA
590 +    type: boolean
591 +    default: false
592 +  ONOSPort:
593 +    default: 8181
594 +    description: Set onos service port
595 +    type: number
596    RabbitHost:
597      type: string
598      default: ''  # Has to be here because of the ignored empty value bug
599 @@ -320,6 +341,11 @@ resources:
600      properties:
601        ControlPlaneIP: {get_attr: [NovaCompute, networks, ctlplane, 0]}
602  
603 +  ExternalPort:
604 +    type: OS::TripleO::Controller::Ports::ExternalPort
605 +    properties:
606 +      ControlPlaneIP: {get_attr: [NovaCompute, networks, ctlplane, 0]}
607 +
608    NetIpMap:
609      type: OS::TripleO::Network::Ports::NetIpMap
610      properties:
611 @@ -327,6 +353,7 @@ resources:
612        InternalApiIp: {get_attr: [InternalApiPort, ip_address]}
613        StorageIp: {get_attr: [StoragePort, ip_address]}
614        TenantIp: {get_attr: [TenantPort, ip_address]}
615 +      ExternalIp: {get_attr: [ExternalPort, ip_address]}
616  
617    NetworkConfig:
618      type: OS::TripleO::Compute::Net::SoftwareConfig
619 @@ -335,6 +362,7 @@ resources:
620        InternalApiIpSubnet: {get_attr: [InternalApiPort, ip_subnet]}
621        StorageIpSubnet: {get_attr: [StoragePort, ip_subnet]}
622        TenantIpSubnet: {get_attr: [TenantPort, ip_subnet]}
623 +      ExternalIpSubnet: {get_attr: [ExternalPort, ip_subnet]}
624  
625    NetworkDeployment:
626      type: OS::TripleO::SoftwareDeployment
627 @@ -406,6 +434,11 @@ resources:
628                  neutron::rabbit_user: {get_input: rabbit_user}
629                  neutron::rabbit_use_ssl: {get_input: rabbit_client_use_ssl}
630                  neutron::rabbit_port: {get_input: rabbit_client_port}
631 +                opendaylight_port: {get_input: opendaylight_port}
632 +                opendaylight_username: {get_input: opendaylight_username}
633 +                opendaylight_password: {get_input: opendaylight_password}
634 +                opendaylight_enable_ha: {get_input: opendaylight_enable_ha}
635 +                onos_port: {get_input: onos_port}
636                  neutron_flat_networks: {get_input: neutron_flat_networks}
637                  neutron_host: {get_input: neutron_host}
638                  neutron::agents::ml2::ovs::local_ip: {get_input: neutron_local_ip}
639 @@ -459,6 +492,11 @@ resources:
640          snmpd_readonly_user_name: {get_param: SnmpdReadonlyUserName}
641          snmpd_readonly_user_password: {get_param: SnmpdReadonlyUserPassword}
642          glance_api_servers: {get_param: [EndpointMap, GlanceInternal, uri]}
643 +        opendaylight_port: {get_param: OpenDaylightPort}
644 +        opendaylight_username: {get_param: OpenDaylightUsername}
645 +        opendaylight_password: {get_param: OpenDaylightPassword}
646 +        opendaylight_enable_ha: {get_param: OpenDaylightEnableHA}
647 +        onos_port: {get_param: ONOSPort}
648          neutron_flat_networks: {get_param: NeutronFlatNetworks}
649          neutron_host: {get_param: NeutronHost}
650          neutron_local_ip: {get_attr: [NetIpMap, net_ip_map, {get_param: [ServiceNetMap, NeutronTenantNetwork]}]}
651 @@ -570,6 +608,9 @@ outputs:
652    tenant_ip_address:
653      description: IP address of the server in the tenant network
654      value: {get_attr: [TenantPort, ip_address]}
655 +  external_ip_address:
656 +    description: IP address of the server in the external network
657 +    value: {get_attr: [ExternalPort, ip_address]}
658    hostname:
659      description: Hostname of the server
660      value: {get_attr: [NovaCompute, name]}
661 diff --git a/puppet/controller.yaml b/puppet/controller.yaml
662 index ea0b3af..0a3668e 100644
663 --- a/puppet/controller.yaml
664 +++ b/puppet/controller.yaml
665 @@ -14,6 +14,14 @@ parameters:
666      description: The keystone auth secret and db password.
667      type: string
668      hidden: true
669 +  AodhApiVirtualIP:
670 +    type: string
671 +    default: ''
672 +  AodhPassword:
673 +    default: unset
674 +    description: The password for the aodh services.
675 +    type: string
676 +    hidden: true
677    CeilometerApiVirtualIP:
678      type: string
679      default: ''
680 @@ -357,6 +365,10 @@ parameters:
681      default: 'True'
682      description: Allow automatic l3-agent failover
683      type: string
684 +  NeutronEnableForceMetadata:
685 +    default: 'False'
686 +    description: If True, DHCP always provides metadata route to VM.
687 +    type: string
688    NeutronEnableTunnelling:
689      type: string
690      default: "True"
691 @@ -443,6 +455,42 @@ parameters:
692    NtpServer:
693      type: string
694      default: ''
695 +  OpenDaylightPort:
696 +    default: 8081
697 +    description: Set opendaylight service port
698 +    type: number
699 +  OpenDaylightInstall:
700 +    default: false
701 +    description: Whether to install OpenDaylight on the control nodes.
702 +    type: boolean
703 +  OpenDaylightUsername:
704 +    default: 'admin'
705 +    description: The username for the opendaylight server.
706 +    type: string
707 +  OpenDaylightPassword:
708 +    default: 'admin'
709 +    type: string
710 +    description: The password for the opendaylight server.
711 +    hidden: true
712 +  OpenDaylightEnableL3:
713 +    description: Knob to enable/disable ODL L3
714 +    type: string
715 +    default: 'no'
716 +  OpenDaylightEnableHA:
717 +    description: Knob to enable/disable ODL HA
718 +    type: boolean
719 +    default: false
720 +  OpenDaylightFeatures:
721 +    description: List of features to install with ODL
722 +    type: comma_delimited_list
723 +    default: "odl-ovsdb-openstack"
724 +  OpenDaylightApiVirtualIP:
725 +    type: string
726 +    default: ''
727 +  ONOSPort:
728 +    default: 8181
729 +    description: Set onos service port
730 +    type: number
731    PcsdPassword:
732      type: string
733      description: The password for the 'pcsd' user.
734 @@ -696,6 +744,7 @@ resources:
735        input_values:
736          bootstack_nodeid: {get_attr: [Controller, name]}
737          neutron_enable_tunneling: {get_param: NeutronEnableTunnelling}
738 +        neutron_enable_force_metadata: {get_param: NeutronEnableForceMetadata}
739          haproxy_log_address: {get_param: HAProxySyslogAddress}
740          heat.watch_server_url:
741            list_join:
742 @@ -774,6 +823,7 @@ resources:
743                - {get_param: MysqlVirtualIP}
744                - '/heat'
745          keystone_ca_certificate: {get_param: KeystoneCACertificate}
746 +        keystone_admin_vip: {get_param: KeystoneAdminApiVirtualIP}
747          keystone_signing_key: {get_param: KeystoneSigningKey}
748          keystone_signing_certificate: {get_param: KeystoneSigningCertificate}
749          keystone_ssl_certificate: {get_param: KeystoneSSLCertificate}
750 @@ -805,6 +855,14 @@ resources:
751              template: tripleo-CLUSTER
752              params:
753                CLUSTER: {get_param: MysqlClusterUniquePart}
754 +        opendaylight_port: {get_param: OpenDaylightPort}
755 +        opendaylight_install: {get_param: OpenDaylightInstall}
756 +        opendaylight_username: {get_param: OpenDaylightUsername}
757 +        opendaylight_password: {get_param: OpenDaylightPassword}
758 +        opendaylight_enable_l3: {get_param: OpenDaylightEnableL3}
759 +        opendaylight_enable_ha: {get_param: OpenDaylightEnableHA}
760 +        opendaylight_features: {get_param: OpenDaylightFeatures}
761 +        onos_port: {get_param: ONOSPort}
762          neutron_flat_networks: {get_param: NeutronFlatNetworks}
763          neutron_metadata_proxy_shared_secret: {get_param: NeutronMetadataProxySharedSecret}
764          neutron_agent_mode: {get_param: NeutronAgentMode}
765 @@ -879,6 +937,7 @@ resources:
766          ceilometer_backend: {get_param: CeilometerBackend}
767          ceilometer_metering_secret: {get_param: CeilometerMeteringSecret}
768          ceilometer_password: {get_param: CeilometerPassword}
769 +        aodh_password: {get_param: AodhPassword}
770          ceilometer_coordination_url:
771            list_join:
772              - ''
773 @@ -891,6 +950,12 @@ resources:
774              - - 'mysql://ceilometer:unset@'
775                - {get_param: MysqlVirtualIP}
776                - '/ceilometer'
777 +        ceilometer_public_url: {get_param: [EndpointMap, CeilometerPublic, uri]}
778 +        ceilometer_internal_url: {get_param: [EndpointMap, CeilometerInternal, uri]}
779 +        ceilometer_admin_url: {get_param: [EndpointMap, CeilometerAdmin, uri]}
780 +        aodh_public_url: {get_param: [EndpointMap, AodhPublic, uri]}
781 +        aodh_internal_url: {get_param: [EndpointMap, AodhInternal, uri]}
782 +        aodh_admin_url: {get_param: [EndpointMap, AodhAdmin, uri]}
783          snmpd_readonly_user_name: {get_param: SnmpdReadonlyUserName}
784          snmpd_readonly_user_password: {get_param: SnmpdReadonlyUserPassword}
785          nova_password: {get_param: NovaPassword}
786 @@ -948,6 +1013,8 @@ resources:
787          neutron_api_network: {get_attr: [NetIpMap, net_ip_map, {get_param: [ServiceNetMap, NeutronApiNetwork]}]}
788          neutron_local_ip: {get_attr: [NetIpMap, net_ip_map, {get_param: [ServiceNetMap, NeutronTenantNetwork]}]}
789          ceilometer_api_network: {get_attr: [NetIpMap, net_ip_map, {get_param: [ServiceNetMap, CeilometerApiNetwork]}]}
790 +        aodh_api_network: {get_attr: [NetIpMap, net_ip_map, {get_param: [ServiceNetMap, AodhApiNetwork]}]}
791 +        opendaylight_api_network: {get_attr: [NetIpMap, net_ip_map, {get_param: [ServiceNetMap, OpenDaylightApiNetwork]}]}
792          nova_api_network: {get_attr: [NetIpMap, net_ip_map, {get_param: [ServiceNetMap, NovaApiNetwork]}]}
793          nova_metadata_network: {get_attr: [NetIpMap, net_ip_map, {get_param: [ServiceNetMap, NovaMetadataNetwork]}]}
794          horizon_network: {get_attr: [NetIpMap, net_ip_map, {get_param: [ServiceNetMap, HorizonNetwork]}]}
795 @@ -1041,7 +1108,7 @@ resources:
796                  cinder_iscsi_ip_address: {get_input: cinder_iscsi_network}
797                  cinder::database_connection: {get_input: cinder_dsn}
798                  cinder::api::keystone_password: {get_input: cinder_password}
799 -                cinder::api::auth_uri: {get_input: keystone_auth_uri}
800 +                cinder::api::keystone_auth_host: {get_input: keystone_admin_vip}
801                  cinder::api::identity_uri: {get_input: keystone_identity_uri}
802                  cinder::api::bind_host: {get_input: cinder_api_network}
803                  cinder::rabbit_userid: {get_input: rabbit_username}
804 @@ -1136,6 +1203,18 @@ resources:
805                  mysql_bind_host: {get_input: mysql_network}
806                  mysql_virtual_ip: {get_input: mysql_virtual_ip}
807  
808 +                # OpenDaylight
809 +                opendaylight_port: {get_input: opendaylight_port}
810 +                opendaylight_install: {get_input: opendaylight_install}
811 +                opendaylight_username: {get_input: opendaylight_username}
812 +                opendaylight_password: {get_input: opendaylight_password}
813 +                opendaylight_enable_l3: {get_input: opendaylight_enable_l3}
814 +                opendaylight_enable_ha: {get_input: opendaylight_enable_ha}
815 +                opendaylight_features: {get_input: opendaylight_features}
816 +
817 +                # ONOS
818 +                onos_port: {get_input: onos_port}
819 +
820                  # Neutron
821                  neutron::bind_host: {get_input: neutron_api_network}
822                  neutron::rabbit_password: {get_input: rabbit_password}
823 @@ -1152,6 +1231,7 @@ resources:
824                  neutron_flat_networks: {get_input: neutron_flat_networks}
825                  neutron::agents::metadata::shared_secret: {get_input: neutron_metadata_proxy_shared_secret}
826                  neutron::agents::metadata::metadata_ip: {get_input: neutron_api_network}
827 +                neutron::agents::dhcp::enable_force_metadata: {get_input: neutron_enable_force_metadata}
828                  neutron_agent_mode: {get_input: neutron_agent_mode}
829                  neutron_router_distributed: {get_input: neutron_router_distributed}
830                  neutron::core_plugin: {get_input: neutron_core_plugin}
831 @@ -1198,6 +1278,27 @@ resources:
832                  snmpd_readonly_user_name: {get_input: snmpd_readonly_user_name}
833                  snmpd_readonly_user_password: {get_input: snmpd_readonly_user_password}
834  
835 +                # Aodh
836 +                aodh::rabbit_userid: {get_input: rabbit_username}
837 +                aodh::rabbit_password: {get_input: rabbit_password}
838 +                aodh::rabbit_use_ssl: {get_input: rabbit_client_use_ssl}
839 +                aodh::rabbit_port: {get_input: rabbit_client_port}
840 +                aodh::debug: {get_input: debug}
841 +                aodh::wsgi::apache::ssl: false
842 +                aodh::api::service_name: 'httpd'
843 +                aodh::api::host: {get_input: aodh_api_network}
844 +                aodh::api::keystone_password: {get_input: aodh_password}
845 +                aodh::api::keystone_auth_uri: {get_input: keystone_auth_uri}
846 +                aodh::api::keystone_identity_uri: {get_input: keystone_identity_uri}
847 +                aodh::auth::auth_password: {get_input: aodh_password}
848 +                aodh::keystone::auth::public_url: {get_input: aodh_public_url }
849 +                aodh::keystone::auth::internal_url: {get_input: aodh_internal_url }
850 +                aodh::keystone::auth::admin_url: {get_input: aodh_admin_url }
851 +                aodh::keystone::auth::password: {get_input: aodh_password }
852 +                aodh::keystone::auth::region: {get_input: keystone_region}
853 +                # for a migration path from ceilometer-alarm to aodh, we use the same database & coordination
854 +                aodh::evaluator::coordination_url: {get_input: ceilometer_coordination_url}
855 +
856                  # Nova
857                  nova::rabbit_userid: {get_input: rabbit_username}
858                  nova::rabbit_password: {get_input: rabbit_password}
859 @@ -1244,6 +1345,7 @@ resources:
860                  tripleo::loadbalancer::haproxy_log_address: {get_input: haproxy_log_address}
861                  tripleo::packages::enable_install: {get_input: enable_package_install}
862                  tripleo::packages::enable_upgrade: {get_input: enable_package_upgrade}
863 +                tripleo::loadbalancer::opendaylight: {get_input: opendaylight_enable_ha}
864  
865    # Hook for site-specific additional pre-deployment config, e.g extra hieradata
866    ControllerExtraConfigPre:
867 diff --git a/puppet/hieradata/common.yaml b/puppet/hieradata/common.yaml
868 index 030f661..5840016 100644
869 --- a/puppet/hieradata/common.yaml
870 +++ b/puppet/hieradata/common.yaml
871 @@ -6,6 +6,7 @@ ceilometer::agent::auth::auth_region: 'regionOne'
872  # FIXME: Might be better to use 'service' tenant here but this requires
873  # changes in the tripleo-incubator keystone role setup
874  ceilometer::agent::auth::auth_tenant_name: 'admin'
875 +aodh::auth::auth_tenant_name: 'admin'
876  
877  nova::network::neutron::neutron_admin_tenant_name: 'service'
878  nova::network::neutron::neutron_admin_username: 'neutron'
879 diff --git a/puppet/hieradata/controller.yaml b/puppet/hieradata/controller.yaml
880 index 4b7fd81..7dbc2e9 100644
881 --- a/puppet/hieradata/controller.yaml
882 +++ b/puppet/hieradata/controller.yaml
883 @@ -32,6 +32,7 @@ redis::sentinel::notification_script: '/usr/local/bin/redis-notifications.sh'
884  # service tenant
885  nova::api::admin_tenant_name: 'service'
886  glance::api::keystone_tenant: 'service'
887 +aodh::api::keystone_tenant: 'service'
888  glance::registry::keystone_tenant: 'service'
889  neutron::server::auth_tenant: 'service'
890  neutron::agents::metadata::auth_tenant: 'service'
891 @@ -39,6 +40,7 @@ cinder::api::keystone_tenant: 'service'
892  swift::proxy::authtoken::admin_tenant_name: 'service'
893  ceilometer::api::keystone_tenant: 'service'
894  heat::keystone_tenant: 'service'
895 +aodh::keystone::auth::tenant: 'service'
896  
897  # keystone
898  keystone::cron::token_flush::maxdelay: 3600
899 @@ -72,7 +74,7 @@ neutron::agents::dhcp::dnsmasq_config_file: /etc/neutron/dnsmasq-neutron.conf
900  
901  # nova
902  nova::notify_on_state_change: 'vm_and_task_state'
903 -nova::api::default_floating_pool: 'public'
904 +nova::api::default_floating_pool: 'external'
905  nova::api::osapi_v3: true
906  nova::scheduler::filter::ram_allocation_ratio: '1.0'
907  
908 @@ -115,6 +117,7 @@ tripleo::loadbalancer::mysql: true
909  tripleo::loadbalancer::redis: true
910  tripleo::loadbalancer::swift_proxy_server: true
911  tripleo::loadbalancer::ceilometer: true
912 +tripleo::loadbalancer::aodh: true
913  tripleo::loadbalancer::heat_api: true
914  tripleo::loadbalancer::heat_cloudwatch: true
915  tripleo::loadbalancer::heat_cfn: true
916 diff --git a/puppet/manifests/overcloud_compute.pp b/puppet/manifests/overcloud_compute.pp
917 index cd41cc7..474d782 100644
918 --- a/puppet/manifests/overcloud_compute.pp
919 +++ b/puppet/manifests/overcloud_compute.pp
920 @@ -75,9 +75,52 @@ class { '::neutron::plugins::ml2':
921    tenant_network_types => [hiera('neutron_tenant_network_type')],
922  }
923  
924 -class { '::neutron::agents::ml2::ovs':
925 -  bridge_mappings => split(hiera('neutron_bridge_mappings'), ','),
926 -  tunnel_types    => split(hiera('neutron_tunnel_types'), ','),
927 +if 'opendaylight' in hiera('neutron_mechanism_drivers') {
928 +
929 +  if str2bool(hiera('opendaylight_install', 'false')) {
930 +    $controller_ips = split(hiera('controller_node_ips'), ',')
931 +    if hiera('opendaylight_enable_ha', false) {
932 +      $odl_ovsdb_iface = "tcp:${controller_ips[0]}:6640 tcp:${controller_ips[1]}:6640 tcp:${controller_ips[2]}:6640"
933 +      # Workaround to work with current puppet-neutron
934 +      # This isn't the best solution, since the odl check URL ends up being only the first node in HA case
935 +      $opendaylight_controller_ip = $controller_ips[0]
936 +      # Bug where netvirt:1 doesn't come up right with HA
937 +      # Check ovsdb:1 instead
938 +      $net_virt_url = 'restconf/operational/network-topology:network-topology/topology/ovsdb:1'
939 +    } else {
940 +      $opendaylight_controller_ip = $controller_ips[0]
941 +      $odl_ovsdb_iface = "tcp:${opendaylight_controller_ip}:6640"
942 +      $net_virt_url = 'restconf/operational/network-topology:network-topology/topology/netvirt:1'
943 +    }
944 +  } else {
945 +    $opendaylight_controller_ip = hiera('opendaylight_controller_ip')
946 +    $odl_ovsdb_iface = "tcp:${opendaylight_controller_ip}:6640"
947 +    $net_virt_url = 'restconf/operational/network-topology:network-topology/topology/netvirt:1'
948 +  }
949 +
950 +  $opendaylight_port = hiera('opendaylight_port')
951 +  $private_ip = hiera('neutron::agents::ml2::ovs::local_ip')
952 +  $opendaylight_url = "http://${opendaylight_controller_ip}:${opendaylight_port}/${net_virt_url}"
953 +
954 +  class { '::neutron::plugins::ovs::opendaylight':
955 +    tunnel_ip             => $private_ip,
956 +    odl_username          => hiera('opendaylight_username'),
957 +    odl_password          => hiera('opendaylight_password'),
958 +    odl_check_url         => $opendaylight_url,
959 +    odl_ovsdb_iface       => $odl_ovsdb_iface,
960 +  }
961 +
962 +} elsif 'onos_ml2' in hiera('neutron_mechanism_drivers') {
963 +  $controller_ips = split(hiera('controller_node_ips'), ',')
964 +  class {'onos::ovs_computer':
965 +    manager_ip => $controller_ips[0]
966 +  }
967 +
968 +} else {
969 +  class { 'neutron::agents::ml2::ovs':
970 +    bridge_mappings => split(hiera('neutron_bridge_mappings'), ','),
971 +    tunnel_types    => split(hiera('neutron_tunnel_types'), ','),
972 +  }
973  }
974  
975  if 'cisco_n1kv' in hiera('neutron_mechanism_drivers') {
976 diff --git a/puppet/manifests/overcloud_controller.pp b/puppet/manifests/overcloud_controller.pp
977 index 1f6c2be..5114f80 100644
978 --- a/puppet/manifests/overcloud_controller.pp
979 +++ b/puppet/manifests/overcloud_controller.pp
980 @@ -30,6 +30,21 @@ if hiera('step') >= 1 {
981  
982  if hiera('step') >= 2 {
983  
984 +  if str2bool(hiera('opendaylight_install', 'false')) {
985 +    class {"opendaylight":
986 +      extra_features => any2array(hiera('opendaylight_features', 'odl-ovsdb-openstack')),
987 +      odl_rest_port  => hiera('opendaylight_port'),
988 +      enable_l3      => hiera('opendaylight_enable_l3', 'no'),
989 +    }
990 +  }
991 +  
992 +  if 'onos_ml2' in hiera('neutron_mechanism_drivers') {
993 +    # install onos and config ovs
994 +    class {"onos":
995 +      controllers_ip => $controller_node_ips
996 +    }
997 +  }
998 +
999    if count(hiera('ntp::servers')) > 0 {
1000      include ::ntp
1001    }
1002 @@ -158,6 +173,9 @@ if hiera('step') >= 2 {
1003  
1004  if hiera('step') >= 3 {
1005  
1006 +  # Apache
1007 +  include ::apache
1008 +
1009    include ::keystone
1010  
1011    #TODO: need a cleanup-keystone-tokens.sh solution here
1012 @@ -223,9 +241,7 @@ if hiera('step') >= 3 {
1013    include ::nova::scheduler
1014    include ::nova::scheduler::filter
1015  
1016 -  include ::neutron
1017    include ::neutron::server
1018 -  include ::neutron::agents::l3
1019    include ::neutron::agents::dhcp
1020    include ::neutron::agents::metadata
1021  
1022 @@ -237,15 +253,103 @@ if hiera('step') >= 3 {
1023      require => Package['neutron'],
1024    }
1025  
1026 +  if 'onos_ml2' in hiera('neutron_mechanism_drivers') {
1027 +    # config neutron service_plugins to onos driver
1028 +    class { '::neutron':
1029 +      service_plugins  => [hiera('neutron_service_plugins')]
1030 +    }
1031 +  } else {
1032 +    include ::neutron
1033 +    if 'opendaylight' in hiera('neutron_mechanism_drivers') {
1034 +      if ! str2bool(hiera('opendaylight_enable_l3', 'no')) {
1035 +        include ::neutron::agents::l3
1036 +      }
1037 +    }
1038 +  }
1039 +  
1040    class { '::neutron::plugins::ml2':
1041      flat_networks        => split(hiera('neutron_flat_networks'), ','),
1042      tenant_network_types => [hiera('neutron_tenant_network_type')],
1043      mechanism_drivers    => [hiera('neutron_mechanism_drivers')],
1044    }
1045 -  class { '::neutron::agents::ml2::ovs':
1046 -    bridge_mappings => split(hiera('neutron_bridge_mappings'), ','),
1047 -    tunnel_types    => split(hiera('neutron_tunnel_types'), ','),
1048 +
1049 +  if 'opendaylight' in hiera('neutron_mechanism_drivers') {
1050 +    if ! str2bool(hiera('opendaylight_enable_l3', 'no')) {
1051 +      Service['neutron-server'] -> Service['neutron-l3']
1052 +    }
1053 +
1054 +    if str2bool(hiera('opendaylight_install', 'false')) {
1055 +      $controller_ips = split(hiera('controller_node_ips'), ',')
1056 +      $opendaylight_controller_ip = $controller_ips[0]
1057 +    } else {
1058 +      $opendaylight_controller_ip = hiera('opendaylight_controller_ip')
1059 +    }
1060 +
1061 +    # co-existence hacks for SFC
1062 +    if hiera('opendaylight_features', 'odl-ovsdb-openstack') =~ /odl-ovsdb-sfc-rest/ {
1063 +      $opendaylight_port = hiera('opendaylight_port')
1064 +      $netvirt_coexist_url = "http://${opendaylight_controller_ip}:${opendaylight_port}/restconf/config/netvirt-providers-config:netvirt-providers-config"
1065 +      $netvirt_post_body = "{'netvirt-providers-config': {'table-offset': 1}}"
1066 +      $sfc_coexist_url = "http://${opendaylight_controller_ip}:${opendaylight_port}/restconf/config/sfc-of-renderer:sfc-of-renderer-config"
1067 +      $sfc_post_body = "{ 'sfc-of-renderer-config' : { 'sfc-of-table-offset' : 150, 'sfc-of-app-egress-table-offset' : 11 }}"
1068 +      $odl_username = hiera('opendaylight_username')
1069 +      $odl_password = hiera('opendaylight_password')
1070 +      exec { 'Coexistence table offsets for netvirt':
1071 +        command   => "curl -o /dev/null --fail --silent -u ${odl_username}:${odl_password} ${netvirt_coexist_url} -i -H 'Content-Type: application/json' --data \'${netvirt_post_body}\' -X PUT",
1072 +        tries     => 5,
1073 +        try_sleep => 30,
1074 +        path      => '/usr/sbin:/usr/bin:/sbin:/bin',
1075 +      } ->
1076 +      # Coexist for SFC
1077 +      exec { 'Coexistence table offsets for sfc':
1078 +        command   => "curl -o /dev/null --fail --silent -u ${odl_username}:${odl_password} ${sfc_coexist_url} -i -H 'Content-Type: application/json' --data \'${sfc_post_body}\' -X PUT",
1079 +        tries     => 5,
1080 +        try_sleep => 30,
1081 +        path      => '/usr/sbin:/usr/bin:/sbin:/bin',
1082 +      }
1083 +    }
1084 +
1085 +    $private_ip = hiera('neutron::agents::ml2::ovs::local_ip')
1086 +    $net_virt_url = 'restconf/operational/network-topology:network-topology/topology/netvirt:1'
1087 +    $opendaylight_url = "http://${opendaylight_controller_ip}:${opendaylight_port}/${net_virt_url}"
1088 +    $odl_ovsdb_iface = "tcp:${opendaylight_controller_ip}:6640"
1089 +
1090 +    class { '::neutron::plugins::ml2::opendaylight':
1091 +      odl_username  => hiera('opendaylight_username'),
1092 +      odl_password  => hiera('opendaylight_password'),
1093 +      odl_url => "http://${opendaylight_controller_ip}:${opendaylight_port}/controller/nb/v2/neutron";
1094 +    }
1095 +
1096 +    class { '::neutron::plugins::ovs::opendaylight':
1097 +      tunnel_ip             => $private_ip,
1098 +      odl_username          => hiera('opendaylight_username'),
1099 +      odl_password          => hiera('opendaylight_password'),
1100 +      odl_check_url         => $opendaylight_url,
1101 +      odl_ovsdb_iface       => $odl_ovsdb_iface,
1102 +    }
1103 +
1104 +  } elsif 'onos_ml2' in hiera('neutron_mechanism_drivers') {
1105 +    #config ml2_conf.ini with onos url address
1106 +    $onos_port = hiera('onos_port')
1107 +    $private_ip = hiera('neutron::agents::ml2::ovs::local_ip')
1108 +
1109 +    neutron_plugin_ml2 {
1110 +      'onos/username':         value => 'admin';
1111 +      'onos/password':         value => 'admin';
1112 +      'onos/url_path':         value => "http://${controller_node_ips[0]}:${onos_port}/onos/vtn";
1113 +    }
1114 +
1115 +  } else {
1116 +
1117 +    class { 'neutron::agents::ml2::ovs':
1118 +      bridge_mappings => split(hiera('neutron_bridge_mappings'), ','),
1119 +      tunnel_types => split(hiera('neutron_tunnel_types'), ','),
1120 +    }
1121 +
1122 +    Service['neutron-server'] -> Service['neutron-ovs-agent-service']
1123 +    Service['neutron-server'] -> Service['neutron-l3']
1124    }
1125 +
1126    if 'cisco_n1kv' in hiera('neutron_mechanism_drivers') {
1127      include ::neutron::plugins::ml2::cisco::nexus1000v
1128  
1129 @@ -280,8 +384,6 @@ if hiera('step') >= 3 {
1130    }
1131  
1132    Service['neutron-server'] -> Service['neutron-dhcp-service']
1133 -  Service['neutron-server'] -> Service['neutron-l3']
1134 -  Service['neutron-server'] -> Service['neutron-ovs-agent-service']
1135    Service['neutron-server'] -> Service['neutron-metadata']
1136  
1137    include ::cinder
1138 @@ -447,6 +549,20 @@ if hiera('step') >= 3 {
1139  
1140    Cron <| title == 'ceilometer-expirer' |> { command => "sleep $((\$(od -A n -t d -N 3 /dev/urandom) % 86400)) && ${::ceilometer::params::expirer_command}" }
1141  
1142 +  # Aodh
1143 +  include ::aodh::auth
1144 +  include ::aodh::api
1145 +  include ::aodh::evaluator
1146 +  include ::aodh::notifier
1147 +  include ::aodh::listener
1148 +  include ::aodh::client
1149 +  include ::aodh::db::sync
1150 +  class { '::aodh' :
1151 +    database_connection => $ceilometer_database_connection,
1152 +  }
1153 +  # To manage the upgrade:
1154 +  Exec['ceilometer-dbsync'] -> Exec['aodh-db-sync']
1155 +
1156    # Heat
1157    include ::heat
1158    include ::heat::api
1159 diff --git a/puppet/manifests/overcloud_controller_pacemaker.pp b/puppet/manifests/overcloud_controller_pacemaker.pp
1160 index 3fb92f3..29f9c7f 100644
1161 --- a/puppet/manifests/overcloud_controller_pacemaker.pp
1162 +++ b/puppet/manifests/overcloud_controller_pacemaker.pp
1163 @@ -380,6 +380,29 @@ if hiera('step') >= 2 {
1164  
1165    }
1166  
1167 +  if str2bool(hiera('opendaylight_install', 'false')) {
1168 +    $node_string = split(hiera('bootstack_nodeid'), '-')
1169 +    $controller_index = $node_string[-1]
1170 +    $ha_node_index = $controller_index + 1
1171 +
1172 +    class {"opendaylight":
1173 +      extra_features => any2array(hiera('opendaylight_features', 'odl-ovsdb-openstack')),
1174 +      odl_rest_port  => hiera('opendaylight_port'),
1175 +      odl_bind_ip    => $controller_node_ips[$controller_index],
1176 +      enable_l3      => hiera('opendaylight_enable_l3', 'no'),
1177 +      enable_ha      => hiera('opendaylight_enable_ha', false),
1178 +      ha_node_ips    => split(hiera('controller_node_ips'), ','),
1179 +      ha_node_index  => $ha_node_index,
1180 +    }
1181 +  }
1182 +
1183 +  if 'onos_ml2' in hiera('neutron_mechanism_drivers') {
1184 +    # install onos and config ovs
1185 +    class {"onos":
1186 +      controllers_ip => $controller_node_ips
1187 +    }
1188 +  }
1189 +  
1190    exec { 'galera-ready' :
1191      command     => '/usr/bin/clustercheck >/dev/null',
1192      timeout     => 30,
1193 @@ -584,7 +607,14 @@ if hiera('step') >= 3 {
1194    include ::nova::network::neutron
1195  
1196    # Neutron class definitions
1197 -  include ::neutron
1198 +  if 'onos_ml2' in hiera('neutron_mechanism_drivers') {
1199 +    # config neutron service_plugins to onos driver
1200 +    class { '::neutron':
1201 +      service_plugins  => [hiera('neutron_service_plugins')]
1202 +    }
1203 +  } else {
1204 +    include ::neutron
1205 +  }
1206    class { '::neutron::server' :
1207      sync_db        => $sync_db,
1208      manage_service => false,
1209 @@ -594,10 +624,6 @@ if hiera('step') >= 3 {
1210      manage_service => false,
1211      enabled        => false,
1212    }
1213 -  class { '::neutron::agents::l3' :
1214 -    manage_service => false,
1215 -    enabled        => false,
1216 -  }
1217    class { '::neutron::agents::metadata':
1218      manage_service => false,
1219      enabled        => false,
1220 @@ -609,18 +635,98 @@ if hiera('step') >= 3 {
1221      notify  => Service['neutron-dhcp-service'],
1222      require => Package['neutron'],
1223    }
1224 +
1225 +  # SDNVPN Hack
1226 +  if ('networking_bgpvpn.neutron.services.plugin.BGPVPNPlugin' in hiera('neutron::service_plugins'))
1227 +  {
1228 +    class  { 'neutron::config':
1229 +      server_config => {
1230 +        'service_providers/service_provider' => {
1231 +          'value' => 'BGPVPN:Dummy:networking_bgpvpn.neutron.services.service_drivers.driver_api.BGPVPNDriver:default'
1232 +        }
1233 +      }
1234 +    }
1235 +  }
1236 +
1237    class { '::neutron::plugins::ml2':
1238      flat_networks        => split(hiera('neutron_flat_networks'), ','),
1239      tenant_network_types => [hiera('neutron_tenant_network_type')],
1240      mechanism_drivers    => [hiera('neutron_mechanism_drivers')],
1241    }
1242 -  class { '::neutron::agents::ml2::ovs':
1243 -    manage_service  => false,
1244 -    enabled         => false,
1245 -    bridge_mappings => split(hiera('neutron_bridge_mappings'), ','),
1246 -    tunnel_types    => split(hiera('neutron_tunnel_types'), ','),
1247 -  }
1248 +  if 'opendaylight' in hiera('neutron_mechanism_drivers') {
1249 +    if str2bool(hiera('opendaylight_install', 'false')) {
1250 +      $controller_ips = split(hiera('controller_node_ips'), ',')
1251 +      if hiera('opendaylight_enable_ha', false) {
1252 +        $odl_ovsdb_iface = "tcp:${controller_ips[0]}:6640 tcp:${controller_ips[1]}:6640 tcp:${controller_ips[2]}:6640"
1253 +        # Workaround to work with current puppet-neutron
1254 +        # This isn't the best solution, since the odl check URL ends up being only the first node in HA case
1255 +        $opendaylight_controller_ip = $controller_ips[0]
1256 +        # Bug where netvirt:1 doesn't come up right with HA
1257 +        # Check ovsdb:1 instead
1258 +        $net_virt_url = 'restconf/operational/network-topology:network-topology/topology/ovsdb:1'
1259 +      } else {
1260 +        $opendaylight_controller_ip = $controller_ips[0]
1261 +        $odl_ovsdb_iface = "tcp:${opendaylight_controller_ip}:6640"
1262 +        $net_virt_url = 'restconf/operational/network-topology:network-topology/topology/netvirt:1'
1263 +      }
1264 +    } else {
1265 +      $opendaylight_controller_ip = hiera('opendaylight_controller_ip')
1266 +      $odl_ovsdb_iface = "tcp:${opendaylight_controller_ip}:6640"
1267 +      $net_virt_url = 'restconf/operational/network-topology:network-topology/topology/netvirt:1'
1268 +    }
1269 +
1270 +    $opendaylight_port = hiera('opendaylight_port')
1271 +    $private_ip = hiera('neutron::agents::ml2::ovs::local_ip')
1272 +    $opendaylight_url = "http://${opendaylight_controller_ip}:${opendaylight_port}/${net_virt_url}"
1273 +    $odl_vip = hiera('opendaylight_api_vip')
1274 +
1275 +    if ! $odl_vip {
1276 +      fail('ODL VIP not set in hiera or empty')
1277 +    }
1278 +
1279 +    class { '::neutron::plugins::ml2::opendaylight':
1280 +      odl_username  => hiera('opendaylight_username'),
1281 +      odl_password  => hiera('opendaylight_password'),
1282 +      odl_url => "http://${odl_vip}:${opendaylight_port}/controller/nb/v2/neutron";
1283 +    }
1284 +
1285 +    class { '::neutron::plugins::ovs::opendaylight':
1286 +      tunnel_ip             => $private_ip,
1287 +      odl_username          => hiera('opendaylight_username'),
1288 +      odl_password          => hiera('opendaylight_password'),
1289 +      odl_check_url         => $opendaylight_url,
1290 +      odl_ovsdb_iface       => $odl_ovsdb_iface,
1291 +    }
1292  
1293 +    if ! str2bool(hiera('opendaylight_enable_l3', 'no')) {
1294 +      class { '::neutron::agents::l3' :
1295 +        manage_service => false,
1296 +        enabled        => false,
1297 +      }
1298 +    }
1299 +  } elsif 'onos_ml2' in hiera('neutron_mechanism_drivers') {
1300 +    #config ml2_conf.ini with onos url address
1301 +    $onos_port = hiera('onos_port')
1302 +    $private_ip = hiera('neutron::agents::ml2::ovs::local_ip')
1303 +
1304 +    neutron_plugin_ml2 {
1305 +      'onos/username':         value => 'admin';
1306 +      'onos/password':         value => 'admin';
1307 +      'onos/url_path':         value => "http://${controller_node_ips[0]}:${onos_port}/onos/vtn";
1308 +    }
1309 +
1310 +  } else {
1311 +    class { '::neutron::agents::l3' :
1312 +      manage_service => false,
1313 +      enabled        => false,
1314 +    }
1315 +    class { 'neutron::agents::ml2::ovs':
1316 +      manage_service   => false,
1317 +      enabled          => false,
1318 +      bridge_mappings  => split(hiera('neutron_bridge_mappings'), ','),
1319 +      tunnel_types     => split(hiera('neutron_tunnel_types'), ','),
1320 +    }
1321 +  }
1322    if 'cisco_ucsm' in hiera('neutron_mechanism_drivers') {
1323      include ::neutron::plugins::ml2::cisco::ucsm
1324    }
1325 @@ -645,8 +751,10 @@ if hiera('step') >= 3 {
1326    if hiera('neutron_enable_bigswitch_ml2', false) {
1327      include ::neutron::plugins::ml2::bigswitch::restproxy
1328    }
1329 -  neutron_l3_agent_config {
1330 -    'DEFAULT/ovs_use_veth': value => hiera('neutron_ovs_use_veth', false);
1331 +  if !('onos_ml2' in hiera('neutron_mechanism_drivers') or str2bool(hiera('opendaylight_enable_l3', 'no'))) {
1332 +    neutron_l3_agent_config {
1333 +      'DEFAULT/ovs_use_veth': value => hiera('neutron_ovs_use_veth', false);
1334 +    }
1335    }
1336    neutron_dhcp_agent_config {
1337      'DEFAULT/ovs_use_veth': value => hiera('neutron_ovs_use_veth', false);
1338 @@ -813,13 +921,13 @@ if hiera('step') >= 3 {
1339      swift::storage::filter::healthcheck { $swift_components : }
1340    }
1341  
1342 +  $mongo_node_string = join($mongo_node_ips_with_port, ',')
1343    # Ceilometer
1344    case downcase(hiera('ceilometer_backend')) {
1345      /mysql/: {
1346        $ceilometer_database_connection = hiera('ceilometer_mysql_conn_string')
1347      }
1348      default: {
1349 -      $mongo_node_string = join($mongo_node_ips_with_port, ',')
1350        $ceilometer_database_connection = "mongodb://${mongo_node_string}/ceilometer?replicaSet=${mongodb_replset}"
1351      }
1352    }
1353 @@ -879,6 +987,62 @@ if hiera('step') >= 3 {
1354      enabled        => false,
1355    }
1356  
1357 +  $aodh_database_connection = "mongodb://${mongo_node_string}/aodh?replicaSet=${mongodb_replset}"
1358 +
1359 +  class { '::aodh::db':
1360 +    database_connection => $aodh_database_connection
1361 +  }
1362 +
1363 +  # Aodh
1364 +  include ::aodh
1365 +  include ::aodh::config
1366 +  include ::aodh::auth
1367 +  include ::aodh::client
1368 +  class { '::aodh::api':
1369 +    manage_service => false,
1370 +    enabled        => false,
1371 +  }
1372 +  class { '::aodh::evaluator':
1373 +    manage_service => false,
1374 +    enabled        => false,
1375 +  }
1376 +  class { '::aodh::notifier':
1377 +    manage_service => false,
1378 +    enabled        => false,
1379 +  }
1380 +  class { '::aodh::listener':
1381 +    manage_service => false,
1382 +    enabled        => false,
1383 +  }
1384 +
1385 +  $event_pipeline = "---
1386 +sources:
1387 +    - name: event_source
1388 +      events:
1389 +          - \"*\"
1390 +      sinks:
1391 +          - event_sink
1392 +sinks:
1393 +    - name: event_sink
1394 +      transformers:
1395 +      triggers:
1396 +      publishers:
1397 +          - notifier://?topic=alarm.all
1398 +          - notifier://
1399 +"
1400 +
1401 +  # aodh hacks
1402 +  file { '/etc/ceilometer/event_pipeline.yaml':
1403 +    ensure  => present,
1404 +    content => $event_pipeline
1405 +  }
1406 +
1407 +  user { 'aodh':
1408 +     groups => 'nobody'
1409 +  }
1410 +
1411 +
1412 +
1413    # httpd/apache and horizon
1414    # NOTE(gfidente): server-status can be consumed by the pacemaker resource agent
1415    class { '::apache' :
1416 @@ -1055,62 +1219,21 @@ if hiera('step') >= 4 {
1417        clone_params => 'interleave=true',
1418        require      => Pacemaker::Resource::Service[$::keystone::params::service_name],
1419      }
1420 -    pacemaker::resource::service { $::neutron::params::l3_agent_service:
1421 -      clone_params => 'interleave=true',
1422 +    if !('onos_ml2' in hiera('neutron_mechanism_drivers')) {
1423 +      pacemaker::resource::service { $::neutron::params::l3_agent_service:
1424 +        clone_params => 'interleave=true',
1425 +      }
1426      }
1427      pacemaker::resource::service { $::neutron::params::dhcp_agent_service:
1428        clone_params => 'interleave=true',
1429      }
1430 -    pacemaker::resource::service { $::neutron::params::ovs_agent_service:
1431 -      clone_params => 'interleave=true',
1432 -    }
1433      pacemaker::resource::service { $::neutron::params::metadata_agent_service:
1434        clone_params => 'interleave=true',
1435      }
1436 -    pacemaker::resource::ocf { $::neutron::params::ovs_cleanup_service:
1437 -      ocf_agent_name => 'neutron:OVSCleanup',
1438 -      clone_params   => 'interleave=true',
1439 -    }
1440      pacemaker::resource::ocf { 'neutron-netns-cleanup':
1441        ocf_agent_name => 'neutron:NetnsCleanup',
1442        clone_params   => 'interleave=true',
1443      }
1444 -
1445 -    # neutron - one chain ovs-cleanup-->netns-cleanup-->ovs-agent
1446 -    pacemaker::constraint::base { 'neutron-ovs-cleanup-to-netns-cleanup-constraint':
1447 -      constraint_type => 'order',
1448 -      first_resource  => "${::neutron::params::ovs_cleanup_service}-clone",
1449 -      second_resource => 'neutron-netns-cleanup-clone',
1450 -      first_action    => 'start',
1451 -      second_action   => 'start',
1452 -      require         => [Pacemaker::Resource::Ocf[$::neutron::params::ovs_cleanup_service],
1453 -                          Pacemaker::Resource::Ocf['neutron-netns-cleanup']],
1454 -    }
1455 -    pacemaker::constraint::colocation { 'neutron-ovs-cleanup-to-netns-cleanup-colocation':
1456 -      source  => 'neutron-netns-cleanup-clone',
1457 -      target  => "${::neutron::params::ovs_cleanup_service}-clone",
1458 -      score   => 'INFINITY',
1459 -      require => [Pacemaker::Resource::Ocf[$::neutron::params::ovs_cleanup_service],
1460 -                  Pacemaker::Resource::Ocf['neutron-netns-cleanup']],
1461 -    }
1462 -    pacemaker::constraint::base { 'neutron-netns-cleanup-to-openvswitch-agent-constraint':
1463 -      constraint_type => 'order',
1464 -      first_resource  => 'neutron-netns-cleanup-clone',
1465 -      second_resource => "${::neutron::params::ovs_agent_service}-clone",
1466 -      first_action    => 'start',
1467 -      second_action   => 'start',
1468 -      require         => [Pacemaker::Resource::Ocf['neutron-netns-cleanup'],
1469 -                          Pacemaker::Resource::Service[$::neutron::params::ovs_agent_service]],
1470 -    }
1471 -    pacemaker::constraint::colocation { 'neutron-netns-cleanup-to-openvswitch-agent-colocation':
1472 -      source  => "${::neutron::params::ovs_agent_service}-clone",
1473 -      target  => 'neutron-netns-cleanup-clone',
1474 -      score   => 'INFINITY',
1475 -      require => [Pacemaker::Resource::Ocf['neutron-netns-cleanup'],
1476 -                  Pacemaker::Resource::Service[$::neutron::params::ovs_agent_service]],
1477 -    }
1478 -
1479 -    #another chain keystone-->neutron-server-->ovs-agent-->dhcp-->l3
1480      pacemaker::constraint::base { 'keystone-to-neutron-server-constraint':
1481        constraint_type => 'order',
1482        first_resource  => "${::keystone::params::service_name}-clone",
1483 @@ -1120,65 +1243,110 @@ if hiera('step') >= 4 {
1484        require         => [Pacemaker::Resource::Service[$::keystone::params::service_name],
1485                            Pacemaker::Resource::Service[$::neutron::params::server_service]],
1486      }
1487 -    pacemaker::constraint::base { 'neutron-server-to-openvswitch-agent-constraint':
1488 -      constraint_type => 'order',
1489 -      first_resource  => "${::neutron::params::server_service}-clone",
1490 -      second_resource => "${::neutron::params::ovs_agent_service}-clone",
1491 -      first_action    => 'start',
1492 -      second_action   => 'start',
1493 -      require         => [Pacemaker::Resource::Service[$::neutron::params::server_service],
1494 -                          Pacemaker::Resource::Service[$::neutron::params::ovs_agent_service]],
1495 -    }
1496 -    pacemaker::constraint::base { 'neutron-openvswitch-agent-to-dhcp-agent-constraint':
1497 -      constraint_type => 'order',
1498 -      first_resource  => "${::neutron::params::ovs_agent_service}-clone",
1499 -      second_resource => "${::neutron::params::dhcp_agent_service}-clone",
1500 -      first_action    => 'start',
1501 -      second_action   => 'start',
1502 -      require         => [Pacemaker::Resource::Service[$::neutron::params::ovs_agent_service],
1503 -                          Pacemaker::Resource::Service[$::neutron::params::dhcp_agent_service]],
1504 +    if 'openvswitch' in hiera('neutron_mechanism_drivers') {
1505 +      pacemaker::resource::service { $::neutron::params::ovs_agent_service:
1506 +        clone_params => "interleave=true",
1507 +      }
1508 +      pacemaker::resource::ocf { $::neutron::params::ovs_cleanup_service:
1509 +        ocf_agent_name => "neutron:OVSCleanup",
1510 +        clone_params => "interleave=true",
1511 +      }
1512 +      # neutron - one chain ovs-cleanup-->netns-cleanup-->ovs-agent
1513 +      pacemaker::constraint::base { 'neutron-ovs-cleanup-to-netns-cleanup-constraint':
1514 +        constraint_type => "order",
1515 +        first_resource => "${::neutron::params::ovs_cleanup_service}-clone",
1516 +        second_resource => "neutron-netns-cleanup-clone",
1517 +        first_action => "start",
1518 +        second_action => "start",
1519 +        require => [Pacemaker::Resource::Ocf["${::neutron::params::ovs_cleanup_service}"],
1520 +                    Pacemaker::Resource::Ocf['neutron-netns-cleanup']],
1521 +      }
1522 +      pacemaker::constraint::colocation { 'neutron-ovs-cleanup-to-netns-cleanup-colocation':
1523 +        source => "neutron-netns-cleanup-clone",
1524 +        target => "${::neutron::params::ovs_cleanup_service}-clone",
1525 +        score => "INFINITY",
1526 +        require => [Pacemaker::Resource::Ocf["${::neutron::params::ovs_cleanup_service}"],
1527 +                    Pacemaker::Resource::Ocf['neutron-netns-cleanup']],
1528 +      }
1529 +      pacemaker::constraint::base { 'neutron-netns-cleanup-to-openvswitch-agent-constraint':
1530 +        constraint_type => "order",
1531 +        first_resource => "neutron-netns-cleanup-clone",
1532 +        second_resource => "${::neutron::params::ovs_agent_service}-clone",
1533 +        first_action => "start",
1534 +        second_action => "start",
1535 +        require => [Pacemaker::Resource::Ocf["neutron-netns-cleanup"],
1536 +                    Pacemaker::Resource::Service["${::neutron::params::ovs_agent_service}"]],
1537 +      }
1538 +      pacemaker::constraint::colocation { 'neutron-netns-cleanup-to-openvswitch-agent-colocation':
1539 +        source => "${::neutron::params::ovs_agent_service}-clone",
1540 +        target => "neutron-netns-cleanup-clone",
1541 +        score => "INFINITY",
1542 +        require => [Pacemaker::Resource::Ocf["neutron-netns-cleanup"],
1543 +                    Pacemaker::Resource::Service["${::neutron::params::ovs_agent_service}"]],
1544 +      }
1545  
1546 +      #another chain keystone-->neutron-server-->ovs-agent-->dhcp-->l3
1547 +      pacemaker::constraint::base { 'neutron-server-to-openvswitch-agent-constraint':
1548 +        constraint_type => "order",
1549 +        first_resource => "${::neutron::params::server_service}-clone",
1550 +        second_resource => "${::neutron::params::ovs_agent_service}-clone",
1551 +        first_action => "start",
1552 +        second_action => "start",
1553 +        require => [Pacemaker::Resource::Service[$::neutron::params::server_service],
1554 +                    Pacemaker::Resource::Service[$::neutron::params::ovs_agent_service]],
1555 +      }
1556 +      pacemaker::constraint::base { 'neutron-openvswitch-agent-to-dhcp-agent-constraint':
1557 +        constraint_type => "order",
1558 +        first_resource => "${::neutron::params::ovs_agent_service}-clone",
1559 +        second_resource => "${::neutron::params::dhcp_agent_service}-clone",
1560 +        first_action => "start",
1561 +        second_action => "start",
1562 +        require => [Pacemaker::Resource::Service["${::neutron::params::ovs_agent_service}"],
1563 +                    Pacemaker::Resource::Service["${::neutron::params::dhcp_agent_service}"]],
1564 +
1565 +      }
1566 +      pacemaker::constraint::colocation { 'neutron-openvswitch-agent-to-dhcp-agent-colocation':
1567 +        source => "${::neutron::params::dhcp_agent_service}-clone",
1568 +        target => "${::neutron::params::ovs_agent_service}-clone",
1569 +        score => "INFINITY",
1570 +        require => [Pacemaker::Resource::Service["${::neutron::params::ovs_agent_service}"],
1571 +                    Pacemaker::Resource::Service["${::neutron::params::dhcp_agent_service}"]],
1572 +      }
1573      }
1574 -    pacemaker::constraint::colocation { 'neutron-openvswitch-agent-to-dhcp-agent-colocation':
1575 -      source  => "${::neutron::params::dhcp_agent_service}-clone",
1576 -      target  => "${::neutron::params::ovs_agent_service}-clone",
1577 -      score   => 'INFINITY',
1578 -      require => [Pacemaker::Resource::Service[$::neutron::params::ovs_agent_service],
1579 -                  Pacemaker::Resource::Service[$::neutron::params::dhcp_agent_service]],
1580 -    }
1581 -    pacemaker::constraint::base { 'neutron-dhcp-agent-to-l3-agent-constraint':
1582 -      constraint_type => 'order',
1583 -      first_resource  => "${::neutron::params::dhcp_agent_service}-clone",
1584 -      second_resource => "${::neutron::params::l3_agent_service}-clone",
1585 -      first_action    => 'start',
1586 -      second_action   => 'start',
1587 -      require         => [Pacemaker::Resource::Service[$::neutron::params::dhcp_agent_service],
1588 -                          Pacemaker::Resource::Service[$::neutron::params::l3_agent_service]],
1589 -    }
1590 -    pacemaker::constraint::colocation { 'neutron-dhcp-agent-to-l3-agent-colocation':
1591 -      source  => "${::neutron::params::l3_agent_service}-clone",
1592 -      target  => "${::neutron::params::dhcp_agent_service}-clone",
1593 -      score   => 'INFINITY',
1594 -      require => [Pacemaker::Resource::Service[$::neutron::params::dhcp_agent_service],
1595 -                  Pacemaker::Resource::Service[$::neutron::params::l3_agent_service]],
1596 -    }
1597 -    pacemaker::constraint::base { 'neutron-l3-agent-to-metadata-agent-constraint':
1598 -      constraint_type => 'order',
1599 -      first_resource  => "${::neutron::params::l3_agent_service}-clone",
1600 -      second_resource => "${::neutron::params::metadata_agent_service}-clone",
1601 -      first_action    => 'start',
1602 -      second_action   => 'start',
1603 -      require         => [Pacemaker::Resource::Service[$::neutron::params::l3_agent_service],
1604 -                          Pacemaker::Resource::Service[$::neutron::params::metadata_agent_service]],
1605 -    }
1606 -    pacemaker::constraint::colocation { 'neutron-l3-agent-to-metadata-agent-colocation':
1607 -      source  => "${::neutron::params::metadata_agent_service}-clone",
1608 -      target  => "${::neutron::params::l3_agent_service}-clone",
1609 -      score   => 'INFINITY',
1610 -      require => [Pacemaker::Resource::Service[$::neutron::params::l3_agent_service],
1611 -                  Pacemaker::Resource::Service[$::neutron::params::metadata_agent_service]],
1612 +    if !('onos_ml2' in hiera('neutron_mechanism_drivers') or str2bool(hiera('opendaylight_enable_l3', 'no'))) {
1613 +      pacemaker::constraint::base { 'neutron-dhcp-agent-to-l3-agent-constraint':
1614 +        constraint_type => 'order',
1615 +        first_resource  => "${::neutron::params::dhcp_agent_service}-clone",
1616 +        second_resource => "${::neutron::params::l3_agent_service}-clone",
1617 +        first_action    => 'start',
1618 +        second_action   => 'start',
1619 +        require         => [Pacemaker::Resource::Service[$::neutron::params::dhcp_agent_service],
1620 +                            Pacemaker::Resource::Service[$::neutron::params::l3_agent_service]],
1621 +      }
1622 +      pacemaker::constraint::colocation { 'neutron-dhcp-agent-to-l3-agent-colocation':
1623 +        source  => "${::neutron::params::l3_agent_service}-clone",
1624 +        target  => "${::neutron::params::dhcp_agent_service}-clone",
1625 +        score   => 'INFINITY',
1626 +        require => [Pacemaker::Resource::Service[$::neutron::params::dhcp_agent_service],
1627 +                    Pacemaker::Resource::Service[$::neutron::params::l3_agent_service]],
1628 +      }
1629 +      pacemaker::constraint::base { 'neutron-l3-agent-to-metadata-agent-constraint':
1630 +        constraint_type => 'order',
1631 +        first_resource  => "${::neutron::params::l3_agent_service}-clone",
1632 +        second_resource => "${::neutron::params::metadata_agent_service}-clone",
1633 +        first_action    => 'start',
1634 +        second_action   => 'start',
1635 +        require         => [Pacemaker::Resource::Service[$::neutron::params::l3_agent_service],
1636 +                            Pacemaker::Resource::Service[$::neutron::params::metadata_agent_service]],
1637 +      }
1638 +      pacemaker::constraint::colocation { 'neutron-l3-agent-to-metadata-agent-colocation':
1639 +        source  => "${::neutron::params::metadata_agent_service}-clone",
1640 +        target  => "${::neutron::params::l3_agent_service}-clone",
1641 +        score   => 'INFINITY',
1642 +        require => [Pacemaker::Resource::Service[$::neutron::params::l3_agent_service],
1643 +                    Pacemaker::Resource::Service[$::neutron::params::metadata_agent_service]],
1644 +      }
1645      }
1646 -
1647      # Nova
1648      pacemaker::resource::service { $::nova::params::api_service_name :
1649        clone_params => 'interleave=true',
1650 @@ -1276,7 +1444,7 @@ if hiera('step') >= 4 {
1651                    Pacemaker::Resource::Service[$::nova::params::conductor_service_name]],
1652      }
1653  
1654 -    # Ceilometer
1655 +    # Ceilometer and Aodh
1656      case downcase(hiera('ceilometer_backend')) {
1657        /mysql/: {
1658          pacemaker::resource::service { $::ceilometer::params::agent_central_service_name :
1659 @@ -1298,10 +1466,19 @@ if hiera('step') >= 4 {
1660      pacemaker::resource::service { $::ceilometer::params::api_service_name :
1661        clone_params => 'interleave=true',
1662      }
1663 -    pacemaker::resource::service { $::ceilometer::params::alarm_evaluator_service_name :
1664 +    pacemaker::resource::service { $::aodh::params::notifier_service_name :
1665        clone_params => 'interleave=true',
1666      }
1667 -    pacemaker::resource::service { $::ceilometer::params::alarm_notifier_service_name :
1668 +    pacemaker::resource::service { $::aodh::params::expirer_package_serice :
1669 +      clone_params => 'interleave=true',
1670 +    }
1671 +    pacemaker::resource::service { $::aodh::params::listener_service_name :
1672 +      clone_params => 'interleave=true',
1673 +    }
1674 +    pacemaker::resource::service { $::aodh::params::api_service_name :
1675 +      clone_params => 'interleave=true',
1676 +    }
1677 +    pacemaker::resource::service { $::aodh::params::evaluator_service_name :
1678        clone_params => 'interleave=true',
1679      }
1680      pacemaker::resource::service { $::ceilometer::params::agent_notification_service_name :
1681 @@ -1315,8 +1492,19 @@ if hiera('step') >= 4 {
1682      # Fedora doesn't know `require-all` parameter for constraints yet
1683      if $::operatingsystem == 'Fedora' {
1684        $redis_ceilometer_constraint_params = undef
1685 +      $redis_aodh_constraint_params = undef
1686      } else {
1687        $redis_ceilometer_constraint_params = 'require-all=false'
1688 +      $redis_aodh_constraint_params = 'require-all=false'
1689 +    }
1690 +    pacemaker::constraint::base { 'keystone-then-aodh-api-constraint':
1691 +      constraint_type => 'order',
1692 +      first_resource  => "${::keystone::params::service_name}-clone",
1693 +      second_resource => "${::aodh::params::api_service_name}-clone",
1694 +      first_action    => 'start',
1695 +      second_action   => 'start',
1696 +      require         => [Pacemaker::Resource::Service[$::aodh::params::api_service_name],
1697 +                          Pacemaker::Resource::Service[$::keystone::params::service_name]],
1698      }
1699      pacemaker::constraint::base { 'redis-then-ceilometer-central-constraint':
1700        constraint_type   => 'order',
1701 @@ -1328,6 +1516,16 @@ if hiera('step') >= 4 {
1702        require           => [Pacemaker::Resource::Ocf['redis'],
1703                              Pacemaker::Resource::Service[$::ceilometer::params::agent_central_service_name]],
1704      }
1705 +    pacemaker::constraint::base { 'redis-then-aodh-evaluator-constraint':
1706 +      constraint_type   => 'order',
1707 +      first_resource    => 'redis-master',
1708 +      second_resource   => "${::aodh::params::evaluator_service_name}-clone",
1709 +      first_action      => 'promote',
1710 +      second_action     => 'start',
1711 +      constraint_params => $redis_aodh_constraint_params,
1712 +      require           => [Pacemaker::Resource::Ocf['redis'],
1713 +                            Pacemaker::Resource::Service[$::aodh::params::evaluator_service_name]],
1714 +    }
1715      pacemaker::constraint::base { 'keystone-then-ceilometer-central-constraint':
1716        constraint_type => 'order',
1717        first_resource  => "${::keystone::params::service_name}-clone",
1718 @@ -1378,53 +1576,37 @@ if hiera('step') >= 4 {
1719        require => [Pacemaker::Resource::Service[$::ceilometer::params::api_service_name],
1720                    Pacemaker::Resource::Ocf['delay']],
1721      }
1722 -    pacemaker::constraint::base { 'ceilometer-delay-then-ceilometer-alarm-evaluator-constraint':
1723 +    pacemaker::constraint::base { 'aodh-delay-then-aodh-evaluator-constraint':
1724        constraint_type => 'order',
1725        first_resource  => 'delay-clone',
1726 -      second_resource => "${::ceilometer::params::alarm_evaluator_service_name}-clone",
1727 +      second_resource => "${::aodh::params::evaluator_service_name}-clone",
1728        first_action    => 'start',
1729        second_action   => 'start',
1730 -      require         => [Pacemaker::Resource::Service[$::ceilometer::params::alarm_evaluator_service_name],
1731 +      require         => [Pacemaker::Resource::Service[$::aodh::params::evaluator_service_name],
1732                            Pacemaker::Resource::Ocf['delay']],
1733      }
1734 -    pacemaker::constraint::colocation { 'ceilometer-alarm-evaluator-with-ceilometer-delay-colocation':
1735 -      source  => "${::ceilometer::params::alarm_evaluator_service_name}-clone",
1736 +    pacemaker::constraint::colocation { 'aodh-evaluator-with-aodh-delay-colocation':
1737 +      source  => "${::aodh::params::evaluator_service_name}-clone",
1738        target  => 'delay-clone',
1739        score   => 'INFINITY',
1740 -      require => [Pacemaker::Resource::Service[$::ceilometer::params::api_service_name],
1741 +      require => [Pacemaker::Resource::Service[$::horizon::params::http_service],
1742                    Pacemaker::Resource::Ocf['delay']],
1743      }
1744 -    pacemaker::constraint::base { 'ceilometer-alarm-evaluator-then-ceilometer-alarm-notifier-constraint':
1745 -      constraint_type => 'order',
1746 -      first_resource  => "${::ceilometer::params::alarm_evaluator_service_name}-clone",
1747 -      second_resource => "${::ceilometer::params::alarm_notifier_service_name}-clone",
1748 -      first_action    => 'start',
1749 -      second_action   => 'start',
1750 -      require         => [Pacemaker::Resource::Service[$::ceilometer::params::alarm_evaluator_service_name],
1751 -                          Pacemaker::Resource::Service[$::ceilometer::params::alarm_notifier_service_name]],
1752 -    }
1753 -    pacemaker::constraint::colocation { 'ceilometer-alarm-notifier-with-ceilometer-alarm-evaluator-colocation':
1754 -      source  => "${::ceilometer::params::alarm_notifier_service_name}-clone",
1755 -      target  => "${::ceilometer::params::alarm_evaluator_service_name}-clone",
1756 -      score   => 'INFINITY',
1757 -      require => [Pacemaker::Resource::Service[$::ceilometer::params::alarm_evaluator_service_name],
1758 -                  Pacemaker::Resource::Service[$::ceilometer::params::alarm_notifier_service_name]],
1759 -    }
1760 -    pacemaker::constraint::base { 'ceilometer-alarm-notifier-then-ceilometer-notification-constraint':
1761 +    pacemaker::constraint::base { 'aodh-evaluator-then-aodh-notifier-constraint':
1762        constraint_type => 'order',
1763 -      first_resource  => "${::ceilometer::params::alarm_notifier_service_name}-clone",
1764 -      second_resource => "${::ceilometer::params::agent_notification_service_name}-clone",
1765 +      first_resource  => "${::aodh::params::evaluator_service_name}-clone",
1766 +      second_resource => "${::aodh::params::notifier_service_name}-clone",
1767        first_action    => 'start',
1768        second_action   => 'start',
1769 -      require         => [Pacemaker::Resource::Service[$::ceilometer::params::agent_notification_service_name],
1770 -                          Pacemaker::Resource::Service[$::ceilometer::params::alarm_notifier_service_name]],
1771 +      require         => [Pacemaker::Resource::Service[$::aodh::params::evaluator_service_name],
1772 +                          Pacemaker::Resource::Service[$::aodh::params::notifier_service_name]],
1773      }
1774 -    pacemaker::constraint::colocation { 'ceilometer-notification-with-ceilometer-alarm-notifier-colocation':
1775 -      source  => "${::ceilometer::params::agent_notification_service_name}-clone",
1776 -      target  => "${::ceilometer::params::alarm_notifier_service_name}-clone",
1777 +    pacemaker::constraint::colocation { 'aodh-notifier-with-aodh-evaluator-colocation':
1778 +      source  => "${::aodh::params::notifier_service_name}-clone",
1779 +      target  => "${::aodh::params::evaluator_service_name}-clone",
1780        score   => 'INFINITY',
1781 -      require => [Pacemaker::Resource::Service[$::ceilometer::params::agent_notification_service_name],
1782 -                  Pacemaker::Resource::Service[$::ceilometer::params::alarm_notifier_service_name]],
1783 +      require => [Pacemaker::Resource::Service[$::aodh::params::evaluator_service_name],
1784 +                  Pacemaker::Resource::Service[$::aodh::params::notifier_service_name]],
1785      }
1786      if downcase(hiera('ceilometer_backend')) == 'mongodb' {
1787        pacemaker::constraint::base { 'mongodb-then-ceilometer-central-constraint':
1788 diff --git a/puppet/manifests/overcloud_opendaylight.pp b/puppet/manifests/overcloud_opendaylight.pp
1789 new file mode 100644
1790 index 0000000..aeb31be
1791 --- /dev/null
1792 +++ b/puppet/manifests/overcloud_opendaylight.pp
1793 @@ -0,0 +1,27 @@
1794 +# Copyright 2015 Red Hat, Inc.
1795 +# All Rights Reserved.
1796 +#
1797 +# Licensed under the Apache License, Version 2.0 (the "License"); you may
1798 +# not use this file except in compliance with the License. You may obtain
1799 +# a copy of the License at
1800 +#
1801 +#     http://www.apache.org/licenses/LICENSE-2.0
1802 +#
1803 +# Unless required by applicable law or agreed to in writing, software
1804 +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1805 +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1806 +# License for the specific language governing permissions and limitations
1807 +# under the License.
1808 +
1809 +include ::tripleo::packages
1810 +
1811 +if count(hiera('ntp::servers')) > 0 {
1812 +  include ::ntp
1813 +}
1814 +
1815 +class {"opendaylight":
1816 +  extra_features => any2array(hiera('opendaylight_features', 'odl-ovsdb-openstack')),
1817 +  odl_rest_port  => hiera('opendaylight_port'),
1818 +  enable_l3      => hiera('opendaylight_enable_l3', 'no'),
1819 +}
1820 +
1821 diff --git a/puppet/opendaylight-puppet.yaml b/puppet/opendaylight-puppet.yaml
1822 new file mode 100644
1823 index 0000000..6488e0e
1824 --- /dev/null
1825 +++ b/puppet/opendaylight-puppet.yaml
1826 @@ -0,0 +1,223 @@
1827 +heat_template_version: 2015-04-30
1828 +
1829 +description: >
1830 +  OpenDaylight node configured by Puppet.
1831 +
1832 +parameters:
1833 +  OpenDaylightFlavor:
1834 +    default: baremetal
1835 +    description: The flavor to use for the OpenDaylight node
1836 +    type: string
1837 +  OpenDaylightImage:
1838 +    default: overcloud-full
1839 +    description: The image to use for the OpenDaylight node
1840 +    type: string
1841 +  OpenDaylightHostname:
1842 +    default: opendaylight-server
1843 +    description: The hostname to use for the OpenDaylight node
1844 +    type: string
1845 +  OpenDaylightUsername:
1846 +    default: admin
1847 +    description: The admin user for the OpenDaylight node
1848 +    type: string
1849 +  OpenDaylightPassword:
1850 +    default: ''
1851 +    description: The admin password for the OpenDaylight node
1852 +    type: string
1853 +    hidden: true
1854 +  OpenDaylightEnableL3:
1855 +    description: Knob to enable/disable ODL L3
1856 +    type: string
1857 +    default: 'no'
1858 +  OpenDaylightFeatures:
1859 +    description: List of features to install with ODL
1860 +    type: comma_delimited_list
1861 +    default: "odl-ovsdb-openstack"
1862 +  OpenDaylightPort:
1863 +    default: 8081
1864 +    description: Set OpenDaylight service port
1865 +    type: number
1866 +  KeyName:
1867 +    description: The keypair to use for SSH access to the node (via heat-admin user)
1868 +    type: string
1869 +    default: default
1870 +    constraints:
1871 +      - custom_constraint: nova.keypair
1872 +  ImageUpdatePolicy:
1873 +    default: 'REBUILD_PRESERVE_EPHEMERAL'
1874 +    description: What policy to use when reconstructing instances. REBUILD for rebuilds, REBUILD_PRESERVE_EPHEMERAL to preserve /mnt.
1875 +    type: string
1876 +  UpdateIdentifier:
1877 +    default: ''
1878 +    type: string
1879 +    description: >
1880 +      Setting to a previously unused value during stack-update will trigger
1881 +      package update on all nodes
1882 +  NtpServer:
1883 +    type: string
1884 +    default: ''
1885 +  PublicInterface:
1886 +    default: nic1
1887 +    description: What interface to bridge onto br-ex for network nodes.
1888 +    type: string
1889 +
1890 +resources:
1891 +  OpenDaylightNode:
1892 +    type: OS::Nova::Server
1893 +    properties:
1894 +      image: {get_param: OpenDaylightImage}
1895 +      image_update_policy: {get_param: ImageUpdatePolicy}
1896 +      flavor: {get_param: OpenDaylightFlavor}
1897 +      key_name: {get_param: KeyName}
1898 +      networks:
1899 +        - network: ctlplane
1900 +      user_data_format: SOFTWARE_CONFIG
1901 +      user_data: {get_resource: NodeUserData}
1902 +      name: {get_param: OpenDaylightHostname}
1903 +
1904 +  NodeUserData:
1905 +    type: OS::TripleO::NodeUserData
1906 +
1907 +  ExternalPort:
1908 +    type: OS::TripleO::Controller::Ports::ExternalPort
1909 +    properties:
1910 +      ControlPlaneIP: {get_attr: [OpenDaylightNode, networks, ctlplane, 0]}
1911 +
1912 +  InternalApiPort:
1913 +    type: OS::TripleO::Controller::Ports::InternalApiPort
1914 +    properties:
1915 +      ControlPlaneIP: {get_attr: [OpenDaylightNode, networks, ctlplane, 0]}
1916 +
1917 +  NetIpMap:
1918 +    type: OS::TripleO::Network::Ports::NetIpMap
1919 +    properties:
1920 +      ControlPlaneIp: {get_attr: [OpenDaylightNode, networks, ctlplane, 0]}
1921 +      ExternalIp: {get_attr: [ExternalPort, ip_address]}
1922 +      InternalApiIp: {get_attr: [InternalApiPort, ip_address]}
1923 +
1924 +  NetIpSubnetMap:
1925 +    type: OS::TripleO::Network::Ports::NetIpSubnetMap
1926 +    properties:
1927 +      ControlPlaneIp: {get_attr: [OpenDaylightNode, networks, ctlplane, 0]}
1928 +      ExternalIpSubnet: {get_attr: [ExternalPort, ip_subnet]}
1929 +      InternalApiIpSubnet: {get_attr: [InternalApiPort, ip_subnet]}
1930 +
1931 +  NetworkConfig:
1932 +    type: OS::TripleO::Controller::Net::SoftwareConfig
1933 +    properties:
1934 +      ControlPlaneIp: {get_attr: [OpenDaylightNode, networks, ctlplane, 0]}
1935 +      ExternalIpSubnet: {get_attr: [ExternalPort, ip_subnet]}
1936 +      InternalApiIpSubnet: {get_attr: [InternalApiPort, ip_subnet]}
1937 +
1938 +  NetworkDeployment:
1939 +    type: OS::TripleO::SoftwareDeployment
1940 +    properties:
1941 +      config: {get_resource: NetworkConfig}
1942 +      server: {get_resource: OpenDaylightNode}
1943 +      input_values:
1944 +        bridge_name: br-ex
1945 +        interface_name: {get_param: PublicInterface}
1946 +
1947 +  OpenDaylightDeployment:
1948 +    type: OS::TripleO::SoftwareDeployment
1949 +    depends_on: NetworkDeployment
1950 +    properties:
1951 +      config: {get_resource: OpenDaylightConfig}
1952 +      server: {get_resource: OpenDaylightNode}
1953 +      input_values:
1954 +        ntp_servers:
1955 +          str_replace:
1956 +            template: '["server"]'
1957 +            params:
1958 +              server: {get_param: NtpServer}
1959 +        opendaylight_port: {get_param: OpenDaylightPort}
1960 +        opendaylight_enable_l3: {get_param: OpenDaylightEnableL3}
1961 +        opendaylight_username: {get_param: OpenDaylightUsername}
1962 +        opendaylight_password: {get_param: OpenDaylightPassword}
1963 +        opendaylight_features: {get_param: OpenDaylightFeatures}
1964 +
1965 +  OpenDaylightConfig:
1966 +    type: OS::Heat::StructuredConfig
1967 +    properties:
1968 +      group: os-apply-config
1969 +      config:
1970 +        hiera:
1971 +          hierarchy:
1972 +            - '"%{::uuid}"'
1973 +            - heat_config_%{::deploy_config_name}
1974 +            - extraconfig
1975 +            - bootstrap_node # provided by BootstrapNodeConfig
1976 +            - all_nodes # provided by allNodesConfig
1977 +            - vip_data # provided by vip-config
1978 +            - RedHat # Workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1236143
1979 +            - common
1980 +          datafiles:
1981 +            common:
1982 +              raw_data: {get_file: hieradata/common.yaml}
1983 +              mapped_data:
1984 +                ntp::servers: {get_input: ntp_servers}
1985 +                opendaylight::admin_username: {get_param: OpenDaylightUsername}
1986 +                opendaylight::admin_password: {get_param: OpenDaylightPassword}
1987 +                opendaylight_port: {get_input: opendaylight_port}
1988 +                opendaylight_enable_l3: {get_input: opendaylight_enable_l3}
1989 +                opendaylight_features: {get_input: opendaylight_features}
1990 +            ceph:
1991 +              raw_data: {get_file: hieradata/ceph.yaml}
1992 +
1993 +  UpdateConfig:
1994 +    type: OS::TripleO::Tasks::PackageUpdate
1995 +
1996 +  UpdateDeployment:
1997 +    type: OS::Heat::SoftwareDeployment
1998 +    properties:
1999 +      config: {get_resource: UpdateConfig}
2000 +      server: {get_resource: OpenDaylightNode}
2001 +      input_values:
2002 +        update_identifier:
2003 +          get_param: UpdateIdentifier
2004 +
2005 +  OpenDaylightHostsConfig:
2006 +    type: OS::Heat::SoftwareConfig
2007 +    properties:
2008 +      group: script
2009 +      config: |
2010 +        #!/usr/bin/env bash
2011 +        echo -e "$(facter ipaddress)\t\t$(hostname -f)\t$(hostname -s)" >> /etc/hosts
2012 +
2013 +  OpenDaylightHostsDeployment:
2014 +    type: OS::Heat::StructuredDeployment
2015 +    depends_on: OpenDaylightDeployment
2016 +    properties:
2017 +      server: {get_resource: OpenDaylightNode}
2018 +      config: {get_resource: OpenDaylightHostsConfig}
2019 +
2020 +  OpenDaylightPuppetConfig:
2021 +    type: OS::Heat::SoftwareConfig
2022 +    properties:
2023 +      group: puppet
2024 +      config:
2025 +        get_file: manifests/overcloud_opendaylight.pp
2026 +
2027 +  OpenDaylightPuppetDeployment:
2028 +    depends_on: OpenDaylightHostsDeployment
2029 +    type: OS::Heat::StructuredDeployment
2030 +    properties:
2031 +      server: {get_resource: OpenDaylightNode}
2032 +      config: {get_resource: OpenDaylightPuppetConfig}
2033 +      input_values:
2034 +        update_identifier: {get_param: UpdateIdentifier}
2035 +
2036 +outputs:
2037 +  ip_address:
2038 +    description: IP address of the server in the ctlplane network
2039 +    value: {get_attr: [OpenDaylightNode, networks, ctlplane, 0]}
2040 +  opendaylight_controller_ip:
2041 +    description: IP address of the server on the internal network
2042 +    value: {get_attr: [InternalApiPort, ip_address]}
2043 +  config_identifier:
2044 +    description: identifier which changes if the node configuration may need re-applying
2045 +    value:
2046 +      list_join:
2047 +      - ','
2048 +      - - {get_attr: [OpenDaylightDeployment, deploy_stdout]}
2049 +        - {get_param: UpdateIdentifier}
2050 diff --git a/puppet/vip-config.yaml b/puppet/vip-config.yaml
2051 index 1dec489..727bb79 100644
2052 --- a/puppet/vip-config.yaml
2053 +++ b/puppet/vip-config.yaml
2054 @@ -27,6 +27,7 @@ resources:
2055                  horizon_vip: {get_input: horizon_vip}
2056                  redis_vip: {get_input: redis_vip}
2057                  mysql_vip: {get_input: mysql_vip}
2058 +                opendaylight_api_vip: {get_input: opendaylight_api_vip}
2059                  tripleo::loadbalancer::public_virtual_ip: {get_input: public_virtual_ip}
2060                  tripleo::loadbalancer::controller_virtual_ip: {get_input: control_virtual_ip}
2061                  tripleo::loadbalancer::internal_api_virtual_ip: {get_input: internal_api_virtual_ip}
2062 -- 
2063 2.5.0
2064