Add a cron job to release AFS volumes

Every 5 minutes, check to see if the docs volumes have been updated,
and if so, release them.  This means we can serve the docs volumes
from replicated read-only volumes with only a 5 minute delay.

Since this does not coordinate with the docs publishing jobs, we
may end up releasing partial updates, however, those jobs, since they
use rsync, should tolerate this.

Change-Id: I082ae6f37af9a6e12ad62b0cc4cb45e631a0935b
This commit is contained in:
James E. Blair 2016-11-22 09:31:05 -08:00 committed by Andreas Jaeger
parent 7708794221
commit 3fc724a675
3 changed files with 137 additions and 0 deletions

View File

@ -1196,6 +1196,21 @@ node 'kdc02.openstack.org' {
} }
} }
# Node-OS: trusty
node afsdb01.openstack.org/ {
$group = "afsdb"
class { 'openstack_project::server':
iptables_public_udp_ports => [7000,7002,7003,7004,7005,7006,7007],
sysadmins => hiera('sysadmins', []),
afs => true,
manage_exim => true,
}
include openstack_project::afsdb
include openstack_project::afsrelease
}
# Node-OS: trusty # Node-OS: trusty
node /^afsdb.*\.openstack\.org$/ { node /^afsdb.*\.openstack\.org$/ {
$group = "afsdb" $group = "afsdb"

View File

@ -0,0 +1,78 @@
# Copyright 2016 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from datetime import datetime
import re
import subprocess
import logging
VOLUMES = ['docs',
'docs.dev',
]
log = logging.getLogger("release")
UPDATE_RE = re.compile("^\s+Last Update (.*)$")
def get_last_update(volume):
ret = []
out = subprocess.check_output(['vos', 'examine', volume, '-localauth'])
state = 0
for line in out.split('\n'):
if state == 0 and line.startswith(volume):
state = 1
site = None
elif state == 1:
site = line.strip()
state = 0
m = UPDATE_RE.match(line)
if m:
ret.append(dict(site=site,
volume=volume,
updated=datetime.strptime(m.group(1),
'%a %b %d %H:%M:%S %Y')))
return ret
def release(volume):
log.info("Releasing %s" % volume)
subprocess.check_output(['vos', 'release', volume, '-localauth'])
def check_release(volume):
log.info("Checking %s" % volume)
rw = get_last_update(volume)[0]
log.debug(" %s %s %s" % (rw['site'], rw['updated'], rw['volume']))
ros = get_last_update(volume + '.readonly')
update = False
for ro in ros:
log.debug(" %s %s %s" % (ro['site'], ro['updated'], ro['volume']))
if ro['updated'] < rw['updated']:
update = True
if update:
release(volume)
def main():
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)s '
'%(levelname)-8s %(message)s')
for volume in VOLUMES:
check_release(volume)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,44 @@
# Release afs volumes
class openstack_project::afsrelease (
) {
include logrotate
file { '/usr/local/bin/release-volumes':
ensure => present,
owner => 'root',
group => 'root',
mode => '0755',
source => 'puppet:///modules/openstack_project/openafs/release-volumes.py',
}
file { '/var/log/release':
ensure => directory,
owner => 'root',
group => 'root',
mode => '0755',
}
cron { 'release':
user => 'root',
minute => '*/5',
command => '/usr/local/bin/release-volumes >>/var/log/release/release.log 2>&1',
environment => 'PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin',
require => [
File['/usr/local/bin/release-volumes'],
]
}
logrotate::file { 'release':
ensure => present,
log => '/var/log/release/release.log',
options => ['compress',
'copytruncate',
'delaycompress',
'missingok',
'rotate 7',
'daily',
'notifempty',
],
require => Cron['release'],
}
}