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