-
Dimitris Aragiorgis authored
This skips key injection in nodes Signed-off-by:
Dimitris Aragiorgis <dimara@grnet.gr>
356c41bb
fabfile.py 37.57 KiB
from __future__ import with_statement
from fabric.api import *
from fabric.contrib.console import confirm
from random import choice
from fabric.operations import run, put
import re
import shutil, os
from functools import wraps
import imp
import ConfigParser
import sys
import tempfile
import ast
from snfdeploy.lib import *
from snfdeploy import massedit
def setup_env(confdir="conf", packages="packages",
templates="files", cluster_name="ganeti1", autoconf=False, disable_colors=False):
print("Loading configuration for synnefo...")
print(" * Using config files under %s..." % confdir)
print(" * Using %s and %s for packages and templates accordingly..." % (packages, templates))
autoconf = ast.literal_eval(autoconf)
disable_colors = ast.literal_eval(disable_colors)
conf = Conf.configure(confdir=confdir, cluster_name=cluster_name, autoconf=autoconf)
env.env = Env(conf)
env.local = autoconf
env.password = env.env.password
env.user = env.env.user
env.shell = "/bin/bash -c"
if disable_colors:
disable_color()
if env.env.cms.hostname in [env.env.accounts.hostname, env.env.cyclades.hostname, env.env.pithos.hostname]:
env.cms_pass = True
else:
env.cms_pass = False
if env.env.accounts.hostname in [env.env.cyclades.hostname, env.env.pithos.hostname]:
env.csrf_disable = True
else:
env.csrf_disable = False
env.roledefs = {
"nodes": env.env.ips,
"ips": env.env.ips,
"accounts": [env.env.accounts.ip],
"cyclades": [env.env.cyclades.ip],
"pithos": [env.env.pithos.ip],
"cms": [env.env.cms.ip],
"mq": [env.env.mq.ip],
"db": [env.env.db.ip],
"ns": [env.env.ns.ip],
"client": [env.env.client.ip],
"router": [env.env.router.ip],
}
env.enable_lvm = False
env.enable_drbd = False
if ast.literal_eval(env.env.create_extra_disk) and env.env.extra_disk:
env.enable_lvm = True
env.enable_drbd = True
env.roledefs.update({
"ganeti": env.env.cluster_ips,
"master": [env.env.master.ip],
})
def install_package(package):
debug(env.host, " * Installing package %s..." % package)
APT_GET = "export DEBIAN_FRONTEND=noninteractive ;apt-get install -y --force-yes "
if ast.literal_eval(env.env.use_local_packages):
with settings(warn_only=True):
deb = local("ls %s/%s*deb" % (env.env.packages, package))
if deb:
debug(env.host, " * Package %s found in %s..." % (package, env.env.packages))
put(deb, "/tmp/")
try_run("dpkg -i /tmp/%s*deb || " % package + APT_GET + "-f")
try_run("rm /tmp/%s*deb" % package)
return
info = getattr(env.env, package)
if info in ["stable", "squeeze-backports", "testing", "unstable"]:
APT_GET += " -t %s %s " % (info, package)
elif info:
APT_GET += " %s=%s " % (package, info)
else:
APT_GET += package
try_run(APT_GET)
return
@roles("ns")
def update_ns_for_ganeti():
debug(env.host, "Updating name server entries for backend %s..." % env.env.cluster.fqdn)
update_arecord(env.env.cluster)
update_ptrrecord(env.env.cluster)
try_run("/etc/init.d/bind9 restart")
@roles("ns")
def update_ns_for_node(node):
info = env.env.nodes_info.get(node)
update_arecord(info)
update_ptrrecord(info)
try_run("/etc/init.d/bind9 restart")
@roles("ns")
def update_arecord(host):
filename = "/etc/bind/zones/" + env.env.domain
cmd = """
echo '{0}' >> {1}
""".format(host.arecord, filename)
try_run(cmd)
@roles("ns")
def update_cnamerecord(host):
filename = "/etc/bind/zones/" + env.env.domain
cmd = """
echo '{0}' >> {1}
""".format(host.cnamerecord, filename)
try_run(cmd)
@roles("ns")
def update_ptrrecord(host):
filename = "/etc/bind/rev/synnefo.in-addr.arpa.zone"
cmd = """
echo '{0}' >> {1}
""".format(host.ptrrecord, filename)
try_run(cmd)
@roles("nodes")
def apt_get_update():
debug(env.host, "apt-get update....")
try_run("apt-get update")
@roles("ns")
def setup_ns():
debug(env.host, "Setting up name server..")
#WARNING: this should be remove after we are done
# because gevent does pick randomly nameservers and google does
# not know our setup!!!!!
apt_get_update()
install_package("bind9")
tmpl = "/etc/bind/named.conf.local"
replace = {
"domain": env.env.domain,
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
try_run("mkdir -p /etc/bind/zones")
tmpl = "/etc/bind/zones/example.com"
replace = {
"domain": env.env.domain,
"ns_node_ip": env.env.ns.ip,
}
custom = customize_settings_from_tmpl(tmpl, replace)
remote = "/etc/bind/zones/" + env.env.domain
put(custom, remote)
try_run("mkdir -p /etc/bind/rev")
tmpl = "/etc/bind/rev/synnefo.in-addr.arpa.zone"
replace = {
"domain": env.env.domain,
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
tmpl = "/etc/bind/named.conf.options"
replace = {
"NODE_IPS": ";".join(env.env.ips),
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl, mode=0644)
for role, info in env.env.roles.iteritems():
if role == "ns":
continue
update_cnamerecord(info)
for node, info in env.env.nodes_info.iteritems():
update_arecord(info)
update_ptrrecord(info)
try_run("/etc/init.d/bind9 restart")
@roles("nodes")
def check_dhcp():
debug(env.host, "Checking IPs for synnefo..")
for n, info in env.env.nodes_info.iteritems():
try_run("ping -c 1 " + info.ip, True)
@roles("nodes")
def check_dns():
debug(env.host, "Checking fqdns for synnefo..")
for n, info in env.env.nodes_info.iteritems():
try_run("ping -c 1 " + info.fqdn, True)
for n, info in env.env.roles.iteritems():
try_run("ping -c 1 " + info.fqdn, True)
@roles("nodes")
def check_connectivity():
debug(env.host, "Checking internet connectivity..")
try_run("ping -c 1 www.google.com", True)
@roles("nodes")
def check_ssh():
debug(env.host, "Checking password-less ssh..")
for n, info in env.env.nodes_info.iteritems():
try_run("ssh " + info.fqdn + " date", True)
@roles("ips")
def add_keys():
if not ast.literal_eval(env.env.key_inject):
debug(env.host, "Skipping ssh keys injection..")
try_run("mkdir -p /root/.ssh")
cmd = """
for f in $(ls /root/.ssh/*); do
cp $f $f.bak
done
"""
try_run(cmd)
files = ["authorized_keys", "id_dsa", "id_dsa.pub",
"id_rsa", "id_rsa.pub"]
for f in files:
tmpl = "/root/.ssh/" + f
replace = {}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
cmd = """
if [ -e /root/.ssh/authorized_keys.bak ]; then
cat /root/.ssh/authorized_keys.bak >> /root/.ssh/authorized_keys
fi
"""
debug(env.host, "Updating exising authorized keys..")
try_run(cmd)
@roles("ips")
def setup_resolv_conf():
debug(env.host, "Tweak /etc/resolv.conf...")
try_run("/etc/init.d/network-manager stop")
tmpl = "/etc/dhcp/dhclient-enter-hooks.d/nodnsupdate"
replace = {}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl, mode=0644)
try_run("cp /etc/resolv.conf /etc/resolv.conf.bak")
tmpl = "/etc/resolv.conf"
replace = {
"domain": env.env.domain,
"ns_node_ip": env.env.ns.ip,
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
try_run("chattr +i /etc/resolv.conf")
@roles("ips")
def setup_hosts():
debug(env.host, "Tweaking /etc/hosts and ssh_config files...")
try_run("echo StrictHostKeyChecking no >> /etc/ssh/ssh_config")
cmd = " sed -i 's/^127.*/127.0.0.1 localhost/g' /etc/hosts "
try_run(cmd)
def try_run(cmd, abort=False):
try:
if env.local:
return local(cmd, capture=True)
else:
return run(cmd)
except:
debug(env.host, "WARNING: command failed. Continuing anyway...")
if abort:
raise
def create_bridges():
debug(env.host, " * Creating bridges...")
install_package("bridge-utils")
cmd = """
brctl addbr {0} ; ip link set {0} up
""".format(env.env.common_bridge)
try_run(cmd)
def connect_bridges():
debug(env.host, " * Connecting bridges...")
cmd = """
brctl addif {0} {1}
""".format(env.env.common_bridge, env.env.public_iface)
#try_run(cmd)
@roles("ganeti")
def setup_net_infra():
debug(env.host, "Setup networking infrastracture..")
create_bridges()
connect_bridges()
@roles("ganeti")
def setup_lvm():
debug(env.host, "create volume group %s for ganeti.." % env.env.vg)
if env.enable_lvm:
install_package("lvm2")
cmd = """
pvcreate {0}
vgcreate {1} {0}
""".format(env.env.extra_disk, env.env.vg)
try_run(cmd)
def customize_settings_from_tmpl(tmpl, replace):
debug(env.host, " * Customizing template %s..." % tmpl)
local = env.env.templates + tmpl
_, custom = tempfile.mkstemp()
shutil.copyfile(local, custom)
for k, v in replace.iteritems():
regex = "re.sub('%{0}%', '{1}', line)".format(k.upper(), v)
massedit.edit_files([custom], [regex], dry_run=False)
return custom
@roles("nodes")
def setup_apt():
debug(env.host, "Setting up apt sources...")
install_package("curl")
cmd = """
echo 'APT::Install-Suggests "false";' >> /etc/apt/apt.conf
curl -k https://dev.grnet.gr/files/apt-grnetdev.pub | apt-key add -
"""
try_run(cmd)
tmpl = "/etc/apt/sources.list.d/okeanos.list"
replace = {}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
apt_get_update()
@roles("cyclades", "cms", "pithos", "accounts")
def restart_services():
debug(env.host, " * Restarting apache2 and gunicorn...")
try_run("/etc/init.d/gunicorn restart")
try_run("/etc/init.d/apache2 restart")
def setup_gunicorn():
debug(env.host, " * Setting up gunicorn...")
install_package("gunicorn")
tmpl = "/etc/gunicorn.d/synnefo"
replace = {}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl, mode=0644)
try_run("/etc/init.d/gunicorn restart")
def setup_apache():
debug(env.host, " * Setting up apache2...")
host_info = env.env.ips_info[env.host]
install_package("apache2")
tmpl = "/etc/apache2/sites-available/synnefo"
replace = {
"HOST": host_info.fqdn,
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
tmpl = "/etc/apache2/sites-available/synnefo-ssl"
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
cmd = """
a2enmod ssl
a2enmod rewrite
a2dissite default
a2ensite synnefo
a2ensite synnefo-ssl
a2enmod headers
a2enmod proxy_http
a2dismod autoindex
"""
try_run(cmd)
try_run("/etc/init.d/apache2 restart")
@roles("mq")
def setup_mq():
debug(env.host, "Setting up RabbitMQ...")
install_package("rabbitmq-server")
cmd = """
rabbitmqctl add_user {0} {1}
rabbitmqctl set_permissions {0} ".*" ".*" ".*"
rabbitmqctl delete_user guest
rabbitmqctl set_user_tags {0} administrator
""".format(env.env.synnefo_user, env.env.synnefo_rabbitmq_passwd)
try_run(cmd)
try_run("/etc/init.d/rabbitmq-server restart")
@roles("db")
def allow_access_in_db(ip, user="all", trust=""):
cmd = """
echo host all {0} {1}/32 md5 {2} >> /etc/postgresql/8.4/main/pg_hba.conf
""".format(user, ip, trust)
try_run(cmd)
try_run("/etc/init.d/postgresql restart")
@roles("db")
def setup_db():
debug(env.host, "Setting up DataBase server...")
install_package("postgresql")
tmpl = "/tmp/db-init.psql"
replace = {
"synnefo_user": env.env.synnefo_user,
"synnefo_db_passwd": env.env.synnefo_db_passwd,
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
cmd = 'su - postgres -c "psql -w -f %s" ' % tmpl
try_run(cmd)
cmd = """
echo "listen_addresses = '*'" >> /etc/postgresql/8.4/main/postgresql.conf
"""
try_run(cmd)
try_run("/etc/init.d/postgresql restart")
allow_access_in_db("127.0.0.1", "postgres", "trust")
@roles("db")
def destroy_db():
try_run("""su - postgres -c ' psql -w -c "drop database snf_apps" '""")
try_run("""su - postgres -c ' psql -w -c "drop database snf_pithos" '""")
def setup_webproject():
debug(env.host, " * Setting up snf-webproject...")
with settings(hide("everything")):
try_run("ping -c1 " + env.env.db.ip)
setup_common()
install_package("snf-webproject")
install_package("python-psycopg2")
install_package("python-gevent")
tmpl = "/etc/synnefo/webproject.conf"
replace = {
"synnefo_user": env.env.synnefo_user,
"synnefo_db_passwd": env.env.synnefo_db_passwd,
"db_node": env.env.db.ip,
"domain": env.env.domain,
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl, mode=0644)
with settings(host_string=env.env.db.ip):
host_info = env.env.ips_info[env.host]
allow_access_in_db(host_info.ip)
try_run("/etc/init.d/gunicorn restart")
def setup_common():
debug(env.host, " * Setting up snf-common...")
host_info = env.env.ips_info[env.host]
install_package("python-objpool")
install_package("snf-common")
install_package("python-astakosclient")
install_package("snf-django-lib")
install_package("snf-branding")
tmpl = "/etc/synnefo/common.conf"
replace = {
#FIXME:
"EMAIL_SUBJECT_PREFIX": env.host,
"domain": env.env.domain,
"HOST": host_info.fqdn,
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl, mode=0644)
try_run("/etc/init.d/gunicorn restart")
@roles("accounts")
def astakos_loaddata():
debug(env.host, " * Loading initial data to astakos...")
cmd = """
snf-manage loaddata groups
"""
try_run(cmd)
@roles("accounts")
def astakos_register_services():
debug(env.host, " * Register services in astakos...")
cmd = """
snf-manage component-add "home" https://{0} home-icon.png
snf-manage component-add "cyclades" https://{1}/cyclades/ui/
snf-manage component-add "pithos" https://{2}/pithos/ui/
snf-manage component-add "astakos" https://{3}/astakos/ui/
""".format(env.env.cms.fqdn, env.env.cyclades.fqdn, env.env.pithos.fqdn, env.env.accounts.fqdn)
try_run(cmd)
import_service("astakos")
import_service("pithos")
import_service("cyclades")
tmpl = "/tmp/resources.json"
replace = {}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
try_run("snf-manage resource-import --json %s" % tmpl)
cmd = """
snf-manage resource-modify --limit 40G pithos.diskspace
snf-manage resource-modify --limit 2 astakos.pending_app
snf-manage resource-modify --limit 4 cyclades.vm
snf-manage resource-modify --limit 40G cyclades.disk
snf-manage resource-modify --limit 8G cyclades.ram
snf-manage resource-modify --limit 16 cyclades.cpu
snf-manage resource-modify --limit 4 cyclades.network.private
"""
try_run(cmd)
@roles("accounts")
def add_user():
debug(env.host, " * adding user %s to astakos..." % env.env.user_email)
email=env.env.user_email
name=env.env.user_name
lastname=env.env.user_lastname
passwd=env.env.user_passwd
cmd = """
snf-manage user-add {0} {1} {2}
""".format(email, name, lastname)
try_run(cmd)
with settings(host_string=env.env.db.ip):
uid, user_auth_token, user_uuid = get_auth_token_from_db(email)
cmd = """
snf-manage user-modify --password {0} {1}
""".format(passwd, uid)
try_run(cmd)
@roles("accounts")
def activate_user(user_email=None):
if not user_email:
user_email = env.env.user_email
debug(env.host, " * Activate user %s..." % user_email)
with settings(host_string=env.env.db.ip):
uid, user_auth_token, user_uuid = get_auth_token_from_db(user_email)
cmd = """
snf-manage user-modify --verify {0}
snf-manage user-modify --accept {0}
""".format(uid)
try_run(cmd)
@roles("accounts")
def setup_astakos():
debug(env.host, "Setting up snf-astakos-app...")
setup_gunicorn()
setup_apache()
setup_webproject()
install_package("python-django-south")
install_package("snf-astakos-app")
install_package("kamaki")
tmpl = "/etc/synnefo/astakos.conf"
replace = {
"ACCOUNTS": env.env.accounts.fqdn,
"domain": env.env.domain,
"CYCLADES": env.env.cyclades.fqdn,
"PITHOS": env.env.pithos.fqdn,
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl, mode=0644)
if env.csrf_disable:
cmd = """
cat <<EOF >> /etc/synnefo/astakos.conf
try:
MIDDLEWARE_CLASSES.remove('django.middleware.csrf.CsrfViewMiddleware')
except:
pass
EOF
"""
try_run(cmd)
try_run("/etc/init.d/gunicorn restart")
cmd = """
snf-manage syncdb --noinput
snf-manage migrate im --delete-ghost-migrations
snf-manage migrate quotaholder_app
"""
try_run(cmd)
def import_service(service):
tmpl = "/tmp/%s.json" % service
replace = {
"DOMAIN": env.env.domain,
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
try_run("snf-manage service-import --json %s" % tmpl)
@roles("accounts")
def get_service_details(service="pithos"):
debug(env.host, " * Getting registered details for %s service..." % service)
result = try_run("snf-manage component-list")
r = re.compile(r".*%s.*" % service, re.M)
service_id, _, _, service_token = r.search(result).group().split()
# print("%s: %s %s" % (service, service_id, service_token))
return (service_id, service_token)
@roles("db")
def get_auth_token_from_db(user_email=None):
if not user_email:
user_email=env.env.user_email
debug(env.host, " * Getting authentication token and uuid for user %s..." % user_email)
cmd = """
echo "select id, auth_token, uuid, email from auth_user, im_astakosuser where auth_user.id = im_astakosuser.user_ptr_id and auth_user.email = '{0}';" > /tmp/psqlcmd
su - postgres -c "psql -w -d snf_apps -f /tmp/psqlcmd"
""".format(user_email)
result = try_run(cmd)
r = re.compile(r"(\d+)[ |]*(\S+)[ |]*(\S+)[ |]*" + user_email, re.M)
match = r.search(result)
uid, user_auth_token, user_uuid = match.groups()
# print("%s: %s %s %s" % ( user_email, uid, user_auth_token, user_uuid))
return (uid, user_auth_token, user_uuid)
@roles("cms")
def cms_loaddata():
debug(env.host, " * Loading cms initial data...")
if env.cms_pass:
debug(env.host, "Aborting. Prerequisites not met.")
return
tmpl = "/tmp/sites.json"
replace = {}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
tmpl = "/tmp/page.json"
replace = {}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
cmd = """
snf-manage loaddata /tmp/sites.json
snf-manage loaddata /tmp/page.json
snf-manage createsuperuser --username=admin --email=admin@{0} --noinput
""".format(env.env.domain)
try_run(cmd)
@roles("cms")
def setup_cms():
debug(env.host, "Setting up cms...")
if env.cms_pass:
debug(env.host, "Aborting. Prerequisites not met.")
return
with settings(hide("everything")):
try_run("ping -c1 accounts." + env.env.domain)
setup_gunicorn()
setup_apache()
setup_webproject()
install_package("snf-cloudcms")
tmpl = "/etc/synnefo/cms.conf"
replace = {
"ACCOUNTS": env.env.accounts.fqdn,
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl, mode=0644)
try_run("/etc/init.d/gunicorn restart")
cmd = """
snf-manage syncdb
snf-manage migrate --delete-ghost-migrations
""".format(env.env.domain)
try_run(cmd)
def setup_nfs_dirs():
debug(env.host, " * Creating NFS mount point for pithos and ganeti...")
cmd = """
mkdir -p {0}
cd {0}
mkdir -p data
chown www-data:www-data data
chmod g+ws data
mkdir -p /srv/okeanos
""".format(env.env.pithos_dir)
try_run(cmd)
@roles("nodes")
def setup_nfs_clients():
if env.host == env.env.pithos.ip:
return
debug(env.host, " * Mounting pithos NFS mount point...")
with settings(hide("everything")):
try_run("ping -c1 " + env.env.pithos.hostname)
install_package("nfs-common")
for d in [env.env.pithos_dir, "/srv/okeanos"]:
try_run("mkdir -p " + d)
cmd = """
echo "{0}:/{1} {2} nfs4 defaults,rw,noatime,nodiratime,intr,rsize=1048576,wsize=1048576,noacl" >> /etc/fstab
""".format(env.env.pithos.hostname, os.path.basename(d), d)
try_run(cmd)
try_run("mount " + d)
@roles("pithos")
def setup_nfs_server():
debug(env.host, " * Setting up NFS server for pithos...")
setup_nfs_dirs()
install_package("nfs-kernel-server")
tmpl = "/etc/exports"
replace = {
"pithos_dir": env.env.pithos_dir,
"srv": os.path.dirname(env.env.pithos_dir),
"subnet": env.env.subnet
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
try_run("/etc/init.d/nfs-kernel-server restart")
@roles("pithos")
def setup_pithos():
debug(env.host, "Setting up snf-pithos-app...")
with settings(hide("everything")):
try_run("ping -c1 accounts." + env.env.domain)
try_run("ping -c1 " + env.env.db.ip)
setup_gunicorn()
setup_apache()
setup_webproject()
with settings(host_string=env.env.accounts.ip):
service_id, service_token = get_service_details("pithos")
install_package("kamaki")
install_package("snf-pithos-backend")
install_package("snf-pithos-app")
tmpl = "/etc/synnefo/pithos.conf"
replace = {
"ACCOUNTS": env.env.accounts.fqdn,
"PITHOS": env.env.pithos.fqdn,
"db_node": env.env.db.ip,
"synnefo_user": env.env.synnefo_user,
"synnefo_db_passwd": env.env.synnefo_db_passwd,
"pithos_dir": env.env.pithos_dir,
"PITHOS_SERVICE_TOKEN": service_token,
"proxy": env.env.pithos.hostname == env.env.accounts.hostname
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl, mode=0644)
try_run("/etc/init.d/gunicorn restart")
install_package("snf-pithos-webclient")
tmpl = "/etc/synnefo/webclient.conf"
replace = {
"ACCOUNTS": env.env.accounts.fqdn,
"PITHOS_UI_CLOUDBAR_ACTIVE_SERVICE": service_id,
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl, mode=0644)
try_run("/etc/init.d/gunicorn restart")
#TOFIX: the previous command lets pithos-backend create blocks and maps
# with root owner
try_run("chown -R www-data:www-data %s/data " % env.env.pithos_dir)
#try_run("pithos-migrate stamp 4c8ccdc58192")
#try_run("pithos-migrate upgrade head")
def add_wheezy():
tmpl = "/etc/apt/sources.list.d/wheezy.list"
replace = {}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
apt_get_update()
def remove_wheezy():
try_run("rm -f /etc/apt/sources.list.d/wheezy.list")
apt_get_update()
@roles("ganeti")
def setup_ganeti():
debug(env.host, "Setting up snf-ganeti...")
node_info = env.env.ips_info[env.host]
with settings(hide("everything")):
#if env.enable_lvm:
# try_run("vgs " + env.env.vg)
try_run("getent hosts " + env.env.cluster.fqdn)
try_run("getent hosts %s | grep -v ^127" % env.host)
try_run("hostname -f | grep " + node_info.fqdn)
#try_run("ip link show " + env.env.common_bridge)
#try_run("ip link show " + env.env.common_bridge)
#try_run("apt-get update")
install_package("qemu-kvm")
install_package("python-bitarray")
add_wheezy()
install_package("ganeti-htools")
remove_wheezy()
install_package("snf-ganeti")
try_run("mkdir -p /srv/ganeti/file-storage/")
cmd = """
cat <<EOF > /etc/ganeti/file-storage-paths
/srv/ganeti/file-storage
/srv/ganeti/shared-file-storage
EOF
"""
try_run(cmd)
@roles("master")
def add_rapi_user():
debug(env.host, " * Adding RAPI user to Ganeti backend...")
cmd = """
echo -n "{0}:Ganeti Remote API:{1}" | openssl md5
""".format(env.env.synnefo_user, env.env.synnefo_rapi_passwd)
result = try_run(cmd)
cmd = """
echo "{0} {1}{2} write" >> /var/lib/ganeti/rapi/users
""".format(env.env.synnefo_user, '{ha1}',result)
try_run(cmd)
try_run("/etc/init.d/ganeti restart")
@roles("master")
def add_nodes():
nodes = env.env.cluster_nodes.split(",")
nodes.remove(env.env.master_node)
debug(env.host, " * Adding nodes to Ganeti backend...")
for n in nodes:
add_node(n)
@roles("master")
def add_node(node):
node_info = env.env.nodes_info[node]
debug(env.host, " * Adding node %s to Ganeti backend..." % node_info.fqdn)
cmd = "gnt-node add --no-ssh-key-check --master-capable=yes --vm-capable=yes " + node_info.fqdn
try_run(cmd)
@roles("ganeti")
def enable_drbd():
if env.enable_drbd:
debug(env.host, " * Enabling DRBD...")
try_run("modprobe drbd minor_count=255 usermode_helper=/bin/true")
try_run("echo drbd minor_count=255 usermode_helper=/bin/true >> /etc/modules")
@roles("master")
def setup_drbd_dparams():
if env.enable_drbd:
debug(env.host, " * Twicking drbd related disk parameters in Ganeti...")
cmd = """
gnt-cluster modify --disk-parameters=drbd:metavg={0}
gnt-group modify --disk-parameters=drbd:metavg={0} default
""".format(env.env.vg)
try_run(cmd)
@roles("master")
def enable_lvm():
if env.enable_lvm:
debug(env.host, " * Enabling LVM...")
cmd = """
gnt-cluster modify --vg-name={0}
""".format(env.env.vg)
try_run(cmd)
else:
debug(env.host, " * Disabling LVM...")
try_run("gnt-cluster modify --no-lvm-storage")
@roles("master")
def destroy_cluster():
debug(env.host, " * Destroying Ganeti cluster...")
#TODO: remove instances first
allnodes = env.env.cluster_hostnames[:]
allnodes.remove(env.host)
for n in allnodes:
host_info = env.env.ips_info[host]
debug(env.host, " * Removing node %s..." % n)
cmd = "gnt-node remove " + host_info.fqdn
try_run(cmd)
try_run("gnt-cluster destroy --yes-do-it")
@roles("master")
def init_cluster():
debug(env.host, " * Initializing Ganeti backend...")
# extra = ""
# if env.enable_lvm:
# extra += " --vg-name={0} ".format(env.env.vg)
# else:
# extra += " --no-lvm-storage "
# if not env.enable_drbd:
# extra += " --no-drbd-storage "
extra = " --no-lvm-storage --no-drbd-storage "
cmd = """
gnt-cluster init --enabled-hypervisors=kvm \
{0} \
--nic-parameters link={1},mode=bridged \
--master-netdev {2} \
--default-iallocator hail \
--hypervisor-parameters kvm:kernel_path=,vnc_bind_address=0.0.0.0 \
--no-ssh-init --no-etc-hosts \
{3}
""".format(extra, env.env.common_bridge,
env.env.cluster_netdev, env.env.cluster.fqdn)
try_run(cmd)
@roles("ganeti")
def debootstrap():
install_package("ganeti-instance-debootstrap")
@roles("ganeti")
def setup_image_host():
debug(env.host, "Setting up snf-image...")
install_package("snf-pithos-backend")
install_package("snf-image")
try_run("mkdir -p /srv/okeanos")
tmpl = "/etc/default/snf-image"
replace = {
"synnefo_user": env.env.synnefo_user,
"synnefo_db_passwd": env.env.synnefo_db_passwd,
"pithos_dir": env.env.pithos_dir,
"db_node": env.env.db.ip,
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
@roles("ganeti")
def setup_image_helper():
debug(env.host, " * Updating helper image...")
cmd = """
snf-image-update-helper -y
"""
try_run(cmd)
@roles("ganeti")
def setup_gtools():
debug(env.host, " * Setting up snf-cyclades-gtools...")
with settings(hide("everything")):
try_run("ping -c1 " + env.env.mq.ip)
setup_common()
install_package("snf-cyclades-gtools")
tmpl = "/etc/synnefo/gtools.conf"
replace = {
"synnefo_user": env.env.synnefo_user,
"synnefo_rabbitmq_passwd": env.env.synnefo_rabbitmq_passwd,
"mq_node": env.env.mq.ip,
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
cmd = """
sed -i 's/false/true/' /etc/default/snf-ganeti-eventd
/etc/init.d/snf-ganeti-eventd start
"""
try_run(cmd)
@roles("ganeti")
def setup_iptables():
debug(env.host, " * Setting up iptables to mangle DHCP requests...")
cmd = """
iptables -t mangle -A PREROUTING -i br+ -p udp -m udp --dport 67 -j NFQUEUE --queue-num 42
iptables -t mangle -A PREROUTING -i tap+ -p udp -m udp --dport 67 -j NFQUEUE --queue-num 42
iptables -t mangle -A PREROUTING -i prv+ -p udp -m udp --dport 67 -j NFQUEUE --queue-num 42
ip6tables -t mangle -A PREROUTING -i br+ -p ipv6-icmp -m icmp6 --icmpv6-type 133 -j NFQUEUE --queue-num 43
ip6tables -t mangle -A PREROUTING -i br+ -p ipv6-icmp -m icmp6 --icmpv6-type 135 -j NFQUEUE --queue-num 44
"""
try_run(cmd)
@roles("ganeti")
def setup_network():
debug(env.host, "Setting up networking for Ganeti instances (nfdhcpd, etc.)...")
install_package("nfqueue-bindings-python")
install_package("nfdhcpd")
tmpl = "/etc/nfdhcpd/nfdhcpd.conf"
replace = {
"ns_node_ip": env.env.ns.ip
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
try_run("/etc/init.d/nfdhcpd restart")
install_package("snf-network")
cmd = """
sed -i 's/MAC_MASK.*/MAC_MASK = ff:ff:f0:00:00:00/' /etc/default/snf-network
"""
try_run(cmd)
@roles("router")
def setup_router():
debug(env.host, " * Setting up internal router for NAT...")
cmd = """
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s {0} -o {3} -j MASQUERADE
ip addr add {1} dev {2}
ip route add {0} dev {2} src {1}
""".format(env.env.synnefo_public_network_subnet,
env.env.synnefo_public_network_gateway,
env.env.common_bridge, env.env.public_iface)
try_run(cmd)
@roles("cyclades")
def cyclades_loaddata():
debug(env.host, " * Loading initial data for cyclades...")
tmpl = "/tmp/flavor.json"
replace = {}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl)
try_run("snf-manage loaddata " + tmpl)
#run("snf-manage loaddata flavors")
@roles("cyclades")
def setup_cyclades():
debug(env.host, "Setting up snf-cyclades-app...")
with settings(hide("everything")):
try_run("ping -c1 accounts." + env.env.domain)
try_run("ping -c1 " + env.env.db.ip)
try_run("ping -c1 " + env.env.mq.ip)
setup_gunicorn()
setup_apache()
setup_webproject()
install_package("memcached")
install_package("python-memcache")
install_package("snf-pithos-backend")
install_package("kamaki")
install_package("snf-cyclades-app")
install_package("python-django-south")
tmpl = "/etc/synnefo/cyclades.conf"
with settings(host_string=env.env.accounts.ip):
service_id, service_token = get_service_details("cyclades")
replace = {
"ACCOUNTS": env.env.accounts.fqdn,
"CYCLADES": env.env.cyclades.fqdn,
"mq_node": env.env.mq.ip,
"db_node": env.env.db.ip,
"synnefo_user": env.env.synnefo_user,
"synnefo_db_passwd": env.env.synnefo_db_passwd,
"synnefo_rabbitmq_passwd": env.env.synnefo_rabbitmq_passwd,
"pithos_dir": env.env.pithos_dir,
"common_bridge": env.env.common_bridge,
"HOST": env.env.cyclades.ip,
"domain": env.env.domain,
"CYCLADES_SERVICE_TOKEN": service_token,
"proxy": env.env.cyclades.hostname == env.env.accounts.hostname
}
custom = customize_settings_from_tmpl(tmpl, replace)
put(custom, tmpl, mode=0644)
try_run("/etc/init.d/gunicorn restart")
cmd = """
sed -i 's/false/true/' /etc/default/snf-dispatcher
/etc/init.d/snf-dispatcher start
"""
try_run(cmd)
try_run("snf-manage syncdb")
try_run("snf-manage migrate --delete-ghost-migrations")
@roles("cyclades")
def get_backend_id(cluster_name="ganeti1.synnefo.deploy.local"):
backend_id = try_run("snf-manage backend-list 2>/dev/null | grep %s | awk '{print $1}'" % cluster_name)
return backend_id
@roles("cyclades")
def add_backend():
debug(env.host, "adding %s ganeti backend to cyclades..." % env.env.cluster.fqdn)
with settings(hide("everything")):
try_run("ping -c1 " + env.env.cluster.fqdn)
cmd = """
snf-manage backend-add --clustername={0} --user={1} --pass={2}
""".format(env.env.cluster.fqdn, env.env.synnefo_user,
env.env.synnefo_rapi_passwd)
try_run(cmd)
backend_id = get_backend_id(env.env.cluster.fqdn)
try_run("snf-manage backend-modify --drained=False " + backend_id)
@roles("cyclades")
def pin_user_to_backend(user_email):
backend_id = get_backend_id(env.env.cluster.fqdn)
# pin user to backend
cmd = """
cat <<EOF >> /etc/synnefo/cyclades.conf
BACKEND_PER_USER = {
'%s': %s,
}
EOF
/etc/init.d/gunicorn restart
""" % (user_email, backend_id)
try_run(cmd)
@roles("cyclades")
def add_pools():
debug(env.host, " * Creating pools of resources (brigdes, mac prefixes) in cyclades...")
try_run("snf-manage pool-create --type=mac-prefix --base=aa:00:0 --size=65536")
try_run("snf-manage pool-create --type=bridge --base=prv --size=20")
@roles("cyclades")
def add_network():
debug(env.host, " * Adding public network in cyclades...")
backend_id = get_backend_id(env.env.cluster.fqdn)
cmd = """
snf-manage network-create --subnet={0} --gateway={1} --public --dhcp --flavor={2} --mode=bridged --link={3} --name=Internet --backend-id={4}
""".format(env.env.synnefo_public_network_subnet,
env.env.synnefo_public_network_gateway,
env.env.synnefo_public_network_type,
env.env.common_bridge, backend_id)
try_run(cmd)
@roles("cyclades")
def setup_vncauthproxy():
debug(env.host, " * Setting up vncauthproxy...")
install_package("snf-vncauthproxy")
cmd = """
echo CHUID="www-data:nogroup" >> /etc/default/vncauthproxy
rm /var/log/vncauthproxy/vncauthproxy.log
"""
try_run(cmd)
try_run("/etc/init.d/vncauthproxy restart")
@roles("client")
def setup_kamaki():
debug(env.host, "Setting up kamaki client...")
with settings(hide("everything")):
try_run("ping -c1 accounts." + env.env.domain)
try_run("ping -c1 cyclades." + env.env.domain)
try_run("ping -c1 pithos." + env.env.domain)
with settings(host_string=env.env.db.ip):
uid, user_auth_token, user_uuid = get_auth_token_from_db(env.env.user_email)
install_package("python-progress")
install_package("kamaki")
cmd = """
kamaki config set cloud.default.url "https://{0}/astakos/identity/v2.0/"
kamaki config set cloud.default.token {1}
""".format(env.env.accounts.fqdn, user_auth_token)
try_run(cmd)
try_run("kamaki file create images")
@roles("client")
def upload_image(image="debian_base.diskdump"):
debug(env.host, " * Uploading initial image to pithos...")
image = "debian_base.diskdump"
try_run("wget {0} -O /tmp/{1}".format(env.env.debian_base_url, image))
try_run("kamaki file upload --container images /tmp/{0} {0}".format(image))
@roles("client")
def register_image(image="debian_base.diskdump"):
debug(env.host, " * Register image to plankton...")
with settings(host_string=env.env.db.ip):
uid, user_auth_token, user_uuid = get_auth_token_from_db(env.env.user_email)
pithos_url = "pithos://{0}/images/{1}".format(user_uuid, image)
cmd = """
sleep 5
kamaki image register "Debian Base" {0} --public --disk-format=diskdump --property OSFAMILY=linux --property ROOT_PARTITION=1 --property description="Debian Squeeze Base System" --property size=450M --property kernel=2.6.32 --property GUI="No GUI" --property sortorder=1 --property USERS=root --property OS=debian
""".format(pithos_url)
try_run(cmd)
@roles("client")
def setup_burnin():
debug(env.host, "Setting up burnin testing tool...")
install_package("kamaki")
install_package("snf-tools")
@roles("pithos")
def add_image_locally():
debug(env.host, " * Getting image locally in order snf-image to use it directly..")
image = "debian_base.diskdump"
try_run("wget {0} -O /srv/okeanos/{1}".format(env.env.debian_base_url, image))
@roles("master")
def gnt_instance_add(name="test"):
debug(env.host, " * Adding test instance to Ganeti...")
osp="""img_passwd=gamwtosecurity,img_format=diskdump,img_id=debian_base,img_properties='{"OSFAMILY":"linux"\,"ROOT_PARTITION":"1"}'"""
cmd = """
gnt-instance add -o snf-image+default --os-parameters {0} -t plain --disk 0:size=1G --no-name-check --no-ip-check --net 0:ip=pool,network=test --no-install --hypervisor-parameters kvm:machine_version=pc-1.0 {1}
""".format(osp, name)
try_run(cmd)
@roles("master")
def gnt_network_add(name="test", subnet="10.0.0.0/26", gw="10.0.0.1", mode="bridged", link="br0"):
debug(env.host, " * Adding test network to Ganeti...")
cmd = """
gnt-network add --network={1} --gateway={2} {0}
gnt-network connect {0} {3} {4}
""".format(name, subnet, gw, mode, link)
try_run(cmd)
@roles("ips")
def test():
debug(env.host, "Testing...")
try_run("hostname && date")