Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.2 kB)

1
#!/usr/bin/python
2

    
3
import json
4
import time
5
import ipaddr
6
import os
7
import signal
8
import ConfigParser
9
import sys
10
import re
11
import random
12
import subprocess
13
import shutil
14
import imp
15
import tempfile
16
from snfdeploy import massedit
17

    
18

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

    
26

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

    
35

    
36
if not sys.stdout.isatty():
37
    disable_color()
38

    
39

    
40
class Host(object):
41
    def __init__(self, hostname, ip, mac, domain):
42
        self.hostname = hostname
43
        self.ip = ip
44
        self.mac = mac
45
        self.domain = domain
46

    
47
    @property
48
    def fqdn(self):
49
        return self.hostname + "." + self.domain
50

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

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

    
59

    
60
class Alias(Host):
61
    def __init__(self, host, alias):
62
        super(Alias, self).__init__(host.hostname, host.ip, host.mac,
63
                                    host.domain)
64
        self.alias = alias
65

    
66
    @property
67
    def cnamerecord(self):
68
        return (self.alias + " IN CNAME " + self.hostname + "." +
69
                self.domain + ".\n")
70

    
71
    @property
72
    def fqdn(self):
73
        return self.alias + "." + self.domain
74

    
75

    
76
class Env(object):
77

    
78
    def evaluate(self, filename, section):
79
        for k, v in self.conf.get_section(filename, section):
80
            setattr(self, k, v)
81

    
82
    def __init__(self, conf):
83
        self.conf = conf
84
        for f, sections in conf.files.iteritems():
85
            for s in sections:
86
                self.evaluate(f, s)
87

    
88
        self.node2hostname = dict(conf.get_section("nodes", "hostnames"))
89
        self.node2ip = dict(conf.get_section("nodes", "ips"))
90
        self.node2mac = dict(conf.get_section("nodes", "macs"))
91
        self.hostnames = [self.node2hostname[n]
92
                          for n in self.nodes.split(",")]
93

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

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

    
100
        self.cluster_ips = [self.node2ip[n]
101
                            for n in self.cluster_nodes.split(",")]
102

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

    
105
        self.nodes_info = {}
106
        self.hosts_info = {}
107
        self.ips_info = {}
108
        for node in self.nodes.split(","):
109
            host = Host(self.node2hostname[node],
110
                        self.node2ip[node],
111
                        self.node2mac[node], self.domain)
112

    
113
            self.nodes_info[node] = host
114
            self.hosts_info[host.hostname] = host
115
            self.ips_info[host.ip] = host
116

    
117
        self.cluster = Host(self.cluster_name, self.cluster_ip, None,
118
                            self.domain)
119
        self.master = self.nodes_info[self.master_node]
120

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

    
126

    
127
class Conf(object):
128

    
129
    files = {
130
        "nodes": ["network", "info"],
131
        "deploy": ["dirs", "packages", "keys", "options"],
132
        "vcluster": ["cluster", "image"],
133
        "synnefo": ["cred", "synnefo", "roles"],
134
        "packages": ["debian", "ganeti", "synnefo", "other"],
135
        "ganeti": [],
136
    }
137

    
138
    def __init__(self, confdir, cluster_name):
139
        self.confdir = confdir
140
        self.files["ganeti"] = [cluster_name]
141
        for f in self.files.keys():
142
            setattr(self, f, self.read_config(f))
143

    
144
    def read_config(self, f):
145
        config = ConfigParser.ConfigParser()
146
        config.optionxform = str
147
        filename = os.path.join(self.confdir, f) + ".conf"
148
        config.read(filename)
149
        return config
150

    
151
    def set(self, conf, section, option, value):
152
        c = getattr(self, conf)
153
        c.set(section, option, value)
154

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

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

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

    
167
    def _configure(self, args):
168
        for f, sections in self.files.iteritems():
169
            for s in sections:
170
                for k, v in self.get_section(f, s):
171
                    if getattr(args, k, None):
172
                        self.set(f, s, k, getattr(args, k))
173

    
174
    @classmethod
175
    def configure(cls, confdir="/etc/snf-deploy",
176
                  cluster_name="ganeti1", args=None, autoconf=False):
177

    
178
        conf = cls(confdir, cluster_name)
179
        if args:
180
            conf._configure(args)
181
        if autoconf:
182
            conf.autoconf()
183

    
184
        return conf
185

    
186
    def autoconf(self):
187
        #domain = get_domain()
188
        #if domain:
189
        #    self.nodes.set("network", "domain", get_domain())
190
        self.nodes.set("network", "subnet", "/".join(get_netinfo()))
191
        self.nodes.set("network", "gateway", get_default_route()[0])
192
        self.nodes.set("hostnames", "node1", get_hostname())
193
        self.nodes.set("ips", "node1", get_netinfo()[0])
194
        self.nodes.set("info", "nodes", "node1")
195
        self.nodes.set("info", "public_iface", get_default_route()[1])
196

    
197

    
198
def debug(host, msg):
199

    
200
    print HEADER + host + \
201
        OKBLUE + ": " + msg + ENDC
202

    
203

    
204
def check_pidfile(pidfile):
205
    print("Checking pidfile " + pidfile)
206
    try:
207
        f = open(pidfile, "r")
208
        pid = f.readline()
209
        os.kill(int(pid), signal.SIGKILL)
210
        f.close()
211
        os.remove(pidfile)
212
        time.sleep(5)
213
    except:
214
        pass
215

    
216

    
217
def randomMAC():
218
    mac = [0x52, 0x54, 0x56,
219
           random.randint(0x00, 0xff),
220
           random.randint(0x00, 0xff),
221
           random.randint(0x00, 0xff)]
222
    return ':'.join(map(lambda x: "%02x" % x, mac))
223

    
224

    
225
def create_dir(d, clean=False):
226
    os.system("mkdir -p " + d)
227
    if clean:
228
        try:
229
            os.system("rm -f %s/*" % d)
230
        except:
231
            pass
232

    
233

    
234
def get_netinfo():
235
    _, pdev = get_default_route()
236
    r = re.compile(".*inet (\S+)/(\S+).*")
237
    s = subprocess.Popen(['ip', 'addr', 'show', 'dev', pdev],
238
                         stdout=subprocess.PIPE)
239

    
240
    for line in s.stdout.readlines():
241
        match = r.search(line)
242
        if match:
243
            ip, size = match.groups()
244
            break
245

    
246
    return ip, size
247

    
248

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

    
253

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

    
258

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

    
268
    return (gw, dev)
269

    
270

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

    
274

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