Statistics
| Branch: | Tag: | Revision:

root / snf-deploy / snfdeploy / lib.py @ 1bc6d467

History | View | Annotate | Download (7 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
class Host(object):
40
    def __init__(self, hostname, ip, mac, domain):
41
        self.hostname = hostname
42
        self.ip = ip
43
        self.mac = mac
44
        self.domain = domain
45

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

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

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

    
58

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

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

    
68
    @property
69
    def fqdn(self):
70
        return self.alias + "." + self.domain
71

    
72

    
73
class Env(object):
74

    
75
    def evaluate(self, filename, section):
76
        for k, v in self.conf.get_section(filename, section):
77
            setattr(self, k, v)
78

    
79
    def __init__(self, conf):
80
        self.conf = conf
81
        for f, sections in conf.files.iteritems():
82
            for s in sections:
83
                self.evaluate(f, s)
84

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

    
93
        self.net = ipaddr.IPNetwork(self.subnet)
94

    
95
        self.nodes_info = {}
96
        self.hosts_info = {}
97
        self.ips_info = {}
98
        for node in self.nodes.split(","):
99
            host =  Host(self.node2hostname[node],
100
                         self.node2ip[node],
101
                         self.node2mac[node], self.domain)
102

    
103
            self.nodes_info[node] = host
104
            self.hosts_info[host.hostname] = host
105
            self.ips_info[host.ip] = host
106

    
107
        self.cluster = Host(self.cluster_name, self.cluster_ip, None, self.domain)
108
        self.master = self.nodes_info[self.master_node]
109

    
110
        self.roles = {}
111
        for role, node in conf.get_section("synnefo", "roles"):
112
            self.roles[role] = Alias(self.nodes_info[node], role)
113
            setattr(self, role, self.roles[role])
114

    
115
class Conf(object):
116

    
117
    files = {
118
      "nodes": ["network", "info"],
119
      "deploy": ["dirs", "packages"],
120
      "vcluster": ["cluster", "image"],
121
      "synnefo": ["cred", "synnefo", "roles"],
122
      "packages": ["debian", "ganeti", "synnefo", "other"],
123
      "ganeti": [],
124
    }
125

    
126
    def __init__(self, confdir, cluster_name):
127
        self.confdir = confdir
128
        self.files["ganeti"] = [cluster_name]
129
        for f in self.files.keys():
130
            setattr(self, f, self.read_config(f))
131

    
132
    def read_config(self, f):
133
        config = ConfigParser.ConfigParser()
134
        config.optionxform = str
135
        filename = os.path.join(self.confdir, f) + ".conf"
136
        config.read(filename)
137
        return config
138

    
139
    def set(self, conf, section, option, value):
140
        c = getattr(self, conf)
141
        c.set(section, option, value)
142

    
143
    def get(self, conf, section, option):
144
        c = getattr(self, conf)
145
        return c.get(section, option, True)
146

    
147
    def get_section(self, conf, section):
148
        c = getattr(self, conf)
149
        return c.items(section, True)
150

    
151
    def print_config(self):
152
        for f in self.files.keys():
153
            getattr(self, f).write(sys.stdout)
154

    
155
    def _configure(self, args):
156
        for f, sections in self.files.iteritems():
157
            for s in sections:
158
                for k, v in self.get_section(f, s):
159
                    if getattr(args, k, None):
160
                        self.set(f, s, k, getattr(args, k))
161

    
162
    @classmethod
163
    def configure(cls, confdir="/etc/snf-deploy",
164
                  cluster_name="ganeti1", args=None, autoconf=False):
165

    
166
        conf = cls(confdir, cluster_name)
167
        if args:
168
            conf._configure(args)
169
        if autoconf:
170
            conf.autoconf()
171

    
172
        return conf
173

    
174
    def autoconf(self):
175
        #domain = get_domain()
176
        #if domain:
177
        #    self.nodes.set("network", "domain", get_domain())
178
        self.nodes.set("network", "subnet", "/".join(get_netinfo()))
179
        self.nodes.set("network", "gateway", get_default_route()[0])
180
        self.nodes.set("hostnames", "node1", get_hostname())
181
        self.nodes.set("ips", "node1", get_netinfo()[0])
182
        self.nodes.set("info", "nodes", "node1")
183
        self.nodes.set("info", "public_iface", get_default_route()[1])
184

    
185

    
186
def debug(host, msg):
187

    
188
    print HEADER + host + \
189
          OKBLUE + ": " + msg + ENDC
190

    
191

    
192
def check_pidfile(pidfile):
193
    print("Checking pidfile " + pidfile)
194
    try:
195
        f = open(pidfile, "r")
196
        pid = f.readline()
197
        os.kill(int(pid), signal.SIGKILL)
198
        f.close()
199
        os.remove(pidfile)
200
        time.sleep(5)
201
    except:
202
        pass
203

    
204

    
205
def randomMAC():
206
    mac = [ 0x52, 0x54, 0x56,
207
        random.randint(0x00, 0xff),
208
        random.randint(0x00, 0xff),
209
        random.randint(0x00, 0xff) ]
210
    return ':'.join(map(lambda x: "%02x" % x, mac))
211

    
212

    
213
def create_dir(d, clean=False):
214
    os.system("mkdir -p " + d)
215
    if clean:
216
        try:
217
            os.system("rm -f %s/*" % d)
218
        except:
219
            pass
220

    
221

    
222
def get_netinfo():
223
    _, pdev = get_default_route()
224
    r = re.compile(".*inet (\S+)/(\S+).*")
225
    s = subprocess.Popen(['ip', 'addr', 'show', 'dev', pdev], stdout=subprocess.PIPE)
226
    for line in s.stdout.readlines():
227
        match = r.search(line)
228
        if match:
229
            ip, size = match.groups()
230
            break
231

    
232
    return ip, size
233

    
234

    
235
def get_hostname():
236
    s = subprocess.Popen(['hostname', '-s'], stdout=subprocess.PIPE)
237
    return s.stdout.readline().strip()
238

    
239

    
240
def get_domain():
241
    s = subprocess.Popen(['hostname', '-d'], stdout=subprocess.PIPE)
242
    return s.stdout.readline().strip()
243

    
244

    
245
def get_default_route():
246
    r = re.compile("default via (\S+) dev (\S+)")
247
    s = subprocess.Popen(['ip', 'route'], stdout=subprocess.PIPE)
248
    for line in s.stdout.readlines():
249
        match = r.search(line)
250
        if match:
251
            gw, dev = match.groups()
252
            break
253

    
254
    return (gw, dev)
255

    
256

    
257
def import_conf_file(filename, directory):
258
    return imp.load_module(filename, *imp.find_module(filename, [directory]))
259

    
260

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