mirror of
				https://git.proxmox.com/git/qemu-server
				synced 2025-10-31 11:19:54 +00: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;
 | |
| 
 | 
