reviewed list options parsing
[tests.git] / system / Trackers.py
1 #!/usr/bin/python
2
3 # Thierry Parmentelat <thierry.parmentelat@inria.fr>
4 # Copyright (C) 2010 INRIA 
5 #
6 import os
7
8 import utils
9 from TestSsh import TestSsh
10
11 # 2 types of trackers
12 # (*) plc trackers remembers the running myplcs
13 # (*) qemu trackers keeps track of the running qemu nodes
14 #
15 # trackers allow us to let the test run after the build has finished, 
16 # and to kill/stop the oldest instances later when we need space
17
18
19 #################### Tracker
20 class Tracker:
21     
22     def __init__ (self, options,filename, instances):
23         self.options=options
24         self.filename=filename
25         self.instances=instances
26         try:
27             tracks=file(self.filename).readlines()
28             tracks = [ track.strip() for track in tracks ]
29         except:
30             tracks=[]
31         self.tracks = [track for track in tracks if track]
32
33     def list (self):
34         try:
35             contents=file(self.filename).read()
36             print "==>",self.filename,"<=="
37             print contents
38         except:
39             print "xxxxxxxxxxxx",self.filename,"not found"
40
41     def store (self):
42         out = file(self.filename,'w')
43         for track in self.tracks:
44             out.write('%s\n'%(track))
45         out.close()
46
47     def record (self,track):
48         for already in self.tracks:
49             if already==track:
50                 print '%s is already included in %s'%(already,self.filename)
51                 return
52         if self.options.dry_run:
53             print 'dry_run: Tracker.record - skipping %s'%(track)
54             return
55         self.tracks.append( track )
56         print "Recorded %s in tracker %s"%(track,self.filename)
57
58     # this stops the instances currently attached with this test session and release tracker
59     def release (self,track):
60         for already in self.tracks:
61             if already==track:
62                 if self.options.dry_run:
63                     print 'dry_run: Tracker.release - skipping %s'%(track)
64                     return
65                 self.tracks.remove(track)
66                 print "Releasing %s in tracker %s"%(track,self.filename)
67                 command = self.stop_command (track)
68                 utils.header("Trackers.make_space track : %s"%command)
69                 utils.system(command)
70         print '%s was not found in %s'%(track,self.filename)
71         return
72
73     # this actually stops the old instances, so that the total fits in the number of instances 
74     def make_space (self):
75         # number of instances to stop
76         how_many=len(self.tracks)-self.instances
77         # nothing todo until we have more than keep_vservers in the tracker
78         if how_many <= 0:
79             print 'Tracker.make_space : limit %d not reached'%self.instances
80             return
81         to_stop = self.tracks[:how_many]
82         for track in to_stop:
83             command = self.stop_command (track)
84             utils.header("Trackers.make_space track : %s"%command)
85             utils.system(command)
86         if not self.options.dry_run:
87             self.tracks = self.tracks[how_many:]
88
89     # this stops ALL known instances
90     def cleanup (self):
91         for track in self.tracks:
92             command=self.stop_command(track)
93             utils.header("Trackers.cleanup track : %s"%command)
94             utils.system(command)
95         if not self.options.dry_run:
96             self.tracks=[]
97
98 class TrackerPlc (Tracker):
99     
100     DEFAULT_FILENAME=os.environ['HOME']+"/tracker-plcs"
101     # how many concurrent plcs are we keeping alive - adjust with the IP pool size
102     DEFAULT_MAX_INSTANCES = 12
103
104     def __init__ (self,options,filename=None,instances=0):
105         if not filename: filename=TrackerPlc.DEFAULT_FILENAME
106         if not instances: instances=TrackerPlc.DEFAULT_MAX_INSTANCES
107         Tracker.__init__(self,options,filename,instances)
108
109     def record (self, hostname, vservername):
110         Tracker.record (self,"%s@%s"%(hostname,vservername))
111
112     def release (self, hostname, vservername):
113         Tracker.release (self,"%s@%s"%(hostname,vservername))
114
115     def stop_command (self, track):
116         (hostname,vservername) = track.split('@')
117         return TestSsh(hostname).actual_command("vserver --silent %s stop"%vservername)
118         
119     def plcnames (self):
120         return [ self.plcname(track) for track in self.tracks ]
121
122     def plcname (self, track):
123         (hostname,vservername) = track.split('@')
124         return vservername.rsplit('-',1)[1]
125
126 class TrackerQemu (Tracker):
127
128     DEFAULT_FILENAME=os.environ['HOME']+"/tracker-qemus"
129     # how many concurrent plcs are we keeping alive - adjust with the IP pool size
130     DEFAULT_MAX_INSTANCES = 3
131
132     def __init__ (self,options,filename=None,instances=0):
133         if not filename: filename=TrackerQemu.DEFAULT_FILENAME
134         if not instances: instances=TrackerQemu.DEFAULT_MAX_INSTANCES
135         Tracker.__init__(self,options,filename,instances)
136
137     def record (self, hostname, buildname, nodename):
138         Tracker.record (self,"%s@%s@%s"%(hostname,buildname,nodename))
139
140     def release (self, hostname, buildname, nodename):
141         Tracker.release (self,"%s@%s@%s"%(hostname,buildname,nodename))
142
143     def stop_command (self, track):
144         (hostname,buildname,nodename) = track.split('@')
145         return TestSsh(hostname).actual_command("%s/qemu-%s/qemu-kill-node this"%(buildname,nodename))
146
147     def hostnames (self):
148         return [ self.hostname(track) for track in self.tracks ]
149
150     def hostname (self, track):
151         (hostname,buildname,nodename) = track.split('@')
152         return hostname
153
154     def nodenames (self):
155         return [ self.nodename(track) for track in self.tracks ]
156         
157     def nodename (self, track):
158         (hostname,buildname,nodename) = track.split('@')
159         return nodename
160