summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cdr1.sunet.se/overlay/etc/network/interfaces52
-rw-r--r--fabfile/__init__.py2
-rw-r--r--global/overlay/etc/cosmos/keys/ft-505152DD.pub88
-rw-r--r--global/overlay/etc/cosmos/keys/swold-BD115DD6.pub65
-rw-r--r--global/overlay/etc/cron.d/cosmos2
-rwxr-xr-xglobal/overlay/etc/cron.daily/scriptherder_cleanup10
-rw-r--r--global/overlay/etc/puppet/cosmos-modules.conf1
-rw-r--r--global/overlay/etc/puppet/facter/cosmos.rb22
-rw-r--r--global/overlay/etc/puppet/hiera.yaml14
-rw-r--r--global/overlay/etc/puppet/manifests/cosmos-site.pp150
-rw-r--r--global/overlay/etc/puppet/modules/sunet/manifests/server.pp47
-rw-r--r--global/overlay/etc/puppet/puppet.conf4
-rw-r--r--global/overlay/etc/scriptherder/check/cosmos.ini3
-rwxr-xr-xglobal/overlay/usr/local/bin/scriptherder302
-rwxr-xr-xglobal/post-tasks.d/015cosmos-trust7
15 files changed, 540 insertions, 229 deletions
diff --git a/cdr1.sunet.se/overlay/etc/network/interfaces b/cdr1.sunet.se/overlay/etc/network/interfaces
index 7475c35..edcc8fd 100644
--- a/cdr1.sunet.se/overlay/etc/network/interfaces
+++ b/cdr1.sunet.se/overlay/etc/network/interfaces
@@ -22,40 +22,42 @@
auto lo
iface lo inet loopback
-auto eth0
-iface eth0 inet manual
-bond-master bond0
-bond-primary eth0
+auto em1
+iface em1 inet manual
+ bond-master bond0
+ bond-primary em1
-auto eth1
-iface eth1 inet manual
-bond-master bond0
+auto em2
+iface em2 inet manual
+ bond-master bond0
# bond0 is the bonding NIC and can be used like any other normal NIC.
auto bond0
-iface bond0 inet static
- address 130.242.125.70
- netmask 255.255.255.192
- network 130.242.125.64
- broadcast 130.242.125.127
- gateway 130.242.125.65
- # dns-* options are implemented by the resolvconf package, if installed
- dns-nameservers 130.242.80.14 130.242.80.99
- dns-search sunet.se
- bond-mode active-backup
- bond-miimon 100
- bond-slaves none
-
-iface bond0 inet6 static
- address 2001:6b0:8:4::70
- netmask 64
- gateway 2001:6b0:8:4::1
+iface bond0 inet manual
+ bond-mode active-backup
+ bond-miimon 100
+ bond-slaves none
# Bridge interface for KVM guests
auto br0
-iface br0 inet dhcp
+iface br0 inet static
pre-up sleep 4 # must make br0 start _after_ bond0 is configured
bridge_ports bond0
bridge_stp off
bridge_fd 0
bridge_maxwait 0
+ #
+ address 130.242.125.70
+ netmask 255.255.255.192
+ network 130.242.125.64
+ broadcast 130.242.125.127
+ gateway 130.242.125.65
+ # dns-* options are implemented by the resolvconf package, if installed
+ dns-nameservers 130.242.80.14 130.242.80.99
+ dns-search sunet.se
+
+iface br0 inet6 static
+ pre-up sleep 4 # must make br0 start _after_ bond0 is configured
+ address 2001:6b0:8:4::70
+ netmask 64
+ gateway 2001:6b0:8:4::1
diff --git a/fabfile/__init__.py b/fabfile/__init__.py
index d87fbdd..3933104 100644
--- a/fabfile/__init__.py
+++ b/fabfile/__init__.py
@@ -17,7 +17,7 @@ def all():
env.hosts = cosmos_db()['members']['all']
def cosmos():
- run("cosmos update ; cosmos -v apply");
+ run("/usr/local/bin/run-cosmos -v");
def upgrade():
run("apt-get -qq update && apt-get -y -q dist-upgrade");
diff --git a/global/overlay/etc/cosmos/keys/ft-505152DD.pub b/global/overlay/etc/cosmos/keys/ft-505152DD.pub
index 092b32e..433fd6d 100644
--- a/global/overlay/etc/cosmos/keys/ft-505152DD.pub
+++ b/global/overlay/etc/cosmos/keys/ft-505152DD.pub
@@ -1,5 +1,5 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v1.4.14 (GNU/Linux)
+Version: GnuPG v1
mQENBFJB3u8BCADKh5OKbT0QJGM9e5ZNaQ1D5nICfM2u9S4x/iBsIsCt7W7h022j
hkW0AKFEhqUixLzl9TgjAMawW3V+59C/FkGWdvyGtOLu90tnjLXhFFc/wG5kv7Fq
@@ -8,13 +8,13 @@ s8CiC82VftOr/QWKNys+kTGMgv0rpBgZ0ZmNe4qKTBKrVlzESMD/bWOVga70Rfsp
MRY0cKK/V6gUDvaGtivg06SJNJzup8XzLYIclgwU3+U7c7YlseH7sUQlMUJ+Q2ij
c+P3EkLNU2IOrJ/m9QwHl2EYG0GDaKz5IQGZABEBAAG0I0ZyZWRyaWsgVGh1bGlu
IDxmcmVkcmlrQHRodWxpbi5uZXQ+iQE+BBMBCgAoAhsDBgsJCAcDAgYVCAIJCgsE
-FgIDAQIeAQIXgAUCUqc44gUJAVKn6wAKCRAZjBr9UFFS3SU6B/482umbN+mjTtZT
-RV8kqwvEawr5MP92sF5FNfgYmo4MVmUbyY/i7jrXEXKR4SlQIfE0eIxBqAFXJVdU
-ZF8tyNay85tZXuZ+pFbIPUMLadnq54HY6QrMXiFR45Q+fNNCluLqDB+p0ANmL4nO
-kboJnUGsm/c87gLuUda1Eo4S0opvYkTy7OmSh4PMAEZxObjU82svaD4eoqLbllF0
-8vAz/KoCScMQ+YqUhvCAhkxE8oHlvPLfo3VYkF0Gy8ofaj3cE68KUdXhlfdRizMn
-jXJDXuVNMmUojEM6u1j2tRObeUoITnPZRs7PID/wLnhG66WcF7CyGyjQbQX7VNck
-VYn7hMaZiQEcBBABCgAGBQJSQ+AeAAoJEE7yk05OqkIyTswH/jmbf6BKVwhpYNZz
+FgIDAQIeAQIXgAUCU4LqJwUJAi5ZNQAKCRAZjBr9UFFS3Q7UCACOApsR4fqVXcZF
+49df+DxlGXLLzjiIL9dezduTcFqGAxFUCqC/hnw26UKmvUTshYvnUC336FCdg2u7
+oOxIE+u9+In3M8sqnNWax0lBG/Y3Gmk4YwJH1cL1phXwFDh4xU2xrGPS1hkVOtUO
+l8GEB+v+l9P/WgMMPbdNQr/J4UnlZ7jZpeE7QadbvCE7q1U1Rw9wYG9o5c/BzQ/X
+htQz/oedmZlyyftHppAL3jGjNWnSWf042hn9nFsPLpJjEXWy+XVo0pQOBfitt+Oj
+sap1DEyuAFqEwbVIQyGCTyXIwo88VnLxZ6EkR9VvX3RnccVr03izqk1JoULkmLh9
+USHxrBtCiQEcBBABCgAGBQJSQ+AeAAoJEE7yk05OqkIyTswH/jmbf6BKVwhpYNZz
S/nlKGIhf0R0g4LPPOep25EwJfmUk54Mvi48/TBdZ9cy5Kwj3nlTXvviC72c7KvI
ViZuZwO+jv0JOr2H5+xtT2zfWOeYFK0vlHPk1dUI++h84bnM/DCyGWdP6My1leRN
VRySQI9E4NfHI03EN8fhoSKwHXfwrZOu5O8/8t4odJjo9IhnRiPvqFDqfbKDby+X
@@ -75,30 +75,50 @@ JpT4fGGkFAfltEZLvU2i7PfjVAFLYlNpHAo++7Ihpk/mtIYuNp2Jc3On1XGDCOY+
FTHNrkzF4zaU1eqJCzBC3UVu9oc28Ztsqf1OKr/hFRzL+uoxDnFYOspOtuIigDs5
lvXYbMbiIn6CyhvDhLXmODHvYk1O2qN9ZzVQZ+xTpJHSD3WUMNa0cPfln/2banqZ
Njoa684QCdPx5v1ut3YXlNzsbvZzqWicFXOSncqWGBlF8AYZdisgF3oUWcZ5UU9m
-m/xFOH2iKSgx95LT2KGPpt6Hrf99MeYQPrBDufyinsrnPqzwACaMqMxMiI6tuQEN
-BFJB3u8BCADcdMuW3XLX+TBrZj2Kg9j7TOgRJZFSDSl8yDdzk3/nZKa41TjBnWf/
-gU6mqpPmZ5idSQ7DnFWg7bZOV/NF0Be6IRVn/P6NOyJTEAPGQOg6oH+TTidasBlu
-i46g2j6vHqJc2dKHMeGZyes2sEMv0M33wIGFfYSqm19FXlNJftH/ceA4ETbdBPtP
-EvaYhVNHwTrg2YlZX027m69BeeDp6U3OnX3OFPrnloPof4gEVUKr+mqPb2DAdPAg
-jlJS+q1GjzGoldSdZbbztJLwEPBun89xK0a/SY+fjVvBVSIciOVHdTvkF2VmQRZ+
-yshdoH1DKFMit9O9wiHPH4T5GmH0sxGZABEBAAGJASUEGAEKAA8CGwwFAlKnORoF
-CQFSqCgACgkQGYwa/VBRUt0ryggAhYsqnDY5BU/kadgYTAjnzxDK+HyXqZiPHpbC
-LOwB/8v7YSmiCnQaeGNcOkd/Cp23nBhkCbYyHxRU5iok6qqVe3zaHCQ7PM9wwJeO
-T0HK6TmGn05PXjMAlbseBWAeGA93Jl9dVRJWF4yUY5esw226mSsEtZgZjFSy51Gd
-HRFsqL2UJjyVZQL46pizex0BK/XaKcaeAMPpbkXTEaJGwf2rFOSQLz9EmIqZVZZX
-B9+SatOq2pfHM9Kc4SOl/Bz7m8rPuWOn13v8g2NgZN6dqxT00kKy2Vhnh+bZP9iX
-/DUbuBYo1sbFae1gJO55A9KdWys1iXX5F5N7G5QCLCCIMgBvZLkBDQRSQylwAQgA
-p7JEaTcViRP2IA0d6OrDFsMJm1CfH9kiWtIB3xzPn3McQts0Dff/ZqiUsUtRPUHX
-rkW2x6WMRFLR6F9L0q5omv1QCw4kADKbOdUQaqumJa2Krz/0W9IWdGeP2II06LC3
-btT3k84oepsG8jTRdPoGPfOyIN9al0MrTRfvRtaEmPXYAQKudpbte9EF00cLpuAe
-hoeP6QpzOscfu52NqKpYL5dsGB1QDid/Vva+MvZAYXFbOdV7yamHoY2qMimH9fj8
-wNBbL4SZGbhusLOXhBkgfdJQMyhshWV3nbzi5pxZqgK2qC3rimoxyBSQ3yjXxx22
-KZ/BESH1Vuup26pVxTtoNwARAQABiQElBBgBCgAPAhsgBQJSpzkpBQkBUV2zAAoJ
-EBmMGv1QUVLdKGQH/Ar8l3+ViR0XMYCMt9GFnP/+7zYfUdqYBvgp0FxIRkxqY0Se
-6ehVgjBZv91Vzha1zno+Ei6unp9ntP0FY9ftwLpqX/VJseG2DO834N9o7q02cgIf
-pHJ2nwmnhndMeIy+vhrTzEzv/3cPb6EUOLApbULpJYoNLvbrrgmVrJN81ryKPybs
-rcbUWosHxovXADuokvYTH2M8H47tSX0f+W//kDhhXWlQW/WUucYxMDY8Hw1xJWQa
-rBMjA6cT3s4EZ2D0H09UeQEysKYWFprKud2Iy54Gq7242adDH/zNDV/weuBdPlnm
-EuQYOGdfxTfFw/MRvkm8MVehOCu/MvEGqzeCC9E=
-=T6TK
+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
+=yrrA
-----END PGP PUBLIC KEY BLOCK-----
diff --git a/global/overlay/etc/cosmos/keys/swold-BD115DD6.pub b/global/overlay/etc/cosmos/keys/swold-BD115DD6.pub
deleted file mode 100644
index ecc5c8c..0000000
--- a/global/overlay/etc/cosmos/keys/swold-BD115DD6.pub
+++ /dev/null
@@ -1,65 +0,0 @@
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v1.4.12 (GNU/Linux)
-
-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
-=iEp/
------END PGP PUBLIC KEY BLOCK-----
diff --git a/global/overlay/etc/cron.d/cosmos b/global/overlay/etc/cron.d/cosmos
index 70af3a4..58b45af 100644
--- a/global/overlay/etc/cron.d/cosmos
+++ b/global/overlay/etc/cron.d/cosmos
@@ -1,4 +1,4 @@
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
-*/15 * * * * root test -f /etc/no-automatic-cosmos || (cosmos update ; cosmos apply)
+*/15 * * * * root test -f /etc/no-automatic-cosmos || scriptherder --mode wrap --syslog --name cosmos -- /usr/local/bin/run-cosmos -v
diff --git a/global/overlay/etc/cron.daily/scriptherder_cleanup b/global/overlay/etc/cron.daily/scriptherder_cleanup
new file mode 100755
index 0000000..08ec7f5
--- /dev/null
+++ b/global/overlay/etc/cron.daily/scriptherder_cleanup
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Remove scriptherder data older than 7 days.
+#
+
+DIR="/var/cache/scriptherder/"
+
+test -d ${DIR} || exit 0
+
+find ${DIR} -type f -mtime +7 -print0 | xargs -0 rm -f
diff --git a/global/overlay/etc/puppet/cosmos-modules.conf b/global/overlay/etc/puppet/cosmos-modules.conf
index 7a95b31..bde1b61 100644
--- a/global/overlay/etc/puppet/cosmos-modules.conf
+++ b/global/overlay/etc/puppet/cosmos-modules.conf
@@ -22,3 +22,4 @@ mysql puppetlabs/mysql no
apache puppetlabs/apache no
pyff git://github.com/samlbits/puppet-pyff.git yes sunet-*
postgresql git://github.com/SUNET/puppetlabs-postgresql.git yes sunet-*
+dhcp git://github.com/SUNET/puppetlabs-dhcp.git yes sunet-*
diff --git a/global/overlay/etc/puppet/facter/cosmos.rb b/global/overlay/etc/puppet/facter/cosmos.rb
new file mode 100644
index 0000000..d810082
--- /dev/null
+++ b/global/overlay/etc/puppet/facter/cosmos.rb
@@ -0,0 +1,22 @@
+#
+# Extract local Cosmos configuration
+#
+require 'facter'
+Facter.add(:cosmos_repo) do
+ setcode do
+ Facter::Util::Resolution.exec("sh -c '. /etc/cosmos/cosmos.conf && echo $COSMOS_REPO'")
+ end
+end
+
+Facter.add(:cosmos_tag_pattern) do
+ setcode do
+ Facter::Util::Resolution.exec("sh -c '. /etc/cosmos/cosmos.conf && echo $COSMOS_UPDATE_VERIFY_GIT_TAG_PATTERN'")
+ end
+end
+
+Facter.add(:cosmos_repo_origin_url) do
+ setcode do
+ Facter::Util::Resolution.exec("sh -c '. /etc/cosmos/cosmos.conf && cd $COSMOS_REPO && git remote show -n origin | grep \"Fetch URL\" | awk \"{print \\$NF }\"'")
+ end
+end
+
diff --git a/global/overlay/etc/puppet/hiera.yaml b/global/overlay/etc/puppet/hiera.yaml
index cd619bb..782fa7f 100644
--- a/global/overlay/etc/puppet/hiera.yaml
+++ b/global/overlay/etc/puppet/hiera.yaml
@@ -1,13 +1,15 @@
---
-:backends: - yaml
- - gpg
+:backends:
+ - yaml
+ - gpg
:logger: console
-:hierarchy: - %{env}/%{location}/%{calling_module}
- - %{env}/%{calling_module}
- - secrets.yaml
- - common
+:hierarchy:
+ - "%{env}/%{location}/%{calling_module}"
+ - "%{env}/%{calling_module}"
+ - secrets.yaml
+ - common
:yaml:
diff --git a/global/overlay/etc/puppet/manifests/cosmos-site.pp b/global/overlay/etc/puppet/manifests/cosmos-site.pp
index 34ff4cb..8835226 100644
--- a/global/overlay/etc/puppet/manifests/cosmos-site.pp
+++ b/global/overlay/etc/puppet/manifests/cosmos-site.pp
@@ -44,11 +44,11 @@ node default {
node 'sto-tug-kvm1.swamid.se' {
-
+
package {'python-vm-builder':
ensure => 'installed',
- } ->
-
+ } ->
+
cosmos::dhcp_kvm { 'registry.swamid.se':
mac => '52:54:00:52:53:0b',
repo => 'git://git.nordu.net/sunet-ops.git',
@@ -286,36 +286,100 @@ class sunet-dhcp-hosts {
# eduID Development subnets
- dhcp::pool {'eduid-tug-dev':
- network => '194.68.13.128',
- mask => '255.255.255.224',
- gateway => '194.68.13.129',
- range => '',
- options => 'domain-name-servers 109.105.111.31, 109.105.110.31',
- }
+ #dhcp::pool {'eduid-tug-dev':
+ # network => '194.68.13.128',
+ # mask => '255.255.255.224',
+ # gateway => '194.68.13.129',
+ # range => '',
+ # options => 'domain-name-servers 109.105.111.31, 109.105.110.31',
+ #}
- dhcp::pool {'eduid-fre-dev':
- network => '194.68.13.160',
- mask => '255.255.255.224',
- gateway => '194.68.13.161',
- range => '',
- options => 'domain-name-servers 109.105.111.31, 109.105.110.31',
+ #dhcp::pool {'eduid-fre-dev':
+ # network => '194.68.13.160',
+ # mask => '255.255.255.224',
+ # gateway => '194.68.13.161',
+ # range => '',
+ # options => 'domain-name-servers 109.105.111.31, 109.105.110.31',
+ #}
+
+ dhcp::pool {'eduid-dev-tug':
+ network => '130.242.130.192',
+ mask => '255.255.255.224',
+ gateway => '130.242.130.193',
+ range => ''
}
+ # One big subnet used for now
+ #dhcp::pool {'eduid-dev-tug-IdP':
+ # network => '130.242.130.192',
+ # mask => '255.255.255.248',
+ # gateway => '130.242.130.201',
+ # range => ''
+ #}
+
+ # One big subnet used for now
+ #dhcp::pool {'eduid-dev-tug-auth':
+ # network => '130.242.130.200',
+ # mask => '255.255.255.248',
+ # gateway => '130.242.130.201',
+ # range => ''
+ #}
+
+ # One big subnet used for now
+ #dhcp::pool {'eduid-dev-tug-other':
+ # network => '130.242.130.208',
+ # mask => '255.255.255.240',
+ # gateway => '130.242.130.209',
+ # range => ''
+ #}
+
# eduID TUG development hosts
- dhcp::host { 'idp-tug-1': mac => "52:54:00:a0:00:92", ip => "194.68.13.146" }
+ dhcp::host { 'worker-fre-1': mac => "52:54:00:a0:01:c4", ip => "130.242.130.196" }
+
+ dhcp::host { 'auth-fre-1_eth0': mac => "78:45:c4:f7:91:67", ip => "130.242.130.204", hostname => 'auth-fre-1'; }
+ dhcp::host { 'auth-fre-1_eth1': mac => "78:45:c4:f7:91:68", ip => "130.242.130.204", hostname => 'auth-fre-1'; }
+
+ dhcp::host { 'auth-tug-1_eth0': mac => "78:45:c4:f8:43:c5", ip => "130.242.130.205", hostname => 'auth-tug-1'; }
+ dhcp::host { 'auth-tug-1_eth1': mac => "78:45:c4:f8:43:c6", ip => "130.242.130.205", hostname => 'auth-tug-1'; }
+
+ dhcp::host { 'admin-tug-1': mac => "52:54:00:a0:01:d4", ip => "130.242.130.212" }
+
+ dhcp::host { 'dash-fre-1': mac => "52:54:00:a0:01:d5", ip => "130.242.130.213" }
+
+ dhcp::host { 'idp-fre-1': mac => "52:54:00:a0:01:d6", ip => "130.242.130.214" }
+
+ dhcp::host { 'idp-tug-1': mac => "52:54:00:a0:01:d7", ip => "130.242.130.215" }
+
+ dhcp::host { 'kvm-fre-1_eth0': mac => "78:45:c4:f8:45:15", ip => "130.242.130.216", hostname => 'kvm-fre-1'; }
+ dhcp::host { 'kvm-fre-1_eth1': mac => "78:45:c4:f8:45:16", ip => "130.242.130.216", hostname => 'kvm-fre-1'; }
+
+ dhcp::host { 'kvm-tug-1_eth0': mac => "78:45:c4:f8:47:be", ip => "130.242.130.217", hostname => 'kvm-tug-1'; }
+ dhcp::host { 'kvm-tug-1_eth1': mac => "78:45:c4:f8:47:bf", ip => "130.242.130.217", hostname => 'kvm-tug-1'; }
+
+ dhcp::host { 'monitor-fre-1': mac => "52:54:00:a0:01:da", ip => "130.242.130.218" }
- dhcp::host { 'testvm-tug-1': mac => "52:54:00:11:22:33", ip => "194.68.13.136" }
+ dhcp::host { 'mq-fre-1': mac => "52:54:00:a0:01:db", ip => "130.242.130.219" }
- dhcp::host { 'userdb-tug-1': mac => "52:54:00:93:22:29", ip => "194.68.13.132" }
- dhcp::host { 'userdb-tug-2': mac => "52:54:00:17:13:ff", ip => "194.68.13.133" }
+ dhcp::host { 'userdb-fre-1': mac => "52:54:00:a0:01:dc", ip => "130.242.130.220" }
+
+ dhcp::host { 'userdb-tug-1': mac => "52:54:00:a0:01:dd", ip => "130.242.130.221" }
+
+ dhcp::host { 'userdb-tug-2': mac => "52:54:00:a0:01:de", ip => "130.242.130.222" }
+
+
+ #dhcp::host { 'idp-tug-1': mac => "52:54:00:a0:00:92", ip => "194.68.13.146" }
+
+ #dhcp::host { 'testvm-tug-1': mac => "52:54:00:11:22:33", ip => "194.68.13.136" }
+
+ #dhcp::host { 'userdb-tug-1': mac => "52:54:00:93:22:29", ip => "194.68.13.132" }
+ #dhcp::host { 'userdb-tug-2': mac => "52:54:00:17:13:ff", ip => "194.68.13.133" }
# eduID FRE development hosts
- dhcp::host { 'idp-fre-1': mac => "52:54:00:a1:00:b2", ip => "194.68.13.178" }
+ #dhcp::host { 'idp-fre-1': mac => "52:54:00:a1:00:b2", ip => "194.68.13.178" }
- dhcp::host { 'dash-fre-1': mac => "52:54:00:a2:00:a7", ip => "194.68.13.167" }
+ #dhcp::host { 'dash-fre-1': mac => "52:54:00:a2:00:a7", ip => "194.68.13.167" }
- dhcp::host { 'userdb-fre-1': mac => "52:54:00:17:13:f6", ip => "194.68.13.164" }
+ #dhcp::host { 'userdb-fre-1': mac => "52:54:00:17:13:f6", ip => "194.68.13.164" }
# SUNET TUG hosts
@@ -325,6 +389,10 @@ class sunet-dhcp-hosts {
dhcp::host { 'md-master.reep': mac => "52:54:00:39:8d:ac", ip => "130.242.125.83" }
dhcp::host { 'lobo2.lab': mac => "52:54:00:5e:72:91", ip => "130.242.125.86" }
+ # SUNET TUG eduID hosts (KVM host cdr1.sunet.se)
+ dhcp::host { 'backup-tug-3': mac => "52:54:00:f2:7d:54", ip => "130.242.125.84" }
+ dhcp::host { 'proxy-tug-3': mac => "52:54:00:f2:7d:55", ip => "130.242.125.85" }
+
# SWAMID production
dhcp::host { 'registry.swamid': mac => "52:54:00:52:53:0b", ip => "130.242.125.90" }
}
@@ -481,13 +549,47 @@ node 'wp.sunet.se' {
}
}
+node 'cdr1.sunet.se' {
+
+ package {'python-vm-builder':
+ ensure => 'installed',
+ } ->
+
+ cosmos::dhcp_kvm { 'backup-tug-3.eduid.se':
+ mac => '52:54:00:f2:7d:54',
+ repo => 'git://git.nordu.net/eduid-ops.git',
+ tagpattern => 'eduid-v3',
+ cpus => '1',
+ memory => '512',
+ suite => 'trusty',
+ extras => '--addpkg linux-image-generic --tmpfs -',
+ }
+
+ cosmos::dhcp_kvm { 'proxy-tug-3.eduid.se':
+ mac => '52:54:00:f2:7d:55',
+ repo => 'git://git.nordu.net/eduid-ops.git',
+ tagpattern => 'eduid-v3',
+ cpus => '1',
+ memory => '512',
+ suite => 'trusty',
+ extras => '--addpkg linux-image-generic --tmpfs -',
+ }
+
+}
+
class sunet-cdr {
+ # Listen on br0 if it exists (cdr1), otherwise bond0 (cdr2).
+ $interface = $::ipaddress_br0 ? {
+ undef => 'bond0',
+ default => 'br0',
+ }
+
class { 'dhcp':
dnsdomain => [ 'eduid.se','sunet.se','swamid.se' ],
nameservers => ['130.242.80.14','130.242.80.99'],
ntpservers => ['ntp1.nordu.net','ntp2.nordu.net','Time1.Stupi.SE'],
- interfaces => ['bond0'],
+ interfaces => [$interface],
#pxeserver => '130.242.125.5',
#pxefilename => 'pxelinux.0'
}
diff --git a/global/overlay/etc/puppet/modules/sunet/manifests/server.pp b/global/overlay/etc/puppet/modules/sunet/manifests/server.pp
index 875dc69..14df323 100644
--- a/global/overlay/etc/puppet/modules/sunet/manifests/server.pp
+++ b/global/overlay/etc/puppet/modules/sunet/manifests/server.pp
@@ -37,4 +37,51 @@ define sunet::server() {
notify => Service['ssh'],
}
+ # already declared in puppet-cosmos/manifests/ntp.pp
+ #service { 'ntp':
+ # ensure => 'running',
+ #}
+
+ # Don't use pool.ntp.org servers, but rather DHCP provided NTP servers
+ line { 'no_pool_ntp_org_servers':
+ file => '/etc/ntp.conf',
+ line => '^server .*\.pool\.ntp\.org',
+ ensure => 'comment',
+ notify => Service['ntp'],
+ }
+
+ file { '/var/cache/scriptherder':
+ ensure => 'directory',
+ path => '/var/cache/scriptherder',
+ mode => '1777', # like /tmp, so user-cronjobs can also use scriptherder
+ }
+
+
+}
+
+# from http://projects.puppetlabs.com/projects/puppet/wiki/Simple_Text_Patterns/5
+define line($file, $line, $ensure = 'present') {
+ case $ensure {
+ default : { err ( "unknown ensure value ${ensure}" ) }
+ present: {
+ exec { "/bin/echo '${line}' >> '${file}'":
+ unless => "/bin/grep -qFx '${line}' '${file}'"
+ }
+ }
+ absent: {
+ exec { "/usr/bin/perl -ni -e 'print unless /^\\Q${line}\\E\$/' '${file}'":
+ onlyif => "/bin/grep -qFx '${line}' '${file}'"
+ }
+ }
+ uncomment: {
+ exec { "/bin/sed -i -e'/${line}/s/^#\\+//' '${file}'":
+ onlyif => "/bin/grep '${line}' '${file}' | /bin/grep '^#' | /usr/bin/wc -l"
+ }
+ }
+ comment: {
+ exec { "/bin/sed -i -e'/${line}/s/^\\(.\\+\\)$/#\\1/' '${file}'":
+ onlyif => "/usr/bin/test `/bin/grep '${line}' '${file}' | /bin/grep -v '^#' | /usr/bin/wc -l` -ne 0"
+ }
+ }
+ }
}
diff --git a/global/overlay/etc/puppet/puppet.conf b/global/overlay/etc/puppet/puppet.conf
index a269892..96f7b44 100644
--- a/global/overlay/etc/puppet/puppet.conf
+++ b/global/overlay/etc/puppet/puppet.conf
@@ -3,7 +3,9 @@ logdir=/var/log/puppet
vardir=/var/lib/puppet
ssldir=/var/lib/puppet/ssl
rundir=/var/run/puppet
-factpath=$vardir/lib/facter
+# factpath is supposed to be colon-delimeted, but that does not appear to work
+# (tested with 'strace -f facter --puppet something' - does not split on colon in Puppet 3.4.2).
+factpath=/etc/puppet/facter
templatedir=$confdir/templates
node_terminus = exec
external_nodes = /etc/puppet/cosmos_enc.py
diff --git a/global/overlay/etc/scriptherder/check/cosmos.ini b/global/overlay/etc/scriptherder/check/cosmos.ini
new file mode 100644
index 0000000..b44a537
--- /dev/null
+++ b/global/overlay/etc/scriptherder/check/cosmos.ini
@@ -0,0 +1,3 @@
+[check]
+ok = exit_status=0, max_age=35m
+warning = exit_status=0, max_age=1h
diff --git a/global/overlay/usr/local/bin/scriptherder b/global/overlay/usr/local/bin/scriptherder
index c11383a..1e00ec0 100755
--- a/global/overlay/usr/local/bin/scriptherder
+++ b/global/overlay/usr/local/bin/scriptherder
@@ -68,6 +68,28 @@ exit_status = {'OK': 0,
}
+class ScriptHerderError(Exception):
+ """
+ Base exception class for scriptherder.
+ """
+
+ def __init__(self, reason, filename):
+ self.reason = reason
+ self.filename = filename
+
+
+class JobLoadError(ScriptHerderError):
+ """
+ Raised when loading a job file fails.
+ """
+
+
+class CheckLoadError(ScriptHerderError):
+ """
+ Raised when loading a check file fails.
+ """
+
+
class Job(object):
"""
Representation of an execution of a job.
@@ -109,6 +131,21 @@ class Job(object):
exit = self.exit_status,
)
+ def status_summary(self):
+ """
+ Return short string with status of job.
+
+ E.g. 'name[exit=0,age=19h]'
+ """
+ if self._end_time is None or self._start_time is None:
+ return '{name}[not_running]'.format(name = self.name)
+ age = _time_to_str(time.time() - self._start_time)
+ return '{name}[exit={exit_status},age={age}]'.format(
+ name = self.name,
+ exit_status = self._exit_status,
+ age = age,
+ )
+
@property
def name(self):
"""
@@ -167,11 +204,10 @@ class Job(object):
@rtype: string
"""
+ if self._end_time is None or self._start_time is None:
+ return 'NaN'
duration = self._end_time - self._start_time
- if duration < 1:
- # milliseconds
- return '{:0.3f}ms'.format(duration * 1000)
- return '{:0.3f}s'.format(duration)
+ return _time_to_str(duration)
@property
def exit_status(self):
@@ -326,7 +362,7 @@ class Job(object):
#self._output_size = data.get('output_size') # currently not used in scriptherder
self._filename = filename
else:
- raise AssertionError('Unknown version in file {!r}: {!r}'.format(filename, data.get('version')))
+ raise JobLoadError('Unknown version: {!r}'.format(data.get('version')), filename=filename)
return self
@@ -355,7 +391,7 @@ class Check(object):
self.logger = logger
self.config = ConfigParser.ConfigParser(_check_defaults)
if not self.config.read([filename]):
- raise ValueError("Failed loading config file {!r}".format(filename))
+ raise ScriptHerderError('Failed loading config file', filename)
_section = 'check'
self._ok_criteria = [x.strip() for x in self.config.get(_section, 'ok').split(',')]
self._warning_criteria = [x.strip() for x in self.config.get(_section, 'warning').split(',')]
@@ -422,6 +458,130 @@ class Check(object):
return False
+class CheckStatus(object):
+ """
+ Aggregated status of job invocations for --mode check.
+
+ Attributes:
+
+ checks_ok: List of checks in OK state ([Job()]).
+ checks_warning: List of checks in WARNING state ([Job()]).
+ checks_critical: List of checks in CRITICAL state ([Job()]).
+ """
+
+ def __init__(self, args, logger):
+ """
+ @param args: Parsed command line arguments
+ @param logger: logging logger
+ """
+
+ self.checks_ok = []
+ self.checks_warning = []
+ self.checks_critical = []
+
+ self._jobs = _get_job_results(args, logger)
+ # group the jobs by their name
+ _by_name = {}
+ for this in self._jobs:
+ if this.name not in _by_name:
+ _by_name[this.name] = []
+ _by_name[this.name].append(this)
+ self._jobs_by_name = _by_name
+
+ self._job_count = len(_by_name)
+
+ self._check_running_jobs(args, logger)
+ if not args.cmd:
+ self._check_not_running(args, logger)
+
+ def _check_running_jobs(self, args, logger):
+ """
+ Look for job execution entrys (parsed into Job() instances), group them
+ per check name and determine the status. For each group, append status
+ to one of the three aggregate status lists of this object (checks_ok,
+ checks_warning or checks_critical).
+
+ @param args: Parsed command line arguments
+ @param logger: logging logger
+ """
+ # determine total check status based on all logged invocations of this job
+ for (name, jobs) in self._jobs_by_name.items():
+ # Load the evaluation criterias for this job
+ check_filename = os.path.join(args.checkdir, name + '.ini')
+ logger.debug("Loading check definition from {!r}".format(check_filename))
+ try:
+ check = Check(check_filename, logger)
+ except ScriptHerderError as exc:
+ logger.warning("Failed loading check: {!r}".format(exc), exc_info=True)
+ raise CheckLoadError('Failed loading check', filename = check_filename)
+
+ # Sort jobs, oldest first
+ jobs = sorted(jobs, key=lambda x: x.start_time)
+ logger.debug("Checking {!r}: {!r}".format(name, jobs))
+
+ jobs_ok = []
+ jobs_warning = []
+ jobs_critical = []
+ for job in jobs:
+ if check.job_is_ok(job):
+ jobs_ok.append(job)
+ elif check.job_is_warning(job):
+ jobs_warning.append(job)
+ else:
+ jobs_critical.append(job)
+
+ logger.debug("Raw status OK : {!r}".format(jobs_ok))
+ logger.debug("Raw status WARN : {!r}".format(jobs_warning))
+ logger.debug("Raw status CRITICAL: {!r}".format(jobs_critical))
+
+ # add most recent job status to the totals
+ if jobs_ok:
+ self.checks_ok.append(jobs_ok[-1])
+ elif jobs_warning:
+ self.checks_warning.append(jobs_warning[-1])
+ else:
+ self.checks_critical.append(jobs_critical[-1])
+
+ def _check_not_running(self, args, logger):
+ """
+ Look for job execution entrys (parsed into Job() instances), group them
+ per check name and determine the status. For each group, append status
+ to one of the three aggregate status lists of this object (checks_ok,
+ checks_warning or checks_critical).
+
+ @param args: Parsed command line arguments
+ @param logger: logging logger
+ """
+ files = [f for f in os.listdir(args.checkdir) if os.path.isfile(os.path.join(args.checkdir, f))]
+ for this in files:
+ if not this.endswith('.ini'):
+ continue
+ filename = os.path.join(args.checkdir, this)
+ logger.debug("Loading check definition from {!r}".format(filename))
+ try:
+ # validate check loads
+ Check(filename, logger)
+ except ValueError as exc:
+ logger.warning("Failed loading check: {!r}".format(exc), exc_info=True)
+ raise CheckLoadError(filename = filename)
+ name = this[:-4] # remove the '.ini' suffix
+ if name not in self._jobs_by_name:
+ logger.debug('Check {!r} (filename {!r}) not found in jobs'.format(name, filename))
+ job = Job(name=name)
+ self.checks_critical.append(job)
+ self._job_count += 1
+ else:
+ logger.debug('Check {!r} has {!r} logged results'.format(name, len(self._jobs_by_name[name])))
+
+ def num_jobs(self):
+ """
+ Return number of jobs processed. This is number of different jobs running + not running.
+
+ @rtype: int
+ """
+ return self._job_count
+
+
def job_from_file(filename):
"""
Recreate Job() instance from saved file.
@@ -488,6 +648,7 @@ def parse_args(defaults):
)
args = parser.parse_args()
+
return args
@@ -537,88 +698,61 @@ def mode_check(args, logger):
@param args: Parsed command line arguments
@param logger: logging logger
"""
- jobs = _get_job_results(args, logger)
- # group the jobs by their name
- by_name = {}
- for this in jobs:
- if this.name not in by_name:
- by_name[this.name] = []
- by_name[this.name].append(this)
-
- total_ok = []
- total_warning = []
- total_critical = []
-
- # determine total check status based on all logged invocations of this job
- for (name, jobs) in by_name.items():
- # Sort jobs, oldest first
- jobs = sorted(jobs, key=lambda x: x.start_time)
- # Load the evaluation criterias for this job
- check_filename = os.path.join(args.checkdir, name + '.ini')
- logger.debug("Loading check definition from {!r}".format(check_filename))
- check = Check(check_filename, logger)
- logger.debug("Checking {!r}: {!r}".format(name, jobs))
-
- jobs_ok = []
- jobs_warning = []
- jobs_critical = []
- for job in jobs:
- if check.job_is_ok(job):
- jobs_ok.append(job)
- elif check.job_is_warning(job):
- jobs_warning.append(job)
- else:
- jobs_critical.append(job)
- logger.debug("Raw status OK : {!r}".format(jobs_ok))
- logger.debug("Raw status WARN : {!r}".format(jobs_warning))
- logger.debug("Raw status CRITICAL: {!r}".format(jobs_critical))
- if jobs_ok:
- total_ok.append(jobs_ok[-1])
- elif jobs_warning:
- total_warning.append(jobs_warning[-1])
- else:
- total_critical.append(jobs_critical[-1])
+ try:
+ status = CheckStatus(args, logger)
+ except CheckLoadError as exc:
+ print("UNKNOWN: Failed loading check from file '{!s}' ({!s})".format(exc.filename, exc.reason))
+ return exit_status['UNKNOWN']
if args.cmd:
# Single job check requested, output detailed information
- if total_ok:
- print('OK: {!s}'.format(total_ok[-1]))
+ if status.checks_ok:
+ print('OK: {!s}'.format(status.checks_ok[-1]))
return exit_status['OK']
- if total_warning:
- print('WARNING: {!s}'.format(total_warning[-1]))
+ if status.checks_warning:
+ print('WARNING: {!s}'.format(status.checks_warning[-1]))
return exit_status['WARNING']
- if total_critical:
- print('CRITICAL: {!s}'.format(total_critical[-1]))
+ if status.checks_critical:
+ print('CRITICAL: {!s}'.format(status.checks_critical[-1]))
return exit_status['CRITICAL']
print "UNKNOWN - no jobs found for {!r}?".format(args.cmd)
return exit_status['UNKNOWN']
- # When not looking at multiple jobs at once, logic gets a bit reversed - if ANY
+ # When looking at multiple jobs at once, logic gets a bit reversed - if ANY
# job invocation is CRITICAL/WARNING, the aggregate message given to
# Nagios will have to be a failure.
- if total_critical:
- print("CRITICAL: {num} job(s) in this state: {names}".format(
- num = len(total_critical),
- names = ', '.join([str(x.name) for x in total_critical]),
- ))
+ if status.checks_critical:
+ print('CRITICAL: {!s}'.format(
+ _status_summary(status.num_jobs(), status.checks_critical)))
return exit_status['CRITICAL']
- if total_warning:
- print("WARNING: {num} job(s) in this state: {names}".format(
- num = len(total_warning),
- names = ', '.join([str(x.name) for x in total_warning]),
- ))
+ if status.checks_warning:
+ print('WARNING: {!s}'.format(
+ _status_summary(status.num_jobs(), status.checks_warning)))
return exit_status['WARNING']
- if total_ok:
- print("OK: {num} job(s) in this state: {names}".format(
- num = len(total_ok),
- names = ', '.join([x.name for x in total_ok]),
- ))
+ if status.checks_ok:
+ print('OK: {!s}'.format(
+ _status_summary(status.num_jobs(), status.checks_ok)))
return exit_status['OK']
print "UNKNOWN - no jobs found?"
return exit_status['UNKNOWN']
+def _status_summary(num_jobs, failed):
+ """
+ String format routine used in output of checks status.
+ """
+ fmt = '1 job in this state: {summary}'
+ if len(failed) == 1:
+ fmt = '{jobs}/{num_jobs} job in this state: {summary}'
+
+ summary = ', '.join(sorted([str(x.status_summary()) for x in failed]))
+ return fmt.format(jobs = len(failed),
+ num_jobs = num_jobs,
+ summary = summary,
+ )
+
+
def _get_job_results(args, logger):
"""
Load all jobs matching any specified name on the command line.
@@ -634,7 +768,10 @@ def _get_job_results(args, logger):
if not this.endswith('.json'):
continue
filename = os.path.join(args.datadir, this)
- job = job_from_file(filename)
+ try:
+ job = job_from_file(filename)
+ except JobLoadError as exc:
+ logger.warning("Failed loading job file '{!s}' ({!s})".format(exc.filename, exc.reason))
if args.cmd:
if args.cmd[0] != job.name:
logger.debug("Skipping '{!s}' not matching '{!s}' (file {!s})".format(job.name, args.cmd[0], filename))
@@ -666,6 +803,27 @@ def _parse_time_value(value):
return num
+def _time_to_str(value):
+ """
+ Format number of seconds to short readable string.
+
+ @type value: float or int
+
+ @rtype: string
+ """
+ if value < 1:
+ # milliseconds
+ return '{:0.3f}ms'.format(value * 1000)
+ if value < 60:
+ return '{!s}s'.format(int(value))
+ if value < 3600:
+ return '{!s}m'.format(int(value))
+ if value < 86400:
+ return '{!s}h'.format(int(value / 3600))
+ days = int(value / 86400)
+ return '{!s}d{!s}h'.format(days, int((value % 86400) / 3600))
+
+
def main(myname = 'scriptherder', args = None, logger = None, defaults=_defaults):
"""
Main entry point for either wrapping a script, or checking the status of it.
@@ -699,6 +857,10 @@ def main(myname = 'scriptherder', args = None, logger = None, defaults=_defaults
syslog_h.setFormatter(formatter)
logger.addHandler(syslog_h)
+ if args.name and args.mode != 'wrap':
+ logger.error('Argument --name only applicable for --mode wrap')
+ return False
+
if args.mode == 'wrap':
return mode_wrap(args, logger)
elif args.mode == 'ls':
diff --git a/global/post-tasks.d/015cosmos-trust b/global/post-tasks.d/015cosmos-trust
index 447d875..5c3359b 100755
--- a/global/post-tasks.d/015cosmos-trust
+++ b/global/post-tasks.d/015cosmos-trust
@@ -4,12 +4,15 @@ if [ -z "$COSMOS_KEYS" ]; then
COSMOS_KEYS=/etc/cosmos/keys
fi
+# Install new keys discovered in the $COSMOS_KEYS directory
for k in $COSMOS_KEYS/*.pub; do
fp=`cosmos gpg --with-colons --with-fingerprint < $k| awk -F: '$1 == "pub" {print $5}'`
- cosmos gpg --with-colons --fingerprint | grep -q ":$fp:" || cosmos gpg --import < $k
+ # The removal of any ^pub:e: entrys means to ignore expired keys - thereby importing them again.
+ cosmos gpg --with-colons --fingerprint | grep -v "^pub:e:" | grep -q ":$fp:" || cosmos gpg --import < $k
done
-for fp in `cosmos gpg --with-colons --fingerprint | awk -F: '$1 == "pub" {print $5}'`; do
+# Delete keys no longer present in $COSMOS_KEYS directory
+for fp in `cosmos gpg --with-colons --fingerprint | awk -F: '$1 == "pub" {print $5 }'`; do
seen="no"
for k in $COSMOS_KEYS/*.pub; do
cosmos gpg --with-colons --with-fingerprint < $k | grep -q ":$fp:" && seen="yes"