Statistics
| Branch: | Tag: | Revision:

root / snf-deploy / snfdeploy / lib.py @ 4b36944e

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