rev |
line source |
igor@0
|
1 #!/usr/bin/python
|
igor@0
|
2
|
igor@0
|
3
|
igor@0
|
4 def the_peer_of(node):
|
igor@2
|
5 if node == node1:
|
igor@2
|
6 another_node=node2
|
igor@2
|
7 else:
|
igor@2
|
8 another_node=node1
|
igor@2
|
9 return another_node
|
igor@0
|
10
|
igor@0
|
11
|
igor@0
|
12 def log_error(error):
|
igor@2
|
13 print error
|
igor@0
|
14
|
igor@37
|
15 def run_now(command,node):
|
igor@2
|
16 if node == i_am:
|
igor@26
|
17 line=command+" > /dev/stderr 2>&1"
|
igor@2
|
18 else:
|
igor@26
|
19 line="ssh %s %s < /dev/null > /dev/stderr 2>&1" % (node,mkarg(command))
|
igor@26
|
20 if debug > 2:
|
igor@26
|
21 print "debug:", line
|
igor@2
|
22 (p, child_stdout, child_stderr) = os.popen3(line)
|
igor@2
|
23 output = child_stderr.read()
|
igor@2
|
24 #p = os.popen(line)
|
igor@2
|
25 #output = p.read()
|
igor@2
|
26 p.close()
|
igor@2
|
27 return output
|
igor@0
|
28
|
igor@37
|
29 def run(command,node):
|
igor@25
|
30 return run_now(command,node)
|
igor@25
|
31 #if node == i_am:
|
igor@25
|
32 # print command
|
igor@25
|
33 #else:
|
igor@25
|
34 # print "ssh %s %s < /dev/null > /dev/stderr" % (node,mkarg(command))
|
igor@0
|
35
|
igor@0
|
36
|
igor@0
|
37 def get_drbd_resources(domain):
|
igor@2
|
38 disk=[]
|
igor@2
|
39 for disk_description in disk_table[domain]:
|
igor@2
|
40 if disk_description.find(":") == -1:
|
igor@2
|
41 disk.append(domain)
|
igor@2
|
42 else:
|
igor@25
|
43 disk.append((disk_description.split(':'))[1])
|
igor@2
|
44 return disk
|
igor@0
|
45
|
igor@37
|
46 def set_drbd_primary(domain, node):
|
igor@26
|
47 res=""
|
igor@2
|
48 drbd_resources=get_drbd_resources(domain)
|
igor@2
|
49 for drbd in drbd_resources:
|
igor@26
|
50 res += run("drbdadm primary %s"%(drbd),node)
|
igor@26
|
51 print "DRBD resource <%s> on the node <%s> is <%s> now" % (drbd,node,get_drbd_state(drbd,node))
|
igor@26
|
52 return res
|
igor@0
|
53
|
igor@37
|
54 def set_drbd_secondary(domain, node):
|
igor@26
|
55 res=""
|
igor@2
|
56 drbd_resources=get_drbd_resources(domain)
|
igor@2
|
57 for drbd in drbd_resources:
|
igor@27
|
58 res += run("until drbdadm secondary %s; do echo Trying to siwtch resource <%s> on the node <%s> to secondary state; sleep 5; done"%(drbd,drbd,node),node)
|
igor@26
|
59 print "DRBD resource <%s> on the node <%s> is <%s> now" % (drbd,node,get_drbd_state(drbd,node))
|
igor@26
|
60 return res
|
igor@0
|
61
|
igor@37
|
62 def get_domain_id(domain,node):
|
igor@2
|
63 """
|
igor@2
|
64 Returns domain id of the <domain> or -1 if the <domain> is not running on the <node>
|
igor@2
|
65 """
|
igor@2
|
66 res=run_now("xm list | awk '{if ($1 == \"'%s'\") print $2}'" % domain, node).rstrip("\n")
|
igor@2
|
67 if not res:
|
igor@2
|
68 res = -1
|
igor@2
|
69 else:
|
igor@2
|
70 res = int(res)
|
igor@2
|
71 return res
|
igor@0
|
72
|
igor@37
|
73 def get_drbd_id(resource,node):
|
igor@2
|
74 res=run_now("ls -l /dev/drbd/%s 2> /dev/null | awk '{print $10}' | sed s@/dev/drbd@@" %resource, node).rstrip("\n")
|
igor@2
|
75 if not res:
|
igor@2
|
76 res = -1
|
igor@2
|
77 else:
|
igor@2
|
78 res = int(res)
|
igor@2
|
79 return res
|
igor@0
|
80
|
igor@37
|
81 def get_drbd_state(resource,node):
|
igor@60
|
82 #before DRBD 8.3.0: res=run_now("drbdadm state %s | sed s@/.*@@" %resource, node).rstrip("\n")
|
igor@60
|
83 res=run_now("drbdadm role %s | sed s@/.*@@" %resource, node).rstrip("\n")
|
igor@2
|
84 if not res:
|
igor@2
|
85 res = -1
|
igor@2
|
86 return res
|
igor@0
|
87
|
igor@37
|
88 def get_drbd_cstate(resource,node):
|
igor@2
|
89 res=run_now("drbdadm cstate %s " %resource, node).rstrip("\n")
|
igor@2
|
90 if not res:
|
igor@2
|
91 res = -1
|
igor@2
|
92 return res
|
igor@0
|
93
|
igor@37
|
94 def start_domain(domain,node):
|
igor@2
|
95 if (get_domain_id(domain,i_am) != -1):
|
igor@2
|
96 log_error("Domain %s is running already on the node %s" % (domain,i_am))
|
igor@2
|
97 return -1
|
igor@2
|
98 if (get_domain_id(domain,he_is) != -1):
|
igor@2
|
99 log_error("Domain %s is running already on the node %s" % (domain,he_is))
|
igor@2
|
100 return -1
|
igor@2
|
101 another_node=the_peer_of(node)
|
igor@26
|
102 print set_drbd_secondary(domain,another_node)
|
igor@26
|
103 print set_drbd_primary(domain,node)
|
igor@29
|
104 print run(domain_create_line % domain, node)
|
igor@0
|
105
|
igor@37
|
106 def migrate_domain_out(domain,node):
|
igor@2
|
107 if (get_domain_id(domain,node) == -1):
|
igor@2
|
108 log_error("Domain %s is not running on the node %s" % (domain,node))
|
igor@2
|
109 return -1
|
igor@2
|
110 another_node=the_peer_of(node)
|
igor@2
|
111 print "Migrating the domain <%s> from the node <%s> to the node <%s>" % (domain, node, another_node)
|
igor@2
|
112 set_drbd_primary(domain,another_node)
|
igor@2
|
113 run("xm migrate %s %s --live" % (domain,another_node),node)
|
igor@42
|
114 run("sleep 2", node)
|
igor@2
|
115 set_drbd_secondary(domain,node)
|
igor@2
|
116 print "+ Done"
|
igor@2
|
117
|
igor@37
|
118 def migrate_domain_in(domain,node):
|
igor@2
|
119 migrate_domain_out(domain,the_peer_of(node))
|
igor@0
|
120
|
igor@0
|
121 def migrate_domain(domain,node):
|
igor@2
|
122 migrate_domain_in(domain,node)
|
igor@0
|
123
|
igor@37
|
124 def running_domains(node):
|
igor@2
|
125 xm_domains=run_now("xm list | awk '{print $1}'", node).split("\n")
|
igor@2
|
126 return filter(lambda x: x in xm_domains, domains)
|
igor@0
|
127
|
igor@37
|
128 def migrate_out_all(node):
|
igor@2
|
129 for domain in running_domains(node):
|
igor@2
|
130 migrate_domain_out(domain,node)
|
igor@0
|
131
|
igor@37
|
132 def migrate_in_all(node):
|
igor@2
|
133 for domain in running_domains(the_peer_of(node)):
|
igor@2
|
134 migrate_domain_in(domain,node)
|
igor@0
|
135
|
igor@37
|
136 def start_all(node):
|
igor@2
|
137 for domain in domains:
|
igor@2
|
138 if not domain in running_domains(node) and not domain in running_domains(the_peer_of(node)):
|
igor@2
|
139 start_domain(domain,node)
|
igor@0
|
140
|
igor@37
|
141 def start_my_domains(node):
|
igor@2
|
142 for domain in domain_home[node]:
|
igor@2
|
143 if not domain in running_domains(node) and not domain in running_domains(the_peer_of(node)):
|
igor@2
|
144 start_domain(domain,node)
|
igor@0
|
145
|
igor@37
|
146 def migrate_my_domains_home(node):
|
igor@2
|
147 for domain in domain_home[node]:
|
igor@2
|
148 if not domain in running_domains(node) and domain in running_domains(the_peer_of(node)):
|
igor@2
|
149 migrate_domain_in(domain,node)
|
igor@28
|
150
|
igor@37
|
151 def migrate_and_start_my_domains(node):
|
igor@28
|
152 migrate_my_domains_home(node)
|
igor@28
|
153 start_my_domains(node)
|
igor@2
|
154
|
igor@37
|
155 def migrate_and_start_all(node):
|
igor@2
|
156 migrate_my_domains_home(node)
|
igor@2
|
157 start_my_domains(node)
|
igor@28
|
158 migrate_my_domains_home(the_peer_of(node))
|
igor@28
|
159 start_my_domains(the_peer_of(node))
|
igor@2
|
160
|
igor@2
|
161 def do_import(name, source):
|
igor@2
|
162 module = imp.new_module(name)
|
igor@2
|
163 sys.modules[name] = module
|
igor@2
|
164 exec source in vars(module)
|
igor@2
|
165 return module
|
igor@2
|
166
|
igor@2
|
167 def load_file(file):
|
igor@2
|
168 f=open(file)
|
igor@2
|
169 result=f.read()
|
igor@2
|
170 return result
|
igor@2
|
171
|
igor@2
|
172 def dump_config(domain):
|
igor@2
|
173 xen_domain=load_file(xen_drbd_start)
|
igor@2
|
174 xen_domain="domain=\"%s\"\n" % (domain) + xen_domain
|
igor@2
|
175 xen_domain="network=\"%s\"\n" % (network) + xen_domain
|
igor@2
|
176 do_import('xen_domain_module',xen_domain)
|
igor@38
|
177 #print "domain=\"%s\"\n" % (domain)
|
igor@38
|
178 #print "network=\"%s\"\n" % (network)
|
igor@2
|
179 import xen_domain_module
|
igor@2
|
180 xen_domain_module.print_config()
|
igor@0
|
181
|
igor@0
|
182 def show_usage():
|
igor@2
|
183 print """
|
igor@0
|
184 Usage:
|
igor@37
|
185 xen-drbd [options] command [domain]
|
igor@0
|
186
|
igor@0
|
187 Commands:
|
igor@2
|
188 start domain
|
igor@2
|
189 start-all
|
igor@2
|
190 start-my-domains
|
igor@0
|
191
|
igor@2
|
192 migrate-out domain
|
igor@2
|
193 migrate-in domain
|
root@55
|
194 migrate-out-all
|
root@55
|
195 migrate-in-all
|
igor@2
|
196 migrate-my-domains-home
|
igor@28
|
197 migrate-and-start-my-domains
|
igor@2
|
198 migrate-and-start-all
|
igor@0
|
199
|
igor@2
|
200 dump-config domain
|
igor@37
|
201
|
igor@37
|
202 Options:
|
igor@37
|
203 --help (-h) -- show usage information
|
root@55
|
204 --network=name (-n) -- the network descriptions is in the file name (default: ''network'')
|
igor@37
|
205
|
igor@37
|
206
|
igor@2
|
207 """
|
igor@0
|
208
|
igor@0
|
209 def test():
|
igor@2
|
210 print "get_drbd_resources(samba)=",get_drbd_resources("samba")
|
igor@2
|
211 print "get_domain_id(Domain-0)=",get_domain_id("Domain-0")
|
igor@2
|
212 print "get_domain_id(samba)=",get_domain_id("samba")
|
igor@2
|
213 print "get_drbd_id(samba)=",get_drbd_id("samba")
|
igor@2
|
214 print "get_drbd_id(samba, he_is)=",get_drbd_id("samba",he_is)
|
igor@2
|
215 print "get_drbd_id(unknown_resource, he_is)=",get_drbd_id("unknown_resource",he_is)
|
igor@2
|
216 print "get_drbd_state(samba, he_is)=",get_drbd_state("samba")
|
igor@2
|
217 print "get_drbd_state(samba, he_is)=",get_drbd_state("samba",he_is)
|
igor@2
|
218 print "get_drbd_cstate(samba)=",get_drbd_cstate("samba")
|
igor@2
|
219 print "get_drbd_cstate(samba, he_is)=",get_drbd_cstate("samba",he_is)
|
igor@2
|
220 print "start_domain(samba)"
|
igor@2
|
221 start_domain("samba")
|
igor@2
|
222 print "migrate_domain_out(samba)"
|
igor@2
|
223 migrate_domain_in("samba")
|
igor@0
|
224
|
igor@0
|
225
|
igor@0
|
226 #print "get_domain_id(samba,node2)=",get_domain_id("samba",node2)
|
igor@0
|
227 #sys.exit(0)
|
igor@0
|
228
|
igor@37
|
229 network='network'
|
igor@37
|
230 import sys,os,imp,getopt
|
igor@37
|
231 from commands import mkarg
|
igor@37
|
232
|
igor@37
|
233 try:
|
igor@37
|
234 opts, args = getopt.getopt(sys.argv[1:], "hn:", ["help", "network="])
|
igor@37
|
235 except getopt.GetoptError, err:
|
igor@38
|
236 print str(err)
|
igor@37
|
237 usage()
|
igor@37
|
238 sys.exit(2)
|
igor@37
|
239
|
igor@37
|
240 for o, a in opts:
|
igor@37
|
241 if o in ("-h", "--help"):
|
igor@37
|
242 show_usage()
|
igor@37
|
243 sys.exit()
|
igor@37
|
244 elif o in ("-n", "--network"):
|
igor@37
|
245 network = a
|
igor@37
|
246 else:
|
igor@37
|
247 assert False, "unhandled option"
|
igor@37
|
248
|
igor@37
|
249
|
igor@37
|
250 debug=2
|
igor@37
|
251
|
igor@38
|
252 if len(args) == 2:
|
igor@38
|
253 domain=args[1]
|
igor@37
|
254
|
igor@37
|
255 sys.path.append('/etc/xen')
|
igor@37
|
256 try:
|
igor@39
|
257 execfile('/etc/xen/'+network)
|
igor@38
|
258 except IOError:
|
igor@38
|
259 print "Network configuration file <%s> not found " % network
|
igor@38
|
260 if network == 'network':
|
igor@38
|
261 print "You can use -n option to specify network filename"
|
igor@38
|
262 sys.exit(2)
|
igor@38
|
263 except NameError:
|
igor@38
|
264 domain=domains[0]
|
igor@40
|
265 execfile('/etc/xen/'+network)
|
igor@37
|
266
|
igor@37
|
267 xen_drbd_start="/etc/xen/xen-drbd-start"
|
igor@37
|
268 domain_create_line="xm create "+xen_drbd_start+" network="+network+" domain=%s"
|
igor@37
|
269
|
igor@37
|
270 if len(args) == 0:
|
igor@2
|
271 show_usage()
|
igor@2
|
272 sys.exit(0)
|
igor@0
|
273
|
igor@37
|
274 he_is=the_peer_of(i_am)
|
igor@37
|
275
|
igor@37
|
276 command=args[0]
|
igor@37
|
277 if len(args) == 2:
|
igor@37
|
278 domain=args[1]
|
igor@2
|
279 if command == 'start':
|
igor@37
|
280 start_domain(domain, i_am)
|
igor@2
|
281 elif command == 'migrate-out':
|
igor@37
|
282 migrate_domain_out(domain, i_am)
|
igor@2
|
283 elif command == 'migrate-in':
|
igor@37
|
284 migrate_domain_in(domain, i_am)
|
igor@2
|
285 elif command == 'dump-config':
|
igor@2
|
286 dump_config(domain)
|
igor@2
|
287 else:
|
igor@2
|
288 show_usage()
|
igor@2
|
289 sys.exit(0)
|
igor@37
|
290 elif len(args) == 1:
|
igor@2
|
291 if command == 'start-all':
|
igor@37
|
292 start_all(i_am)
|
igor@2
|
293 elif command == 'start-my-domains':
|
igor@37
|
294 start_my_domains(i_am)
|
igor@31
|
295 elif command == 'migrate-out-all':
|
igor@37
|
296 migrate_out_all(i_am)
|
igor@31
|
297 elif command == 'migrate-in-all':
|
igor@37
|
298 migrate_in_all(i_am)
|
igor@2
|
299 elif command == 'migrate-my-domains-home':
|
igor@37
|
300 migrate_my_domains_home(i_am)
|
igor@28
|
301 elif command == 'migrate-and-start-my-domains':
|
igor@37
|
302 migrate_and_start_my_domains(i_am)
|
igor@2
|
303 elif command == 'migrate-and-start-all':
|
igor@37
|
304 migrate_and_start_all(i_am)
|
igor@2
|
305 elif command == 'list':
|
igor@37
|
306 print running_domains(i_am)
|
igor@2
|
307 else:
|
igor@2
|
308 show_usage()
|
igor@2
|
309 sys.exit(0)
|
igor@0
|
310
|
igor@0
|
311
|
igor@0
|
312
|
igor@0
|
313
|