xen-drbd
annotate xen-drbd.py @ 60:dd23766a87c6
Minor fixes. Hvmlaoder now can be specified by its path in the netowrk config file.
Also slightly changed drbdadm call
Also slightly changed drbdadm call
author | igor@book.xt.vpn |
---|---|
date | Thu Mar 19 19:42:41 2009 +0200 (2009-03-19) |
parents | 8afb0999f562 |
children |
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 |