lib.py 7.45 KB
Newer Older
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#!/usr/bin/python

import json
import time
import ipaddr
import os
import signal
import ConfigParser
import sys
import re
import random
import subprocess
import shutil
import imp
import tempfile
from snfdeploy import massedit


19 20 21 22 23 24 25 26 27
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'


def disable_color():
28 29 30 31 32 33 34
    global HEADER
    global OKBLUE
    global OKGREEN
    global WARNING
    global FAIL
    global ENDC

35 36 37 38 39 40 41 42 43 44
    HEADER = ''
    OKBLUE = ''
    OKGREEN = ''
    WARNING = ''
    FAIL = ''
    ENDC = ''


if not sys.stdout.isatty():
    disable_color()
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
45

46

Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
47
class Host(object):
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
48
    def __init__(self, hostname, ip, mac, domain, os):
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
49 50 51 52
        self.hostname = hostname
        self.ip = ip
        self.mac = mac
        self.domain = domain
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
53
        self.os = os
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69

    @property
    def fqdn(self):
        return self.hostname + "." + self.domain

    @property
    def arecord(self):
        return self.hostname + " IN A " + self.ip + "\n"

    @property
    def ptrrecord(self):
        return ".".join(raddr(self.ip)) + " IN PTR " + self.fqdn + ".\n"


class Alias(Host):
    def __init__(self, host, alias):
70
        super(Alias, self).__init__(host.hostname, host.ip, host.mac,
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
71
                                    host.domain, host.os)
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
72 73 74 75
        self.alias = alias

    @property
    def cnamerecord(self):
76 77
        return (self.alias + " IN CNAME " + self.hostname + "." +
                self.domain + ".\n")
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
78 79 80 81 82 83 84 85

    @property
    def fqdn(self):
        return self.alias + "." + self.domain


class Env(object):

86 87 88 89
    def update_packages(self, os):
        for section in self.conf.files[os]:
          self.evaluate(os, section)

Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
90 91 92 93 94 95 96 97 98 99 100 101 102
    def evaluate(self, filename, section):
        for k, v in self.conf.get_section(filename, section):
            setattr(self, k, v)

    def __init__(self, conf):
        self.conf = conf
        for f, sections in conf.files.iteritems():
            for s in sections:
                self.evaluate(f, s)

        self.node2hostname = dict(conf.get_section("nodes", "hostnames"))
        self.node2ip = dict(conf.get_section("nodes", "ips"))
        self.node2mac = dict(conf.get_section("nodes", "macs"))
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
103
        self.node2os = dict(conf.get_section("nodes", "os"))
104 105 106 107 108 109 110 111 112 113 114
        self.hostnames = [self.node2hostname[n]
                          for n in self.nodes.split(",")]

        self.ips = [self.node2ip[n]
                    for n in self.nodes.split(",")]

        self.cluster_hostnames = [self.node2hostname[n]
                                  for n in self.cluster_nodes.split(",")]

        self.cluster_ips = [self.node2ip[n]
                            for n in self.cluster_nodes.split(",")]
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
115 116 117 118 119 120 121

        self.net = ipaddr.IPNetwork(self.subnet)

        self.nodes_info = {}
        self.hosts_info = {}
        self.ips_info = {}
        for node in self.nodes.split(","):
122 123
            host = Host(self.node2hostname[node],
                        self.node2ip[node],
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
124
                        self.node2mac[node], self.domain, self.node2os[node])
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
125 126 127 128 129

            self.nodes_info[node] = host
            self.hosts_info[host.hostname] = host
            self.ips_info[host.ip] = host

130
        self.cluster = Host(self.cluster_name, self.cluster_ip, None,
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
131
                            self.domain, None)
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
132 133 134 135 136 137 138
        self.master = self.nodes_info[self.master_node]

        self.roles = {}
        for role, node in conf.get_section("synnefo", "roles"):
            self.roles[role] = Alias(self.nodes_info[node], role)
            setattr(self, role, self.roles[role])

139

Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
140 141 142
class Conf(object):

    files = {
143
        "nodes": ["network", "info"],
144
        "deploy": ["dirs", "packages", "keys", "options"],
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
145
        "vcluster": ["cluster", "image", "network"],
146
        "synnefo": ["cred", "synnefo", "roles"],
147 148
        "squeeze": ["debian", "ganeti", "synnefo", "other"],
        "wheezy": ["debian", "ganeti", "synnefo", "other"],
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
149
    }
150
    confdir = "/etc/snf-deploy"
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
151

152
    def get_ganeti(self, cluster_name):
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
153
        self.files["ganeti"] = [cluster_name]
154 155 156 157 158


    def __init__(self, args):
        self.confdir = args.confdir
        self.get_ganeti(args.cluster_name)
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
159 160
        for f in self.files.keys():
            setattr(self, f, self.read_config(f))
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
        for f, sections in self.files.iteritems():
            for s in sections:
                for k, v in self.get_section(f, s):
                    if getattr(args, k, None):
                        self.set(f, s, k, getattr(args, k))
        if args.autoconf:
            self.autoconf()

    def autoconf(self):
        #domain = get_domain()
        #if domain:
        #    self.nodes.set("network", "domain", get_domain())
        # self.nodes.set("network", "subnet", "/".join(get_netinfo()))
        # self.nodes.set("network", "gateway", get_default_route()[0])
        self.nodes.set("hostnames", "node1", get_hostname())
        self.nodes.set("ips", "node1", get_netinfo()[0])
        self.nodes.set("info", "nodes", "node1")
        self.nodes.set("info", "public_iface", get_default_route()[1])
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202

    def read_config(self, f):
        config = ConfigParser.ConfigParser()
        config.optionxform = str
        filename = os.path.join(self.confdir, f) + ".conf"
        config.read(filename)
        return config

    def set(self, conf, section, option, value):
        c = getattr(self, conf)
        c.set(section, option, value)

    def get(self, conf, section, option):
        c = getattr(self, conf)
        return c.get(section, option, True)

    def get_section(self, conf, section):
        c = getattr(self, conf)
        return c.items(section, True)

    def print_config(self):
        for f in self.files.keys():
            getattr(self, f).write(sys.stdout)

203

Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
204 205
def debug(host, msg):

206
    print HEADER + host + \
207
        OKBLUE + ": " + msg + ENDC
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223


def check_pidfile(pidfile):
    print("Checking pidfile " + pidfile)
    try:
        f = open(pidfile, "r")
        pid = f.readline()
        os.kill(int(pid), signal.SIGKILL)
        f.close()
        os.remove(pidfile)
        time.sleep(5)
    except:
        pass


def randomMAC():
224 225 226 227
    mac = [0x52, 0x54, 0x56,
           random.randint(0x00, 0xff),
           random.randint(0x00, 0xff),
           random.randint(0x00, 0xff)]
Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
    return ':'.join(map(lambda x: "%02x" % x, mac))


def create_dir(d, clean=False):
    os.system("mkdir -p " + d)
    if clean:
        try:
            os.system("rm -f %s/*" % d)
        except:
            pass


def get_netinfo():
    _, pdev = get_default_route()
    r = re.compile(".*inet (\S+)/(\S+).*")
243 244 245
    s = subprocess.Popen(['ip', 'addr', 'show', 'dev', pdev],
                         stdout=subprocess.PIPE)

Dimitris Aragiorgis's avatar
Dimitris Aragiorgis committed
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
    for line in s.stdout.readlines():
        match = r.search(line)
        if match:
            ip, size = match.groups()
            break

    return ip, size


def get_hostname():
    s = subprocess.Popen(['hostname', '-s'], stdout=subprocess.PIPE)
    return s.stdout.readline().strip()


def get_domain():
    s = subprocess.Popen(['hostname', '-d'], stdout=subprocess.PIPE)
    return s.stdout.readline().strip()


def get_default_route():
    r = re.compile("default via (\S+) dev (\S+)")
    s = subprocess.Popen(['ip', 'route'], stdout=subprocess.PIPE)
    for line in s.stdout.readlines():
        match = r.search(line)
        if match:
            gw, dev = match.groups()
            break

    return (gw, dev)


def import_conf_file(filename, directory):
    return imp.load_module(filename, *imp.find_module(filename, [directory]))


def raddr(addr):
282
    return list(reversed(addr.replace("/", "-").split(".")))