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