Statistics
| Branch: | Tag: | Revision:

root / snf-deploy / snfdeploy / lib.py @ c0c8263a

History | View | Annotate | Download (7.5 kB)

1 ad76b118 Dimitris Aragiorgis
#!/usr/bin/python
2 ad76b118 Dimitris Aragiorgis
3 ad76b118 Dimitris Aragiorgis
import json
4 ad76b118 Dimitris Aragiorgis
import time
5 ad76b118 Dimitris Aragiorgis
import ipaddr
6 ad76b118 Dimitris Aragiorgis
import os
7 ad76b118 Dimitris Aragiorgis
import signal
8 ad76b118 Dimitris Aragiorgis
import ConfigParser
9 ad76b118 Dimitris Aragiorgis
import sys
10 ad76b118 Dimitris Aragiorgis
import re
11 ad76b118 Dimitris Aragiorgis
import random
12 ad76b118 Dimitris Aragiorgis
import subprocess
13 ad76b118 Dimitris Aragiorgis
import shutil
14 ad76b118 Dimitris Aragiorgis
import imp
15 ad76b118 Dimitris Aragiorgis
import tempfile
16 ad76b118 Dimitris Aragiorgis
from snfdeploy import massedit
17 ad76b118 Dimitris Aragiorgis
18 ad76b118 Dimitris Aragiorgis
19 b7c00e75 Dionysis Grigoropoulos
HEADER = '\033[95m'
20 b7c00e75 Dionysis Grigoropoulos
OKBLUE = '\033[94m'
21 b7c00e75 Dionysis Grigoropoulos
OKGREEN = '\033[92m'
22 b7c00e75 Dionysis Grigoropoulos
WARNING = '\033[93m'
23 b7c00e75 Dionysis Grigoropoulos
FAIL = '\033[91m'
24 b7c00e75 Dionysis Grigoropoulos
ENDC = '\033[0m'
25 b7c00e75 Dionysis Grigoropoulos
26 b7c00e75 Dionysis Grigoropoulos
27 b7c00e75 Dionysis Grigoropoulos
def disable_color():
28 248ae1d1 Erethon
    global HEADER
29 248ae1d1 Erethon
    global OKBLUE
30 248ae1d1 Erethon
    global OKGREEN
31 248ae1d1 Erethon
    global WARNING
32 248ae1d1 Erethon
    global FAIL
33 248ae1d1 Erethon
    global ENDC
34 248ae1d1 Erethon
35 b7c00e75 Dionysis Grigoropoulos
    HEADER = ''
36 b7c00e75 Dionysis Grigoropoulos
    OKBLUE = ''
37 b7c00e75 Dionysis Grigoropoulos
    OKGREEN = ''
38 b7c00e75 Dionysis Grigoropoulos
    WARNING = ''
39 b7c00e75 Dionysis Grigoropoulos
    FAIL = ''
40 b7c00e75 Dionysis Grigoropoulos
    ENDC = ''
41 b7c00e75 Dionysis Grigoropoulos
42 b7c00e75 Dionysis Grigoropoulos
43 b7c00e75 Dionysis Grigoropoulos
if not sys.stdout.isatty():
44 b7c00e75 Dionysis Grigoropoulos
    disable_color()
45 ad76b118 Dimitris Aragiorgis
46 4c09a54a Dionysis Grigoropoulos
47 ad76b118 Dimitris Aragiorgis
class Host(object):
48 f9b1abe8 Dimitris Aragiorgis
    def __init__(self, hostname, ip, mac, domain, os):
49 ad76b118 Dimitris Aragiorgis
        self.hostname = hostname
50 ad76b118 Dimitris Aragiorgis
        self.ip = ip
51 ad76b118 Dimitris Aragiorgis
        self.mac = mac
52 ad76b118 Dimitris Aragiorgis
        self.domain = domain
53 f9b1abe8 Dimitris Aragiorgis
        self.os = os
54 ad76b118 Dimitris Aragiorgis
55 ad76b118 Dimitris Aragiorgis
    @property
56 ad76b118 Dimitris Aragiorgis
    def fqdn(self):
57 ad76b118 Dimitris Aragiorgis
        return self.hostname + "." + self.domain
58 ad76b118 Dimitris Aragiorgis
59 ad76b118 Dimitris Aragiorgis
    @property
60 ad76b118 Dimitris Aragiorgis
    def arecord(self):
61 ad76b118 Dimitris Aragiorgis
        return self.hostname + " IN A " + self.ip + "\n"
62 ad76b118 Dimitris Aragiorgis
63 ad76b118 Dimitris Aragiorgis
    @property
64 ad76b118 Dimitris Aragiorgis
    def ptrrecord(self):
65 ad76b118 Dimitris Aragiorgis
        return ".".join(raddr(self.ip)) + " IN PTR " + self.fqdn + ".\n"
66 ad76b118 Dimitris Aragiorgis
67 ad76b118 Dimitris Aragiorgis
68 ad76b118 Dimitris Aragiorgis
class Alias(Host):
69 ad76b118 Dimitris Aragiorgis
    def __init__(self, host, alias):
70 4c09a54a Dionysis Grigoropoulos
        super(Alias, self).__init__(host.hostname, host.ip, host.mac,
71 f9b1abe8 Dimitris Aragiorgis
                                    host.domain, host.os)
72 ad76b118 Dimitris Aragiorgis
        self.alias = alias
73 ad76b118 Dimitris Aragiorgis
74 ad76b118 Dimitris Aragiorgis
    @property
75 ad76b118 Dimitris Aragiorgis
    def cnamerecord(self):
76 4c09a54a Dionysis Grigoropoulos
        return (self.alias + " IN CNAME " + self.hostname + "." +
77 4c09a54a Dionysis Grigoropoulos
                self.domain + ".\n")
78 ad76b118 Dimitris Aragiorgis
79 ad76b118 Dimitris Aragiorgis
    @property
80 ad76b118 Dimitris Aragiorgis
    def fqdn(self):
81 ad76b118 Dimitris Aragiorgis
        return self.alias + "." + self.domain
82 ad76b118 Dimitris Aragiorgis
83 ad76b118 Dimitris Aragiorgis
84 ad76b118 Dimitris Aragiorgis
class Env(object):
85 ad76b118 Dimitris Aragiorgis
86 ad76b118 Dimitris Aragiorgis
    def evaluate(self, filename, section):
87 ad76b118 Dimitris Aragiorgis
        for k, v in self.conf.get_section(filename, section):
88 ad76b118 Dimitris Aragiorgis
            setattr(self, k, v)
89 ad76b118 Dimitris Aragiorgis
90 ad76b118 Dimitris Aragiorgis
    def __init__(self, conf):
91 ad76b118 Dimitris Aragiorgis
        self.conf = conf
92 ad76b118 Dimitris Aragiorgis
        for f, sections in conf.files.iteritems():
93 ad76b118 Dimitris Aragiorgis
            for s in sections:
94 ad76b118 Dimitris Aragiorgis
                self.evaluate(f, s)
95 ad76b118 Dimitris Aragiorgis
96 ad76b118 Dimitris Aragiorgis
        self.node2hostname = dict(conf.get_section("nodes", "hostnames"))
97 ad76b118 Dimitris Aragiorgis
        self.node2ip = dict(conf.get_section("nodes", "ips"))
98 ad76b118 Dimitris Aragiorgis
        self.node2mac = dict(conf.get_section("nodes", "macs"))
99 f9b1abe8 Dimitris Aragiorgis
        self.node2os = dict(conf.get_section("nodes", "os"))
100 4c09a54a Dionysis Grigoropoulos
        self.hostnames = [self.node2hostname[n]
101 4c09a54a Dionysis Grigoropoulos
                          for n in self.nodes.split(",")]
102 4c09a54a Dionysis Grigoropoulos
103 4c09a54a Dionysis Grigoropoulos
        self.ips = [self.node2ip[n]
104 4c09a54a Dionysis Grigoropoulos
                    for n in self.nodes.split(",")]
105 4c09a54a Dionysis Grigoropoulos
106 4c09a54a Dionysis Grigoropoulos
        self.cluster_hostnames = [self.node2hostname[n]
107 4c09a54a Dionysis Grigoropoulos
                                  for n in self.cluster_nodes.split(",")]
108 4c09a54a Dionysis Grigoropoulos
109 4c09a54a Dionysis Grigoropoulos
        self.cluster_ips = [self.node2ip[n]
110 4c09a54a Dionysis Grigoropoulos
                            for n in self.cluster_nodes.split(",")]
111 ad76b118 Dimitris Aragiorgis
112 ad76b118 Dimitris Aragiorgis
        self.net = ipaddr.IPNetwork(self.subnet)
113 ad76b118 Dimitris Aragiorgis
114 ad76b118 Dimitris Aragiorgis
        self.nodes_info = {}
115 ad76b118 Dimitris Aragiorgis
        self.hosts_info = {}
116 ad76b118 Dimitris Aragiorgis
        self.ips_info = {}
117 ad76b118 Dimitris Aragiorgis
        for node in self.nodes.split(","):
118 4c09a54a Dionysis Grigoropoulos
            host = Host(self.node2hostname[node],
119 4c09a54a Dionysis Grigoropoulos
                        self.node2ip[node],
120 f9b1abe8 Dimitris Aragiorgis
                        self.node2mac[node], self.domain, self.node2os[node])
121 ad76b118 Dimitris Aragiorgis
122 ad76b118 Dimitris Aragiorgis
            self.nodes_info[node] = host
123 ad76b118 Dimitris Aragiorgis
            self.hosts_info[host.hostname] = host
124 ad76b118 Dimitris Aragiorgis
            self.ips_info[host.ip] = host
125 ad76b118 Dimitris Aragiorgis
126 4c09a54a Dionysis Grigoropoulos
        self.cluster = Host(self.cluster_name, self.cluster_ip, None,
127 4baa4696 Dimitris Aragiorgis
                            self.domain, None)
128 ad76b118 Dimitris Aragiorgis
        self.master = self.nodes_info[self.master_node]
129 ad76b118 Dimitris Aragiorgis
130 ad76b118 Dimitris Aragiorgis
        self.roles = {}
131 ad76b118 Dimitris Aragiorgis
        for role, node in conf.get_section("synnefo", "roles"):
132 ad76b118 Dimitris Aragiorgis
            self.roles[role] = Alias(self.nodes_info[node], role)
133 ad76b118 Dimitris Aragiorgis
            setattr(self, role, self.roles[role])
134 ad76b118 Dimitris Aragiorgis
135 4c09a54a Dionysis Grigoropoulos
136 ad76b118 Dimitris Aragiorgis
class Conf(object):
137 ad76b118 Dimitris Aragiorgis
138 ad76b118 Dimitris Aragiorgis
    files = {
139 4c09a54a Dionysis Grigoropoulos
        "nodes": ["network", "info"],
140 8ed8742f Christos Stavrakakis
        "deploy": ["dirs", "packages", "keys", "options"],
141 4baa4696 Dimitris Aragiorgis
        "vcluster": ["cluster", "image", "network"],
142 4c09a54a Dionysis Grigoropoulos
        "synnefo": ["cred", "synnefo", "roles"],
143 4c09a54a Dionysis Grigoropoulos
        "packages": ["debian", "ganeti", "synnefo", "other"],
144 4c09a54a Dionysis Grigoropoulos
        "ganeti": [],
145 ad76b118 Dimitris Aragiorgis
    }
146 ad76b118 Dimitris Aragiorgis
147 ad76b118 Dimitris Aragiorgis
    def __init__(self, confdir, cluster_name):
148 ad76b118 Dimitris Aragiorgis
        self.confdir = confdir
149 ad76b118 Dimitris Aragiorgis
        self.files["ganeti"] = [cluster_name]
150 ad76b118 Dimitris Aragiorgis
        for f in self.files.keys():
151 ad76b118 Dimitris Aragiorgis
            setattr(self, f, self.read_config(f))
152 ad76b118 Dimitris Aragiorgis
153 ad76b118 Dimitris Aragiorgis
    def read_config(self, f):
154 ad76b118 Dimitris Aragiorgis
        config = ConfigParser.ConfigParser()
155 ad76b118 Dimitris Aragiorgis
        config.optionxform = str
156 ad76b118 Dimitris Aragiorgis
        filename = os.path.join(self.confdir, f) + ".conf"
157 ad76b118 Dimitris Aragiorgis
        config.read(filename)
158 ad76b118 Dimitris Aragiorgis
        return config
159 ad76b118 Dimitris Aragiorgis
160 ad76b118 Dimitris Aragiorgis
    def set(self, conf, section, option, value):
161 ad76b118 Dimitris Aragiorgis
        c = getattr(self, conf)
162 ad76b118 Dimitris Aragiorgis
        c.set(section, option, value)
163 ad76b118 Dimitris Aragiorgis
164 ad76b118 Dimitris Aragiorgis
    def get(self, conf, section, option):
165 ad76b118 Dimitris Aragiorgis
        c = getattr(self, conf)
166 ad76b118 Dimitris Aragiorgis
        return c.get(section, option, True)
167 ad76b118 Dimitris Aragiorgis
168 ad76b118 Dimitris Aragiorgis
    def get_section(self, conf, section):
169 ad76b118 Dimitris Aragiorgis
        c = getattr(self, conf)
170 ad76b118 Dimitris Aragiorgis
        return c.items(section, True)
171 ad76b118 Dimitris Aragiorgis
172 ad76b118 Dimitris Aragiorgis
    def print_config(self):
173 ad76b118 Dimitris Aragiorgis
        for f in self.files.keys():
174 ad76b118 Dimitris Aragiorgis
            getattr(self, f).write(sys.stdout)
175 ad76b118 Dimitris Aragiorgis
176 ad76b118 Dimitris Aragiorgis
    def _configure(self, args):
177 ad76b118 Dimitris Aragiorgis
        for f, sections in self.files.iteritems():
178 ad76b118 Dimitris Aragiorgis
            for s in sections:
179 ad76b118 Dimitris Aragiorgis
                for k, v in self.get_section(f, s):
180 ad76b118 Dimitris Aragiorgis
                    if getattr(args, k, None):
181 ad76b118 Dimitris Aragiorgis
                        self.set(f, s, k, getattr(args, k))
182 ad76b118 Dimitris Aragiorgis
183 ad76b118 Dimitris Aragiorgis
    @classmethod
184 ad76b118 Dimitris Aragiorgis
    def configure(cls, confdir="/etc/snf-deploy",
185 ad76b118 Dimitris Aragiorgis
                  cluster_name="ganeti1", args=None, autoconf=False):
186 ad76b118 Dimitris Aragiorgis
187 ad76b118 Dimitris Aragiorgis
        conf = cls(confdir, cluster_name)
188 ad76b118 Dimitris Aragiorgis
        if args:
189 ad76b118 Dimitris Aragiorgis
            conf._configure(args)
190 ad76b118 Dimitris Aragiorgis
        if autoconf:
191 ad76b118 Dimitris Aragiorgis
            conf.autoconf()
192 ad76b118 Dimitris Aragiorgis
193 ad76b118 Dimitris Aragiorgis
        return conf
194 ad76b118 Dimitris Aragiorgis
195 ad76b118 Dimitris Aragiorgis
    def autoconf(self):
196 ad76b118 Dimitris Aragiorgis
        #domain = get_domain()
197 ad76b118 Dimitris Aragiorgis
        #if domain:
198 ad76b118 Dimitris Aragiorgis
        #    self.nodes.set("network", "domain", get_domain())
199 4baa4696 Dimitris Aragiorgis
        # self.nodes.set("network", "subnet", "/".join(get_netinfo()))
200 4baa4696 Dimitris Aragiorgis
        # self.nodes.set("network", "gateway", get_default_route()[0])
201 ad76b118 Dimitris Aragiorgis
        self.nodes.set("hostnames", "node1", get_hostname())
202 ad76b118 Dimitris Aragiorgis
        self.nodes.set("ips", "node1", get_netinfo()[0])
203 ad76b118 Dimitris Aragiorgis
        self.nodes.set("info", "nodes", "node1")
204 ad76b118 Dimitris Aragiorgis
        self.nodes.set("info", "public_iface", get_default_route()[1])
205 ad76b118 Dimitris Aragiorgis
206 ad76b118 Dimitris Aragiorgis
207 ad76b118 Dimitris Aragiorgis
def debug(host, msg):
208 ad76b118 Dimitris Aragiorgis
209 b7c00e75 Dionysis Grigoropoulos
    print HEADER + host + \
210 4c09a54a Dionysis Grigoropoulos
        OKBLUE + ": " + msg + ENDC
211 ad76b118 Dimitris Aragiorgis
212 ad76b118 Dimitris Aragiorgis
213 ad76b118 Dimitris Aragiorgis
def check_pidfile(pidfile):
214 ad76b118 Dimitris Aragiorgis
    print("Checking pidfile " + pidfile)
215 ad76b118 Dimitris Aragiorgis
    try:
216 ad76b118 Dimitris Aragiorgis
        f = open(pidfile, "r")
217 ad76b118 Dimitris Aragiorgis
        pid = f.readline()
218 ad76b118 Dimitris Aragiorgis
        os.kill(int(pid), signal.SIGKILL)
219 ad76b118 Dimitris Aragiorgis
        f.close()
220 ad76b118 Dimitris Aragiorgis
        os.remove(pidfile)
221 ad76b118 Dimitris Aragiorgis
        time.sleep(5)
222 ad76b118 Dimitris Aragiorgis
    except:
223 ad76b118 Dimitris Aragiorgis
        pass
224 ad76b118 Dimitris Aragiorgis
225 ad76b118 Dimitris Aragiorgis
226 ad76b118 Dimitris Aragiorgis
def randomMAC():
227 4c09a54a Dionysis Grigoropoulos
    mac = [0x52, 0x54, 0x56,
228 4c09a54a Dionysis Grigoropoulos
           random.randint(0x00, 0xff),
229 4c09a54a Dionysis Grigoropoulos
           random.randint(0x00, 0xff),
230 4c09a54a Dionysis Grigoropoulos
           random.randint(0x00, 0xff)]
231 ad76b118 Dimitris Aragiorgis
    return ':'.join(map(lambda x: "%02x" % x, mac))
232 ad76b118 Dimitris Aragiorgis
233 ad76b118 Dimitris Aragiorgis
234 ad76b118 Dimitris Aragiorgis
def create_dir(d, clean=False):
235 ad76b118 Dimitris Aragiorgis
    os.system("mkdir -p " + d)
236 ad76b118 Dimitris Aragiorgis
    if clean:
237 ad76b118 Dimitris Aragiorgis
        try:
238 ad76b118 Dimitris Aragiorgis
            os.system("rm -f %s/*" % d)
239 ad76b118 Dimitris Aragiorgis
        except:
240 ad76b118 Dimitris Aragiorgis
            pass
241 ad76b118 Dimitris Aragiorgis
242 ad76b118 Dimitris Aragiorgis
243 ad76b118 Dimitris Aragiorgis
def get_netinfo():
244 ad76b118 Dimitris Aragiorgis
    _, pdev = get_default_route()
245 ad76b118 Dimitris Aragiorgis
    r = re.compile(".*inet (\S+)/(\S+).*")
246 4c09a54a Dionysis Grigoropoulos
    s = subprocess.Popen(['ip', 'addr', 'show', 'dev', pdev],
247 4c09a54a Dionysis Grigoropoulos
                         stdout=subprocess.PIPE)
248 4c09a54a Dionysis Grigoropoulos
249 ad76b118 Dimitris Aragiorgis
    for line in s.stdout.readlines():
250 ad76b118 Dimitris Aragiorgis
        match = r.search(line)
251 ad76b118 Dimitris Aragiorgis
        if match:
252 ad76b118 Dimitris Aragiorgis
            ip, size = match.groups()
253 ad76b118 Dimitris Aragiorgis
            break
254 ad76b118 Dimitris Aragiorgis
255 ad76b118 Dimitris Aragiorgis
    return ip, size
256 ad76b118 Dimitris Aragiorgis
257 ad76b118 Dimitris Aragiorgis
258 ad76b118 Dimitris Aragiorgis
def get_hostname():
259 ad76b118 Dimitris Aragiorgis
    s = subprocess.Popen(['hostname', '-s'], stdout=subprocess.PIPE)
260 ad76b118 Dimitris Aragiorgis
    return s.stdout.readline().strip()
261 ad76b118 Dimitris Aragiorgis
262 ad76b118 Dimitris Aragiorgis
263 ad76b118 Dimitris Aragiorgis
def get_domain():
264 ad76b118 Dimitris Aragiorgis
    s = subprocess.Popen(['hostname', '-d'], stdout=subprocess.PIPE)
265 ad76b118 Dimitris Aragiorgis
    return s.stdout.readline().strip()
266 ad76b118 Dimitris Aragiorgis
267 ad76b118 Dimitris Aragiorgis
268 ad76b118 Dimitris Aragiorgis
def get_default_route():
269 ad76b118 Dimitris Aragiorgis
    r = re.compile("default via (\S+) dev (\S+)")
270 ad76b118 Dimitris Aragiorgis
    s = subprocess.Popen(['ip', 'route'], stdout=subprocess.PIPE)
271 ad76b118 Dimitris Aragiorgis
    for line in s.stdout.readlines():
272 ad76b118 Dimitris Aragiorgis
        match = r.search(line)
273 ad76b118 Dimitris Aragiorgis
        if match:
274 ad76b118 Dimitris Aragiorgis
            gw, dev = match.groups()
275 ad76b118 Dimitris Aragiorgis
            break
276 ad76b118 Dimitris Aragiorgis
277 ad76b118 Dimitris Aragiorgis
    return (gw, dev)
278 ad76b118 Dimitris Aragiorgis
279 ad76b118 Dimitris Aragiorgis
280 ad76b118 Dimitris Aragiorgis
def import_conf_file(filename, directory):
281 ad76b118 Dimitris Aragiorgis
    return imp.load_module(filename, *imp.find_module(filename, [directory]))
282 ad76b118 Dimitris Aragiorgis
283 ad76b118 Dimitris Aragiorgis
284 ad76b118 Dimitris Aragiorgis
def raddr(addr):
285 4c09a54a Dionysis Grigoropoulos
    return list(reversed(addr.replace("/", "-").split(".")))