Statistics
| Branch: | Tag: | Revision:

root / snf-deploy / snfdeploy / lib.py @ 7aa13555

History | View | Annotate | Download (7.7 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 e083e94c Dimitris Aragiorgis
    def update_packages(self, os):
87 e083e94c Dimitris Aragiorgis
        for section in self.conf.files[os]:
88 e083e94c Dimitris Aragiorgis
          self.evaluate(os, section)
89 e083e94c Dimitris Aragiorgis
90 ad76b118 Dimitris Aragiorgis
    def evaluate(self, filename, section):
91 ad76b118 Dimitris Aragiorgis
        for k, v in self.conf.get_section(filename, section):
92 ad76b118 Dimitris Aragiorgis
            setattr(self, k, v)
93 ad76b118 Dimitris Aragiorgis
94 ad76b118 Dimitris Aragiorgis
    def __init__(self, conf):
95 ad76b118 Dimitris Aragiorgis
        self.conf = conf
96 ad76b118 Dimitris Aragiorgis
        for f, sections in conf.files.iteritems():
97 ad76b118 Dimitris Aragiorgis
            for s in sections:
98 ad76b118 Dimitris Aragiorgis
                self.evaluate(f, s)
99 ad76b118 Dimitris Aragiorgis
100 ad76b118 Dimitris Aragiorgis
        self.node2hostname = dict(conf.get_section("nodes", "hostnames"))
101 ad76b118 Dimitris Aragiorgis
        self.node2ip = dict(conf.get_section("nodes", "ips"))
102 ad76b118 Dimitris Aragiorgis
        self.node2mac = dict(conf.get_section("nodes", "macs"))
103 f9b1abe8 Dimitris Aragiorgis
        self.node2os = dict(conf.get_section("nodes", "os"))
104 4c09a54a Dionysis Grigoropoulos
        self.hostnames = [self.node2hostname[n]
105 4c09a54a Dionysis Grigoropoulos
                          for n in self.nodes.split(",")]
106 4c09a54a Dionysis Grigoropoulos
107 4c09a54a Dionysis Grigoropoulos
        self.ips = [self.node2ip[n]
108 4c09a54a Dionysis Grigoropoulos
                    for n in self.nodes.split(",")]
109 4c09a54a Dionysis Grigoropoulos
110 4c09a54a Dionysis Grigoropoulos
        self.cluster_hostnames = [self.node2hostname[n]
111 4c09a54a Dionysis Grigoropoulos
                                  for n in self.cluster_nodes.split(",")]
112 4c09a54a Dionysis Grigoropoulos
113 4c09a54a Dionysis Grigoropoulos
        self.cluster_ips = [self.node2ip[n]
114 4c09a54a Dionysis Grigoropoulos
                            for n in self.cluster_nodes.split(",")]
115 ad76b118 Dimitris Aragiorgis
116 ad76b118 Dimitris Aragiorgis
        self.net = ipaddr.IPNetwork(self.subnet)
117 ad76b118 Dimitris Aragiorgis
118 ad76b118 Dimitris Aragiorgis
        self.nodes_info = {}
119 ad76b118 Dimitris Aragiorgis
        self.hosts_info = {}
120 ad76b118 Dimitris Aragiorgis
        self.ips_info = {}
121 ad76b118 Dimitris Aragiorgis
        for node in self.nodes.split(","):
122 4c09a54a Dionysis Grigoropoulos
            host = Host(self.node2hostname[node],
123 4c09a54a Dionysis Grigoropoulos
                        self.node2ip[node],
124 f9b1abe8 Dimitris Aragiorgis
                        self.node2mac[node], self.domain, self.node2os[node])
125 ad76b118 Dimitris Aragiorgis
126 ad76b118 Dimitris Aragiorgis
            self.nodes_info[node] = host
127 ad76b118 Dimitris Aragiorgis
            self.hosts_info[host.hostname] = host
128 ad76b118 Dimitris Aragiorgis
            self.ips_info[host.ip] = host
129 ad76b118 Dimitris Aragiorgis
130 4c09a54a Dionysis Grigoropoulos
        self.cluster = Host(self.cluster_name, self.cluster_ip, None,
131 4baa4696 Dimitris Aragiorgis
                            self.domain, None)
132 ad76b118 Dimitris Aragiorgis
        self.master = self.nodes_info[self.master_node]
133 ad76b118 Dimitris Aragiorgis
134 ad76b118 Dimitris Aragiorgis
        self.roles = {}
135 ad76b118 Dimitris Aragiorgis
        for role, node in conf.get_section("synnefo", "roles"):
136 ad76b118 Dimitris Aragiorgis
            self.roles[role] = Alias(self.nodes_info[node], role)
137 ad76b118 Dimitris Aragiorgis
            setattr(self, role, self.roles[role])
138 ad76b118 Dimitris Aragiorgis
139 4c09a54a Dionysis Grigoropoulos
140 ad76b118 Dimitris Aragiorgis
class Conf(object):
141 ad76b118 Dimitris Aragiorgis
142 ad76b118 Dimitris Aragiorgis
    files = {
143 4c09a54a Dionysis Grigoropoulos
        "nodes": ["network", "info"],
144 8ed8742f Christos Stavrakakis
        "deploy": ["dirs", "packages", "keys", "options"],
145 4baa4696 Dimitris Aragiorgis
        "vcluster": ["cluster", "image", "network"],
146 4c09a54a Dionysis Grigoropoulos
        "synnefo": ["cred", "synnefo", "roles"],
147 4c09a54a Dionysis Grigoropoulos
        "packages": ["debian", "ganeti", "synnefo", "other"],
148 e083e94c Dimitris Aragiorgis
        "squeeze": ["debian", "ganeti", "synnefo", "other"],
149 e083e94c Dimitris Aragiorgis
        "wheezy": ["debian", "ganeti", "synnefo", "other"],
150 4c09a54a Dionysis Grigoropoulos
        "ganeti": [],
151 ad76b118 Dimitris Aragiorgis
    }
152 ad76b118 Dimitris Aragiorgis
153 ad76b118 Dimitris Aragiorgis
    def __init__(self, confdir, cluster_name):
154 ad76b118 Dimitris Aragiorgis
        self.confdir = confdir
155 ad76b118 Dimitris Aragiorgis
        self.files["ganeti"] = [cluster_name]
156 ad76b118 Dimitris Aragiorgis
        for f in self.files.keys():
157 ad76b118 Dimitris Aragiorgis
            setattr(self, f, self.read_config(f))
158 ad76b118 Dimitris Aragiorgis
159 ad76b118 Dimitris Aragiorgis
    def read_config(self, f):
160 ad76b118 Dimitris Aragiorgis
        config = ConfigParser.ConfigParser()
161 ad76b118 Dimitris Aragiorgis
        config.optionxform = str
162 ad76b118 Dimitris Aragiorgis
        filename = os.path.join(self.confdir, f) + ".conf"
163 ad76b118 Dimitris Aragiorgis
        config.read(filename)
164 ad76b118 Dimitris Aragiorgis
        return config
165 ad76b118 Dimitris Aragiorgis
166 ad76b118 Dimitris Aragiorgis
    def set(self, conf, section, option, value):
167 ad76b118 Dimitris Aragiorgis
        c = getattr(self, conf)
168 ad76b118 Dimitris Aragiorgis
        c.set(section, option, value)
169 ad76b118 Dimitris Aragiorgis
170 ad76b118 Dimitris Aragiorgis
    def get(self, conf, section, option):
171 ad76b118 Dimitris Aragiorgis
        c = getattr(self, conf)
172 ad76b118 Dimitris Aragiorgis
        return c.get(section, option, True)
173 ad76b118 Dimitris Aragiorgis
174 ad76b118 Dimitris Aragiorgis
    def get_section(self, conf, section):
175 ad76b118 Dimitris Aragiorgis
        c = getattr(self, conf)
176 ad76b118 Dimitris Aragiorgis
        return c.items(section, True)
177 ad76b118 Dimitris Aragiorgis
178 ad76b118 Dimitris Aragiorgis
    def print_config(self):
179 ad76b118 Dimitris Aragiorgis
        for f in self.files.keys():
180 ad76b118 Dimitris Aragiorgis
            getattr(self, f).write(sys.stdout)
181 ad76b118 Dimitris Aragiorgis
182 ad76b118 Dimitris Aragiorgis
    def _configure(self, args):
183 ad76b118 Dimitris Aragiorgis
        for f, sections in self.files.iteritems():
184 ad76b118 Dimitris Aragiorgis
            for s in sections:
185 ad76b118 Dimitris Aragiorgis
                for k, v in self.get_section(f, s):
186 ad76b118 Dimitris Aragiorgis
                    if getattr(args, k, None):
187 ad76b118 Dimitris Aragiorgis
                        self.set(f, s, k, getattr(args, k))
188 ad76b118 Dimitris Aragiorgis
189 ad76b118 Dimitris Aragiorgis
    @classmethod
190 ad76b118 Dimitris Aragiorgis
    def configure(cls, confdir="/etc/snf-deploy",
191 ad76b118 Dimitris Aragiorgis
                  cluster_name="ganeti1", args=None, autoconf=False):
192 ad76b118 Dimitris Aragiorgis
193 ad76b118 Dimitris Aragiorgis
        conf = cls(confdir, cluster_name)
194 ad76b118 Dimitris Aragiorgis
        if args:
195 ad76b118 Dimitris Aragiorgis
            conf._configure(args)
196 ad76b118 Dimitris Aragiorgis
        if autoconf:
197 ad76b118 Dimitris Aragiorgis
            conf.autoconf()
198 ad76b118 Dimitris Aragiorgis
199 ad76b118 Dimitris Aragiorgis
        return conf
200 ad76b118 Dimitris Aragiorgis
201 ad76b118 Dimitris Aragiorgis
    def autoconf(self):
202 ad76b118 Dimitris Aragiorgis
        #domain = get_domain()
203 ad76b118 Dimitris Aragiorgis
        #if domain:
204 ad76b118 Dimitris Aragiorgis
        #    self.nodes.set("network", "domain", get_domain())
205 4baa4696 Dimitris Aragiorgis
        # self.nodes.set("network", "subnet", "/".join(get_netinfo()))
206 4baa4696 Dimitris Aragiorgis
        # self.nodes.set("network", "gateway", get_default_route()[0])
207 ad76b118 Dimitris Aragiorgis
        self.nodes.set("hostnames", "node1", get_hostname())
208 ad76b118 Dimitris Aragiorgis
        self.nodes.set("ips", "node1", get_netinfo()[0])
209 ad76b118 Dimitris Aragiorgis
        self.nodes.set("info", "nodes", "node1")
210 ad76b118 Dimitris Aragiorgis
        self.nodes.set("info", "public_iface", get_default_route()[1])
211 ad76b118 Dimitris Aragiorgis
212 ad76b118 Dimitris Aragiorgis
213 e083e94c Dimitris Aragiorgis
214 ad76b118 Dimitris Aragiorgis
def debug(host, msg):
215 ad76b118 Dimitris Aragiorgis
216 b7c00e75 Dionysis Grigoropoulos
    print HEADER + host + \
217 4c09a54a Dionysis Grigoropoulos
        OKBLUE + ": " + msg + ENDC
218 ad76b118 Dimitris Aragiorgis
219 ad76b118 Dimitris Aragiorgis
220 ad76b118 Dimitris Aragiorgis
def check_pidfile(pidfile):
221 ad76b118 Dimitris Aragiorgis
    print("Checking pidfile " + pidfile)
222 ad76b118 Dimitris Aragiorgis
    try:
223 ad76b118 Dimitris Aragiorgis
        f = open(pidfile, "r")
224 ad76b118 Dimitris Aragiorgis
        pid = f.readline()
225 ad76b118 Dimitris Aragiorgis
        os.kill(int(pid), signal.SIGKILL)
226 ad76b118 Dimitris Aragiorgis
        f.close()
227 ad76b118 Dimitris Aragiorgis
        os.remove(pidfile)
228 ad76b118 Dimitris Aragiorgis
        time.sleep(5)
229 ad76b118 Dimitris Aragiorgis
    except:
230 ad76b118 Dimitris Aragiorgis
        pass
231 ad76b118 Dimitris Aragiorgis
232 ad76b118 Dimitris Aragiorgis
233 ad76b118 Dimitris Aragiorgis
def randomMAC():
234 4c09a54a Dionysis Grigoropoulos
    mac = [0x52, 0x54, 0x56,
235 4c09a54a Dionysis Grigoropoulos
           random.randint(0x00, 0xff),
236 4c09a54a Dionysis Grigoropoulos
           random.randint(0x00, 0xff),
237 4c09a54a Dionysis Grigoropoulos
           random.randint(0x00, 0xff)]
238 ad76b118 Dimitris Aragiorgis
    return ':'.join(map(lambda x: "%02x" % x, mac))
239 ad76b118 Dimitris Aragiorgis
240 ad76b118 Dimitris Aragiorgis
241 ad76b118 Dimitris Aragiorgis
def create_dir(d, clean=False):
242 ad76b118 Dimitris Aragiorgis
    os.system("mkdir -p " + d)
243 ad76b118 Dimitris Aragiorgis
    if clean:
244 ad76b118 Dimitris Aragiorgis
        try:
245 ad76b118 Dimitris Aragiorgis
            os.system("rm -f %s/*" % d)
246 ad76b118 Dimitris Aragiorgis
        except:
247 ad76b118 Dimitris Aragiorgis
            pass
248 ad76b118 Dimitris Aragiorgis
249 ad76b118 Dimitris Aragiorgis
250 ad76b118 Dimitris Aragiorgis
def get_netinfo():
251 ad76b118 Dimitris Aragiorgis
    _, pdev = get_default_route()
252 ad76b118 Dimitris Aragiorgis
    r = re.compile(".*inet (\S+)/(\S+).*")
253 4c09a54a Dionysis Grigoropoulos
    s = subprocess.Popen(['ip', 'addr', 'show', 'dev', pdev],
254 4c09a54a Dionysis Grigoropoulos
                         stdout=subprocess.PIPE)
255 4c09a54a Dionysis Grigoropoulos
256 ad76b118 Dimitris Aragiorgis
    for line in s.stdout.readlines():
257 ad76b118 Dimitris Aragiorgis
        match = r.search(line)
258 ad76b118 Dimitris Aragiorgis
        if match:
259 ad76b118 Dimitris Aragiorgis
            ip, size = match.groups()
260 ad76b118 Dimitris Aragiorgis
            break
261 ad76b118 Dimitris Aragiorgis
262 ad76b118 Dimitris Aragiorgis
    return ip, size
263 ad76b118 Dimitris Aragiorgis
264 ad76b118 Dimitris Aragiorgis
265 ad76b118 Dimitris Aragiorgis
def get_hostname():
266 ad76b118 Dimitris Aragiorgis
    s = subprocess.Popen(['hostname', '-s'], stdout=subprocess.PIPE)
267 ad76b118 Dimitris Aragiorgis
    return s.stdout.readline().strip()
268 ad76b118 Dimitris Aragiorgis
269 ad76b118 Dimitris Aragiorgis
270 ad76b118 Dimitris Aragiorgis
def get_domain():
271 ad76b118 Dimitris Aragiorgis
    s = subprocess.Popen(['hostname', '-d'], stdout=subprocess.PIPE)
272 ad76b118 Dimitris Aragiorgis
    return s.stdout.readline().strip()
273 ad76b118 Dimitris Aragiorgis
274 ad76b118 Dimitris Aragiorgis
275 ad76b118 Dimitris Aragiorgis
def get_default_route():
276 ad76b118 Dimitris Aragiorgis
    r = re.compile("default via (\S+) dev (\S+)")
277 ad76b118 Dimitris Aragiorgis
    s = subprocess.Popen(['ip', 'route'], stdout=subprocess.PIPE)
278 ad76b118 Dimitris Aragiorgis
    for line in s.stdout.readlines():
279 ad76b118 Dimitris Aragiorgis
        match = r.search(line)
280 ad76b118 Dimitris Aragiorgis
        if match:
281 ad76b118 Dimitris Aragiorgis
            gw, dev = match.groups()
282 ad76b118 Dimitris Aragiorgis
            break
283 ad76b118 Dimitris Aragiorgis
284 ad76b118 Dimitris Aragiorgis
    return (gw, dev)
285 ad76b118 Dimitris Aragiorgis
286 ad76b118 Dimitris Aragiorgis
287 ad76b118 Dimitris Aragiorgis
def import_conf_file(filename, directory):
288 ad76b118 Dimitris Aragiorgis
    return imp.load_module(filename, *imp.find_module(filename, [directory]))
289 ad76b118 Dimitris Aragiorgis
290 ad76b118 Dimitris Aragiorgis
291 ad76b118 Dimitris Aragiorgis
def raddr(addr):
292 4c09a54a Dionysis Grigoropoulos
    return list(reversed(addr.replace("/", "-").split(".")))