get config from file.
[nodemanager.git] / codemux.py
1 # $Id$
2 # $URL$
3
4 """Codemux configurator.  Monitors slice attributes and configures CoDemux to mux port 80 based on HOST field in HTTP request.  Forwards to localhost port belonging to configured slice."""
5
6 import logger
7 import os
8 import vserver
9 from sets import Set
10 from config import Config
11
12 CODEMUXCONF="/etc/codemux/codemux.conf"
13
14 def start(options, config):
15     pass
16
17
18 def GetSlivers(data):
19     """For each sliver with the codemux attribute, parse out "host,port" and make entry in conf.  Restart service after."""
20     logger.log("codemux:  Starting.", 2)
21     # slices already in conf
22     slicesinconf = parseConf()
23     # slices that need to be written to the conf
24     codemuxslices = {}
25     
26     # XXX Hack for planetflow
27     if slicesinconf.has_key("root"): _writeconf = False
28     else: _writeconf = True
29
30     # Parse attributes and update dict of scripts
31     for sliver in data['slivers']:
32         for attribute in sliver['attributes']:
33             if attribute['name'] == 'codemux':
34                 # add to conf.  Attribute is [host, port]
35                 [host, port] = attribute['value'].split(",")
36                 try:
37                     # Check to see if sliver is running.  If not, continue
38                     if vserver.VServer(sliver['name']).is_running():
39                         # Add to dict of codemuxslices 
40                         codemuxslices[sliver['name']] = {'host': host, 'port': port}
41                         # Check if new
42                         if sliver['name'] not in slicesinconf.keys():
43                             logger.log("codemux:  New slice %s using %s" % \
44                                 (sliver['name'], host))
45                             #  Toggle write.
46                             _writeconf = True
47                         # Check old slivers for changes
48                         else:
49                             # Get info about slice in conf
50                             sliverinconf = slicesinconf[sliver['name']]
51                             # Check values for changes.
52                             if (sliverinconf['host'] != host) or \
53                                 (sliverinconf['port'] != port):
54                                 logger.log("codemux:  Updating slice %s" % sliver['name'])
55                                 # use updated values
56                                 codemuxslices[sliver['name']] = {'host': host, 'port': port}
57                                 #  Toggle write.
58                                 _writeconf = True
59                 except:
60                     logger.log("codemux:  sliver %s not running yet.  Deferring."\
61                                 % sliver['name'])
62
63                     logger.log_exc(name = "codemux")
64                     pass
65
66     # Remove slices from conf that no longer have the attribute
67     for deadslice in Set(slicesinconf.keys()) - Set(codemuxslices.keys()):
68         # XXX Hack for root slice
69         if deadslice != "root": 
70             logger.log("codemux:  Removing %s" % deadslice)
71             _writeconf = True 
72
73     if _writeconf:  writeConf(codemuxslices)
74
75 def writeConf(slivers, conf = CODEMUXCONF):
76     '''Write conf with default entry up top.  Write lower order domain names first. Restart service.'''
77     f = open(conf, "w")
78     # This needs to be the first entry...
79     f.write("* root %s\n", Config().PLC_PLANETFLOW_HOST)
80     # Sort items for like domains
81     for slice in sortDomains(slivers):
82         if slice == "root":  continue
83         f.write("%s %s %s\n" % (slivers[slice]['host'], slice, slivers[slice]['port']))
84     f.truncate()
85     f.close()
86     try:  restartService()
87     except:  logger.log_exc()
88
89 def sortDomains(slivers):
90     '''Given a dict of {slice: {domainname, port}}, return array of slivers with lower order domains first'''
91     dnames = {} # {host: slice}
92     for (slice,params) in slivers.iteritems():
93         dnames[params['host']] = slice
94     hosts = dnames.keys()
95     # sort by length
96     hosts.sort(key=str.__len__)
97     # longer first
98     hosts.reverse()
99     # make list of slivers
100     sortedslices = []
101     for host in hosts: sortedslices.append(dnames[host])
102     
103     return sortedslices
104         
105 def parseConf(conf = CODEMUXCONF):
106     '''Parse the CODEMUXCONF and return dict of slices in conf. {slice: (host,port)}'''
107     slicesinconf = {} # default
108     try: 
109         f = open(conf)
110         for line in f.readlines():
111             if line.startswith("#") or (len(line.split()) != 3):
112                 continue
113             (host, slice, port) = line.split()[:3]
114             logger.log("codemux:  found %s in conf" % slice, 2)
115             slicesinconf[slice] = {"host": host, "port": port}
116         f.close()
117     except IOError: logger.log_exc()
118     return slicesinconf
119
120 def restartService():
121     logger.log("codemux:  Restarting codemux service")
122     os.system("/etc/init.d/codemux stop")
123     f = os.popen("/sbin/pidof codemux")
124     tmp = f.readlines()
125     f.close()
126     if len(tmp) > 0: 
127         pids = tmp[0].rstrip("\n").split()
128         for pid in pids:
129             logger.log("codemux:  Killing stalled pid %s" % pid, 2)
130             os.kill(pid, 9)
131     os.system("/etc/init.d/codemux start")