]> git.proxmox.com Git - qemu-server.git/blame - qmupdate
drive-mirror : wait that busy eq false before block-job-complete
[qemu-server.git] / qmupdate
CommitLineData
990fc5e2 1#!/usr/bin/perl
1e3baf05
DM
2
3use strict;
990fc5e2 4use warnings;
1e3baf05 5use IO::File;
fc1ddcdc 6use Digest::SHA;
1e3baf05
DM
7
8# script to upgrade V0.9.1 to V0.9.2 format
9
10my $confvars_0_9_1 = {
11 onboot => 'bool',
12 autostart => 'bool',
13 reboot => 'bool',
14 cpulimit => 'natural',
15 cpuunits => 'natural',
16 hda => 'file',
17 hdb => 'file',
18 sda => 'file',
19 sdb => 'file',
20 cdrom => 'file',
21 memory => 'natural',
22 keyboard => 'lang',
23 name => 'string',
24 ostype => 'ostype',
25 boot => 'boot',
26 smp => 'natural',
27 acpi => 'bool',
28 network => 'network',
29};
30
31sub load_config_0_9_1 {
32 my ($vmid, $filename) = @_;
33
34 my $fh = new IO::File ($filename, "r") ||
35 return undef;
36
37 my $res = {};
38
39 while (my $line = <$fh>) {
40
41 next if $line =~ m/^\#/;
42
43 next if $line =~ m/^\s*$/;
44
45 if ($line =~ m/^([a-z]+):\s*(\S+)\s*$/) {
46 my $key = $1;
47 my $value = $2;
48 if (my $type = $confvars_0_9_1->{$key}) {
49 $res->{$key} = $value;
50 } else {
51 return undef; # unknown setting
52 }
53 }
54 }
55
56 return $res;
57}
58
59sub parse_network_0_9_1 {
60 my ($data) = @_;
61
62 my $res = {
63 type => 'tap',
64 };
65 foreach my $rec (split (/\s*,\s*/, $data)) {
66 if ($rec =~ m/^(tap|user)$/) {
67 $res->{type} = $rec;
68 } elsif ($rec =~ m/^model\s*=\s*(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)$/) {
69 $res->{model} = $1;
70 } elsif ($rec =~ m/macaddr\s*=\s*([0-9a-f:]+)/i) {
71 $res->{macaddr} = $1;
72 } else {
73 return undef;
74 }
75 }
76
77 return $res;
78}
79
80sub random_ether_addr {
81
fc1ddcdc 82 my $rand = Digest::SHA::sha1_hex (rand(), time());
1e3baf05
DM
83
84 my $mac = '';
85 for (my $i = 0; $i < 6; $i++) {
86 my $ss = hex (substr ($rand, $i*2, 2));
87 if (!$i) {
88 $ss &= 0xfe; # clear multicast
89 $ss |= 2; # set local id
90 }
91 $ss = sprintf ("%02X", $ss);
92
93 if (!$i) {
94 $mac .= "$ss";
95 } else {
96 $mac .= ":$ss";
97 }
98 }
99
100 return $mac;
101}
102
103sub convert_0_9_1_to_0_9_2 {
104 my ($vmid, $cfile, $conf) = @_;
105
106 print "Upgrading VM $vmid to new format\n";
107
108 die "undefined vm id" if !$vmid || $vmid !~ m/^\d+$/;
109
110 my $dmap = {
111 hda => 'ide0',
112 hdb => 'ide1',
113 sda => 'scsi0',
114 sdb => 'scsi1',
115 };
116
117 my $tmpdir = "/var/lib/vz/images/$vmid.upgrade";
118 my $tmpconf = "$cfile.upgrade";
119
120 my $images = [];
121
122 eval {
123 mkdir $tmpdir || die "unable to create dir '$tmpdir'\n";
124
125 my $fh = new IO::File ($cfile, "r") ||
126 die "unable to read config for VM $vmid\n";
127 my $newfh = new IO::File ($tmpconf, "w") ||
128 die "unable to create file '$tmpconf'\n";
129
130 while (my $line = <$fh>) {
131
132 next if $line =~ m/^\#/;
133
134 next if $line =~ m/^\s*$/;
135
136 if ($line =~ m/^([a-z]+):\s*(\S+)\s*$/) {
137 my $key = $1;
138 my $value = $2;
139 if (my $type = $confvars_0_9_1->{$key}) {
140 if ($key eq 'network') {
141 my $onw = parse_network_0_9_1 ($value);
142 if ($onw && ($onw->{type} eq 'tap')) {
143 if (!$onw->{macaddr}) {
144 $onw->{macaddr} = random_ether_addr ();
145 }
146 print $newfh "vlan0: $onw->{model}=$onw->{macaddr}\n";
147 } elsif ($onw && ($onw->{type} eq 'user')) {
148 if (!$onw->{macaddr}) {
149 $onw->{macaddr} = random_ether_addr ();
150 }
151 print $newfh "vlanu: $onw->{model}=$onw->{macaddr}\n";
152 } else {
153 die "unable to convert network specification\n";
154 }
155 } elsif ($key eq 'cdrom') {
156 $value =~ s|^/.*/||;
157 print $newfh "ide2: $value,media=cdrom\n";
158 } elsif (defined ($dmap->{$key})) {
159 if ($value =~ m|^/var/lib/vz/images/([^/]+)$|) {
160 $value = $1;
161 } elsif ($value !~ m|/|) {
162 # no nothing
163 } else {
164 die "wrong image path";
165 }
166
167 link "/var/lib/vz/images/$value", "$tmpdir/$value";
168
169 (-f "$tmpdir/$value") ||
170 die "unable to create image link\n";
171
172 push @$images, $value;
173
174 print $newfh "$dmap->{$key}: $value\n";
175 } else {
176 print $newfh "$key: $value\n";
177 }
178 } else {
179 die "unknown setting '$key'\n";
180 }
181 }
182 }
183
184 if ($conf->{hda}) {
185 print $newfh "bootdisk: ide0\n";
186 } elsif ($conf->{hdb}) {
187 print $newfh "bootdisk: ide1\n";
188 } elsif ($conf->{sda}) {
189 print $newfh "bootdisk: scsi0\n";
190 } elsif ($conf->{sdb}) {
191 print $newfh "bootdisk: scsi1\n";
192 }
193 };
194
195 my $err = $@;
196
197 if ($err) {
198 system ("rm -rf $tmpdir $tmpconf");
199 } else {
200
201 if (!rename $tmpdir, "/var/lib/vz/images/$vmid") {
202 system ("rm -rf $tmpdir $tmpconf");
203 die "commiting '/var/lib/vz/images/$vmid' failed - $!\n";
204 }
205 if (!rename $tmpconf, $cfile) {
206 system ("rm -rf /var/lib/vz/images/$vmid $tmpconf");
207 die "commiting new configuration '$cfile' failed - $!\n";
208 }
209
210 foreach my $img (@$images) {
211 unlink "/var/lib/vz/images/$img";
212 }
213 }
214 die $err if $err;
215}
216
217foreach my $vmconf (</etc/qemu-server/*.conf>) {
218 next if $vmconf !~ m|/etc/qemu-server/(\d+)\.conf|;
219 my $vmid = $1;
220 next if -d "/var/lib/vz/images/$vmid"; # already new format
221
222 eval {
223 my $res = load_config_0_9_1 ($vmid, $vmconf);
224
225 if ($res && ($res->{network} || $res->{hda} || $res->{hdb} ||
226 $res->{sda} || $res->{sda} || $res->{cdrom})) {
227 convert_0_9_1_to_0_9_2 ($vmid, $vmconf, $res);
228 }
229 };
230
231 warn $@ if $@;
232}
233
234exit 0;
235