mirror of
git://git.proxmox.com/git/qemu-server.git
synced 2024-12-24 21:34:43 +03:00
235 lines
5.2 KiB
Perl
Executable File
235 lines
5.2 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
|
|
|
use strict;
|
|
use IO::File;
|
|
use Digest::SHA;
|
|
|
|
# script to upgrade V0.9.1 to V0.9.2 format
|
|
|
|
my $confvars_0_9_1 = {
|
|
onboot => 'bool',
|
|
autostart => 'bool',
|
|
reboot => 'bool',
|
|
cpulimit => 'natural',
|
|
cpuunits => 'natural',
|
|
hda => 'file',
|
|
hdb => 'file',
|
|
sda => 'file',
|
|
sdb => 'file',
|
|
cdrom => 'file',
|
|
memory => 'natural',
|
|
keyboard => 'lang',
|
|
name => 'string',
|
|
ostype => 'ostype',
|
|
boot => 'boot',
|
|
smp => 'natural',
|
|
acpi => 'bool',
|
|
network => 'network',
|
|
};
|
|
|
|
sub load_config_0_9_1 {
|
|
my ($vmid, $filename) = @_;
|
|
|
|
my $fh = new IO::File ($filename, "r") ||
|
|
return undef;
|
|
|
|
my $res = {};
|
|
|
|
while (my $line = <$fh>) {
|
|
|
|
next if $line =~ m/^\#/;
|
|
|
|
next if $line =~ m/^\s*$/;
|
|
|
|
if ($line =~ m/^([a-z]+):\s*(\S+)\s*$/) {
|
|
my $key = $1;
|
|
my $value = $2;
|
|
if (my $type = $confvars_0_9_1->{$key}) {
|
|
$res->{$key} = $value;
|
|
} else {
|
|
return undef; # unknown setting
|
|
}
|
|
}
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
sub parse_network_0_9_1 {
|
|
my ($data) = @_;
|
|
|
|
my $res = {
|
|
type => 'tap',
|
|
};
|
|
foreach my $rec (split (/\s*,\s*/, $data)) {
|
|
if ($rec =~ m/^(tap|user)$/) {
|
|
$res->{type} = $rec;
|
|
} elsif ($rec =~ m/^model\s*=\s*(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)$/) {
|
|
$res->{model} = $1;
|
|
} elsif ($rec =~ m/macaddr\s*=\s*([0-9a-f:]+)/i) {
|
|
$res->{macaddr} = $1;
|
|
} else {
|
|
return undef;
|
|
}
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
sub random_ether_addr {
|
|
|
|
my $rand = Digest::SHA::sha1_hex (rand(), time());
|
|
|
|
my $mac = '';
|
|
for (my $i = 0; $i < 6; $i++) {
|
|
my $ss = hex (substr ($rand, $i*2, 2));
|
|
if (!$i) {
|
|
$ss &= 0xfe; # clear multicast
|
|
$ss |= 2; # set local id
|
|
}
|
|
$ss = sprintf ("%02X", $ss);
|
|
|
|
if (!$i) {
|
|
$mac .= "$ss";
|
|
} else {
|
|
$mac .= ":$ss";
|
|
}
|
|
}
|
|
|
|
return $mac;
|
|
}
|
|
|
|
sub convert_0_9_1_to_0_9_2 {
|
|
my ($vmid, $cfile, $conf) = @_;
|
|
|
|
print "Upgrading VM $vmid to new format\n";
|
|
|
|
die "undefined vm id" if !$vmid || $vmid !~ m/^\d+$/;
|
|
|
|
my $dmap = {
|
|
hda => 'ide0',
|
|
hdb => 'ide1',
|
|
sda => 'scsi0',
|
|
sdb => 'scsi1',
|
|
};
|
|
|
|
my $tmpdir = "/var/lib/vz/images/$vmid.upgrade";
|
|
my $tmpconf = "$cfile.upgrade";
|
|
|
|
my $images = [];
|
|
|
|
eval {
|
|
mkdir $tmpdir || die "unable to create dir '$tmpdir'\n";
|
|
|
|
my $fh = new IO::File ($cfile, "r") ||
|
|
die "unable to read config for VM $vmid\n";
|
|
my $newfh = new IO::File ($tmpconf, "w") ||
|
|
die "unable to create file '$tmpconf'\n";
|
|
|
|
while (my $line = <$fh>) {
|
|
|
|
next if $line =~ m/^\#/;
|
|
|
|
next if $line =~ m/^\s*$/;
|
|
|
|
if ($line =~ m/^([a-z]+):\s*(\S+)\s*$/) {
|
|
my $key = $1;
|
|
my $value = $2;
|
|
if (my $type = $confvars_0_9_1->{$key}) {
|
|
if ($key eq 'network') {
|
|
my $onw = parse_network_0_9_1 ($value);
|
|
if ($onw && ($onw->{type} eq 'tap')) {
|
|
if (!$onw->{macaddr}) {
|
|
$onw->{macaddr} = random_ether_addr ();
|
|
}
|
|
print $newfh "vlan0: $onw->{model}=$onw->{macaddr}\n";
|
|
} elsif ($onw && ($onw->{type} eq 'user')) {
|
|
if (!$onw->{macaddr}) {
|
|
$onw->{macaddr} = random_ether_addr ();
|
|
}
|
|
print $newfh "vlanu: $onw->{model}=$onw->{macaddr}\n";
|
|
} else {
|
|
die "unable to convert network specification\n";
|
|
}
|
|
} elsif ($key eq 'cdrom') {
|
|
$value =~ s|^/.*/||;
|
|
print $newfh "ide2: $value,media=cdrom\n";
|
|
} elsif (defined ($dmap->{$key})) {
|
|
if ($value =~ m|^/var/lib/vz/images/([^/]+)$|) {
|
|
$value = $1;
|
|
} elsif ($value !~ m|/|) {
|
|
# no nothing
|
|
} else {
|
|
die "wrong image path";
|
|
}
|
|
|
|
link "/var/lib/vz/images/$value", "$tmpdir/$value";
|
|
|
|
(-f "$tmpdir/$value") ||
|
|
die "unable to create image link\n";
|
|
|
|
push @$images, $value;
|
|
|
|
print $newfh "$dmap->{$key}: $value\n";
|
|
} else {
|
|
print $newfh "$key: $value\n";
|
|
}
|
|
} else {
|
|
die "unknown setting '$key'\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($conf->{hda}) {
|
|
print $newfh "bootdisk: ide0\n";
|
|
} elsif ($conf->{hdb}) {
|
|
print $newfh "bootdisk: ide1\n";
|
|
} elsif ($conf->{sda}) {
|
|
print $newfh "bootdisk: scsi0\n";
|
|
} elsif ($conf->{sdb}) {
|
|
print $newfh "bootdisk: scsi1\n";
|
|
}
|
|
};
|
|
|
|
my $err = $@;
|
|
|
|
if ($err) {
|
|
system ("rm -rf $tmpdir $tmpconf");
|
|
} else {
|
|
|
|
if (!rename $tmpdir, "/var/lib/vz/images/$vmid") {
|
|
system ("rm -rf $tmpdir $tmpconf");
|
|
die "commiting '/var/lib/vz/images/$vmid' failed - $!\n";
|
|
}
|
|
if (!rename $tmpconf, $cfile) {
|
|
system ("rm -rf /var/lib/vz/images/$vmid $tmpconf");
|
|
die "commiting new configuration '$cfile' failed - $!\n";
|
|
}
|
|
|
|
foreach my $img (@$images) {
|
|
unlink "/var/lib/vz/images/$img";
|
|
}
|
|
}
|
|
die $err if $err;
|
|
}
|
|
|
|
foreach my $vmconf (</etc/qemu-server/*.conf>) {
|
|
next if $vmconf !~ m|/etc/qemu-server/(\d+)\.conf|;
|
|
my $vmid = $1;
|
|
next if -d "/var/lib/vz/images/$vmid"; # already new format
|
|
|
|
eval {
|
|
my $res = load_config_0_9_1 ($vmid, $vmconf);
|
|
|
|
if ($res && ($res->{network} || $res->{hda} || $res->{hdb} ||
|
|
$res->{sda} || $res->{sda} || $res->{cdrom})) {
|
|
convert_0_9_1_to_0_9_2 ($vmid, $vmconf, $res);
|
|
}
|
|
};
|
|
|
|
warn $@ if $@;
|
|
}
|
|
|
|
exit 0;
|
|
|