Add IP to HAProxy kind=Optional constraint
[apex-tripleo-heat-templates.git] / puppet / manifests / overcloud_controller_pacemaker.pp
1 # Copyright 2015 Red Hat, Inc.
2 # All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15
16 Pcmk_resource <| |> {
17   tries     => 10,
18   try_sleep => 3,
19 }
20
21 if !str2bool(hiera('enable_package_install', 'false')) {
22   case $::osfamily {
23     'RedHat': {
24       Package { provider => 'norpm' } # provided by tripleo-puppet
25     }
26     default: {
27       warning('enable_package_install option not supported.')
28     }
29   }
30 }
31
32 if $::hostname == downcase(hiera('bootstrap_nodeid')) {
33   $pacemaker_master = true
34   $sync_db = true
35 } else {
36   $pacemaker_master = false
37   $sync_db = false
38 }
39
40 # When to start and enable services which haven't been Pacemakerized
41 # FIXME: remove when we start all OpenStack services using Pacemaker
42 # (occurences of this variable will be gradually replaced with false)
43 $non_pcmk_start = hiera('step') >= 4
44
45 if hiera('step') >= 1 {
46
47   create_resources(sysctl::value, hiera('sysctl_settings'), {})
48
49   if count(hiera('ntp::servers')) > 0 {
50     include ::ntp
51   }
52
53   $controller_node_ips = split(hiera('controller_node_ips'), ',')
54   $controller_node_names = split(downcase(hiera('controller_node_names')), ',')
55   class { '::tripleo::loadbalancer' :
56     controller_hosts       => $controller_node_ips,
57     controller_hosts_names => $controller_node_names,
58     manage_vip             => false,
59     mysql_clustercheck     => true,
60     haproxy_service_manage => false,
61   }
62
63   $pacemaker_cluster_members = downcase(regsubst(hiera('controller_node_names'), ',', ' ', 'G'))
64   user { 'hacluster':
65    ensure => present,
66   } ->
67   class { '::pacemaker':
68     hacluster_pwd => hiera('hacluster_pwd'),
69   } ->
70   class { '::pacemaker::corosync':
71     cluster_members => $pacemaker_cluster_members,
72     setup_cluster   => $pacemaker_master,
73   }
74   class { '::pacemaker::stonith':
75     disable => true,
76   }
77
78   # Only configure RabbitMQ in this step, don't start it yet to
79   # avoid races where non-master nodes attempt to start without
80   # config (eg. binding on 0.0.0.0)
81   # The module ignores erlang_cookie if cluster_config is false
82   class { '::rabbitmq':
83     service_manage          => false,
84     tcp_keepalive           => false,
85     config_kernel_variables => hiera('rabbitmq_kernel_variables'),
86     config_variables        => hiera('rabbitmq_config_variables'),
87     environment_variables   => hiera('rabbitmq_environment'),
88   } ->
89   file { '/var/lib/rabbitmq/.erlang.cookie':
90     ensure  => 'present',
91     owner   => 'rabbitmq',
92     group   => 'rabbitmq',
93     mode    => '0400',
94     content => hiera('rabbitmq::erlang_cookie'),
95     replace => true,
96   }
97
98   if downcase(hiera('ceilometer_backend')) == 'mongodb' {
99     include ::mongodb::globals
100     class { '::mongodb::server' :
101       service_manage => false,
102     }
103   }
104
105   # Memcached
106   class {'::memcached' :
107     service_manage => false,
108   }
109
110   # Redis
111   class { '::redis' :
112     service_manage => false,
113     notify_service => false,
114   }
115
116   # Galera
117   if str2bool(hiera('enable_galera', 'true')) {
118     $mysql_config_file = '/etc/my.cnf.d/galera.cnf'
119   } else {
120     $mysql_config_file = '/etc/my.cnf.d/server.cnf'
121   }
122   $galera_nodes = downcase(hiera('galera_node_names', $::hostname))
123   $galera_nodes_count = count(split($galera_nodes, ','))
124
125   $mysqld_options = {
126     'mysqld' => {
127       'skip-name-resolve'             => '1',
128       'binlog_format'                 => 'ROW',
129       'default-storage-engine'        => 'innodb',
130       'innodb_autoinc_lock_mode'      => '2',
131       'innodb_locks_unsafe_for_binlog'=> '1',
132       'query_cache_size'              => '0',
133       'query_cache_type'              => '0',
134       'bind-address'                  => hiera('mysql_bind_host'),
135       'max_connections'               => '1024',
136       'open_files_limit'              => '-1',
137       'wsrep_provider'                => '/usr/lib64/galera/libgalera_smm.so',
138       'wsrep_cluster_name'            => 'galera_cluster',
139       'wsrep_slave_threads'           => '1',
140       'wsrep_certify_nonPK'           => '1',
141       'wsrep_max_ws_rows'             => '131072',
142       'wsrep_max_ws_size'             => '1073741824',
143       'wsrep_debug'                   => '0',
144       'wsrep_convert_LOCK_to_trx'     => '0',
145       'wsrep_retry_autocommit'        => '1',
146       'wsrep_auto_increment_control'  => '1',
147       'wsrep_drupal_282555_workaround'=> '0',
148       'wsrep_causal_reads'            => '0',
149       'wsrep_notify_cmd'              => '',
150       'wsrep_sst_method'              => 'rsync',
151     }
152   }
153
154   class { '::mysql::server':
155     create_root_user   => false,
156     create_root_my_cnf => false,
157     config_file        => $mysql_config_file,
158     override_options   => $mysqld_options,
159     service_manage     => false,
160     service_enabled    => false,
161   }
162
163 }
164
165 if hiera('step') >= 2 {
166
167   # NOTE(gfidente): the following vars are needed on all nodes so they
168   # need to stay out of pacemaker_master conditional
169   $mongo_node_ips_with_port = suffix(hiera('mongo_node_ips'), ':27017')
170   $mongodb_replset = hiera('mongodb::server::replset')
171
172   if $pacemaker_master {
173
174     # FIXME: we should not have to access tripleo::loadbalancer class
175     # parameters here to configure pacemaker VIPs. The configuration
176     # of pacemaker VIPs could move into puppet-tripleo or we should
177     # make use of less specific hiera parameters here for the settings.
178     pacemaker::resource::service { 'haproxy':
179       clone_params => true,
180     }
181
182     $control_vip = hiera('tripleo::loadbalancer::controller_virtual_ip')
183     pacemaker::resource::ip { 'control_vip':
184       ip_address => $control_vip,
185     }
186     pacemaker::constraint::base { 'control_vip-then-haproxy':
187       constraint_type   => 'order',
188       first_resource    => "ip-${control_vip}",
189       second_resource   => 'haproxy-clone',
190       first_action      => 'start',
191       second_action     => 'start',
192       constraint_params => 'kind=Optional',
193       require => [Pacemaker::Resource::Service['haproxy'],
194                   Pacemaker::Resource::Ip['control_vip']],
195     }
196     pacemaker::constraint::colocation { 'control_vip-with-haproxy':
197       source  => "ip-${control_vip}",
198       target  => 'haproxy-clone',
199       score   => 'INFINITY',
200       require => [Pacemaker::Resource::Service['haproxy'],
201                   Pacemaker::Resource::Ip['control_vip']],
202     }
203
204     $public_vip = hiera('tripleo::loadbalancer::public_virtual_ip')
205     if $public_vip and $public_vip != $control_vip {
206       pacemaker::resource::ip { 'public_vip':
207         ip_address => $public_vip,
208       }
209       pacemaker::constraint::base { 'public_vip-then-haproxy':
210         constraint_type   => 'order',
211         first_resource    => "ip-${public_vip}",
212         second_resource   => 'haproxy-clone',
213         first_action      => 'start',
214         second_action     => 'start',
215         constraint_params => 'kind=Optional',
216         require => [Pacemaker::Resource::Service['haproxy'],
217                     Pacemaker::Resource::Ip['public_vip']],
218       }
219       pacemaker::constraint::colocation { 'public_vip-with-haproxy':
220         source  => "ip-${public_vip}",
221         target  => 'haproxy-clone',
222         score   => 'INFINITY',
223         require => [Pacemaker::Resource::Service['haproxy'],
224                     Pacemaker::Resource::Ip['public_vip']],
225       }
226     }
227
228     $redis_vip = hiera('redis_vip')
229     if $redis_vip and $redis_vip != $control_vip {
230       pacemaker::resource::ip { 'redis_vip':
231         ip_address => $redis_vip,
232       }
233       pacemaker::constraint::base { 'redis_vip-then-haproxy':
234         constraint_type   => 'order',
235         first_resource    => "ip-${redis_vip}",
236         second_resource   => 'haproxy-clone',
237         first_action      => 'start',
238         second_action     => 'start',
239         constraint_params => 'kind=Optional',
240         require => [Pacemaker::Resource::Service['haproxy'],
241                     Pacemaker::Resource::Ip['redis_vip']],
242       }
243       pacemaker::constraint::colocation { 'redis_vip-with-haproxy':
244         source  => "ip-${redis_vip}",
245         target  => 'haproxy-clone',
246         score   => 'INFINITY',
247         require => [Pacemaker::Resource::Service['haproxy'],
248                     Pacemaker::Resource::Ip['redis_vip']],
249       }
250     }
251
252     $internal_api_vip = hiera('tripleo::loadbalancer::internal_api_virtual_ip')
253     if $internal_api_vip and $internal_api_vip != $control_vip {
254       pacemaker::resource::ip { 'internal_api_vip':
255         ip_address => $internal_api_vip,
256       }
257       pacemaker::constraint::base { 'internal_api_vip-then-haproxy':
258         constraint_type   => 'order',
259         first_resource    => "ip-${internal_api_vip}",
260         second_resource   => 'haproxy-clone',
261         first_action      => 'start',
262         second_action     => 'start',
263         constraint_params => 'kind=Optional',
264         require => [Pacemaker::Resource::Service['haproxy'],
265                     Pacemaker::Resource::Ip['internal_api_vip']],
266       }
267       pacemaker::constraint::colocation { 'internal_api_vip-with-haproxy':
268         source  => "ip-${internal_api_vip}",
269         target  => 'haproxy-clone',
270         score   => 'INFINITY',
271         require => [Pacemaker::Resource::Service['haproxy'],
272                     Pacemaker::Resource::Ip['internal_api_vip']],
273       }
274     }
275
276     $storage_vip = hiera('tripleo::loadbalancer::storage_virtual_ip')
277     if $storage_vip and $storage_vip != $control_vip {
278       pacemaker::resource::ip { 'storage_vip':
279         ip_address => $storage_vip,
280       }
281       pacemaker::constraint::base { 'storage_vip-then-haproxy':
282         constraint_type   => 'order',
283         first_resource    => "ip-${storage_vip}",
284         second_resource   => 'haproxy-clone',
285         first_action      => 'start',
286         second_action     => 'start',
287         constraint_params => 'kind=Optional',
288         require => [Pacemaker::Resource::Service['haproxy'],
289                     Pacemaker::Resource::Ip['storage_vip']],
290       }
291       pacemaker::constraint::colocation { 'storage_vip-with-haproxy':
292         source  => "ip-${storage_vip}",
293         target  => 'haproxy-clone',
294         score   => 'INFINITY',
295         require => [Pacemaker::Resource::Service['haproxy'],
296                     Pacemaker::Resource::Ip['storage_vip']],
297       }
298     }
299
300     $storage_mgmt_vip = hiera('tripleo::loadbalancer::storage_mgmt_virtual_ip')
301     if $storage_mgmt_vip and $storage_mgmt_vip != $control_vip {
302       pacemaker::resource::ip { 'storage_mgmt_vip':
303         ip_address => $storage_mgmt_vip,
304       }
305       pacemaker::constraint::base { 'storage_mgmt_vip-then-haproxy':
306         constraint_type   => 'order',
307         first_resource    => "ip-${storage_mgmt_vip}",
308         second_resource   => 'haproxy-clone',
309         first_action      => 'start',
310         second_action     => 'start',
311         constraint_params => 'kind=Optional',
312         require => [Pacemaker::Resource::Service['haproxy'],
313                     Pacemaker::Resource::Ip['storage_mgmt_vip']],
314       }
315       pacemaker::constraint::colocation { 'storage_mgmt_vip-with-haproxy':
316         source  => "ip-${storage_mgmt_vip}",
317         target  => 'haproxy-clone',
318         score   => 'INFINITY',
319         require => [Pacemaker::Resource::Service['haproxy'],
320                     Pacemaker::Resource::Ip['storage_mgmt_vip']],
321       }
322     }
323
324     pacemaker::resource::service { $::memcached::params::service_name :
325       clone_params => true,
326       require      => Class['::memcached'],
327     }
328
329     pacemaker::resource::ocf { 'rabbitmq':
330       ocf_agent_name  => 'heartbeat:rabbitmq-cluster',
331       resource_params => 'set_policy=\'ha-all ^(?!amq\.).* {"ha-mode":"all"}\'',
332       clone_params    => 'ordered=true interleave=true',
333       require         => Class['::rabbitmq'],
334     }
335
336     if downcase(hiera('ceilometer_backend')) == 'mongodb' {
337       pacemaker::resource::service { $::mongodb::params::service_name :
338         op_params    => 'start timeout=120s',
339         clone_params => true,
340         require      => Class['::mongodb::server'],
341       }
342       # NOTE (spredzy) : The replset can only be run
343       # once all the nodes have joined the cluster.
344       mongodb_conn_validator { $mongo_node_ips_with_port :
345         timeout => '600',
346         require => Pacemaker::Resource::Service[$::mongodb::params::service_name],
347         before  => Mongodb_replset[$mongodb_replset],
348       }
349       mongodb_replset { $mongodb_replset :
350         members => $mongo_node_ips_with_port,
351       }
352     }
353
354     pacemaker::resource::ocf { 'galera' :
355       ocf_agent_name  => 'heartbeat:galera',
356       op_params       => 'promote timeout=300s on-fail=block',
357       master_params   => '',
358       meta_params     => "master-max=${galera_nodes_count} ordered=true",
359       resource_params => "additional_parameters='--open-files-limit=16384' enable_creation=true wsrep_cluster_address='gcomm://${galera_nodes}'",
360       require         => Class['::mysql::server'],
361       before          => Exec['galera-ready'],
362     }
363
364     pacemaker::resource::ocf { 'redis':
365       ocf_agent_name  => 'heartbeat:redis',
366       master_params   => '',
367       meta_params     => 'notify=true ordered=true interleave=true',
368       resource_params => 'wait_last_known_master=true',
369       require         => Class['::redis'],
370     }
371
372   }
373
374   exec { 'galera-ready' :
375     command     => '/usr/bin/clustercheck >/dev/null',
376     timeout     => 30,
377     tries       => 180,
378     try_sleep   => 10,
379     environment => ["AVAILABLE_WHEN_READONLY=0"],
380     require     => File['/etc/sysconfig/clustercheck'],
381   }
382
383   file { '/etc/sysconfig/clustercheck' :
384     ensure  => file,
385     content => "MYSQL_USERNAME=root\n
386 MYSQL_PASSWORD=''\n
387 MYSQL_HOST=localhost\n",
388   }
389
390   xinetd::service { 'galera-monitor' :
391     port           => '9200',
392     server         => '/usr/bin/clustercheck',
393     per_source     => 'UNLIMITED',
394     log_on_success => '',
395     log_on_failure => 'HOST',
396     flags          => 'REUSE',
397     service_type   => 'UNLISTED',
398     user           => 'root',
399     group          => 'root',
400     require        => File['/etc/sysconfig/clustercheck'],
401   }
402
403   # Create all the database schemas
404   # Example DSN format: mysql://user:password@host/dbname
405   if $sync_db {
406     $allowed_hosts = ['%',hiera('mysql_bind_host')]
407     $keystone_dsn = split(hiera('keystone::database_connection'), '[@:/?]')
408     class { 'keystone::db::mysql':
409       user          => $keystone_dsn[3],
410       password      => $keystone_dsn[4],
411       host          => $keystone_dsn[5],
412       dbname        => $keystone_dsn[6],
413       allowed_hosts => $allowed_hosts,
414       require       => Exec['galera-ready'],
415     }
416     $glance_dsn = split(hiera('glance::api::database_connection'), '[@:/?]')
417     class { 'glance::db::mysql':
418       user          => $glance_dsn[3],
419       password      => $glance_dsn[4],
420       host          => $glance_dsn[5],
421       dbname        => $glance_dsn[6],
422       allowed_hosts => $allowed_hosts,
423       require       => Exec['galera-ready'],
424     }
425     $nova_dsn = split(hiera('nova::database_connection'), '[@:/?]')
426     class { 'nova::db::mysql':
427       user          => $nova_dsn[3],
428       password      => $nova_dsn[4],
429       host          => $nova_dsn[5],
430       dbname        => $nova_dsn[6],
431       allowed_hosts => $allowed_hosts,
432       require       => Exec['galera-ready'],
433     }
434     $neutron_dsn = split(hiera('neutron::server::database_connection'), '[@:/?]')
435     class { 'neutron::db::mysql':
436       user          => $neutron_dsn[3],
437       password      => $neutron_dsn[4],
438       host          => $neutron_dsn[5],
439       dbname        => $neutron_dsn[6],
440       allowed_hosts => $allowed_hosts,
441       require       => Exec['galera-ready'],
442     }
443     $cinder_dsn = split(hiera('cinder::database_connection'), '[@:/?]')
444     class { 'cinder::db::mysql':
445       user          => $cinder_dsn[3],
446       password      => $cinder_dsn[4],
447       host          => $cinder_dsn[5],
448       dbname        => $cinder_dsn[6],
449       allowed_hosts => $allowed_hosts,
450       require       => Exec['galera-ready'],
451     }
452     $heat_dsn = split(hiera('heat::database_connection'), '[@:/?]')
453     class { 'heat::db::mysql':
454       user          => $heat_dsn[3],
455       password      => $heat_dsn[4],
456       host          => $heat_dsn[5],
457       dbname        => $heat_dsn[6],
458       allowed_hosts => $allowed_hosts,
459       require       => Exec['galera-ready'],
460     }
461     if downcase(hiera('ceilometer_backend')) == 'mysql' {
462       $ceilometer_dsn = split(hiera('ceilometer_mysql_conn_string'), '[@:/?]')
463       class { 'ceilometer::db::mysql':
464         user          => $ceilometer_dsn[3],
465         password      => $ceilometer_dsn[4],
466         host          => $ceilometer_dsn[5],
467         dbname        => $ceilometer_dsn[6],
468         allowed_hosts => $allowed_hosts,
469         require       => Exec['galera-ready'],
470       }
471     }
472   }
473
474   # pre-install swift here so we can build rings
475   include ::swift
476
477   # Ceph
478   $cinder_enable_rbd_backend = hiera('cinder_enable_rbd_backend', false)
479   $enable_ceph = $cinder_enable_rbd_backend
480
481   if $enable_ceph {
482     class { 'ceph::profile::params':
483       mon_initial_members => downcase(hiera('ceph_mon_initial_members'))
484     }
485     include ::ceph::profile::mon
486   }
487
488   if str2bool(hiera('enable_ceph_storage', 'false')) {
489     include ::ceph::profile::client
490     include ::ceph::profile::osd
491   }
492
493
494 } #END STEP 2
495
496 if hiera('step') >= 3 {
497
498   class { '::keystone':
499     sync_db => $sync_db,
500     manage_service => false,
501     enabled => false,
502   }
503
504   #TODO: need a cleanup-keystone-tokens.sh solution here
505   keystone_config {
506     'ec2/driver': value => 'keystone.contrib.ec2.backends.sql.Ec2';
507   }
508   file { [ '/etc/keystone/ssl', '/etc/keystone/ssl/certs', '/etc/keystone/ssl/private' ]:
509     ensure  => 'directory',
510     owner   => 'keystone',
511     group   => 'keystone',
512     require => Package['keystone'],
513   }
514   file { '/etc/keystone/ssl/certs/signing_cert.pem':
515     content => hiera('keystone_signing_certificate'),
516     owner   => 'keystone',
517     group   => 'keystone',
518     notify  => Service['keystone'],
519     require => File['/etc/keystone/ssl/certs'],
520   }
521   file { '/etc/keystone/ssl/private/signing_key.pem':
522     content => hiera('keystone_signing_key'),
523     owner   => 'keystone',
524     group   => 'keystone',
525     notify  => Service['keystone'],
526     require => File['/etc/keystone/ssl/private'],
527   }
528   file { '/etc/keystone/ssl/certs/ca.pem':
529     content => hiera('keystone_ca_certificate'),
530     owner   => 'keystone',
531     group   => 'keystone',
532     notify  => Service['keystone'],
533     require => File['/etc/keystone/ssl/certs'],
534   }
535
536   $glance_backend = downcase(hiera('glance_backend', 'swift'))
537   case $glance_backend {
538       swift: { $glance_store = 'glance.store.swift.Store' }
539       file: { $glance_store = 'glance.store.filesystem.Store' }
540       rbd: { $glance_store = 'glance.store.rbd.Store' }
541       default: { fail('Unrecognized glance_backend parameter.') }
542   }
543
544   # TODO: notifications, scrubber, etc.
545   include ::glance
546   class { 'glance::api':
547     known_stores => [$glance_store],
548     manage_service => false,
549     enabled => false,
550   }
551   class { '::glance::registry' :
552     sync_db => $sync_db,
553     manage_service => false,
554     enabled => false,
555   }
556   include join(['::glance::backend::', $glance_backend])
557
558   include ::nova
559
560   class { '::nova::api' :
561     sync_db => $sync_db,
562     manage_service => false,
563     enabled => false,
564   }
565   class { '::nova::cert' :
566     manage_service => false,
567     enabled => false,
568   }
569   class { '::nova::conductor' :
570     manage_service => false,
571     enabled => false,
572   }
573   class { '::nova::consoleauth' :
574     manage_service => false,
575     enabled => false,
576   }
577   class { '::nova::vncproxy' :
578     manage_service => false,
579     enabled => false,
580   }
581   class { '::nova::scheduler' :
582     manage_service => false,
583     enabled => false,
584   }
585   include ::nova::network::neutron
586
587   # Neutron class definitions
588   include ::neutron
589   class { '::neutron::server' :
590     sync_db => $sync_db,
591     manage_service => false,
592     enabled => false,
593   }
594   class { '::neutron::agents::dhcp' :
595     manage_service => false,
596     enabled => false,
597   }
598   class { '::neutron::agents::l3' :
599     manage_service => false,
600     enabled => false,
601   }
602   class { 'neutron::agents::metadata':
603     manage_service => false,
604     enabled => false,
605   }
606   file { '/etc/neutron/dnsmasq-neutron.conf':
607     content => hiera('neutron_dnsmasq_options'),
608     owner   => 'neutron',
609     group   => 'neutron',
610     notify  => Service['neutron-dhcp-service'],
611     require => Package['neutron'],
612   }
613   class { 'neutron::plugins::ml2':
614     flat_networks   => split(hiera('neutron_flat_networks'), ','),
615     tenant_network_types => [hiera('neutron_tenant_network_type')],
616   }
617   class { 'neutron::agents::ml2::ovs':
618     # manage_service   => false # not implemented
619     enabled          => false,
620     bridge_mappings  => split(hiera('neutron_bridge_mappings'), ','),
621     tunnel_types     => split(hiera('neutron_tunnel_types'), ','),
622   }
623
624   include ::cinder
625   class { '::cinder::api':
626     sync_db => $sync_db,
627     manage_service => false,
628     enabled => false,
629   }
630   class { '::cinder::scheduler' :
631     manage_service => false,
632     enabled => false,
633   }
634   class { '::cinder::volume' :
635     manage_service => false,
636     enabled => false,
637   }
638   include ::cinder::glance
639   class {'cinder::setup_test_volume':
640     size => join([hiera('cinder_lvm_loop_device_size'), 'M']),
641   }
642
643   $cinder_enable_iscsi = hiera('cinder_enable_iscsi_backend', true)
644   if $cinder_enable_iscsi {
645     $cinder_iscsi_backend = 'tripleo_iscsi'
646
647     cinder::backend::iscsi { $cinder_iscsi_backend :
648       iscsi_ip_address => hiera('cinder_iscsi_ip_address'),
649       iscsi_helper     => hiera('cinder_iscsi_helper'),
650     }
651   }
652
653   if $enable_ceph {
654
655     Ceph_pool {
656       pg_num  => hiera('ceph::profile::params::osd_pool_default_pg_num'),
657       pgp_num => hiera('ceph::profile::params::osd_pool_default_pgp_num'),
658       size    => hiera('ceph::profile::params::osd_pool_default_size'),
659     }
660
661     $ceph_pools = hiera('ceph_pools')
662     ceph::pool { $ceph_pools : }
663   }
664
665   if $cinder_enable_rbd_backend {
666     $cinder_rbd_backend = 'tripleo_ceph'
667
668     cinder_config {
669       "${cinder_rbd_backend}/host": value => 'hostgroup';
670     }
671
672     cinder::backend::rbd { $cinder_rbd_backend :
673       rbd_pool        => 'volumes',
674       rbd_user        => 'openstack',
675       rbd_secret_uuid => hiera('ceph::profile::params::fsid'),
676       require         => Ceph::Pool['volumes'],
677     }
678   }
679
680   if hiera('cinder_enable_netapp_backend', false) {
681     $cinder_netapp_backend = hiera('cinder::backend::netapp::title')
682
683     cinder_config {
684       "${cinder_netapp_backend}/host": value => 'hostgroup';
685     }
686
687     if hiera('cinder_netapp_nfs_shares', undef) {
688       $cinder_netapp_nfs_shares = split(hiera('cinder_netapp_nfs_shares', undef), ',')
689     }
690
691     cinder::backend::netapp { $cinder_netapp_backend :
692       nfs_shares => $cinder_netapp_nfs_shares,
693     }
694   }
695
696   $cinder_enabled_backends = delete_undef_values([$cinder_iscsi_backend, $cinder_rbd_backend, $cinder_netapp_backend])
697   class { '::cinder::backends' :
698     enabled_backends => $cinder_enabled_backends,
699   }
700
701   # swift proxy
702   class { '::swift::proxy' :
703     manage_service => $non_pcmk_start,
704     enabled => $non_pcmk_start,
705   }
706   include ::swift::proxy::proxy_logging
707   include ::swift::proxy::healthcheck
708   include ::swift::proxy::cache
709   include ::swift::proxy::keystone
710   include ::swift::proxy::authtoken
711   include ::swift::proxy::staticweb
712   include ::swift::proxy::ceilometer
713   include ::swift::proxy::ratelimit
714   include ::swift::proxy::catch_errors
715   include ::swift::proxy::tempurl
716   include ::swift::proxy::formpost
717
718   # swift storage
719   if str2bool(hiera('enable_swift_storage', 'true')) {
720     class {'::swift::storage::all':
721       mount_check => str2bool(hiera('swift_mount_check'))
722     }
723     class {'::swift::storage::account':
724       manage_service => $non_pcmk_start,
725       enabled => $non_pcmk_start,
726     }
727     class {'::swift::storage::container':
728       manage_service => $non_pcmk_start,
729       enabled => $non_pcmk_start,
730     }
731     class {'::swift::storage::object':
732       manage_service => $non_pcmk_start,
733       enabled => $non_pcmk_start,
734     }
735     if(!defined(File['/srv/node'])) {
736       file { '/srv/node':
737         ensure  => directory,
738         owner   => 'swift',
739         group   => 'swift',
740         require => Package['openstack-swift'],
741       }
742     }
743     $swift_components = ['account', 'container', 'object']
744     swift::storage::filter::recon { $swift_components : }
745     swift::storage::filter::healthcheck { $swift_components : }
746   }
747
748   # Ceilometer
749   $ceilometer_backend = downcase(hiera('ceilometer_backend'))
750   case $ceilometer_backend {
751     /mysql/ : {
752       $ceilometer_database_connection = hiera('ceilometer_mysql_conn_string')
753     }
754     default : {
755       $mongo_node_string = join($mongo_node_ips_with_port, ',')
756       $ceilometer_database_connection = "mongodb://${mongo_node_string}/ceilometer?replicaSet=${mongodb_replset}"
757     }
758   }
759   include ::ceilometer
760   class { '::ceilometer::api' :
761     manage_service => false,
762     enabled => false,
763   }
764   class { '::ceilometer::agent::notification' :
765     manage_service => false,
766     enabled => false,
767   }
768   class { '::ceilometer::agent::central' :
769     manage_service => false,
770     enabled => false,
771   }
772   class { '::ceilometer::alarm::notifier' :
773     manage_service => false,
774     enabled => false,
775   }
776   class { '::ceilometer::alarm::evaluator' :
777     manage_service => false,
778     enabled => false,
779   }
780   class { '::ceilometer::collector' :
781     manage_service => false,
782     enabled => false,
783   }
784   include ::ceilometer::expirer
785   class { '::ceilometer::db' :
786     database_connection => $ceilometer_database_connection,
787     sync_db             => $sync_db,
788   }
789   include ceilometer::agent::auth
790
791   Cron <| title == 'ceilometer-expirer' |> { command => "sleep $((\$(od -A n -t d -N 3 /dev/urandom) % 86400)) && ${::ceilometer::params::expirer_command}" }
792
793   # Heat
794   class { '::heat' :
795     sync_db => $sync_db,
796   }
797   class { '::heat::api' :
798     manage_service => false,
799     enabled => false,
800   }
801   class { '::heat::api_cfn' :
802     manage_service => false,
803     enabled => false,
804   }
805   class { '::heat::api_cloudwatch' :
806     manage_service => false,
807     enabled => false,
808   }
809   class { '::heat::engine' :
810     manage_service => false,
811     enabled => false,
812   }
813
814   # httpd/apache and horizon
815   # NOTE(gfidente): server-status can be consumed by the pacemaker resource agent
816   include ::apache
817   include ::apache::mod::status
818   $vhost_params = {
819     add_listen => false,
820     priority   => 10,
821   }
822   class { 'horizon':
823     cache_server_ip    => hiera('memcache_node_ips', '127.0.0.1'),
824     vhost_extra_params => $vhost_params,
825     server_aliases     => $::hostname,
826   }
827
828   $snmpd_user = hiera('snmpd_readonly_user_name')
829   snmp::snmpv3_user { $snmpd_user:
830     authtype => 'MD5',
831     authpass => hiera('snmpd_readonly_user_password'),
832   }
833   class { 'snmp':
834     agentaddress => ['udp:161','udp6:[::1]:161'],
835     snmpd_config => [ join(['rouser ', hiera('snmpd_readonly_user_name')]), 'proc  cron', 'includeAllDisks  10%', 'master agentx', 'trapsink localhost public', 'iquerySecName internalUser', 'rouser internalUser', 'defaultMonitors yes', 'linkUpDownNotifications yes' ],
836   }
837
838 } #END STEP 3
839
840 if hiera('step') >= 4 {
841   if $pacemaker_master {
842
843     # Keystone
844     pacemaker::resource::service { $::keystone::params::service_name :
845       clone_params => "interleave=true",
846     }
847
848     # Cinder
849     pacemaker::resource::service { $::cinder::params::api_service :
850       clone_params => "interleave=true",
851       require      => Pacemaker::Resource::Service[$::keystone::params::service_name],
852     }
853     pacemaker::resource::service { $::cinder::params::scheduler_service :
854       clone_params => "interleave=true",
855     }
856     pacemaker::resource::service { $::cinder::params::volume_service : }
857
858     pacemaker::constraint::base { 'keystone-then-cinder-api-constraint':
859       constraint_type => 'order',
860       first_resource  => "${::keystone::params::service_name}-clone",
861       second_resource => "${::cinder::params::api_service}-clone",
862       first_action    => 'start',
863       second_action   => 'start',
864       require         => [Pacemaker::Resource::Service[$::cinder::params::api_service],
865                           Pacemaker::Resource::Service[$::keystone::params::service_name]],
866     }
867     pacemaker::constraint::base { 'cinder-api-then-cinder-scheduler-constraint':
868       constraint_type => "order",
869       first_resource => "${::cinder::params::api_service}-clone",
870       second_resource => "${::cinder::params::scheduler_service}-clone",
871       first_action => "start",
872       second_action => "start",
873       require => [Pacemaker::Resource::Service[$::cinder::params::api_service],
874                   Pacemaker::Resource::Service[$::cinder::params::scheduler_service]],
875     }
876     pacemaker::constraint::colocation { 'cinder-scheduler-with-cinder-api-colocation':
877       source => "${::cinder::params::scheduler_service}-clone",
878       target => "${::cinder::params::api_service}-clone",
879       score => "INFINITY",
880       require => [Pacemaker::Resource::Service[$::cinder::params::api_service],
881                   Pacemaker::Resource::Service[$::cinder::params::scheduler_service]],
882     }
883     pacemaker::constraint::base { 'cinder-scheduler-then-cinder-volume-constraint':
884       constraint_type => "order",
885       first_resource => "${::cinder::params::scheduler_service}-clone",
886       second_resource => "${::cinder::params::volume_service}",
887       first_action => "start",
888       second_action => "start",
889       require => [Pacemaker::Resource::Service[$::cinder::params::scheduler_service],
890                   Pacemaker::Resource::Service[$::cinder::params::volume_service]],
891     }
892     pacemaker::constraint::colocation { 'cinder-volume-with-cinder-scheduler-colocation':
893       source => "${::cinder::params::volume_service}",
894       target => "${::cinder::params::scheduler_service}-clone",
895       score => "INFINITY",
896       require => [Pacemaker::Resource::Service[$::cinder::params::scheduler_service],
897                   Pacemaker::Resource::Service[$::cinder::params::volume_service]],
898     }
899
900     # Glance
901     pacemaker::resource::service { $::glance::params::registry_service_name :
902       clone_params => "interleave=true",
903       require      => Pacemaker::Resource::Service[$::keystone::params::service_name],
904     }
905     pacemaker::resource::service { $::glance::params::api_service_name :
906       clone_params => "interleave=true",
907     }
908
909     pacemaker::constraint::base { 'keystone-then-glance-registry-constraint':
910       constraint_type => 'order',
911       first_resource  => "${::keystone::params::service_name}-clone",
912       second_resource => "${::glance::params::registry_service_name}-clone",
913       first_action    => 'start',
914       second_action   => 'start',
915       require         => [Pacemaker::Resource::Service[$::glance::params::registry_service_name],
916                           Pacemaker::Resource::Service[$::keystone::params::service_name]],
917     }
918     pacemaker::constraint::base { 'glance-registry-then-glance-api-constraint':
919       constraint_type => "order",
920       first_resource  => "${::glance::params::registry_service_name}-clone",
921       second_resource => "${::glance::params::api_service_name}-clone",
922       first_action    => "start",
923       second_action   => "start",
924       require => [Pacemaker::Resource::Service[$::glance::params::registry_service_name],
925                   Pacemaker::Resource::Service[$::glance::params::api_service_name]],
926     }
927     pacemaker::constraint::colocation { 'glance-api-with-glance-registry-colocation':
928       source  => "${::glance::params::api_service_name}-clone",
929       target  => "${::glance::params::registry_service_name}-clone",
930       score   => "INFINITY",
931       require => [Pacemaker::Resource::Service[$::glance::params::registry_service_name],
932                   Pacemaker::Resource::Service[$::glance::params::api_service_name]],
933     }
934
935     # Neutron
936     pacemaker::resource::service { $::neutron::params::server_service:
937       op_params => "start timeout=90",
938       clone_params   => "interleave=true",
939       require => Pacemaker::Resource::Service[$::keystone::params::service_name]
940     }
941     pacemaker::resource::service { $::neutron::params::l3_agent_service:
942       clone_params   => "interleave=true",
943     }
944     pacemaker::resource::service { $::neutron::params::dhcp_agent_service:
945       clone_params   => "interleave=true",
946     }
947     pacemaker::resource::service { $::neutron::params::ovs_agent_service:
948       clone_params => "interleave=true",
949     }
950     pacemaker::resource::service { $::neutron::params::metadata_agent_service:
951       clone_params => "interleave=true",
952     }
953     pacemaker::resource::ocf { $::neutron::params::ovs_cleanup_service:
954       ocf_agent_name => "neutron:OVSCleanup",
955       clone_params => "interleave=true",
956     }
957     pacemaker::resource::ocf { 'neutron-netns-cleanup':
958       ocf_agent_name => "neutron:NetnsCleanup",
959       clone_params => "interleave=true",
960     }
961     pacemaker::resource::ocf { 'neutron-scale':
962       ocf_agent_name => "neutron:NeutronScale",
963       clone_params => "globally-unique=true clone-max=3 interleave=true",
964     }
965     pacemaker::constraint::base { 'keystone-to-neutron-server-constraint':
966       constraint_type => "order",
967       first_resource => "${::keystone::params::service_name}-clone",
968       second_resource => "${::neutron::params::server_service}-clone",
969       first_action => "start",
970       second_action => "start",
971       require => [Pacemaker::Resource::Service[$::keystone::params::service_name],
972                   Pacemaker::Resource::Service[$::neutron::params::server_service]],
973     }
974     pacemaker::constraint::base { 'neutron-server-to-neutron-scale-constraint':
975       constraint_type => "order",
976       first_resource => "${::neutron::params::server_service}-clone",
977       second_resource => "neutron-scale-clone",
978       first_action => "start",
979       second_action => "start",
980       require => [Pacemaker::Resource::Service[$::neutron::params::server_service],
981                   Pacemaker::Resource::Ocf['neutron-scale']],
982     }
983     pacemaker::constraint::base { 'neutron-scale-to-ovs-cleanup-constraint':
984       constraint_type => "order",
985       first_resource => "neutron-scale-clone",
986       second_resource => "${::neutron::params::ovs_cleanup_service}-clone",
987       first_action => "start",
988       second_action => "start",
989       require => [Pacemaker::Resource::Ocf['neutron-scale'],
990                   Pacemaker::Resource::Ocf["${::neutron::params::ovs_cleanup_service}"]],
991     }
992     pacemaker::constraint::colocation { 'neutron-scale-to-ovs-cleanup-colocation':
993       source => "${::neutron::params::ovs_cleanup_service}-clone",
994       target => "neutron-scale-clone",
995       score => "INFINITY",
996       require => [Pacemaker::Resource::Ocf['neutron-scale'],
997                   Pacemaker::Resource::Ocf["${::neutron::params::ovs_cleanup_service}"]],
998     }
999     pacemaker::constraint::base { 'neutron-ovs-cleanup-to-netns-cleanup-constraint':
1000       constraint_type => "order",
1001       first_resource => "${::neutron::params::ovs_cleanup_service}-clone",
1002       second_resource => "neutron-netns-cleanup-clone",
1003       first_action => "start",
1004       second_action => "start",
1005       require => [Pacemaker::Resource::Ocf["${::neutron::params::ovs_cleanup_service}"],
1006                   Pacemaker::Resource::Ocf['neutron-netns-cleanup']],
1007     }
1008     pacemaker::constraint::colocation { 'neutron-ovs-cleanup-to-netns-cleanup-colocation':
1009       source => "neutron-netns-cleanup-clone",
1010       target => "${::neutron::params::ovs_cleanup_service}-clone",
1011       score => "INFINITY",
1012       require => [Pacemaker::Resource::Ocf["${::neutron::params::ovs_cleanup_service}"],
1013                   Pacemaker::Resource::Ocf['neutron-netns-cleanup']],
1014     }
1015     pacemaker::constraint::base { 'neutron-netns-cleanup-to-openvswitch-agent-constraint':
1016       constraint_type => "order",
1017       first_resource => "neutron-netns-cleanup-clone",
1018       second_resource => "${::neutron::params::ovs_agent_service}-clone",
1019       first_action => "start",
1020       second_action => "start",
1021       require => [Pacemaker::Resource::Ocf["neutron-netns-cleanup"],
1022                   Pacemaker::Resource::Service["${::neutron::params::ovs_agent_service}"]],
1023     }
1024     pacemaker::constraint::colocation { 'neutron-netns-cleanup-to-openvswitch-agent-colocation':
1025       source => "${::neutron::params::ovs_agent_service}-clone",
1026       target => "neutron-netns-cleanup-clone",
1027       score => "INFINITY",
1028       require => [Pacemaker::Resource::Ocf["neutron-netns-cleanup"],
1029                   Pacemaker::Resource::Service["${::neutron::params::ovs_agent_service}"]],
1030     }
1031     pacemaker::constraint::base { 'neutron-openvswitch-agent-to-dhcp-agent-constraint':
1032       constraint_type => "order",
1033       first_resource => "${::neutron::params::ovs_agent_service}-clone",
1034       second_resource => "${::neutron::params::dhcp_agent_service}-clone",
1035       first_action => "start",
1036       second_action => "start",
1037       require => [Pacemaker::Resource::Service["${::neutron::params::ovs_agent_service}"],
1038                   Pacemaker::Resource::Service["${::neutron::params::dhcp_agent_service}"]],
1039
1040     }
1041     pacemaker::constraint::colocation { 'neutron-openvswitch-agent-to-dhcp-agent-colocation':
1042       source => "${::neutron::params::dhcp_agent_service}-clone",
1043       target => "${::neutron::params::ovs_agent_service}-clone",
1044       score => "INFINITY",
1045       require => [Pacemaker::Resource::Service["${::neutron::params::ovs_agent_service}"],
1046                   Pacemaker::Resource::Service["${::neutron::params::dhcp_agent_service}"]],
1047     }
1048     pacemaker::constraint::base { 'neutron-dhcp-agent-to-l3-agent-constraint':
1049       constraint_type => "order",
1050       first_resource => "${::neutron::params::dhcp_agent_service}-clone",
1051       second_resource => "${::neutron::params::l3_agent_service}-clone",
1052       first_action => "start",
1053       second_action => "start",
1054       require => [Pacemaker::Resource::Service["${::neutron::params::dhcp_agent_service}"],
1055                   Pacemaker::Resource::Service["${::neutron::params::l3_agent_service}"]]
1056     }
1057     pacemaker::constraint::colocation { 'neutron-dhcp-agent-to-l3-agent-colocation':
1058       source => "${::neutron::params::l3_agent_service}-clone",
1059       target => "${::neutron::params::dhcp_agent_service}-clone",
1060       score => "INFINITY",
1061       require => [Pacemaker::Resource::Service["${::neutron::params::dhcp_agent_service}"],
1062                   Pacemaker::Resource::Service["${::neutron::params::l3_agent_service}"]]
1063     }
1064     pacemaker::constraint::base { 'neutron-l3-agent-to-metadata-agent-constraint':
1065       constraint_type => "order",
1066       first_resource => "${::neutron::params::l3_agent_service}-clone",
1067       second_resource => "${::neutron::params::metadata_agent_service}-clone",
1068       first_action => "start",
1069       second_action => "start",
1070       require => [Pacemaker::Resource::Service["${::neutron::params::l3_agent_service}"],
1071                   Pacemaker::Resource::Service["${::neutron::params::metadata_agent_service}"]]
1072     }
1073     pacemaker::constraint::colocation { 'neutron-l3-agent-to-metadata-agent-colocation':
1074       source => "${::neutron::params::metadata_agent_service}-clone",
1075       target => "${::neutron::params::l3_agent_service}-clone",
1076       score => "INFINITY",
1077       require => [Pacemaker::Resource::Service["${::neutron::params::l3_agent_service}"],
1078                   Pacemaker::Resource::Service["${::neutron::params::metadata_agent_service}"]]
1079     }
1080
1081     # Nova
1082     pacemaker::resource::service { $::nova::params::api_service_name :
1083       clone_params    => "interleave=true",
1084       op_params       => "monitor start-delay=10s",
1085     }
1086     pacemaker::resource::service { $::nova::params::conductor_service_name :
1087       clone_params    => "interleave=true",
1088       op_params       => "monitor start-delay=10s",
1089     }
1090     pacemaker::resource::service { $::nova::params::consoleauth_service_name :
1091       clone_params    => "interleave=true",
1092       op_params       => "monitor start-delay=10s",
1093       require         => Pacemaker::Resource::Service[$::keystone::params::service_name],
1094     }
1095     pacemaker::resource::service { $::nova::params::vncproxy_service_name :
1096       clone_params    => "interleave=true",
1097       op_params       => "monitor start-delay=10s",
1098     }
1099     pacemaker::resource::service { $::nova::params::scheduler_service_name :
1100       clone_params    => "interleave=true",
1101       op_params       => "monitor start-delay=10s",
1102     }
1103
1104     pacemaker::constraint::base { 'keystone-then-nova-consoleauth-constraint':
1105       constraint_type => 'order',
1106       first_resource  => "${::keystone::params::service_name}-clone",
1107       second_resource => "${::nova::params::consoleauth_service_name}-clone",
1108       first_action    => 'start',
1109       second_action   => 'start',
1110       require         => [Pacemaker::Resource::Service[$::nova::params::consoleauth_service_name],
1111                           Pacemaker::Resource::Service[$::keystone::params::service_name]],
1112     }
1113     pacemaker::constraint::base { 'nova-consoleauth-then-nova-vncproxy-constraint':
1114       constraint_type => "order",
1115       first_resource  => "${::nova::params::consoleauth_service_name}-clone",
1116       second_resource => "${::nova::params::vncproxy_service_name}-clone",
1117       first_action    => "start",
1118       second_action   => "start",
1119       require => [Pacemaker::Resource::Service[$::nova::params::consoleauth_service_name],
1120                   Pacemaker::Resource::Service[$::nova::params::vncproxy_service_name]],
1121     }
1122     pacemaker::constraint::colocation { 'nova-vncproxy-with-nova-consoleauth-colocation':
1123       source => "${::nova::params::vncproxy_service_name}-clone",
1124       target => "${::nova::params::consoleauth_service_name}-clone",
1125       score => "INFINITY",
1126       require => [Pacemaker::Resource::Service[$::nova::params::consoleauth_service_name],
1127                   Pacemaker::Resource::Service[$::nova::params::vncproxy_service_name]],
1128     }
1129     # FIXME(gfidente): novncproxy will not start unless websockify is updated to 0.6
1130     # which is not the case for f20 nor f21; ucomment when it becomes available
1131     #pacemaker::constraint::base { 'nova-vncproxy-then-nova-api-constraint':
1132     #  constraint_type => "order",
1133     #  first_resource  => "${::nova::params::vncproxy_service_name}-clone",
1134     #  second_resource => "${::nova::params::api_service_name}-clone",
1135     #  first_action    => "start",
1136     #  second_action   => "start",
1137     #  require => [Pacemaker::Resource::Service[$::nova::params::vncproxy_service_name],
1138     #              Pacemaker::Resource::Service[$::nova::params::api_service_name]],
1139     #}
1140     #pacemaker::constraint::colocation { 'nova-api-with-nova-vncproxy-colocation':
1141     #  source => "${::nova::params::api_service_name}-clone",
1142     #  target => "${::nova::params::vncproxy_service_name}-clone",
1143     #  score => "INFINITY",
1144     #  require => [Pacemaker::Resource::Service[$::nova::params::vncproxy_service_name],
1145     #              Pacemaker::Resource::Service[$::nova::params::api_service_name]],
1146     #}
1147     pacemaker::constraint::base { 'nova-api-then-nova-scheduler-constraint':
1148       constraint_type => "order",
1149       first_resource  => "${::nova::params::api_service_name}-clone",
1150       second_resource => "${::nova::params::scheduler_service_name}-clone",
1151       first_action    => "start",
1152       second_action   => "start",
1153       require => [Pacemaker::Resource::Service[$::nova::params::api_service_name],
1154                   Pacemaker::Resource::Service[$::nova::params::scheduler_service_name]],
1155     }
1156     pacemaker::constraint::colocation { 'nova-scheduler-with-nova-api-colocation':
1157       source => "${::nova::params::scheduler_service_name}-clone",
1158       target => "${::nova::params::api_service_name}-clone",
1159       score => "INFINITY",
1160       require => [Pacemaker::Resource::Service[$::nova::params::api_service_name],
1161                   Pacemaker::Resource::Service[$::nova::params::scheduler_service_name]],
1162     }
1163     pacemaker::constraint::base { 'nova-scheduler-then-nova-conductor-constraint':
1164       constraint_type => "order",
1165       first_resource  => "${::nova::params::scheduler_service_name}-clone",
1166       second_resource => "${::nova::params::conductor_service_name}-clone",
1167       first_action    => "start",
1168       second_action   => "start",
1169       require => [Pacemaker::Resource::Service[$::nova::params::scheduler_service_name],
1170                   Pacemaker::Resource::Service[$::nova::params::conductor_service_name]],
1171     }
1172     pacemaker::constraint::colocation { 'nova-conductor-with-nova-scheduler-colocation':
1173       source => "${::nova::params::conductor_service_name}-clone",
1174       target => "${::nova::params::scheduler_service_name}-clone",
1175       score => "INFINITY",
1176       require => [Pacemaker::Resource::Service[$::nova::params::scheduler_service_name],
1177                   Pacemaker::Resource::Service[$::nova::params::conductor_service_name]],
1178     }
1179
1180     # Ceilometer
1181     pacemaker::resource::service { $::ceilometer::params::agent_central_service_name :
1182       clone_params => 'interleave=true',
1183       require      => [Pacemaker::Resource::Service[$::keystone::params::service_name],
1184                        Pacemaker::Resource::Service[$::mongodb::params::service_name]],
1185     }
1186     pacemaker::resource::service { $::ceilometer::params::collector_service_name :
1187       clone_params => 'interleave=true',
1188     }
1189     pacemaker::resource::service { $::ceilometer::params::api_service_name :
1190       clone_params => 'interleave=true',
1191     }
1192     pacemaker::resource::service { $::ceilometer::params::alarm_evaluator_service_name :
1193       clone_params => 'interleave=true',
1194     }
1195     pacemaker::resource::service { $::ceilometer::params::alarm_notifier_service_name :
1196       clone_params => 'interleave=true',
1197     }
1198     pacemaker::resource::service { $::ceilometer::params::agent_notification_service_name :
1199       clone_params => 'interleave=true',
1200     }
1201     pacemaker::resource::ocf { 'delay' :
1202       ocf_agent_name  => 'heartbeat:Delay',
1203       clone_params    => 'interleave=true',
1204       resource_params => 'startdelay=10',
1205     }
1206     pacemaker::constraint::base { 'keystone-then-ceilometer-central-constraint':
1207       constraint_type => 'order',
1208       first_resource  => "${::keystone::params::service_name}-clone",
1209       second_resource => "${::ceilometer::params::agent_central_service_name}-clone",
1210       first_action    => 'start',
1211       second_action   => 'start',
1212       require         => [Pacemaker::Resource::Service[$::ceilometer::params::agent_central_service_name],
1213                           Pacemaker::Resource::Service[$::keystone::params::service_name]],
1214     }
1215     pacemaker::constraint::base { 'ceilometer-central-then-ceilometer-collector-constraint':
1216       constraint_type => 'order',
1217       first_resource  => "${::ceilometer::params::agent_central_service_name}-clone",
1218       second_resource => "${::ceilometer::params::collector_service_name}-clone",
1219       first_action    => 'start',
1220       second_action   => 'start',
1221       require         => [Pacemaker::Resource::Service[$::ceilometer::params::agent_central_service_name],
1222                           Pacemaker::Resource::Service[$::ceilometer::params::collector_service_name]],
1223     }
1224     pacemaker::constraint::base { 'ceilometer-collector-then-ceilometer-api-constraint':
1225       constraint_type => 'order',
1226       first_resource  => "${::ceilometer::params::collector_service_name}-clone",
1227       second_resource => "${::ceilometer::params::api_service_name}-clone",
1228       first_action    => 'start',
1229       second_action   => 'start',
1230       require         => [Pacemaker::Resource::Service[$::ceilometer::params::collector_service_name],
1231                           Pacemaker::Resource::Service[$::ceilometer::params::api_service_name]],
1232     }
1233     pacemaker::constraint::colocation { 'ceilometer-api-with-ceilometer-collector-colocation':
1234       source  => "${::ceilometer::params::api_service_name}-clone",
1235       target  => "${::ceilometer::params::collector_service_name}-clone",
1236       score   => 'INFINITY',
1237       require => [Pacemaker::Resource::Service[$::ceilometer::params::api_service_name],
1238                   Pacemaker::Resource::Service[$::ceilometer::params::collector_service_name]],
1239     }
1240     pacemaker::constraint::base { 'ceilometer-api-then-ceilometer-delay-constraint':
1241       constraint_type => 'order',
1242       first_resource  => "${::ceilometer::params::api_service_name}-clone",
1243       second_resource => 'delay-clone',
1244       first_action    => 'start',
1245       second_action   => 'start',
1246       require         => [Pacemaker::Resource::Service[$::ceilometer::params::api_service_name],
1247                           Pacemaker::Resource::Ocf['delay']],
1248     }
1249     pacemaker::constraint::colocation { 'ceilometer-delay-with-ceilometer-api-colocation':
1250       source  => 'delay-clone',
1251       target  => "${::ceilometer::params::api_service_name}-clone",
1252       score   => 'INFINITY',
1253       require => [Pacemaker::Resource::Service[$::ceilometer::params::api_service_name],
1254                   Pacemaker::Resource::Ocf['delay']],
1255     }
1256     pacemaker::constraint::base { 'ceilometer-delay-then-ceilometer-alarm-evaluator-constraint':
1257       constraint_type => 'order',
1258       first_resource  => 'delay-clone',
1259       second_resource => "${::ceilometer::params::alarm_evaluator_service_name}-clone",
1260       first_action    => 'start',
1261       second_action   => 'start',
1262       require         => [Pacemaker::Resource::Service[$::ceilometer::params::alarm_evaluator_service_name],
1263                           Pacemaker::Resource::Ocf['delay']],
1264     }
1265     pacemaker::constraint::colocation { 'ceilometer-alarm-evaluator-with-ceilometer-delay-colocation':
1266       source  => "${::ceilometer::params::alarm_evaluator_service_name}-clone",
1267       target  => 'delay-clone',
1268       score   => 'INFINITY',
1269       require => [Pacemaker::Resource::Service[$::ceilometer::params::api_service_name],
1270                   Pacemaker::Resource::Ocf['delay']],
1271     }
1272     pacemaker::constraint::base { 'ceilometer-alarm-evaluator-then-ceilometer-alarm-notifier-constraint':
1273       constraint_type => 'order',
1274       first_resource  => "${::ceilometer::params::alarm_evaluator_service_name}-clone",
1275       second_resource => "${::ceilometer::params::alarm_notifier_service_name}-clone",
1276       first_action    => 'start',
1277       second_action   => 'start',
1278       require         => [Pacemaker::Resource::Service[$::ceilometer::params::alarm_evaluator_service_name],
1279                           Pacemaker::Resource::Service[$::ceilometer::params::alarm_notifier_service_name]],
1280     }
1281     pacemaker::constraint::colocation { 'ceilometer-alarm-notifier-with-ceilometer-alarm-evaluator-colocation':
1282       source  => "${::ceilometer::params::alarm_notifier_service_name}-clone",
1283       target  => "${::ceilometer::params::alarm_evaluator_service_name}-clone",
1284       score   => 'INFINITY',
1285       require => [Pacemaker::Resource::Service[$::ceilometer::params::alarm_evaluator_service_name],
1286                   Pacemaker::Resource::Service[$::ceilometer::params::alarm_notifier_service_name]],
1287     }
1288     pacemaker::constraint::base { 'ceilometer-alarm-notifier-then-ceilometer-notification-constraint':
1289       constraint_type => 'order',
1290       first_resource  => "${::ceilometer::params::alarm_notifier_service_name}-clone",
1291       second_resource => "${::ceilometer::params::agent_notification_service_name}-clone",
1292       first_action    => 'start',
1293       second_action   => 'start',
1294       require         => [Pacemaker::Resource::Service[$::ceilometer::params::agent_notification_service_name],
1295                           Pacemaker::Resource::Service[$::ceilometer::params::alarm_notifier_service_name]],
1296     }
1297     pacemaker::constraint::colocation { 'ceilometer-notification-with-ceilometer-alarm-notifier-colocation':
1298       source  => "${::ceilometer::params::agent_notification_service_name}-clone",
1299       target  => "${::ceilometer::params::alarm_notifier_service_name}-clone",
1300       score   => 'INFINITY',
1301       require => [Pacemaker::Resource::Service[$::ceilometer::params::agent_notification_service_name],
1302                   Pacemaker::Resource::Service[$::ceilometer::params::alarm_notifier_service_name]],
1303     }
1304     if downcase(hiera('ceilometer_backend')) == 'mongodb' {
1305       pacemaker::constraint::base { 'mongodb-then-ceilometer-central-constraint':
1306         constraint_type => 'order',
1307         first_resource  => "${::mongodb::params::service_name}-clone",
1308         second_resource => "${::ceilometer::params::agent_central_service_name}-clone",
1309         first_action    => 'start',
1310         second_action   => 'start',
1311         require         => [Pacemaker::Resource::Service[$::ceilometer::params::agent_central_service_name],
1312                             Pacemaker::Resource::Service[$::mongodb::params::service_name]],
1313       }
1314     }
1315
1316     # Heat
1317     pacemaker::resource::service { $::heat::params::api_service_name :
1318       clone_params => 'interleave=true',
1319     }
1320     pacemaker::resource::service { $::heat::params::api_cloudwatch_service_name :
1321       clone_params => 'interleave=true',
1322     }
1323     pacemaker::resource::service { $::heat::params::api_cfn_service_name :
1324       clone_params => 'interleave=true',
1325     }
1326     pacemaker::resource::service { $::heat::params::engine_service_name :
1327       clone_params => 'interleave=true',
1328     }
1329     pacemaker::constraint::base { 'keystone-then-heat-api-constraint':
1330       constraint_type => 'order',
1331       first_resource  => "${::keystone::params::service_name}-clone",
1332       second_resource => "${::heat::params::api_service_name}-clone",
1333       first_action    => 'start',
1334       second_action   => 'start',
1335       require         => [Pacemaker::Resource::Service[$::heat::params::api_service_name],
1336                           Pacemaker::Resource::Service[$::keystone::params::service_name]],
1337     }
1338     pacemaker::constraint::base { 'heat-api-then-heat-api-cfn-constraint':
1339       constraint_type => 'order',
1340       first_resource  => "${::heat::params::api_service_name}-clone",
1341       second_resource => "${::heat::params::api_cfn_service_name}-clone",
1342       first_action    => 'start',
1343       second_action   => 'start',
1344       require => [Pacemaker::Resource::Service[$::heat::params::api_service_name],
1345                   Pacemaker::Resource::Service[$::heat::params::api_cfn_service_name]],
1346     }
1347     pacemaker::constraint::colocation { 'heat-api-cfn-with-heat-api-colocation':
1348       source  => "${::heat::params::api_cfn_service_name}-clone",
1349       target  => "${::heat::params::api_service_name}-clone",
1350       score   => 'INFINITY',
1351       require => [Pacemaker::Resource::Service[$::heat::params::api_cfn_service_name],
1352                   Pacemaker::Resource::Service[$::heat::params::api_service_name]],
1353     }
1354     pacemaker::constraint::base { 'heat-api-cfn-then-heat-api-cloudwatch-constraint':
1355       constraint_type => 'order',
1356       first_resource  => "${::heat::params::api_cfn_service_name}-clone",
1357       second_resource => "${::heat::params::api_cloudwatch_service_name}-clone",
1358       first_action    => 'start',
1359       second_action   => 'start',
1360       require => [Pacemaker::Resource::Service[$::heat::params::api_cloudwatch_service_name],
1361                   Pacemaker::Resource::Service[$::heat::params::api_cfn_service_name]],
1362     }
1363     pacemaker::constraint::colocation { 'heat-api-cloudwatch-with-heat-api-cfn-colocation':
1364       source  => "${::heat::params::api_cloudwatch_service_name}-clone",
1365       target  => "${::heat::params::api_cfn_service_name}-clone",
1366       score   => 'INFINITY',
1367       require => [Pacemaker::Resource::Service[$::heat::params::api_cfn_service_name],
1368                   Pacemaker::Resource::Service[$::heat::params::api_cloudwatch_service_name]],
1369     }
1370     pacemaker::constraint::base { 'heat-api-cloudwatch-then-heat-engine-constraint':
1371       constraint_type => 'order',
1372       first_resource  => "${::heat::params::api_cloudwatch_service_name}-clone",
1373       second_resource => "${::heat::params::engine_service_name}-clone",
1374       first_action    => 'start',
1375       second_action   => 'start',
1376       require => [Pacemaker::Resource::Service[$::heat::params::api_cloudwatch_service_name],
1377                   Pacemaker::Resource::Service[$::heat::params::engine_service_name]],
1378     }
1379     pacemaker::constraint::colocation { 'heat-engine-with-heat-api-cloudwatch-colocation':
1380       source  => "${::heat::params::engine_service_name}-clone",
1381       target  => "${::heat::params::api_cloudwatch_service_name}-clone",
1382       score   => 'INFINITY',
1383       require => [Pacemaker::Resource::Service[$::heat::params::api_cloudwatch_service_name],
1384                   Pacemaker::Resource::Service[$::heat::params::engine_service_name]],
1385     }
1386     pacemaker::constraint::base { 'ceilometer-notification-then-heat-api-constraint':
1387       constraint_type => 'order',
1388       first_resource  => "${::ceilometer::params::agent_notification_service_name}-clone",
1389       second_resource => "${::heat::params::api_service_name}-clone",
1390       first_action    => 'start',
1391       second_action   => 'start',
1392       require         => [Pacemaker::Resource::Service[$::heat::params::api_service_name],
1393                           Pacemaker::Resource::Service[$::ceilometer::params::agent_notification_service_name]],
1394     }
1395
1396     # Horizon
1397     pacemaker::resource::service { $::horizon::params::http_service:
1398         clone_params => "interleave=true",
1399     }
1400
1401
1402   }
1403
1404 } #END STEP 4