KVM SR: Remove brain overhead of having a dict created from another dict.
[slapos.git] / slapos / recipe / kvm / template / kvm_run.in
1 #!%(python-path)s
2 # BEWARE: This file is operated by slapgrid
3 # BEWARE: It will be overwritten automatically
4
5 import hashlib
6 import os
7 import socket
8 import subprocess
9 import urllib
10
11 # XXX: give all of this through parameter, don't use this as template, but as module
12 qemu_img_path = '%(qemu-img-path)s'
13 qemu_path = '%(qemu-path)s'
14 disk_size = '%(disk-size)s'
15 disk_type = '%(disk-type)s'
16 socket_path = '%(socket-path)s'
17 nbd_list = (('%(nbd-host)s', %(nbd-port)s), ('%(nbd2-host)s', %(nbd2-port)s))
18 default_disk_image = '%(default-disk-image)s'
19 disk_path = '%(disk-path)s'
20 virtual_hard_drive_url = '%(virtual-hard-drive-url)s'.strip()
21 virtual_hard_drive_md5_url = '%(virtual-hard-drive-md5-url)s'.strip()
22 nat_rules = '%(nat-rules)s'.strip()
23 use_tap = '%(use-tap)s'
24 tap_interface = '%(tap-interface)s'
25 listen_ip = '%(ipv4)s'
26 mac_address = '%(mac-address)s'
27 smp_count = '%(smp-count)s'
28 ram_size = '%(ram-size)s'
29 pid_file_path = '%(pid-file-path)s'
30
31 def md5Checksum(file_path):
32     with open(file_path, 'rb') as fh:
33         m = hashlib.md5()
34         while True:
35             data = fh.read(8192)
36             if not data:
37                 break
38             m.update(data)
39         return m.hexdigest()
40
41 def getSocketStatus(host, port):
42   s = None
43   for res in socket.getaddrinfo(host, port,
44       socket.AF_UNSPEC, socket.SOCK_STREAM):
45     af, socktype, proto, canonname, sa = res
46     try:
47       s = socket.socket(af, socktype, proto)
48     except socket.error, msg:
49       s = None
50       continue
51     try:
52       s.connect(sa)
53     except socket.error, msg:
54       s.close()
55       s = None
56       continue
57     break
58   return s
59
60 # Download existing hard drive if needed at first boot
61 if not os.path.exists(disk_path) and virtual_hard_drive_url != '':
62   urllib.urlretrieve(virtual_hard_drive_url, disk_path)
63   local_md5sum = md5Checksum(disk_path)
64   md5sum = urllib.urlopen(virtual_hard_drive_md5_url).read().strip()
65   if local_md5sum != md5sum:
66     os.remove(disk_path)
67     raise Exception('MD5 mismatch.')
68
69 # Create disk if doesn't exist
70 # XXX: move to Buildout profile
71 if not os.path.exists(disk_path):
72   subprocess.Popen([qemu_img_path, 'create' ,'-f', 'qcow2',
73       disk_path, '%%sG' %% disk_size])
74
75 # Generate network parameters
76 # XXX: use_tap should be a boolean
77 if use_tap == 'True':
78   qemu_network_parameter = 'tap,ifname=%%s,script=no,downscript=no' %% tap_interface
79 else:
80   qemu_network_parameter = 'user,' + ','.join('hostfwd=tcp:%%s:%%s-:%%s' %% (listen_ip, int(port) + 10000, port) for port in nat_rules.split())
81
82 kvm_argument_list = [qemu_path,
83   '-enable-kvm', '-net', 'nic,macaddr=%%s' %% mac_address,
84   '-net', qemu_network_parameter,
85   '-smp', smp_count,
86   '-m', ram_size,
87   '-drive', 'file=%%s,if=%%s' %% (disk_path, disk_type),
88   '-vnc', '%%s:1,ipv4,password' %% listen_ip,
89   '-boot', 'menu=on',
90   '-qmp', 'unix:%%s,server' %% socket_path,
91   '-pidfile', pid_file_path,
92 ]
93
94 # Try to connect to NBD server (and second nbd if defined).
95 # If not available, don't even specify it in qemu command line parameters.
96 # Reason: if qemu starts with unavailable NBD drive, it will just crash.
97 for nbd_ip, nbd_port in nbd_list:
98   if nbd_ip and nbd_port:
99     s = getSocketStatus(nbd_ip, nbd_port)
100     if s is None:
101       # NBD is not available : launch kvm without it
102       print 'Warning : Nbd is not available.'
103     else:
104       # NBD is available
105       kvm_argument_list.extend([
106           '-drive',
107           'file=nbd:[%%s]:%%s,media=cdrom' %% (nbd_ip, nbd_port)])
108 # If no NBD is specified/available: use internal disk image
109 else:
110   kvm_argument_list.extend([
111       '-drive', 'file=%%s,media=cdrom' %% default_disk_image
112   ])
113
114 os.execv(qemu_path, kvm_argument_list)