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