#!/usr/bin/env python # -*- coding: utf-8 -*- # upgradeos.py # Copyright (C) 2010-2015 Andrew Colin Kissa # vim: ai ts=4 sts=4 et sw=4 "BaruwaOS upgrade script" import os import re import shutil import string import hashlib import tarfile import fnmatch import yum import psutil from copy import deepcopy from random import choice from subprocess import Popen, PIPE from cracklib import VeryFascistCheck PKGS = [ 'GeoIP', 'MAKEDEV', 'MySQL-python', 'SDL', 'acl', 'aic94xx-firmware', 'altermime', 'antiword', 'atk', 'atmel-firmware', 'attr', 'audit', 'audit-libs', 'augeas', 'augeas-libs', 'authconfig', 'avahi-libs', 'b43-openfwwf', 'backupninja', 'baruwa', 'baruwa-common', 'baruwa-mailscanner', 'baruwa-puppet', 'baruwa-release', 'baruwa-setup', 'baruwa-sphinx', 'baruwa-theme-baruwahosted', 'baruwa-yum', 'basesystem', 'bash', 'bash-completion', 'bfa-firmware', 'bind', 'bind-libs', 'bind-utils', 'binutils', 'bridge-utils', 'bzip2', 'bzip2-libs', 'ca-certificates', 'cairo', 'checkpolicy', 'chkconfig', 'clamav', 'clamav-db', 'clamav-unofficial-sigs', 'clamd', 'cloog-ppl', 'colorize', 'compat-readline5', 'coreutils', 'coreutils-libs', 'cpio', 'cpp', 'cracklib', 'cracklib-dicts', 'cronie', 'cronie-anacron', 'crontabs', 'cryptsetup-luks', 'cryptsetup-luks-libs', 'cups-libs', 'curl', 'cyrus-sasl', 'cyrus-sasl-devel', 'cyrus-sasl-lib', 'dash', 'db4', 'db4-cxx', 'db4-devel', 'db4-utils', 'dbus-glib', 'dbus-libs', 'dbus-python', 'dcc', 'dcc-client', 'dcc-server', 'dejavu-fonts-common', 'dejavu-sans-fonts', 'device-mapper', 'device-mapper-event', 'device-mapper-event-libs', 'device-mapper-libs', 'device-mapper-persistent-data', 'dhclient', 'dhcp-common', 'diffutils', 'dmidecode', 'dmraid', 'dmraid-events', 'dracut', 'dracut-kernel', 'duplicity', 'e2fsprogs', 'e2fsprogs-libs', 'efibootmgr', 'elfutils-libelf', 'erlang', 'erlang-appmon', 'erlang-asn1', 'erlang-common_test', 'erlang-compiler', 'erlang-cosEvent', 'erlang-cosEventDomain', 'erlang-cosFileTransfer', 'erlang-cosNotification', 'erlang-cosProperty', 'erlang-cosTime', 'erlang-cosTransactions', 'erlang-crypto', 'erlang-debugger', 'erlang-dialyzer', 'erlang-diameter', 'erlang-docbuilder', 'erlang-edoc', 'erlang-erl_docgen', 'erlang-erl_interface', 'erlang-erts', 'erlang-et', 'erlang-eunit', 'erlang-examples', 'erlang-gs', 'erlang-hipe', 'erlang-ic', 'erlang-inets', 'erlang-inviso', 'erlang-jinterface', 'erlang-kernel', 'erlang-megaco', 'erlang-mnesia', 'erlang-observer', 'erlang-odbc', 'erlang-orber', 'erlang-os_mon', 'erlang-otp_mibs', 'erlang-parsetools', 'erlang-percept', 'erlang-pman', 'erlang-public_key', 'erlang-reltool', 'erlang-runtime_tools', 'erlang-sasl', 'erlang-snmp', 'erlang-ssh', 'erlang-ssl', 'erlang-stdlib', 'erlang-syntax_tools', 'erlang-test_server', 'erlang-toolbar', 'erlang-tools', 'erlang-tv', 'erlang-typer', 'erlang-webtool', 'erlang-wx', 'erlang-xmerl', 'etckeeper', 'ethtool', 'exim', 'expat', 'expect', 'f-prot', 'facter', 'file', 'file-libs', 'filesystem', 'findutils', 'fipscheck', 'fipscheck-lib', 'fontconfig', 'fontpackages-filesystem', 'freetype', 'gamin', 'gawk', 'gcc', 'gd', 'gdbm', 'gdbm-devel', 'gdk-pixbuf2', 'git', 'glib2', 'glibc', 'glibc-common', 'glibc-devel', 'glibc-headers', 'gmp', 'gnupg2', 'gnutls', 'gpgme', 'gpm-libs', 'grep', 'groff', 'grub', 'grubby', 'gtk2', 'gzip', 'hdparm', 'hicolor-icon-theme', 'hwdata', 'info', 'initscripts', 'iproute', 'iptables', 'iptables-ipv6', 'iputils', 'ipw2100-firmware', 'ipw2200-firmware', 'ivtv-firmware', 'iwl100-firmware', 'iwl1000-firmware', 'iwl3945-firmware', 'iwl4965-firmware', 'iwl5000-firmware', 'iwl5150-firmware', 'iwl6000-firmware', 'iwl6000g2a-firmware', 'iwl6050-firmware', 'jasper-libs', 'kbd', 'kbd-misc', 'kernel', 'kernel-firmware', 'kernel-headers', 'keyutils', 'keyutils-libs', 'kpartx', 'krb5-libs', 'less', 'libICE', 'libSM', 'libX11', 'libX11-common', 'libXau', 'libXcomposite', 'libXcursor', 'libXdamage', 'libXext', 'libXfixes', 'libXft', 'libXi', 'libXinerama', 'libXpm', 'libXrandr', 'libXrender', 'libXxf86vm', 'libacl', 'libaio', 'libattr', 'libblkid', 'libcap', 'libcap-ng', 'libcom_err', 'libcurl', 'libdrm', 'libedit', 'libertas-usb8388-firmware', 'libevent', 'libffi', 'libgcc', 'libgcrypt', 'libgomp', 'libgpg-error', 'libgsasl', 'libgsasl-devel', 'libgssglue', 'libgudev1', 'libidn', 'libjpeg-turbo', 'libmemcached', 'libmemcached-devel', 'libnih', 'libnl', 'libntlm', 'libopendmarc', 'libopendmarc-devel', 'libpcap', 'libpciaccess', 'libpng', 'librabbitmq', 'librabbitmq-devel', 'librsync', 'libselinux', 'libselinux-ruby', 'libselinux-utils', 'libsemanage', 'libsepol', 'libspf2', 'libspf2-devel', 'libsrs_alt', 'libsrs_alt-devel', 'libss', 'libssh2', 'libstdc++', 'libtasn1', 'libthai', 'libtiff', 'libtirpc', 'libtool-ltdl', 'libudev', 'libusb', 'libuser', 'libutempter', 'libuuid', 'libxcb', 'libxml2', 'libxml2-python', 'libxslt', 'logrotate', 'logwatch', 'lsof', 'lua', 'lvm2', 'lvm2-libs', 'm2crypto', 'm4', 'mailcap', 'mailscanner', 'mailx', 'make', 'man', 'mdadm', 'memcached', 'mesa-dri-drivers', 'mesa-dri-filesystem', 'mesa-dri1-drivers', 'mesa-libGL', 'mesa-libGLU', 'mesa-private-llvm', 'mingetty', 'module-init-tools', 'mpfr', 'mysql', 'mysql-libs', 'nagios-common', 'nagios-plugins', 'nagios-plugins-check-updates', 'nagios-plugins-disk', 'nagios-plugins-load', 'nagios-plugins-mailq', 'nagios-plugins-perl', 'nagios-plugins-pgsql', 'nagios-plugins-procs', 'ncftp', 'ncurses', 'ncurses-base', 'ncurses-libs', 'net-tools', 'newt', 'newt-python', 'nfs-utils', 'nfs-utils-lib', 'nginx', 'nginx-filesystem', 'nrpe', 'nspr', 'nss', 'nss-softokn', 'nss-softokn-freebl', 'nss-sysinit', 'nss-tools', 'nss-util', 'ntp', 'ntpdate', 'openldap', 'openssh', 'openssh-clients', 'openssh-server', 'openssl', 'p11-kit', 'p11-kit-trust', 'pam', 'pango', 'passwd', 'patch', 'pciutils', 'pciutils-libs', 'pcre', 'perl', 'perl-AnyEvent', 'perl-AnyEvent-AIO', 'perl-Archive-Tar', 'perl-Archive-Zip', 'perl-Async-MergePoint', 'perl-Authen-DecHpwd', 'perl-Authen-Passphrase', 'perl-CDB_File', 'perl-CPS', 'perl-Class-Accessor', 'perl-Class-Mix', 'perl-Compress-Raw-Zlib', 'perl-Compress-Zlib', 'perl-Config-IniFiles', 'perl-Config-Tiny', 'perl-Convert-BinHex', 'perl-Convert-TNEF', 'perl-Crypt-DES', 'perl-Crypt-Eksblowfish', 'perl-Crypt-MySQL', 'perl-Crypt-OpenSSL-Bignum', 'perl-Crypt-OpenSSL-RSA', 'perl-Crypt-OpenSSL-Random', 'perl-Crypt-PasswdMD5', 'perl-Crypt-UnixCrypt_XS', 'perl-DBD-MySQL', 'perl-DBD-Pg', 'perl-DBD-SQLite', 'perl-DBI', 'perl-Data-Entropy', 'perl-Data-Float', 'perl-Data-Integer', 'perl-Date-Manip', 'perl-Devel-Refcount', 'perl-Digest-CRC', 'perl-Digest-HMAC', 'perl-Digest-MD4', 'perl-Digest-SHA', 'perl-Digest-SHA1', 'perl-EV', 'perl-Encode-Detect', 'perl-Encoding-FixLatin', 'perl-Error', 'perl-ExtUtils-MakeMaker', 'perl-ExtUtils-ParseXS', 'perl-Filesys-Df', 'perl-Geo-IP', 'perl-Geography-Countries', 'perl-Git', 'perl-HTML-Parser', 'perl-HTML-Tagset', 'perl-HTTP-Lite', 'perl-Heap', 'perl-IO-AIO', 'perl-IO-Async', 'perl-IO-Compress-Base', 'perl-IO-Compress-Zlib', 'perl-IO-Socket-INET6', 'perl-IO-Socket-SSL', 'perl-IO-String', 'perl-IO-Zlib', 'perl-IO-stringy', 'perl-IP-Country', 'perl-Inline', 'perl-List-MoreUtils', 'perl-MIME-tools', 'perl-Mail-DKIM', 'perl-Mail-SPF', 'perl-MailTools', 'perl-Math-Calc-Units', 'perl-Module-Pluggable', 'perl-Module-Runtime', 'perl-Nagios-Plugin', 'perl-Net-CIDR', 'perl-Net-CIDR-Lite', 'perl-Net-DNS', 'perl-Net-DNS-Resolver-Programmable', 'perl-Net-IP', 'perl-Net-LibIDN', 'perl-Net-Patricia', 'perl-Net-SSLeay', 'perl-NetAddr-IP', 'perl-OLE-Storage_Lite', 'perl-Package-Constants', 'perl-Params-Classify', 'perl-Params-Validate', 'perl-Parse-RecDescent', 'perl-Pod-Escapes', 'perl-Pod-Simple', 'perl-Razor-Agent', 'perl-Readonly', 'perl-Readonly-XS', 'perl-Scalar-String', 'perl-Socket6', 'perl-String-CRC32', 'perl-Sys-Hostname-Long', 'perl-Sys-SigAction', 'perl-Test-Fatal', 'perl-Test-Harness', 'perl-Test-Identity', 'perl-Test-Refcount', 'perl-Test-Simple', 'perl-Time-HiRes', 'perl-TimeDate', 'perl-Try-Tiny', 'perl-URI', 'perl-YAML-Syck', 'perl-common-sense', 'perl-devel', 'perl-libs', 'perl-libwww-perl', 'perl-parent', 'perl-version', 'pgbouncer', 'pinentry', 'pixman', 'pkgconfig', 'plymouth', 'plymouth-core-libs', 'plymouth-scripts', 'policycoreutils', 'popt', 'portreserve', 'postgresql', 'postgresql-libs', 'postgresql-plpython', 'postgresql-server', 'ppl', 'procmail', 'procps', 'psmisc', 'pth', 'publicsuffix', 'puppet', 'py-bcrypt', 'pyOpenSSL', 'pygobject2', 'pygpgme', 'pylibacl', 'pyparsing', 'pysqlcipher', 'python', 'python-GeoIP', 'python-GnuPGInterface', 'python-IPy', 'python-PyPDF2', 'python-amqp', 'python-amqplib', 'python-anyjson', 'python-arrow', 'python-augeas', 'python-babel', 'python-backports', 'python-backports-ssl_match_hostname', 'python-beaker', 'python-billiard', 'python-boto', 'python-cdb', 'python-celery', 'python-chardet', 'python-cheetah', 'python-cracklib', 'python-crypto', 'python-crypto2.6', 'python-cssutils', 'python-dateutil', 'python-decorator', 'python-dmidecode', 'python-ethtool', 'python-eventlet', 'python-formencode', 'python-futures', 'python-greenlet', 'python-gudev', 'python-hwdata', 'python-imaging', 'python-importlib', 'python-iniparse', 'python-kombu', 'python-ldap', 'python-librabbitmq', 'python-libs', 'python-lxml', 'python-magic', 'python-mako', 'python-markdown', 'python-markupsafe', 'python-marrow-interface', 'python-marrow-mailer', 'python-marrow-util', 'python-netifaces', 'python-newt-syrup', 'python-nose', 'python-oauthlib', 'python-ordereddict', 'python-paramiko', 'python-paste', 'python-paste-deploy', 'python-paste-script', 'python-psutil', 'python-psycopg2', 'python-pycountry', 'python-pycurl', 'python-pygments', 'python-pylibmc', 'python-pylons', 'python-pyrad', 'python-pyzmail', 'python-reportlab', 'python-repoze-lru', 'python-repoze-what', 'python-repoze-what-plugins-config', 'python-repoze-what-plugins-sql', 'python-repoze-what-pylons', 'python-repoze-who', 'python-repoze-who-friendlyform', 'python-repoze-who-plugins-ldap', 'python-repoze-who-plugins-memcached', 'python-repoze-who-plugins-sa', 'python-repoze-who-plugins-x509', 'python-repoze-who-testutil', 'python-requests', 'python-routes', 'python-rsa', 'python-setuptools', 'python-simplejson', 'python-six', 'python-sqlalchemy', 'python-sqlparse', 'python-svg2rlg', 'python-tempita', 'python-tinycss', 'python-twisted-core', 'python-urlgrabber', 'python-urllib3', 'python-weberror', 'python-webhelpers', 'python-webob', 'python-webtest', 'python-wtforms', 'python-z3c.rml', 'python-zope-event', 'python-zope-filesystem', 'python-zope-interface', 'python-zope-schema', 'pytz', 'pyxattr', 'pyzor', 'pyzor-server', 'ql2100-firmware', 'ql2200-firmware', 'ql23xx-firmware', 'ql2400-firmware', 'ql2500-firmware', 'rabbitmq-server', 'rdiff-backup', 're2c', 'readline', 'redhat-logos', 'rhn-check', 'rhn-client-tools', 'rhn-setup', 'rhnlib', 'rhnsd', 'rootfiles', 'rpcbind', 'rpm', 'rpm-libs', 'rpm-python', 'rsync', 'rsyslog', 'rt61pci-firmware', 'rt73usb-firmware', 'ruby', 'ruby-augeas', 'ruby-libs', 'ruby-shadow', 'screen', 'sed', 'selinux-policy', 'selinux-policy-targeted', 'setup', 'sgpio', 'shadow-utils', 'shared-mime-info', 'slang', 'snf', 'snf-server', 'spamassassin', 'spamassassin-plugin-DecodeShortURLs', 'spamassassin-plugin-iXhash2', 'spamassassin-plugin-snf', 'sphinx', 'sphinx-python', 'sqlcipher', 'sqlcipher-devel', 'sqlite', 'strace', 'strongswan', 'sudo', 'sysstat', 'system-config-firewall-base', 'sysvinit-tools', 'tar', 'tcl', 'tcp_wrappers-libs', 'tcpdump', 'tk', 'tnef', 'tzdata', 'udev', 'udns', 'udns-devel', 'unixODBC', 'unrar', 'upstart', 'usermode', 'ustr', 'util-linux-ng', 'uwsgi', 'uwsgi-devel', 'uwsgi-plugin-common', 'vim-common', 'vim-enhanced', 'vim-minimal', 'virt-what', 'wget', 'which', 'wxBase', 'wxGTK', 'wxGTK-gl', 'xfsprogs', 'xorg-x11-drv-ati-firmware', 'xz', 'xz-libs', 'xz-lzma-compat', 'yum', 'yum-metadata-parser', 'yum-plugin-fastestmirror', 'yum-plugin-security', 'yum-rhn-plugin', 'zd1211-firmware', 'zlib', "libbsd", ] RELEASE_PKGS = [ 'baruwa-enterprise-release', # 'epel-release', 'centos-release', 'oraclelinux-release', 'sl-release', 'redhat-release', 'redhat-release-as', 'redhat-release-es', 'redhat-release-ws', 'redhat-release-de' ] PGBOUNCER_INI = """[databases] template0=port=6432 template1=port=6432 baruwa=port=6432 pool_size=80 reserve_pool=10 postgres=port=6432 [pgbouncer] logfile = /var/log/pgbouncer/pgbouncer.log pidfile = /var/run/pgbouncer/pgbouncer.pid listen_addr = 0.0.0.0 listen_port = 5432 unix_socket_dir = /tmp auth_type = md5 auth_file = /var/lib/pgsql/data/global/pg_auth admin_users = postgres stats_users = postgres, root pool_mode = session server_reset_query = DISCARD ALL; server_check_query = SELECT 1 server_check_delay = 10 max_client_conn = 1000 default_pool_size = 20 log_connections = 1 log_disconnections = 1 log_pooler_errors = 1 """ RATELIMIT_CNF = """$SystemLogRateLimitInterval 0 $SystemLogRateLimitBurst 0 $IMUxSockRateLimitBurst 0 $IMUXSockRateLimitInterval 0 $IMUxSockRateLimitSeverity 7 """ PSQL = "ALTER ROLE %s WITH PASSWORD '%s';" POSTACTION = """baruwa-common:update:rm -rf /var/lib/baruwa/data/templates/* baruwa-common:install:rm -rf /var/lib/baruwa/data/templates/* """ CLEAN_UP = re.compile(r'[\[\]\n,\']') CLEAN_UP_SPLIT = re.compile(r'\s+') PUPPET_FILE_RE = re.compile(r'^(?P\$[A-Za-z0-9_]+)' r'(:?\s+)?=(:?\s+)?(:?(?P' r'((\'|")(.*?)(\'|")|\[.*?\]|' r'\$baruwa_web_vhost|\$baruwa_admin_email' r'|\$baruwa_web_serveraliases)))', re.MULTILINE | re.DOTALL) TAR_DIR = '/usr/local/src' PUPPET_DIR = '/etc/puppet' def log(text): """print in green""" print '[+] ' + '\033[92m' + text + '\033[0m' def warn(text): """print in yellow""" print '\033[93m' + text + '\033[0m' def alert(text): """print in red""" print '\033[91m' + text + '\033[0m' def check_passwd(passwds, value): """docstring for check_passwd""" passwd_fields = deepcopy(passwds) passwd_fields.remove(value) rt_val = True for field in passwd_fields: if value == field or fnmatch.fnmatch(value, '%s*' % field) or \ fnmatch.fnmatch(value, '*%s' % field): rt_val = False break return rt_val def check_password(password): """docstring for check_password""" is_valid = False try: VeryFascistCheck(password) is_valid = True except ValueError: pass return is_valid def mkpasswd(length=25, include_chars=True): """Generate a random password""" chars = "%*-=?^_~" if include_chars: return ''.join([choice(string.letters + string.digits + chars) for i in range(length)]) else: return ''.join([choice(string.letters + string.digits) for i in range(length)]) def read_puppet_manifest(filename): """Read a puppet manifest into a dict""" puppet_config = {} if os.path.exists(filename): for match in PUPPET_FILE_RE.finditer(open(filename).read()): key = match.groupdict()['variable'].lstrip('$') val = match.groupdict()['value'] if val.startswith('[') and val.endswith(']'): val = CLEAN_UP.sub(' ', val) val = ' '.join(CLEAN_UP_SPLIT.split(val)).strip() if key in ['clamav_sane_sigs', 'clamav_securiteinfo_sigs']: val = val.split() else: val = val.rstrip('"').lstrip('"').rstrip("'").lstrip("'") if isinstance(val, basestring) and val.startswith('$baruwa'): try: val = puppet_config[val.lstrip('$')] except KeyError: pass if isinstance(val, basestring) and val.endswith('$fqdn'): try: val = val.replace('$fqdn', puppet_config['baruwa_mail_host']) except KeyError: pass puppet_config[key] = val return puppet_config def get_md5(filename): """filename""" blocksize = 65536 hasher = hashlib.md5() with open(filename, 'rb') as afile: buf = afile.read(blocksize) while len(buf) > 0: hasher.update(buf) buf = afile.read(blocksize) return hasher.hexdigest() def run_cmd(cmd): """Run a command""" pipe = Popen(cmd, stdout=PIPE, stderr=PIPE) output = pipe.communicate()[0] ret_val = pipe.wait() if ret_val != 0: try: output = pipe.communicate()[1] except ValueError, msg: output = str(msg) return output.strip() def system_hostname(): "Get the machines hostname" pipe = Popen(['/bin/hostname'], stdout=PIPE, stderr=PIPE) hostname = pipe.communicate()[0] pipe.wait() return hostname.strip() def install_pkg(base, pkgname): """Install a package""" base.doLock() base.install(pattern=pkgname) base.resolveDeps() base.processTransaction() base.closeRpmDB() base.doUnlock() def upgrade_pkg(base, pkgname): """Upgrade a package""" base.doLock() updates = base.update(pattern=pkgname) if updates: base.resolveDeps() base.processTransaction() base.closeRpmDB() base.doUnlock() def setup_postactions(base): """Setup postinstall actions""" # install_pkg(base, 'yum-plugin-post-transaction-actions') # with open('/etc/yum/post-actions/baruwa-common.actions', 'w') as actions: # actions.write(POSTACTION) # os.chmod('/etc/yum/post-actions/baruwa-common.actions', 0644) if not os.path.exists('/etc/yum/pluginconf.d/baruwa.conf'): install_pkg(base, 'baruwa-yum') def make_archive(): """Make a puppet backup""" p_filename = 'puppet-os-backup.tar.bz2' p_path = os.path.join(TAR_DIR, p_filename) if not os.path.exists(p_path) and os.path.exists(PUPPET_DIR): os.chdir(PUPPET_DIR) tar = tarfile.open(p_path, mode='w:bz2') for cf_file in os.listdir('.'): tar.add(cf_file) tar.close() def copy_manifest(): """Make a copy of the manifest""" hostname = system_hostname() src = '/etc/puppet/manifests/toasters/baruwa/%s.pp' % hostname dst = '%s/%s.pp' % (TAR_DIR, hostname) if os.path.exists(src) and not os.path.exists(dst): shutil.copy2(src, dst) os.chmod(dst, 0600) def rm_dirs(): """Remove puppet directories""" modules_dir = '%s/modules' % PUPPET_DIR manifest_dir = '%s/manifests' % PUPPET_DIR if os.path.exists(modules_dir): shutil.rmtree(modules_dir) if os.path.exists(manifest_dir): shutil.rmtree(manifest_dir) def rm_pkgs(base, pkg_names): """Remove none BaruwaOS packages""" base.doLock() for pkg_name in pkg_names: base.remove(pattern=pkg_name) if pkg_names: base.resolveDeps() base.processTransaction() base.closeRpmDB() base.doUnlock() def stop_services(): """Stop services""" for service in ['mailscanner', 'pgbouncer', 'postgresql', 'searchd']: if os.path.exists('/etc/init.d/%s' % service): cmd = ['/sbin/service', service, 'stop'] run_cmd(cmd) if service == 'mailscanner': for process in psutil.process_iter(): if process.name == 'MailScanner' or \ process.name.startswith('MailScanner'): warn("MailScanner process lingering, killing it") process.kill() def start_services(): """Stop services""" for service in ['postgresql', 'pgbouncer']: if os.path.exists('/etc/init.d/%s' % service): cmd = ['/sbin/service', service, 'start'] run_cmd(cmd) def clean_index(): """Cleanup the index files""" if os.path.exists('/var/lib/sphinx'): os.chdir('/var/lib/sphinx') for cf_file in os.listdir('.'): if os.path.isfile(cf_file): os.unlink(cf_file) def update_pgsql(): """Update PostgreSQL/Pgbouncer setup""" if os.path.exists('/etc/pgbouncer.ini'): with open('/etc/pgbouncer.ini', 'w') as handle: handle.write(PGBOUNCER_INI) with open('/etc/sysconfig/pgsql/postgresql', 'w') as handle: handle.write("PGPORT=6432\n") def disable_ratelimits(): """Disable syslog ratelimiting""" if not os.path.exists('/etc/rsyslog.d/ratelimit.conf'): with open('/etc/rsyslog.d/ratelimit.conf', 'w') as ratelimit: ratelimit.write(RATELIMIT_CNF) cmd = ['/sbin/service', 'rsyslog', 'restart'] run_cmd(cmd) def create_pgpass(data): """Create .pgpass file""" with open('/root/.pgpass', 'w') as pgpass: pgpass.write(data) os.chmod('/root/.pgpass', 0600) def delete_file(file_name): """Delete a file""" if os.path.exists(file_name): os.unlink(file_name) def update_manifest(pass_dict): """update manifest with new passwords""" hostname = system_hostname() src = '/usr/local/src/%s.pp' % hostname dst = '%s.new' % src if pass_dict: with open(dst, 'w') as newfile: with open(src) as oldfile: for line in oldfile: write = False for field in pass_dict.keys(): if line.startswith('$%s' % field): data = "$%s = '%s'\n" % (field, pass_dict[field]) newfile.write(data) write = False break else: write = True if write: newfile.write(line) newfile.flush() shutil.move(dst, src) os.chmod(src, 0600) def writeout_passwds(new_passwds): """Writeout New passwords""" with open('/root/.cluster-pws.txt', 'w') as cpasswds: for field in new_passwds: cpasswds.write("$%s = '%s'\n" % (field, new_passwds[field])) os.chmod('/root/.cluster-pws.txt', 0600) warn("The new passwords saved to '/root/.cluster-pws.txt'") def upgrade_passwords(): """Upgrade DB passwords""" create_new_config = False updates = [] updated_passwds = {} hostname = system_hostname() src = '/usr/local/src/%s.pp' % hostname passwd_fields = ['pgsql_password', 'baruwa_pgsql_passwd', 'baruwa_bayes_pgsql_pass', 'baruwa_rabbitmq_passwd'] puppet_config = read_puppet_manifest(src) stored_passwds = [puppet_config[field] for field in puppet_config if field in passwd_fields] for passwd in passwd_fields: if passwd in puppet_config and \ (not check_password(puppet_config[passwd]) or not check_passwd(stored_passwds, puppet_config[passwd])): warn("Password: %s is weak, updating it." % passwd) create_new_config = True if passwd == 'pgsql_password': user = 'postgres' if passwd == 'baruwa_pgsql_passwd': user = puppet_config['baruwa_pgsql_user'] if passwd == 'baruwa_bayes_pgsql_pass': user = puppet_config['baruwa_bayes_pgsql_user'] new_passwd = mkpasswd(25, False) if passwd != 'baruwa_rabbitmq_passwd': updates.extend([PSQL % (user, new_passwd)]) updated_passwds[passwd] = new_passwd if create_new_config: sql = "\n".join(updates) # if not os.path.exists('/root/.pgpass'): if updates: create_pgpass("*:*:*:postgres:%s\n" % puppet_config['pgsql_password']) with open('/root/pw-updates.sql', 'w') as pwupdates: pwupdates.write(sql) os.chmod('/root/pw-updates.sql', 0600) cmd = ['psql', '-U', 'postgres', '-f', '/root/pw-updates.sql'] if puppet_config['baruwa_pgsql_host'] != '127.0.0.1': cmd.extend(['-h', puppet_config['baruwa_pgsql_host']]) run_cmd(cmd) delete_file('/root/pw-updates.sql') update_manifest(updated_passwds) delete_file('/root/.pgpass') if puppet_config['baruwa_cluster_peers']: writeout_passwds(updated_passwds) if __name__ == '__main__': try: if os.geteuid() != 0: raise ValueError('This script needs to run as root') if os.path.exists('/var/lock/baruwaos'): raise ValueError('This system is already running BaruwaOS') if not os.path.exists('/etc/rsyslog.d/ratelimit.conf'): log("Disabling rsyslog ratelimiting") disable_ratelimits() log("Calculating the packages not in BaruwaOS") yumbase = yum.YumBase() yumbase.setCacheDir() pkgs = yumbase.rpmdb.returnPackages() packages = [pkg.name for pkg in pkgs] pkgs_to_rm = list(set(packages) - set(PKGS)) for release_pkg in RELEASE_PKGS: if release_pkg in pkgs_to_rm: pkgs_to_rm.remove(release_pkg) log("Performing sanity checks") interset = list(set(pkgs_to_rm) & set(PKGS)) if interset: req = ' '.join(interset) raise ValueError('Required package being removed: %s' % req) if 'baruwa-puppet' not in packages: log("Creating the backup archive") make_archive() log("Copying manifest file") copy_manifest() log("Removing the puppet directories") rm_dirs() if 'baruwa-release' not in packages: log("Installing the BaruwaOS release package") install_pkg(yumbase, 'baruwa-release') if pkgs_to_rm: log("Removing the following %d packages:" % len(pkgs_to_rm)) warn(' '.join(pkgs_to_rm)) rm_pkgs(yumbase, pkgs_to_rm) if 'baruwa-setup' not in packages: log("Installing the baruwa-setup package") install_pkg(yumbase, 'baruwa-setup') log("Upgrading passwords") upgrade_passwords() log("Upgrading the etckeeper package") upgrade_pkg(yumbase, 'etckeeper') log("Stopping services") stop_services() log("Cleanup the old format index files") clean_index() if os.path.exists('/etc/pgbouncer.ini') and \ get_md5('/etc/pgbouncer.ini') != \ 'f937ad4ea58ed4a54b8a936be5446f9e': log("Update PgSQL/Pgbouncer settings") update_pgsql() log("Starting up stopped services") start_services() log("Setting up post transaction actions") setup_postactions(yumbase) log("Finished upgrading, writing lock file") with open('/var/lock/baruwaos', 'w') as hdl: hdl.write('BaruwaOS\n') except Exception, msg: alert("ERROR: %s" % str(msg)) finally: if 'yumbase' in locals(): yumbase.close()