Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.7 kB)

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