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