Skip to content

Commit

Permalink
Ensure the topology takes the correct shape.
Browse files Browse the repository at this point in the history
This connects and disconnects peers until the requested topology matches
what was requested manually, or by one of the topology algorithms.
  • Loading branch information
purpleidea committed Jul 11, 2014
1 parent ddc435e commit 73712d1
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 0 deletions.
13 changes: 13 additions & 0 deletions manifests/server.pp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
$host_excludes = [], # never purge these host excludes...
$service_excludes = [], # never purge these service excludes...
$user_excludes = [], # never purge these user excludes...
$peer_excludes = [], # never purge these peer excludes...
$ensure = present # TODO: support uninstall with 'absent'
) {
$FW = '$FW' # make using $FW in shorewall easier...
Expand Down Expand Up @@ -102,6 +103,13 @@
$replica_peers_fact = "${::ipa_server_replica_peers}" # fact!
$replica_peers = split($replica_peers_fact, ',') # list!

# NOTE: this algorithm transforms a sorted list of peers into a set of:
# from -> to pairs (as a hash), or from -> to and to -> from pairs that
# are symmetrical since peering is bi-directional... this list of hosts
# could either be determined automatically with "exported resources" or
# specified manually. just select an algorithm for automatic peering...
# the $key in the hash is the from value. the $value of the hash is the
# list of whichever hosts we should peer with, ordered by preference...

# run the appropriate topology function here
$empty_hash = {}
Expand Down Expand Up @@ -637,6 +645,11 @@
}
}

# ensure the topology has the right shape...
ipa::server::replica::manage { $valid_peers["${::fqdn}"]: # magic
peer => "${::fqdn}",
}

# this fact gets created once the installation is complete... the first
# time that puppet runs, it won't be set. after installation it will :)
# this mechanism provides a way to only run the 'helpful' notifies once
Expand Down
77 changes: 77 additions & 0 deletions manifests/server/replica/manage.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# FreeIPA templating module by James
# Copyright (C) 2012-2013+ James Shubin
# Written by James Shubin <james@shubin.ca>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

# NOTE: all replication agreements are bi-directional for now due to FreeIPA...
# NOTE: in the future, it would be quite cool to allow uni-directional replicas
# NOTE: this type has been engineered to fit easily with the topology datatype:
# $ring = { # example flat topology as expressed in the std. format
# 'fqdn1': ['fqdn2', 'fqdn3'],
# 'fqdn2': ['fqdn3', 'fqdn1'],
# 'fqdn3': ['fqdn1', 'fqdn2'],
# }
#
# ipa::server::replica::manage { $ring["${::fqdn}"]: # all automatic
# peer => "${::fqdn}",
# }
define ipa::server::replica::manage( # to
$peer = '' # from
) {
# TODO: this type could grow fancy name parsing to specify: to and from

include ipa::server::replica::manage::base
include ipa::common
include ipa::vardir
#$vardir = $::ipa::vardir::module_vardir # with trailing slash
$vardir = regsubst($::ipa::vardir::module_vardir, '\/$', '')

# NOTE: the peer vs. valid_peer names are by convention (but confusing)
$args = "${peer}" # from (a)
$valid_peer = "${name}" # to (b)

# switch bad characters for file name friendly characters (unused atm!)
# this could be useful if we allow peers's with $ and others in them...
$valid_peer_file = regsubst("${valid_peer}", '\$', '-', 'G')
file { "${vardir}/replica/manage/peers/${valid_peer_file}.peer":
content => "${valid_peer}\n${args}\n",
owner => root,
group => nobody,
mode => 600, # u=rw,go=
require => File["${vardir}/replica/manage/peers/"],
ensure => present,
}

# NOTE: this shouldn't depend on the VIP because it runs on each host...
exec { "/usr/sbin/ipa-replica-manage connect '${peer}' '${valid_peer}'":
logoutput => on_failure,
onlyif => "${::ipa::common::ipa_installed}",
unless => "/usr/sbin/ipa-replica-manage list '${peer}' | /bin/awk -F ':' '{print \$1}' | /bin/grep -qxF '${valid_peer}'",
timeout => 900, # hope it doesn't take more than 15 min
before => Exec['ipa-clean-peers'], # try to connect first!
require => [
Exec['ipa-install'], # show for readability!
Exec['ipa-server-kinit'], # needs auth to work...
],
# NOTE: these two aliases can be used to prevent reverse dupes!
# NOTE: remove these if FreeIPA ever supports unidirectionality
alias => [
"${peer} -> ${valid_peer}",
"${valid_peer} -> ${peer}",
],
}
}

# vim: ts=8
97 changes: 97 additions & 0 deletions manifests/server/replica/manage/base.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# FreeIPA templating module by James
# Copyright (C) 2012-2013+ James Shubin
# Written by James Shubin <james@shubin.ca>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

class ipa::server::replica::manage::base {
include ipa::server
include ipa::vardir
#$vardir = $::ipa::vardir::module_vardir # with trailing slash
$vardir = regsubst($::ipa::vardir::module_vardir, '\/$', '')

# TODO: do we need this extra nesting here, or should we use it below ?
file { "${vardir}/replica/manage/":
ensure => directory, # make sure this is a directory
recurse => true, # recursively manage directory
purge => true, # purge all unmanaged files
force => true, # also purge subdirs and links
owner => root, group => nobody, mode => 600, backup => false,
require => File["${vardir}/replica/"],
}

# since we don't want to purge them, we need to exclude them...
$peer_always_ignore = ["${::fqdn}"] # never try and purge yourself!
$peer_excludes = $ipa::server::peer_excludes
$valid_peer_excludes = type($peer_excludes) ? {
'string' => [$peer_excludes],
'array' => $peer_excludes,
'boolean' => $peer_excludes ? {
# TODO: there's probably a better peer match expression
# this is an expression to prevent all peer deletion...
#true => ['^[a-zA-Z0-9]*$'],
true => ['^[[:alpha:]]{1}[[:alnum:]]*$'],
default => false,
},
default => false, # trigger error...
}

if type($valid_peer_excludes) != 'array' {
fail('The $peer_excludes must be an array.')
}

# directory of system tags which should exist (as managed by puppet)
file { "${vardir}/replica/manage/peers/":
ensure => directory, # make sure this is a directory
recurse => true, # recursively manage directory
purge => true, # purge all unmanaged files
force => true, # also purge subdirs and links
owner => root, group => nobody, mode => 600, backup => false,
notify => Exec['ipa-clean-peers'],
require => File["${vardir}/replica/manage/"],
}

# these are template variables for the clean.sh.erb script
$id_dir = 'replica/manage/peers'
$ls_cmd = "/usr/sbin/ipa-replica-manage list '${::fqdn}'" # show ipa peers
$rm_cmd = "/usr/sbin/ipa-replica-manage disconnect '${::fqdn}' " # disconnect ipa peers
$fs_chr = ':' # remove the ':replica' suffix
$suffix = '.peer'
$regexp = $valid_peer_excludes
$ignore = $peer_always_ignore

# build the clean script
file { "${vardir}/clean-peers.sh":
content => template('ipa/clean.sh.erb'),
owner => root,
group => nobody,
mode => 700, # u=rwx
backup => false, # don't backup to filebucket
ensure => present,
require => File["${vardir}/"],
}

# run the cleanup
exec { "${vardir}/clean-peers.sh":
logoutput => on_failure,
refreshonly => true,
require => [
Exec['ipa-server-kinit'],
File["${vardir}/clean-peers.sh"],
],
alias => 'ipa-clean-peers',
}
}

# vim: ts=8

0 comments on commit 73712d1

Please sign in to comment.