Merge "Fixes ODL L3 so that it now deploys correctly"
[apex.git] / build / opnfv-tripleo-heat-templates.patch
1 From d9b3ccc28ff57bfa4e1135cea038ac4e5318947c 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  overcloud-resource-registry-puppet.yaml            |   3 +
12  overcloud-without-mergepy.yaml                     |  73 +++++
13  puppet/all-nodes-config.yaml                       |   6 +
14  puppet/compute.yaml                                |  35 +++
15  puppet/controller.yaml                             |  47 ++++
16  puppet/manifests/overcloud_compute.pp              |  33 ++-
17  puppet/manifests/overcloud_controller.pp           |  86 +++++-
18  puppet/manifests/overcloud_controller_pacemaker.pp | 302 +++++++++++++--------
19  puppet/manifests/overcloud_opendaylight.pp         |  27 ++
20  puppet/opendaylight-puppet.yaml                    | 217 +++++++++++++++
21  14 files changed, 772 insertions(+), 124 deletions(-)
22  create mode 100644 environments/onos.yaml
23  create mode 100644 environments/opendaylight-external.yaml
24  create mode 100644 environments/opendaylight.yaml
25  create mode 100644 environments/opendaylight_l3.yaml
26  create mode 100644 puppet/manifests/overcloud_opendaylight.pp
27  create mode 100644 puppet/opendaylight-puppet.yaml
28
29 diff --git a/environments/onos.yaml b/environments/onos.yaml
30 new file mode 100644
31 index 0000000..510aca9
32 --- /dev/null
33 +++ b/environments/onos.yaml
34 @@ -0,0 +1,8 @@
35 +parameters:
36 +    #This a bug for odl deployment. Once bug fixed OpenDaylightCount can be remove.
37 +    OpenDaylightCount: 0
38 +    NeutronL3HA: false
39 +    ExtraConfig:
40 +      neutron_service_plugins: ['onos_router']
41 +      neutron_mechanism_drivers: ['onos_ml2']
42 +      neutron_tenant_network_type: vxlan
43 diff --git a/environments/opendaylight-external.yaml b/environments/opendaylight-external.yaml
44 new file mode 100644
45 index 0000000..411df21
46 --- /dev/null
47 +++ b/environments/opendaylight-external.yaml
48 @@ -0,0 +1,25 @@
49 +# Environment file used to enable OpenDaylight
50 +# Currently uses overcloud image that is assumed
51 +# to be virt-customized with ODL RPM already on it
52 +
53 +# These parameters customize the OpenDaylight Node
54 +# The user name and password are for the ODL service
55 +# Defaults are included here for reference
56 +#parameter_defaults:
57 +#  OpenDaylightFlavor: baremetal
58 +#  OpenDaylightHostname: opendaylight-server
59 +#  OpenDaylightImage: overcloud-full
60 +#  OpenDaylightUsername: admin
61 +#  OpenDaylightPassword: admin
62 +
63 +parameters:
64 +    # increase this if you need more ODL nodes
65 +    OpenDaylightCount: 1
66 +    NeutronL3HA: false
67 +    ExtraConfig:
68 +      neutron_mechanism_drivers: ['opendaylight']
69 +      neutron_tenant_network_type: vxlan
70 +      # Enable this if you want OpenDaylight on the contollers
71 +      # reduce OpenDaylightCount to 0 if you don't want any
72 +      # OpenDaylight only nodes
73 +      #opendaylight_install: true
74 diff --git a/environments/opendaylight.yaml b/environments/opendaylight.yaml
75 new file mode 100644
76 index 0000000..c8abf75
77 --- /dev/null
78 +++ b/environments/opendaylight.yaml
79 @@ -0,0 +1,25 @@
80 +# Environment file used to enable OpenDaylight
81 +# Currently uses overcloud image that is assumed
82 +# to be virt-customized with ODL RPM already on it
83 +
84 +# These parameters customize the OpenDaylight Node
85 +# The user name and password are for the ODL service
86 +# Defaults are included here for reference
87 +#parameter_defaults:
88 +#  OpenDaylightFlavor: baremetal
89 +#  OpenDaylightHostname: opendaylight-server
90 +#  OpenDaylightImage: overcloud-full
91 +#  OpenDaylightUsername: admin
92 +#  OpenDaylightPassword: admin
93 +
94 +parameters:
95 +    # increase this if you need more ODL nodes
96 +    # OpenDaylightCount: 1
97 +    NeutronL3HA: false
98 +    ExtraConfig:
99 +      neutron_mechanism_drivers: ['opendaylight']
100 +      neutron_tenant_network_type: vxlan
101 +      # Enable this if you want OpenDaylight on the contollers
102 +      # reduce OpenDaylightCount to 0 if you don't want any
103 +      # OpenDaylight only nodes
104 +      opendaylight_install: true
105 diff --git a/environments/opendaylight_l3.yaml b/environments/opendaylight_l3.yaml
106 new file mode 100644
107 index 0000000..ffdb017
108 --- /dev/null
109 +++ b/environments/opendaylight_l3.yaml
110 @@ -0,0 +1,9 @@
111 +parameters:
112 +    #NeutronEnableL3Agent: false
113 +    NeutronEnableForceMetadata: true
114 +    OpenDaylightEnableL3: true
115 +    NeutronServicePlugins: "networking_odl.l3.l3_odl.OpenDaylightL3RouterPlugin"
116 +    ExtraConfig:
117 +      neutron_mechanism_drivers: ['opendaylight']
118 +      neutron_tenant_network_type: vxlan
119 +      opendaylight_install: true
120 diff --git a/overcloud-resource-registry-puppet.yaml b/overcloud-resource-registry-puppet.yaml
121 index 4cfed6b..adecc79 100644
122 --- a/overcloud-resource-registry-puppet.yaml
123 +++ b/overcloud-resource-registry-puppet.yaml
124 @@ -27,6 +27,9 @@ resource_registry:
125    # To disable, replace with firstboot/userdata_default.yaml
126    OS::TripleO::NodeAdminUserData: firstboot/userdata_heat_admin.yaml
127  
128 +  # This configures OpenDaylight to drive the network
129 +  OS::TripleO::OpenDaylightNode: puppet/opendaylight-puppet.yaml
130 +
131    # Hooks for operator extra config
132    # NodeUserData == Cloud-init additional user-data, e.g cloud-config
133    # ControllerExtraConfigPre == Controller configuration pre service deployment
134 diff --git a/overcloud-without-mergepy.yaml b/overcloud-without-mergepy.yaml
135 index a532c2f..1aa87ae 100644
136 --- a/overcloud-without-mergepy.yaml
137 +++ b/overcloud-without-mergepy.yaml
138 @@ -113,6 +113,10 @@ parameters:
139      default: ''
140      type: string
141      description: Neutron ID for ctlplane network.
142 +  NeutronEnableForceMetadata:
143 +    default: 'False'
144 +    description: If True, DHCP always provides metadata route to VM.
145 +    type: string
146    NeutronEnableTunnelling:
147      type: string
148      default: "True"
149 @@ -227,6 +231,27 @@ parameters:
150      default: false
151      description: Should MongoDb journaling be disabled
152      type: boolean
153 +  OpenDaylightPort:
154 +    default: 8081
155 +    description: Set opendaylight service port
156 +    type: number
157 +  OpenDaylightEnableL3:
158 +    description: Knob to enable/disable ODL L3
159 +    type: string
160 +    default: 'no'
161 +  OpenDaylightInstall:
162 +    default: false
163 +    description: Whether to install OpenDaylight on the control nodes.
164 +    type: boolean
165 +  OpenDaylightUsername:
166 +    default: 'admin'
167 +    description: The username for the opendaylight server.
168 +    type: string
169 +  OpenDaylightPassword:
170 +    default: 'admin'
171 +    type: string
172 +    description: The password for the opendaylight server.
173 +    hidden: true
174    PublicVirtualFixedIPs:
175      default: []
176      description: >
177 @@ -664,6 +689,18 @@ parameters:
178        structure as ExtraConfig.
179      type: json
180  
181 +# OpenDaylight specific parameters
182 +  OpenDaylightCount:
183 +    type: number
184 +    default: 0
185 +  OpenDaylightImage:
186 +    default: overcloud-full
187 +    type: string
188 +  OpenDaylightFlavor:
189 +    default: baremetal
190 +    description: Flavor for OpenDaylight node
191 +    type: string
192 +
193    # Hostname format for each role
194    # Note %index% is translated into the index of the node, e.g 0/1/2 etc
195    # and %stackname% is replaced with OS::stack_name in the template below.
196 @@ -688,6 +725,10 @@ parameters:
197      type: string
198      description: Format for CephStorage node hostnames
199      default: '%stackname%-cephstorage-%index%'
200 +  OpenDaylightHostnameFormat:
201 +    type: string
202 +    description: Format for OpenDaylight node hostnames
203 +    default: '%stackname%-opendaylight-%index%'
204  
205    # Identifiers to trigger tasks on nodes
206    UpdateIdentifier:
207 @@ -770,6 +811,28 @@ resources:
208        SwiftProxyVirtualIP: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, SwiftProxyNetwork]}]}
209        PublicVirtualIP: {get_attr: [VipMap, net_ip_map, external]}
210  
211 +  OpenDaylightNode:
212 +    type: OS::Heat::ResourceGroup
213 +    depends_on: Networks
214 +    properties:
215 +      count: {get_param: OpenDaylightCount}
216 +      removal_policies: {get_param: ComputeRemovalPolicies}
217 +      resource_def:
218 +        type: OS::TripleO::OpenDaylightNode
219 +        properties:
220 +          UpdateIdentifier: {get_param: UpdateIdentifier}
221 +          OpenDaylightFlavor: {get_param: OpenDaylightFlavor}
222 +          OpenDaylightImage: {get_param: OpenDaylightImage}
223 +          OpenDaylightPort: {get_param: OpenDaylightPort}
224 +          OpenDaylightUsername: {get_param: OpenDaylightUsername}
225 +          OpenDaylightPassword: {get_param: OpenDaylightPassword}
226 +          OpenDaylightEnableL3: {get_param: OpenDaylightEnableL3}
227 +          OpenDaylightHostname:
228 +            str_replace:
229 +              template: {get_param: OpenDaylightHostnameFormat}
230 +              params:
231 +                '%stackname%': {get_param: 'OS::stack_name'}
232 +
233    Controller:
234      type: OS::Heat::ResourceGroup
235      depends_on: Networks
236 @@ -832,6 +895,7 @@ resources:
237            NeutronBridgeMappings: {get_param: NeutronBridgeMappings}
238            NeutronExternalNetworkBridge: {get_param: NeutronExternalNetworkBridge}
239            NeutronEnableTunnelling: {get_param: NeutronEnableTunnelling}
240 +          NeutronEnableForceMetadata: {get_param: NeutronEnableForceMetadata}
241            NeutronNetworkVLANRanges: {get_param: NeutronNetworkVLANRanges}
242            NeutronPublicInterface: {get_param: NeutronPublicInterface}
243            NeutronPublicInterfaceDefaultRoute: {get_param: NeutronPublicInterfaceDefaultRoute}
244 @@ -853,6 +917,11 @@ resources:
245            NovaPassword: {get_param: NovaPassword}
246            NtpServer: {get_param: NtpServer}
247            MongoDbNoJournal: {get_param: MongoDbNoJournal}
248 +          OpenDaylightPort: {get_param: OpenDaylightPort}
249 +          OpenDaylightInstall: {get_param: OpenDaylightInstall}
250 +          OpenDaylightUsername: {get_param: OpenDaylightUsername}
251 +          OpenDaylightPassword: {get_param: OpenDaylightPassword}
252 +          OpenDaylightEnableL3: {get_param: OpenDaylightEnableL3}
253            PcsdPassword: {get_resource: PcsdPassword}
254            PublicVirtualInterface: {get_param: PublicVirtualInterface}
255            RabbitPassword: {get_param: RabbitPassword}
256 @@ -948,6 +1017,9 @@ resources:
257            NovaPublicIP: {get_attr: [PublicVirtualIP, ip_address]}
258            NovaPassword: {get_param: NovaPassword}
259            NtpServer: {get_param: NtpServer}
260 +          OpenDaylightPort: {get_param: OpenDaylightPort}
261 +          OpenDaylightUsername: {get_param: OpenDaylightUsername}
262 +          OpenDaylightPassword: {get_param: OpenDaylightPassword}
263            RabbitHost: {get_attr: [VipMap, net_ip_map, {get_param: [ServiceNetMap, RabbitMqNetwork]}]}
264            RabbitPassword: {get_param: RabbitPassword}
265            RabbitUserName: {get_param: RabbitUserName}
266 @@ -1068,6 +1140,7 @@ resources:
267        compute_hosts: {get_attr: [Compute, hosts_entry]}
268        controller_hosts: {get_attr: [Controller, hosts_entry]}
269        controller_ips: {get_attr: [Controller, ip_address]}
270 +      opendaylight_ip: {get_attr: [OpenDaylightNode, ip_address]}
271        block_storage_hosts: {get_attr: [BlockStorage, hosts_entry]}
272        object_storage_hosts: {get_attr: [ObjectStorage, hosts_entry]}
273        ceph_storage_hosts: {get_attr: [CephStorage, hosts_entry]}
274 diff --git a/puppet/all-nodes-config.yaml b/puppet/all-nodes-config.yaml
275 index 2bc519b..98283c2 100644
276 --- a/puppet/all-nodes-config.yaml
277 +++ b/puppet/all-nodes-config.yaml
278 @@ -8,6 +8,8 @@ parameters:
279      type: comma_delimited_list
280    controller_ips:
281      type: comma_delimited_list
282 +  opendaylight_ip:
283 +    type: comma_delimited_list
284    block_storage_hosts:
285      type: comma_delimited_list
286    object_storage_hosts:
287 @@ -82,6 +84,10 @@ resources:
288                raw_data: {get_file: hieradata/RedHat.yaml}
289              all_nodes:
290                mapped_data:
291 +                opendaylight_controller_ip:
292 +                  list_join:
293 +                  - ','
294 +                  - {get_param: opendaylight_ip}
295                  controller_node_ips:
296                    list_join:
297                    - ','
298 diff --git a/puppet/compute.yaml b/puppet/compute.yaml
299 index 70c7403..13fd4f6 100644
300 --- a/puppet/compute.yaml
301 +++ b/puppet/compute.yaml
302 @@ -213,6 +213,23 @@ parameters:
303    NtpServer:
304      type: string
305      default: ''
306 +  OpenDaylightPort:
307 +    default: 8081
308 +    description: Set opendaylight service port
309 +    type: number
310 +  OpenDaylightUsername:
311 +    default: 'admin'
312 +    description: The username for the opendaylight server.
313 +    type: string
314 +  OpenDaylightPassword:
315 +    default: 'admin'
316 +    type: string
317 +    description: The password for the opendaylight server.
318 +    hidden: true
319 +  ONOSPort:
320 +    default: 8181
321 +    description: Set onos service port
322 +    type: number
323    RabbitHost:
324      type: string
325      default: ''  # Has to be here because of the ignored empty value bug
326 @@ -320,6 +337,11 @@ resources:
327      properties:
328        ControlPlaneIP: {get_attr: [NovaCompute, networks, ctlplane, 0]}
329  
330 +  ExternalPort:
331 +    type: OS::TripleO::Controller::Ports::ExternalPort
332 +    properties:
333 +      ControlPlaneIP: {get_attr: [NovaCompute, networks, ctlplane, 0]}
334 +
335    NetIpMap:
336      type: OS::TripleO::Network::Ports::NetIpMap
337      properties:
338 @@ -327,6 +349,7 @@ resources:
339        InternalApiIp: {get_attr: [InternalApiPort, ip_address]}
340        StorageIp: {get_attr: [StoragePort, ip_address]}
341        TenantIp: {get_attr: [TenantPort, ip_address]}
342 +      ExternalIp: {get_attr: [ExternalPort, ip_address]}
343  
344    NetworkConfig:
345      type: OS::TripleO::Compute::Net::SoftwareConfig
346 @@ -335,6 +358,7 @@ resources:
347        InternalApiIpSubnet: {get_attr: [InternalApiPort, ip_subnet]}
348        StorageIpSubnet: {get_attr: [StoragePort, ip_subnet]}
349        TenantIpSubnet: {get_attr: [TenantPort, ip_subnet]}
350 +      ExternalIpSubnet: {get_attr: [ExternalPort, ip_subnet]}
351  
352    NetworkDeployment:
353      type: OS::TripleO::SoftwareDeployment
354 @@ -406,6 +430,10 @@ resources:
355                  neutron::rabbit_user: {get_input: rabbit_user}
356                  neutron::rabbit_use_ssl: {get_input: rabbit_client_use_ssl}
357                  neutron::rabbit_port: {get_input: rabbit_client_port}
358 +                opendaylight_port: {get_input: opendaylight_port}
359 +                opendaylight_username: {get_input: opendaylight_username}
360 +                opendaylight_password: {get_input: opendaylight_password}
361 +                onos_port: {get_input: onos_port}
362                  neutron_flat_networks: {get_input: neutron_flat_networks}
363                  neutron_host: {get_input: neutron_host}
364                  neutron::agents::ml2::ovs::local_ip: {get_input: neutron_local_ip}
365 @@ -459,6 +487,10 @@ resources:
366          snmpd_readonly_user_name: {get_param: SnmpdReadonlyUserName}
367          snmpd_readonly_user_password: {get_param: SnmpdReadonlyUserPassword}
368          glance_api_servers: {get_param: [EndpointMap, GlanceInternal, uri]}
369 +        opendaylight_port: {get_param: OpenDaylightPort}
370 +        opendaylight_username: {get_param: OpenDaylightUsername}
371 +        opendaylight_password: {get_param: OpenDaylightPassword}
372 +        onos_port: {get_param: ONOSPort}
373          neutron_flat_networks: {get_param: NeutronFlatNetworks}
374          neutron_host: {get_param: NeutronHost}
375          neutron_local_ip: {get_attr: [NetIpMap, net_ip_map, {get_param: [ServiceNetMap, NeutronTenantNetwork]}]}
376 @@ -570,6 +602,9 @@ outputs:
377    tenant_ip_address:
378      description: IP address of the server in the tenant network
379      value: {get_attr: [TenantPort, ip_address]}
380 +  external_ip_address:
381 +    description: IP address of the server in the external network
382 +    value: {get_attr: [ExternalPort, ip_address]}
383    hostname:
384      description: Hostname of the server
385      value: {get_attr: [NovaCompute, name]}
386 diff --git a/puppet/controller.yaml b/puppet/controller.yaml
387 index ea0b3af..1d52922 100644
388 --- a/puppet/controller.yaml
389 +++ b/puppet/controller.yaml
390 @@ -357,6 +357,10 @@ parameters:
391      default: 'True'
392      description: Allow automatic l3-agent failover
393      type: string
394 +  NeutronEnableForceMetadata:
395 +    default: 'False'
396 +    description: If True, DHCP always provides metadata route to VM.
397 +    type: string
398    NeutronEnableTunnelling:
399      type: string
400      default: "True"
401 @@ -443,6 +447,31 @@ parameters:
402    NtpServer:
403      type: string
404      default: ''
405 +  OpenDaylightPort:
406 +    default: 8081
407 +    description: Set opendaylight service port
408 +    type: number
409 +  OpenDaylightInstall:
410 +    default: false
411 +    description: Whether to install OpenDaylight on the control nodes.
412 +    type: boolean
413 +  OpenDaylightUsername:
414 +    default: 'admin'
415 +    description: The username for the opendaylight server.
416 +    type: string
417 +  OpenDaylightPassword:
418 +    default: 'admin'
419 +    type: string
420 +    description: The password for the opendaylight server.
421 +    hidden: true
422 +  OpenDaylightEnableL3:
423 +    description: Knob to enable/disable ODL L3
424 +    type: string
425 +    default: 'no'
426 +  ONOSPort:
427 +    default: 8181
428 +    description: Set onos service port
429 +    type: number
430    PcsdPassword:
431      type: string
432      description: The password for the 'pcsd' user.
433 @@ -696,6 +725,7 @@ resources:
434        input_values:
435          bootstack_nodeid: {get_attr: [Controller, name]}
436          neutron_enable_tunneling: {get_param: NeutronEnableTunnelling}
437 +        neutron_enable_force_metadata: {get_param: NeutronEnableForceMetadata}
438          haproxy_log_address: {get_param: HAProxySyslogAddress}
439          heat.watch_server_url:
440            list_join:
441 @@ -805,6 +835,12 @@ resources:
442              template: tripleo-CLUSTER
443              params:
444                CLUSTER: {get_param: MysqlClusterUniquePart}
445 +        opendaylight_port: {get_param: OpenDaylightPort}
446 +        opendaylight_install: {get_param: OpenDaylightInstall}
447 +        opendaylight_username: {get_param: OpenDaylightUsername}
448 +        opendaylight_password: {get_param: OpenDaylightPassword}
449 +        opendaylight_enable_l3: {get_param: OpenDaylightEnableL3}
450 +        onos_port: {get_param: ONOSPort}
451          neutron_flat_networks: {get_param: NeutronFlatNetworks}
452          neutron_metadata_proxy_shared_secret: {get_param: NeutronMetadataProxySharedSecret}
453          neutron_agent_mode: {get_param: NeutronAgentMode}
454 @@ -1136,6 +1172,16 @@ resources:
455                  mysql_bind_host: {get_input: mysql_network}
456                  mysql_virtual_ip: {get_input: mysql_virtual_ip}
457  
458 +                # OpenDaylight
459 +                opendaylight_port: {get_input: opendaylight_port}
460 +                opendaylight_install: {get_input: opendaylight_install}
461 +                opendaylight_username: {get_input: opendaylight_username}
462 +                opendaylight_password: {get_input: opendaylight_password}
463 +                opendaylight_enable_l3: {get_input: opendaylight_enable_l3}
464 +                
465 +                # ONOS
466 +                onos_port: {get_input: onos_port}
467 +
468                  # Neutron
469                  neutron::bind_host: {get_input: neutron_api_network}
470                  neutron::rabbit_password: {get_input: rabbit_password}
471 @@ -1152,6 +1198,7 @@ resources:
472                  neutron_flat_networks: {get_input: neutron_flat_networks}
473                  neutron::agents::metadata::shared_secret: {get_input: neutron_metadata_proxy_shared_secret}
474                  neutron::agents::metadata::metadata_ip: {get_input: neutron_api_network}
475 +                neutron::agents::dhcp::enable_force_metadata: {get_input: neutron_enable_force_metadata}
476                  neutron_agent_mode: {get_input: neutron_agent_mode}
477                  neutron_router_distributed: {get_input: neutron_router_distributed}
478                  neutron::core_plugin: {get_input: neutron_core_plugin}
479 diff --git a/puppet/manifests/overcloud_compute.pp b/puppet/manifests/overcloud_compute.pp
480 index cd41cc7..b8336ee 100644
481 --- a/puppet/manifests/overcloud_compute.pp
482 +++ b/puppet/manifests/overcloud_compute.pp
483 @@ -75,9 +75,36 @@ class { '::neutron::plugins::ml2':
484    tenant_network_types => [hiera('neutron_tenant_network_type')],
485  }
486  
487 -class { '::neutron::agents::ml2::ovs':
488 -  bridge_mappings => split(hiera('neutron_bridge_mappings'), ','),
489 -  tunnel_types    => split(hiera('neutron_tunnel_types'), ','),
490 +if 'opendaylight' in hiera('neutron_mechanism_drivers') {
491 +
492 +  if str2bool(hiera('opendaylight_install', 'false')) {
493 +    $controller_ips = split(hiera('controller_node_ips'), ',')
494 +    $opendaylight_controller_ip = $controller_ips[0]
495 +  } else {
496 +    $opendaylight_controller_ip = hiera('opendaylight_controller_ip')
497 +  }
498 +
499 +  if str2bool(hiera('opendaylight_install', 'false')) {
500 +    class { 'neutron::plugins::ovs::opendaylight':
501 +      odl_controller_ip => $opendaylight_controller_ip,
502 +      tunnel_ip         => hiera('neutron::agents::ml2::ovs::local_ip'),
503 +      odl_port          => hiera('opendaylight_port'),
504 +      odl_username      => hiera('opendaylight_username'),
505 +      odl_password      => hiera('opendaylight_password'),
506 +    }
507 +  }
508 +
509 +} elsif 'onos_ml2' in hiera('neutron_mechanism_drivers') {
510 +  $controller_ips = split(hiera('controller_node_ips'), ',')
511 +  class {'onos::ovs_computer':
512 +    manager_ip => $controller_ips[0]
513 +  }
514 +
515 +} else {
516 +  class { 'neutron::agents::ml2::ovs':
517 +    bridge_mappings => split(hiera('neutron_bridge_mappings'), ','),
518 +    tunnel_types    => split(hiera('neutron_tunnel_types'), ','),
519 +  }
520  }
521  
522  if 'cisco_n1kv' in hiera('neutron_mechanism_drivers') {
523 diff --git a/puppet/manifests/overcloud_controller.pp b/puppet/manifests/overcloud_controller.pp
524 index 1f6c2be..7851b45 100644
525 --- a/puppet/manifests/overcloud_controller.pp
526 +++ b/puppet/manifests/overcloud_controller.pp
527 @@ -30,6 +30,21 @@ if hiera('step') >= 1 {
528  
529  if hiera('step') >= 2 {
530  
531 +  if str2bool(hiera('opendaylight_install', 'false')) {
532 +    class {"opendaylight":
533 +      extra_features => ['odl-ovsdb-openstack'],
534 +      odl_rest_port  => hiera('opendaylight_port'),
535 +      enable_l3      => hiera('opendaylight_enable_l3', 'no'),
536 +    }
537 +  }
538 +  
539 +  if 'onos_ml2' in hiera('neutron_mechanism_drivers') {
540 +    # install onos and config ovs
541 +    class {"onos":
542 +      controllers_ip => $controller_node_ips
543 +    }
544 +  }
545 +
546    if count(hiera('ntp::servers')) > 0 {
547      include ::ntp
548    }
549 @@ -223,9 +238,7 @@ if hiera('step') >= 3 {
550    include ::nova::scheduler
551    include ::nova::scheduler::filter
552  
553 -  include ::neutron
554    include ::neutron::server
555 -  include ::neutron::agents::l3
556    include ::neutron::agents::dhcp
557    include ::neutron::agents::metadata
558  
559 @@ -237,15 +250,76 @@ if hiera('step') >= 3 {
560      require => Package['neutron'],
561    }
562  
563 +  if 'onos_ml2' in hiera('neutron_mechanism_drivers') {
564 +    # config neutron service_plugins to onos driver
565 +    class { '::neutron':
566 +      service_plugins  => [hiera('neutron_service_plugins')]
567 +    }
568 +  } else {
569 +    include ::neutron
570 +    if 'opendaylight' in hiera('neutron_mechanism_drivers') {
571 +      if ! str2bool(hiera('opendaylight_enable_l3', 'no')) {
572 +        include ::neutron::agents::l3
573 +      }
574 +    }
575 +  }
576 +  
577    class { '::neutron::plugins::ml2':
578      flat_networks        => split(hiera('neutron_flat_networks'), ','),
579      tenant_network_types => [hiera('neutron_tenant_network_type')],
580      mechanism_drivers    => [hiera('neutron_mechanism_drivers')],
581    }
582 -  class { '::neutron::agents::ml2::ovs':
583 -    bridge_mappings => split(hiera('neutron_bridge_mappings'), ','),
584 -    tunnel_types    => split(hiera('neutron_tunnel_types'), ','),
585 +
586 +  if 'opendaylight' in hiera('neutron_mechanism_drivers') {
587 +    if ! str2bool(hiera('opendaylight_enable_l3', 'no')) {
588 +      Service['neutron-server'] -> Service['neutron-l3']
589 +    }
590 +    if str2bool(hiera('opendaylight_install', 'false')) {
591 +      $controller_ips = split(hiera('controller_node_ips'), ',')
592 +      $opendaylight_controller_ip = $controller_ips[0]
593 +    } else {
594 +      $opendaylight_controller_ip = hiera('opendaylight_controller_ip')
595 +    }
596 +
597 +    class { 'neutron::plugins::ml2::opendaylight':
598 +      odl_controller_ip => $opendaylight_controller_ip,
599 +      odl_username      => hiera('opendaylight_username'),
600 +      odl_password      => hiera('opendaylight_password'),
601 +      odl_port          => hiera('opendaylight_port'),
602 +    }
603 +
604 +    if str2bool(hiera('opendaylight_install', 'false')) {
605 +      class { 'neutron::plugins::ovs::opendaylight':
606 +        odl_controller_ip => $opendaylight_controller_ip,
607 +        tunnel_ip         => hiera('neutron::agents::ml2::ovs::local_ip'),
608 +        odl_port          => hiera('opendaylight_port'),
609 +        odl_username      => hiera('opendaylight_username'),
610 +        odl_password      => hiera('opendaylight_password'),
611 +      }
612 +    }
613 +
614 +  } elsif 'onos_ml2' in hiera('neutron_mechanism_drivers') {
615 +    #config ml2_conf.ini with onos url address
616 +    $onos_port = hiera('onos_port')
617 +    $private_ip = hiera('neutron::agents::ml2::ovs::local_ip')
618 +
619 +    neutron_plugin_ml2 {
620 +      'onos/username':         value => 'admin';
621 +      'onos/password':         value => 'admin';
622 +      'onos/url_path':         value => "http://${controller_node_ips[0]}:${onos_port}/onos/vtn";
623 +    }
624 +
625 +  } else {
626 +
627 +    class { 'neutron::agents::ml2::ovs':
628 +      bridge_mappings => split(hiera('neutron_bridge_mappings'), ','),
629 +      tunnel_types => split(hiera('neutron_tunnel_types'), ','),
630 +    }
631 +
632 +    Service['neutron-server'] -> Service['neutron-ovs-agent-service']
633 +    Service['neutron-server'] -> Service['neutron-l3']
634    }
635 +
636    if 'cisco_n1kv' in hiera('neutron_mechanism_drivers') {
637      include ::neutron::plugins::ml2::cisco::nexus1000v
638  
639 @@ -280,8 +354,6 @@ if hiera('step') >= 3 {
640    }
641  
642    Service['neutron-server'] -> Service['neutron-dhcp-service']
643 -  Service['neutron-server'] -> Service['neutron-l3']
644 -  Service['neutron-server'] -> Service['neutron-ovs-agent-service']
645    Service['neutron-server'] -> Service['neutron-metadata']
646  
647    include ::cinder
648 diff --git a/puppet/manifests/overcloud_controller_pacemaker.pp b/puppet/manifests/overcloud_controller_pacemaker.pp
649 index 3fb92f3..9568390 100644
650 --- a/puppet/manifests/overcloud_controller_pacemaker.pp
651 +++ b/puppet/manifests/overcloud_controller_pacemaker.pp
652 @@ -380,6 +380,21 @@ if hiera('step') >= 2 {
653  
654    }
655  
656 +  if str2bool(hiera('opendaylight_install', 'false')) {
657 +    class {"opendaylight":
658 +      extra_features => ['odl-ovsdb-openstack'],
659 +      odl_rest_port  => hiera('opendaylight_port'),
660 +      enable_l3      => hiera('opendaylight_enable_l3', 'no'),
661 +    }
662 +  }
663 +
664 +  if 'onos_ml2' in hiera('neutron_mechanism_drivers') {
665 +    # install onos and config ovs
666 +    class {"onos":
667 +      controllers_ip => $controller_node_ips
668 +    }
669 +  }
670 +  
671    exec { 'galera-ready' :
672      command     => '/usr/bin/clustercheck >/dev/null',
673      timeout     => 30,
674 @@ -584,7 +599,14 @@ if hiera('step') >= 3 {
675    include ::nova::network::neutron
676  
677    # Neutron class definitions
678 -  include ::neutron
679 +  if 'onos_ml2' in hiera('neutron_mechanism_drivers') {
680 +    # config neutron service_plugins to onos driver
681 +    class { '::neutron':
682 +      service_plugins  => [hiera('neutron_service_plugins')]
683 +    }
684 +  } else {
685 +    include ::neutron
686 +  }
687    class { '::neutron::server' :
688      sync_db        => $sync_db,
689      manage_service => false,
690 @@ -594,10 +616,6 @@ if hiera('step') >= 3 {
691      manage_service => false,
692      enabled        => false,
693    }
694 -  class { '::neutron::agents::l3' :
695 -    manage_service => false,
696 -    enabled        => false,
697 -  }
698    class { '::neutron::agents::metadata':
699      manage_service => false,
700      enabled        => false,
701 @@ -609,18 +627,68 @@ if hiera('step') >= 3 {
702      notify  => Service['neutron-dhcp-service'],
703      require => Package['neutron'],
704    }
705 +
706    class { '::neutron::plugins::ml2':
707      flat_networks        => split(hiera('neutron_flat_networks'), ','),
708      tenant_network_types => [hiera('neutron_tenant_network_type')],
709      mechanism_drivers    => [hiera('neutron_mechanism_drivers')],
710    }
711 -  class { '::neutron::agents::ml2::ovs':
712 -    manage_service  => false,
713 -    enabled         => false,
714 -    bridge_mappings => split(hiera('neutron_bridge_mappings'), ','),
715 -    tunnel_types    => split(hiera('neutron_tunnel_types'), ','),
716 -  }
717 +  if 'opendaylight' in hiera('neutron_mechanism_drivers') {
718 +    if str2bool(hiera('opendaylight_install', 'false')) {
719 +      $controller_ips = split(hiera('controller_node_ips'), ',')
720 +      $opendaylight_controller_ip = $controller_ips[0]
721 +    } else {
722 +      $opendaylight_controller_ip = hiera('opendaylight_controller_ip')
723 +    }
724 +
725 +    $opendaylight_port = hiera('opendaylight_port')
726 +    $private_ip = hiera('neutron::agents::ml2::ovs::local_ip')
727 +
728 +    class { 'neutron::plugins::ml2::opendaylight':
729 +      odl_controller_ip => $opendaylight_controller_ip,
730 +      odl_username      => hiera('opendaylight_username'),
731 +      odl_password      => hiera('opendaylight_password'),
732 +      odl_port          => hiera('opendaylight_port'),
733 +    }
734  
735 +    if str2bool(hiera('opendaylight_install', 'false')) {
736 +      class { 'neutron::plugins::ovs::opendaylight':
737 +        odl_controller_ip => $opendaylight_controller_ip,
738 +        tunnel_ip         => hiera('neutron::agents::ml2::ovs::local_ip'),
739 +        odl_port          => hiera('opendaylight_port'),
740 +        odl_username      => hiera('opendaylight_username'),
741 +        odl_password      => hiera('opendaylight_password'),
742 +      }
743 +    }
744 +    if ! str2bool(hiera('opendaylight_enable_l3', 'no')) {
745 +      class { '::neutron::agents::l3' :
746 +        manage_service => false,
747 +        enabled        => false,
748 +      }
749 +    }
750 +  } elsif 'onos_ml2' in hiera('neutron_mechanism_drivers') {
751 +    #config ml2_conf.ini with onos url address
752 +    $onos_port = hiera('onos_port')
753 +    $private_ip = hiera('neutron::agents::ml2::ovs::local_ip')
754 +
755 +    neutron_plugin_ml2 {
756 +      'onos/username':         value => 'admin';
757 +      'onos/password':         value => 'admin';
758 +      'onos/url_path':         value => "http://${controller_node_ips[0]}:${onos_port}/onos/vtn";
759 +    }
760 +
761 +  } else {
762 +    class { '::neutron::agents::l3' :
763 +      manage_service => false,
764 +      enabled        => false,
765 +    }
766 +    class { 'neutron::agents::ml2::ovs':
767 +      manage_service   => false,
768 +      enabled          => false,
769 +      bridge_mappings  => split(hiera('neutron_bridge_mappings'), ','),
770 +      tunnel_types     => split(hiera('neutron_tunnel_types'), ','),
771 +    }
772 +  }
773    if 'cisco_ucsm' in hiera('neutron_mechanism_drivers') {
774      include ::neutron::plugins::ml2::cisco::ucsm
775    }
776 @@ -645,8 +713,10 @@ if hiera('step') >= 3 {
777    if hiera('neutron_enable_bigswitch_ml2', false) {
778      include ::neutron::plugins::ml2::bigswitch::restproxy
779    }
780 -  neutron_l3_agent_config {
781 -    'DEFAULT/ovs_use_veth': value => hiera('neutron_ovs_use_veth', false);
782 +  if !('onos_ml2' in hiera('neutron_mechanism_drivers') or str2bool(hiera('opendaylight_enable_l3', 'no'))) {
783 +    neutron_l3_agent_config {
784 +      'DEFAULT/ovs_use_veth': value => hiera('neutron_ovs_use_veth', false);
785 +    }
786    }
787    neutron_dhcp_agent_config {
788      'DEFAULT/ovs_use_veth': value => hiera('neutron_ovs_use_veth', false);
789 @@ -1055,62 +1125,21 @@ if hiera('step') >= 4 {
790        clone_params => 'interleave=true',
791        require      => Pacemaker::Resource::Service[$::keystone::params::service_name],
792      }
793 -    pacemaker::resource::service { $::neutron::params::l3_agent_service:
794 -      clone_params => 'interleave=true',
795 +    if !('onos_ml2' in hiera('neutron_mechanism_drivers')) {
796 +      pacemaker::resource::service { $::neutron::params::l3_agent_service:
797 +        clone_params => 'interleave=true',
798 +      }
799      }
800      pacemaker::resource::service { $::neutron::params::dhcp_agent_service:
801        clone_params => 'interleave=true',
802      }
803 -    pacemaker::resource::service { $::neutron::params::ovs_agent_service:
804 -      clone_params => 'interleave=true',
805 -    }
806      pacemaker::resource::service { $::neutron::params::metadata_agent_service:
807        clone_params => 'interleave=true',
808      }
809 -    pacemaker::resource::ocf { $::neutron::params::ovs_cleanup_service:
810 -      ocf_agent_name => 'neutron:OVSCleanup',
811 -      clone_params   => 'interleave=true',
812 -    }
813      pacemaker::resource::ocf { 'neutron-netns-cleanup':
814        ocf_agent_name => 'neutron:NetnsCleanup',
815        clone_params   => 'interleave=true',
816      }
817 -
818 -    # neutron - one chain ovs-cleanup-->netns-cleanup-->ovs-agent
819 -    pacemaker::constraint::base { 'neutron-ovs-cleanup-to-netns-cleanup-constraint':
820 -      constraint_type => 'order',
821 -      first_resource  => "${::neutron::params::ovs_cleanup_service}-clone",
822 -      second_resource => 'neutron-netns-cleanup-clone',
823 -      first_action    => 'start',
824 -      second_action   => 'start',
825 -      require         => [Pacemaker::Resource::Ocf[$::neutron::params::ovs_cleanup_service],
826 -                          Pacemaker::Resource::Ocf['neutron-netns-cleanup']],
827 -    }
828 -    pacemaker::constraint::colocation { 'neutron-ovs-cleanup-to-netns-cleanup-colocation':
829 -      source  => 'neutron-netns-cleanup-clone',
830 -      target  => "${::neutron::params::ovs_cleanup_service}-clone",
831 -      score   => 'INFINITY',
832 -      require => [Pacemaker::Resource::Ocf[$::neutron::params::ovs_cleanup_service],
833 -                  Pacemaker::Resource::Ocf['neutron-netns-cleanup']],
834 -    }
835 -    pacemaker::constraint::base { 'neutron-netns-cleanup-to-openvswitch-agent-constraint':
836 -      constraint_type => 'order',
837 -      first_resource  => 'neutron-netns-cleanup-clone',
838 -      second_resource => "${::neutron::params::ovs_agent_service}-clone",
839 -      first_action    => 'start',
840 -      second_action   => 'start',
841 -      require         => [Pacemaker::Resource::Ocf['neutron-netns-cleanup'],
842 -                          Pacemaker::Resource::Service[$::neutron::params::ovs_agent_service]],
843 -    }
844 -    pacemaker::constraint::colocation { 'neutron-netns-cleanup-to-openvswitch-agent-colocation':
845 -      source  => "${::neutron::params::ovs_agent_service}-clone",
846 -      target  => 'neutron-netns-cleanup-clone',
847 -      score   => 'INFINITY',
848 -      require => [Pacemaker::Resource::Ocf['neutron-netns-cleanup'],
849 -                  Pacemaker::Resource::Service[$::neutron::params::ovs_agent_service]],
850 -    }
851 -
852 -    #another chain keystone-->neutron-server-->ovs-agent-->dhcp-->l3
853      pacemaker::constraint::base { 'keystone-to-neutron-server-constraint':
854        constraint_type => 'order',
855        first_resource  => "${::keystone::params::service_name}-clone",
856 @@ -1120,65 +1149,110 @@ if hiera('step') >= 4 {
857        require         => [Pacemaker::Resource::Service[$::keystone::params::service_name],
858                            Pacemaker::Resource::Service[$::neutron::params::server_service]],
859      }
860 -    pacemaker::constraint::base { 'neutron-server-to-openvswitch-agent-constraint':
861 -      constraint_type => 'order',
862 -      first_resource  => "${::neutron::params::server_service}-clone",
863 -      second_resource => "${::neutron::params::ovs_agent_service}-clone",
864 -      first_action    => 'start',
865 -      second_action   => 'start',
866 -      require         => [Pacemaker::Resource::Service[$::neutron::params::server_service],
867 -                          Pacemaker::Resource::Service[$::neutron::params::ovs_agent_service]],
868 -    }
869 -    pacemaker::constraint::base { 'neutron-openvswitch-agent-to-dhcp-agent-constraint':
870 -      constraint_type => 'order',
871 -      first_resource  => "${::neutron::params::ovs_agent_service}-clone",
872 -      second_resource => "${::neutron::params::dhcp_agent_service}-clone",
873 -      first_action    => 'start',
874 -      second_action   => 'start',
875 -      require         => [Pacemaker::Resource::Service[$::neutron::params::ovs_agent_service],
876 -                          Pacemaker::Resource::Service[$::neutron::params::dhcp_agent_service]],
877 +    if 'openvswitch' in hiera('neutron_mechanism_drivers') {
878 +      pacemaker::resource::service { $::neutron::params::ovs_agent_service:
879 +        clone_params => "interleave=true",
880 +      }
881 +      pacemaker::resource::ocf { $::neutron::params::ovs_cleanup_service:
882 +        ocf_agent_name => "neutron:OVSCleanup",
883 +        clone_params => "interleave=true",
884 +      }
885 +      # neutron - one chain ovs-cleanup-->netns-cleanup-->ovs-agent
886 +      pacemaker::constraint::base { 'neutron-ovs-cleanup-to-netns-cleanup-constraint':
887 +        constraint_type => "order",
888 +        first_resource => "${::neutron::params::ovs_cleanup_service}-clone",
889 +        second_resource => "neutron-netns-cleanup-clone",
890 +        first_action => "start",
891 +        second_action => "start",
892 +        require => [Pacemaker::Resource::Ocf["${::neutron::params::ovs_cleanup_service}"],
893 +                    Pacemaker::Resource::Ocf['neutron-netns-cleanup']],
894 +      }
895 +      pacemaker::constraint::colocation { 'neutron-ovs-cleanup-to-netns-cleanup-colocation':
896 +        source => "neutron-netns-cleanup-clone",
897 +        target => "${::neutron::params::ovs_cleanup_service}-clone",
898 +        score => "INFINITY",
899 +        require => [Pacemaker::Resource::Ocf["${::neutron::params::ovs_cleanup_service}"],
900 +                    Pacemaker::Resource::Ocf['neutron-netns-cleanup']],
901 +      }
902 +      pacemaker::constraint::base { 'neutron-netns-cleanup-to-openvswitch-agent-constraint':
903 +        constraint_type => "order",
904 +        first_resource => "neutron-netns-cleanup-clone",
905 +        second_resource => "${::neutron::params::ovs_agent_service}-clone",
906 +        first_action => "start",
907 +        second_action => "start",
908 +        require => [Pacemaker::Resource::Ocf["neutron-netns-cleanup"],
909 +                    Pacemaker::Resource::Service["${::neutron::params::ovs_agent_service}"]],
910 +      }
911 +      pacemaker::constraint::colocation { 'neutron-netns-cleanup-to-openvswitch-agent-colocation':
912 +        source => "${::neutron::params::ovs_agent_service}-clone",
913 +        target => "neutron-netns-cleanup-clone",
914 +        score => "INFINITY",
915 +        require => [Pacemaker::Resource::Ocf["neutron-netns-cleanup"],
916 +                    Pacemaker::Resource::Service["${::neutron::params::ovs_agent_service}"]],
917 +      }
918  
919 +      #another chain keystone-->neutron-server-->ovs-agent-->dhcp-->l3
920 +      pacemaker::constraint::base { 'neutron-server-to-openvswitch-agent-constraint':
921 +        constraint_type => "order",
922 +        first_resource => "${::neutron::params::server_service}-clone",
923 +        second_resource => "${::neutron::params::ovs_agent_service}-clone",
924 +        first_action => "start",
925 +        second_action => "start",
926 +        require => [Pacemaker::Resource::Service[$::neutron::params::server_service],
927 +                    Pacemaker::Resource::Service[$::neutron::params::ovs_agent_service]],
928 +      }
929 +      pacemaker::constraint::base { 'neutron-openvswitch-agent-to-dhcp-agent-constraint':
930 +        constraint_type => "order",
931 +        first_resource => "${::neutron::params::ovs_agent_service}-clone",
932 +        second_resource => "${::neutron::params::dhcp_agent_service}-clone",
933 +        first_action => "start",
934 +        second_action => "start",
935 +        require => [Pacemaker::Resource::Service["${::neutron::params::ovs_agent_service}"],
936 +                    Pacemaker::Resource::Service["${::neutron::params::dhcp_agent_service}"]],
937 +
938 +      }
939 +      pacemaker::constraint::colocation { 'neutron-openvswitch-agent-to-dhcp-agent-colocation':
940 +        source => "${::neutron::params::dhcp_agent_service}-clone",
941 +        target => "${::neutron::params::ovs_agent_service}-clone",
942 +        score => "INFINITY",
943 +        require => [Pacemaker::Resource::Service["${::neutron::params::ovs_agent_service}"],
944 +                    Pacemaker::Resource::Service["${::neutron::params::dhcp_agent_service}"]],
945 +      }
946      }
947 -    pacemaker::constraint::colocation { 'neutron-openvswitch-agent-to-dhcp-agent-colocation':
948 -      source  => "${::neutron::params::dhcp_agent_service}-clone",
949 -      target  => "${::neutron::params::ovs_agent_service}-clone",
950 -      score   => 'INFINITY',
951 -      require => [Pacemaker::Resource::Service[$::neutron::params::ovs_agent_service],
952 -                  Pacemaker::Resource::Service[$::neutron::params::dhcp_agent_service]],
953 -    }
954 -    pacemaker::constraint::base { 'neutron-dhcp-agent-to-l3-agent-constraint':
955 -      constraint_type => 'order',
956 -      first_resource  => "${::neutron::params::dhcp_agent_service}-clone",
957 -      second_resource => "${::neutron::params::l3_agent_service}-clone",
958 -      first_action    => 'start',
959 -      second_action   => 'start',
960 -      require         => [Pacemaker::Resource::Service[$::neutron::params::dhcp_agent_service],
961 -                          Pacemaker::Resource::Service[$::neutron::params::l3_agent_service]],
962 -    }
963 -    pacemaker::constraint::colocation { 'neutron-dhcp-agent-to-l3-agent-colocation':
964 -      source  => "${::neutron::params::l3_agent_service}-clone",
965 -      target  => "${::neutron::params::dhcp_agent_service}-clone",
966 -      score   => 'INFINITY',
967 -      require => [Pacemaker::Resource::Service[$::neutron::params::dhcp_agent_service],
968 -                  Pacemaker::Resource::Service[$::neutron::params::l3_agent_service]],
969 -    }
970 -    pacemaker::constraint::base { 'neutron-l3-agent-to-metadata-agent-constraint':
971 -      constraint_type => 'order',
972 -      first_resource  => "${::neutron::params::l3_agent_service}-clone",
973 -      second_resource => "${::neutron::params::metadata_agent_service}-clone",
974 -      first_action    => 'start',
975 -      second_action   => 'start',
976 -      require         => [Pacemaker::Resource::Service[$::neutron::params::l3_agent_service],
977 -                          Pacemaker::Resource::Service[$::neutron::params::metadata_agent_service]],
978 -    }
979 -    pacemaker::constraint::colocation { 'neutron-l3-agent-to-metadata-agent-colocation':
980 -      source  => "${::neutron::params::metadata_agent_service}-clone",
981 -      target  => "${::neutron::params::l3_agent_service}-clone",
982 -      score   => 'INFINITY',
983 -      require => [Pacemaker::Resource::Service[$::neutron::params::l3_agent_service],
984 -                  Pacemaker::Resource::Service[$::neutron::params::metadata_agent_service]],
985 +    if !('onos_ml2' in hiera('neutron_mechanism_drivers') or str2bool(hiera('opendaylight_enable_l3', 'no'))) {
986 +      pacemaker::constraint::base { 'neutron-dhcp-agent-to-l3-agent-constraint':
987 +        constraint_type => 'order',
988 +        first_resource  => "${::neutron::params::dhcp_agent_service}-clone",
989 +        second_resource => "${::neutron::params::l3_agent_service}-clone",
990 +        first_action    => 'start',
991 +        second_action   => 'start',
992 +        require         => [Pacemaker::Resource::Service[$::neutron::params::dhcp_agent_service],
993 +                            Pacemaker::Resource::Service[$::neutron::params::l3_agent_service]],
994 +      }
995 +      pacemaker::constraint::colocation { 'neutron-dhcp-agent-to-l3-agent-colocation':
996 +        source  => "${::neutron::params::l3_agent_service}-clone",
997 +        target  => "${::neutron::params::dhcp_agent_service}-clone",
998 +        score   => 'INFINITY',
999 +        require => [Pacemaker::Resource::Service[$::neutron::params::dhcp_agent_service],
1000 +                    Pacemaker::Resource::Service[$::neutron::params::l3_agent_service]],
1001 +      }
1002 +      pacemaker::constraint::base { 'neutron-l3-agent-to-metadata-agent-constraint':
1003 +        constraint_type => 'order',
1004 +        first_resource  => "${::neutron::params::l3_agent_service}-clone",
1005 +        second_resource => "${::neutron::params::metadata_agent_service}-clone",
1006 +        first_action    => 'start',
1007 +        second_action   => 'start',
1008 +        require         => [Pacemaker::Resource::Service[$::neutron::params::l3_agent_service],
1009 +                            Pacemaker::Resource::Service[$::neutron::params::metadata_agent_service]],
1010 +      }
1011 +      pacemaker::constraint::colocation { 'neutron-l3-agent-to-metadata-agent-colocation':
1012 +        source  => "${::neutron::params::metadata_agent_service}-clone",
1013 +        target  => "${::neutron::params::l3_agent_service}-clone",
1014 +        score   => 'INFINITY',
1015 +        require => [Pacemaker::Resource::Service[$::neutron::params::l3_agent_service],
1016 +                    Pacemaker::Resource::Service[$::neutron::params::metadata_agent_service]],
1017 +      }
1018      }
1019 -
1020      # Nova
1021      pacemaker::resource::service { $::nova::params::api_service_name :
1022        clone_params => 'interleave=true',
1023 diff --git a/puppet/manifests/overcloud_opendaylight.pp b/puppet/manifests/overcloud_opendaylight.pp
1024 new file mode 100644
1025 index 0000000..33f609a
1026 --- /dev/null
1027 +++ b/puppet/manifests/overcloud_opendaylight.pp
1028 @@ -0,0 +1,27 @@
1029 +# Copyright 2015 Red Hat, Inc.
1030 +# All Rights Reserved.
1031 +#
1032 +# Licensed under the Apache License, Version 2.0 (the "License"); you may
1033 +# not use this file except in compliance with the License. You may obtain
1034 +# a copy of the License at
1035 +#
1036 +#     http://www.apache.org/licenses/LICENSE-2.0
1037 +#
1038 +# Unless required by applicable law or agreed to in writing, software
1039 +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1040 +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1041 +# License for the specific language governing permissions and limitations
1042 +# under the License.
1043 +
1044 +include ::tripleo::packages
1045 +
1046 +if count(hiera('ntp::servers')) > 0 {
1047 +  include ::ntp
1048 +}
1049 +
1050 +class {"opendaylight":
1051 +  extra_features => ['odl-ovsdb-openstack'],
1052 +  odl_rest_port  => hiera('opendaylight_port'),
1053 +  enable_l3      => hiera('opendaylight_enable_l3', 'no'),
1054 +}
1055 +
1056 diff --git a/puppet/opendaylight-puppet.yaml b/puppet/opendaylight-puppet.yaml
1057 new file mode 100644
1058 index 0000000..b876dc7
1059 --- /dev/null
1060 +++ b/puppet/opendaylight-puppet.yaml
1061 @@ -0,0 +1,217 @@
1062 +heat_template_version: 2015-04-30
1063 +
1064 +description: >
1065 +  OpenDaylight node configured by Puppet.
1066 +
1067 +parameters:
1068 +  OpenDaylightFlavor:
1069 +    default: baremetal
1070 +    description: The flavor to use for the OpenDaylight node
1071 +    type: string
1072 +  OpenDaylightImage:
1073 +    default: overcloud-full
1074 +    description: The image to use for the OpenDaylight node
1075 +    type: string
1076 +  OpenDaylightHostname:
1077 +    default: opendaylight-server
1078 +    description: The hostname to use for the OpenDaylight node
1079 +    type: string
1080 +  OpenDaylightUsername:
1081 +    default: admin
1082 +    description: The admin user for the OpenDaylight node
1083 +    type: string
1084 +  OpenDaylightPassword:
1085 +    default: ''
1086 +    description: The admin password for the OpenDaylight node
1087 +    type: string
1088 +    hidden: true
1089 +  OpenDaylightEnableL3:
1090 +    description: Knob to enable/disable ODL L3
1091 +    type: string
1092 +    default: 'no'
1093 +  OpenDaylightPort:
1094 +    default: 8081
1095 +    description: Set OpenDaylight service port
1096 +    type: number
1097 +  KeyName:
1098 +    description: The keypair to use for SSH access to the node (via heat-admin user)
1099 +    type: string
1100 +    default: default
1101 +    constraints:
1102 +      - custom_constraint: nova.keypair
1103 +  ImageUpdatePolicy:
1104 +    default: 'REBUILD_PRESERVE_EPHEMERAL'
1105 +    description: What policy to use when reconstructing instances. REBUILD for rebuilds, REBUILD_PRESERVE_EPHEMERAL to preserve /mnt.
1106 +    type: string
1107 +  UpdateIdentifier:
1108 +    default: ''
1109 +    type: string
1110 +    description: >
1111 +      Setting to a previously unused value during stack-update will trigger
1112 +      package update on all nodes
1113 +  NtpServer:
1114 +    type: string
1115 +    default: ''
1116 +  PublicInterface:
1117 +    default: nic1
1118 +    description: What interface to bridge onto br-ex for network nodes.
1119 +    type: string
1120 +
1121 +resources:
1122 +  OpenDaylightNode:
1123 +    type: OS::Nova::Server
1124 +    properties:
1125 +      image: {get_param: OpenDaylightImage}
1126 +      image_update_policy: {get_param: ImageUpdatePolicy}
1127 +      flavor: {get_param: OpenDaylightFlavor}
1128 +      key_name: {get_param: KeyName}
1129 +      networks:
1130 +        - network: ctlplane
1131 +      user_data_format: SOFTWARE_CONFIG
1132 +      user_data: {get_resource: NodeUserData}
1133 +      name: {get_param: OpenDaylightHostname}
1134 +
1135 +  NodeUserData:
1136 +    type: OS::TripleO::NodeUserData
1137 +
1138 +  ExternalPort:
1139 +    type: OS::TripleO::Controller::Ports::ExternalPort
1140 +    properties:
1141 +      ControlPlaneIP: {get_attr: [OpenDaylightNode, networks, ctlplane, 0]}
1142 +
1143 +  InternalApiPort:
1144 +    type: OS::TripleO::Controller::Ports::InternalApiPort
1145 +    properties:
1146 +      ControlPlaneIP: {get_attr: [OpenDaylightNode, networks, ctlplane, 0]}
1147 +
1148 +  NetIpMap:
1149 +    type: OS::TripleO::Network::Ports::NetIpMap
1150 +    properties:
1151 +      ControlPlaneIp: {get_attr: [OpenDaylightNode, networks, ctlplane, 0]}
1152 +      ExternalIp: {get_attr: [ExternalPort, ip_address]}
1153 +      InternalApiIp: {get_attr: [InternalApiPort, ip_address]}
1154 +
1155 +  NetIpSubnetMap:
1156 +    type: OS::TripleO::Network::Ports::NetIpSubnetMap
1157 +    properties:
1158 +      ControlPlaneIp: {get_attr: [OpenDaylightNode, networks, ctlplane, 0]}
1159 +      ExternalIpSubnet: {get_attr: [ExternalPort, ip_subnet]}
1160 +      InternalApiIpSubnet: {get_attr: [InternalApiPort, ip_subnet]}
1161 +
1162 +  NetworkConfig:
1163 +    type: OS::TripleO::Controller::Net::SoftwareConfig
1164 +    properties:
1165 +      ControlPlaneIp: {get_attr: [OpenDaylightNode, networks, ctlplane, 0]}
1166 +      ExternalIpSubnet: {get_attr: [ExternalPort, ip_subnet]}
1167 +      InternalApiIpSubnet: {get_attr: [InternalApiPort, ip_subnet]}
1168 +
1169 +  NetworkDeployment:
1170 +    type: OS::TripleO::SoftwareDeployment
1171 +    properties:
1172 +      config: {get_resource: NetworkConfig}
1173 +      server: {get_resource: OpenDaylightNode}
1174 +      input_values:
1175 +        bridge_name: br-ex
1176 +        interface_name: {get_param: PublicInterface}
1177 +
1178 +  OpenDaylightDeployment:
1179 +    type: OS::TripleO::SoftwareDeployment
1180 +    depends_on: NetworkDeployment
1181 +    properties:
1182 +      config: {get_resource: OpenDaylightConfig}
1183 +      server: {get_resource: OpenDaylightNode}
1184 +      input_values:
1185 +        ntp_servers:
1186 +          str_replace:
1187 +            template: '["server"]'
1188 +            params:
1189 +              server: {get_param: NtpServer}
1190 +        opendaylight_port: {get_param: OpenDaylightPort}
1191 +        opendaylight_enable_l3: {get_param: OpenDaylightEnableL3}
1192 +        opendaylight_username: {get_param: OpenDaylightUsername}
1193 +        opendaylight_password: {get_param: OpenDaylightPassword}
1194 +
1195 +  OpenDaylightConfig:
1196 +    type: OS::Heat::StructuredConfig
1197 +    properties:
1198 +      group: os-apply-config
1199 +      config:
1200 +        hiera:
1201 +          hierarchy:
1202 +            - '"%{::uuid}"'
1203 +            - heat_config_%{::deploy_config_name}
1204 +            - extraconfig
1205 +            - bootstrap_node # provided by BootstrapNodeConfig
1206 +            - all_nodes # provided by allNodesConfig
1207 +            - vip_data # provided by vip-config
1208 +            - RedHat # Workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1236143
1209 +            - common
1210 +          datafiles:
1211 +            common:
1212 +              raw_data: {get_file: hieradata/common.yaml}
1213 +              mapped_data:
1214 +                ntp::servers: {get_input: ntp_servers}
1215 +                opendaylight::admin_username: {get_param: OpenDaylightUsername}
1216 +                opendaylight::admin_password: {get_param: OpenDaylightPassword}
1217 +                opendaylight_port: {get_input: opendaylight_port}
1218 +                opendaylight_enable_l3: {get_input: opendaylight_enable_l3}
1219 +            ceph:
1220 +              raw_data: {get_file: hieradata/ceph.yaml}
1221 +
1222 +  UpdateConfig:
1223 +    type: OS::TripleO::Tasks::PackageUpdate
1224 +
1225 +  UpdateDeployment:
1226 +    type: OS::Heat::SoftwareDeployment
1227 +    properties:
1228 +      config: {get_resource: UpdateConfig}
1229 +      server: {get_resource: OpenDaylightNode}
1230 +      input_values:
1231 +        update_identifier:
1232 +          get_param: UpdateIdentifier
1233 +
1234 +  OpenDaylightHostsConfig:
1235 +    type: OS::Heat::SoftwareConfig
1236 +    properties:
1237 +      group: script
1238 +      config: |
1239 +        #!/usr/bin/env bash
1240 +        echo -e "$(facter ipaddress)\t\t$(hostname -f)\t$(hostname -s)" >> /etc/hosts
1241 +
1242 +  OpenDaylightHostsDeployment:
1243 +    type: OS::Heat::StructuredDeployment
1244 +    depends_on: OpenDaylightDeployment
1245 +    properties:
1246 +      server: {get_resource: OpenDaylightNode}
1247 +      config: {get_resource: OpenDaylightHostsConfig}
1248 +
1249 +  OpenDaylightPuppetConfig:
1250 +    type: OS::Heat::SoftwareConfig
1251 +    properties:
1252 +      group: puppet
1253 +      config:
1254 +        get_file: manifests/overcloud_opendaylight.pp
1255 +
1256 +  OpenDaylightPuppetDeployment:
1257 +    depends_on: OpenDaylightHostsDeployment
1258 +    type: OS::Heat::StructuredDeployment
1259 +    properties:
1260 +      server: {get_resource: OpenDaylightNode}
1261 +      config: {get_resource: OpenDaylightPuppetConfig}
1262 +      input_values:
1263 +        update_identifier: {get_param: UpdateIdentifier}
1264 +
1265 +outputs:
1266 +  ip_address:
1267 +    description: IP address of the server in the ctlplane network
1268 +    value: {get_attr: [OpenDaylightNode, networks, ctlplane, 0]}
1269 +  opendaylight_controller_ip:
1270 +    description: IP address of the server on the internal network
1271 +    value: {get_attr: [InternalApiPort, ip_address]}
1272 +  config_identifier:
1273 +    description: identifier which changes if the node configuration may need re-applying
1274 +    value:
1275 +      list_join:
1276 +      - ','
1277 +      - - {get_attr: [OpenDaylightDeployment, deploy_stdout]}
1278 +        - {get_param: UpdateIdentifier}
1279 -- 
1280 2.5.0
1281