]>
Commit | Line | Data |
---|---|---|
990fc5e2 | 1 | #!/usr/bin/perl |
1e3baf05 DM |
2 | |
3 | use strict; | |
990fc5e2 | 4 | use warnings; |
1e3baf05 | 5 | use IO::File; |
fc1ddcdc | 6 | use Digest::SHA; |
1e3baf05 DM |
7 | |
8 | # script to upgrade V0.9.1 to V0.9.2 format | |
9 | ||
10 | my $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 | ||
31 | sub 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 | ||
59 | sub 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 | ||
80 | sub 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 | ||
103 | sub 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 | ||
217 | foreach 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 | ||
234 | exit 0; | |
235 |