summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Alcantara <paulo@paulo.ac>2018-05-18 16:21:57 -0300
committerPaulo Alcantara <paulo@paulo.ac>2018-05-18 16:21:57 -0300
commitde819838a7c346aca78055e7967e0003be9fe12a (patch)
treef062ec56fd535d4f8442996363db1d1c730064da
parent57c2b80d3f7888458481b6a82079c5c648c45a0b (diff)
downloadvmhtool-de819838a7c346aca78055e7967e0003be9fe12a.tar.gz
vmhtool-de819838a7c346aca78055e7967e0003be9fe12a.tar.xz
vmhtool-de819838a7c346aca78055e7967e0003be9fe12a.zip
Make network bridging optional
Besides, introduce a '--bridge' cmd option to force creation of a network bridge. Signed-off-by: Paulo Alcantara <paulo@paulo.ac>
-rwxr-xr-xvmhelper168
1 files changed, 106 insertions, 62 deletions
diff --git a/vmhelper b/vmhelper
index 2830f21..bb636ec 100755
--- a/vmhelper
+++ b/vmhelper
@@ -12,8 +12,6 @@ use File::Copy;
use Cwd 'abs_path';
use File::Basename;
-my %cmd_opts = ();
-
sub usage {
print STDERR "Usage: " . basename($0). " [name] [options]
--help print this help
@@ -33,10 +31,14 @@ sub usage {
--new generate new config file
--nographic disable graphics when running vm
--hdd=img0,img1,... boot up a vm with additional hdd images
+ --bridge create a network bridge
+ (this overrides current settings)
";
exit 1;
}
+my %cmd_opts = ();
+
GetOptions("install=s" => \$cmd_opts{install_iso_path},
"virtio=s" => \$cmd_opts{virtio_drv_path},
"kernel=s" => \$cmd_opts{kernel_path},
@@ -52,13 +54,14 @@ GetOptions("install=s" => \$cmd_opts{install_iso_path},
"new" => \$cmd_opts{gen_new_conf},
"hdd=s" => \$cmd_opts{vm_hdds},
"rootfs=s" => \$cmd_opts{rootfs_path},
+ "bridge" => \$cmd_opts{create_bridge},
"nographic" => \$cmd_opts{nographic}) or usage();
usage() if $cmd_opts{print_help};
my $vm_path = $ENV{'VMHELPER_VM_PATH'};
die "VMHELPER_VM_PATH env var is not set" unless $vm_path;
-die "$vm_path does not exist" unless -e $vm_path or -d $vm_path;
+die "$vm_path does not exist" if ! -e $vm_path || ! -d $vm_path;
my $vm_info = $vm_path . '/.vminfo';
my $vm_conf = $vm_path . '/.vmconf';
@@ -77,7 +80,8 @@ sub parse_user_hdds {
}
my %vm_conf_opts = (
- ETH_IFACE => 'eth0',
+ HOST_IFACE => 'eth0',
+ BRIDGE_ENABLE => 'no',
BRIDGE_IFACE => 'br0',
BRIDGE_CFG_METHOD => 'auto',
BRIDGE_IP_ADDR => '',
@@ -96,19 +100,27 @@ sub gen_conf {
open(my $f, ">", $vm_conf) or die "failed to create config file: $!";
print "[*] generate initial config file\n";
- print " eth iface (default $vm_conf_opts{'ETH_IFACE'}): ";
- in2opts('ETH_IFACE');
- print " bridge iface (default $vm_conf_opts{'BRIDGE_IFACE'}): ";
- in2opts('BRIDGE_IFACE');
- print " bridge method: (default auto) [auto|static]: ";
- in2opts('BRIDGE_CFG_METHOD');
- if ($vm_conf_opts{'BRIDGE_CFG_METHOD'} eq 'static') {
- print " bridge ip: ";
- in2opts('BRIDGE_IP_ADDR');
- }
- print " bridge gateway (default auto): ";
- in2opts('BRIDGE_GW_ADDR');
+ print " host iface (default $vm_conf_opts{'HOST_IFACE'}): ";
+ in2opts('HOST_IFACE');
+
+ print " enable bridging (default $vm_conf_opts{'BRIDGE_ENABLE'}): ";
+ in2opts('BRIDGE_ENABLE');
+
+ unless ($vm_conf_opts{'BRIDGE_ENABLE'} eq 'no') {
+ print " bridge iface (default $vm_conf_opts{'BRIDGE_IFACE'}): ";
+ in2opts('BRIDGE_IFACE');
+
+ print " bridge ip method: (default auto) [auto|static]: ";
+ in2opts('BRIDGE_CFG_METHOD');
+ if ($vm_conf_opts{'BRIDGE_CFG_METHOD'} eq 'static') {
+ print " bridge ip: ";
+ in2opts('BRIDGE_IP_ADDR');
+ }
+
+ print " bridge gateway (default auto): ";
+ in2opts('BRIDGE_GW_ADDR');
+ }
print $f "$_ = $vm_conf_opts{$_}\n" for (keys %vm_conf_opts);
close($f) or die "failed to close config file: $!";
@@ -130,7 +142,7 @@ sub parse_conf {
close($f) or die "failed to close config file: $!";
}
-if ($cmd_opts{gen_new_conf} || ! -e $vm_conf || ! -f $vm_conf) {
+if ($cmd_opts{gen_new_conf} || ! -e $vm_conf || ! -s $vm_conf) {
gen_conf();
exit 0;
}
@@ -156,7 +168,9 @@ sub resolve_name {
}
if ($cmd_opts{list_vms}) {
- open(my $conf, "<", $vm_info) or exit 0;
+ exit 0 if ! -e $vm_info || ! -s $vm_info;
+
+ open(my $conf, "<", $vm_info) or die "failed to open vm info file: $!";
printf STDERR "%-25s%-20s%-15s\n", "name", "macaddr", "ipaddr";
while (<$conf>) {
my ($name, $macaddr) = split(/\s/);
@@ -167,9 +181,10 @@ if ($cmd_opts{list_vms}) {
exit 0;
}
-my $eth_iface = $vm_conf_opts{'ETH_IFACE'};
+my $host_iface = $vm_conf_opts{'HOST_IFACE'};
my $bridge_iface = $vm_conf_opts{'BRIDGE_IFACE'};
my $tap_iface = '';
+my $bridge_enabled = $vm_conf_opts{BRIDGE_ENABLE} eq 'yes' || $cmd_opts{create_bridge};
sub is_net_iface_created {
my $iface = $_[0];
@@ -188,9 +203,9 @@ sub is_net_iface_created {
}
sub create_bridge_dev {
- system("sudo /sbin/brctl addbr $bridge_iface");
- system("sudo /bin/ip addr flush dev $eth_iface");
- system("sudo /sbin/brctl addif $bridge_iface $eth_iface");
+ system("sudo //usr/sbin/brctl addbr $bridge_iface");
+ system("sudo /bin/ip addr flush dev $host_iface");
+ system("sudo /usr/sbin/brctl addif $bridge_iface $host_iface");
if ($vm_conf_opts{'BRIDGE_CFG_METHOD'} eq 'static') {
my $ip = $vm_conf_opts{'BRIDGE_IP_ADDR'};
@@ -209,27 +224,53 @@ sub create_bridge_dev {
system("sudo /bin/ip link set dev $bridge_iface up");
}
+sub destroy_tap_dev {
+ system("sudo /bin/ip link delete $tap_iface") if $tap_iface;
+}
+
sub create_tap_dev {
- create_bridge_dev() unless is_net_iface_created($bridge_iface);
+ my $iface = shift;
+ die "no host iface specified" unless $iface;
my $user = $ENV{'USER'};
die "failed to determine username" unless $user;
$tap_iface = `sudo /sbin/tunctl -u $user -b`;
$tap_iface =~ s/^\s+|\s+$//g;
- system("sudo /sbin/brctl addif $bridge_iface $tap_iface") == 0 or
- die "failed to create tap dev: $?";
- system("sudo /bin/ip link set dev $tap_iface up") == 0 or
- die "failed to create tap dev: $?";
+ my $ret;
+ if ($bridge_enabled) {
+ if (system("sudo /usr/sbin/brctl addif $iface $tap_iface")) {
+ $ret = $?;
+ destroy_tap_dev();
+ die "failed to create tap dev: $ret";
+ }
+ }
+
+ if (system("sudo /bin/ip link set dev $tap_iface up")) {
+ $ret = $?;
+ destroy_tap_dev();
+ die "failed to create tap dev: $ret";
+ }
}
-sub destroy_tap_dev {
- system("sudo /bin/ip link delete $tap_iface") if $tap_iface;
+sub setup_vm_net {
+ my $iface = '';
+ if ($bridge_enabled) {
+ create_bridge_dev() unless is_net_iface_created($bridge_iface);
+ $iface = $bridge_iface;
+ } else {
+ $iface = $host_iface;
+ }
+ create_tap_dev($iface);
+}
+
+sub destroy_vm_net {
+ destroy_tap_dev();
}
my %qemu_linux_opts = (
mach => "-machine q35",
- cpu => "-enable-kvm -cpu host -smp sockets=1,cores=1,threads=1",
+ cpu => "-enable-kvm -cpu host",
mem => "-m 1024",
bus => "-device qemu-xhci,id=xhci -device virtio-scsi-pci,id=scsi",
hdd => " -device scsi-hd,drive=hd -drive if=none,file=%s,cache=writeback,id=hd,format=raw,unit=0",
@@ -244,7 +285,7 @@ my %qemu_linux_opts = (
my %qemu_win_opts = (
mach => "-machine q35",
- cpu => "-enable-kvm -cpu host -smp sockets=1,cores=1,threads=1",
+ cpu => "-enable-kvm -cpu host",
mem => "-m 1024",
bus => "-device ich9-ahci,id=ahci -device virtio-scsi-pci,id=scsi -device qemu-xhci,id=xhci",
hdd => "-device scsi-hd,drive=hd,bootindex=0 -drive if=none,file=%s,cache=writeback,id=hd,format=raw,unit=0",
@@ -288,14 +329,19 @@ sub rem_vm_info {
sub save_vm_info {
my ($name, $macaddr) = @_;
- open(my $rconf, "+<", $vm_info) or die "failed to open vm info file: $!";
+
my @lines = ();
- while (<$rconf>) {
- next if /^$name\s+.*$/;
- push @lines, $_;
+
+ if (-e $vm_info) {
+ open(my $rconf, "+<", $vm_info) or die "failed to open vm info file: $!";
+ while (<$rconf>) {
+ next if /^$name\s+.*$/;
+ push @lines, $_;
+ }
+ close($rconf) or die "failed to close file: $!";
}
+
push @lines, "$name $macaddr\n";
- close($rconf) or die "failed to close file: $!";
open(my $wconf, ">", $vm_info) or die "failed to open vm info file: $!";
print $wconf @lines;
@@ -308,21 +354,25 @@ usage() unless $vm_name;
my $vm_img_path = "$vm_path/$vm_name.img";
sub get_vm_macaddr {
+ return '' if ! -e $vm_info || ! -s $vm_info;
+
open(my $conf, "<", $vm_info) or die "failed to open vm info file: $!";
+ my $ret = '';
while (<$conf>) {
chomp;
next unless /^$vm_name\s+.*$/;
my ($name, $macaddr) = split /\s+/;
- return $macaddr;
+ $ret = $macaddr;
+ last;
}
close($conf) or die "failed to close file: $!";
- return '';
+ return $ret;
}
if ($cmd_opts{install_iso_path}) {
create_guest_img($vm_img_path);
- create_tap_dev();
+ setup_vm_net();
my $macaddr = get_vm_macaddr();
unless ($macaddr) {
@@ -357,15 +407,15 @@ if ($cmd_opts{install_iso_path}) {
print "[*] install $vm_name vm\n";
print "[*] macaddr: $macaddr\n";
- print "[*] cmd: $qemu_cmd\n";
+ print "[*] cmd: $qemu_cmd\n";
if (system($qemu_cmd)) {
- destroy_tap_dev();
+ destroy_vm_net();
die "failed to exec cmd: $qemu_cmd";
}
- print "\n[*] done\n";
+ print "[*] done\n";
save_vm_info($vm_name, $macaddr);
- destroy_tap_dev();
+ destroy_vm_net();
exit 0;
}
@@ -379,11 +429,8 @@ if ($cmd_opts{delete_vm}) {
exit 0;
}
-##
-## windows vm
-#
if ($cmd_opts{windows_guest}) {
- create_tap_dev();
+ setup_vm_net();
my $macaddr = get_random_macaddr();
my $qemu_cmd = "/usr/bin/qemu-system-x86_64";
@@ -408,13 +455,13 @@ if ($cmd_opts{windows_guest}) {
print "[*] $vm_name is up and running\n";
print "[*] ipaddr: " . resolve_name($vm_name) . "\n";
print "[*] macaddr: " . get_vm_macaddr() . "\n";
- print "[*] cmd: $qemu_cmd\n";
+ print "[*] cmd: $qemu_cmd\n";
if (system($qemu_cmd)) {
- destroy_tap_dev();
+ destroy_vm_net();
die "failed to exec cmd: $qemu_cmd";
}
print "[*] terminated\n";
- destroy_tap_dev();
+ destroy_vm_net();
exit 0;
}
@@ -423,8 +470,7 @@ my $rootfs_path = `mktemp -d`;
chomp($rootfs_path) if $rootfs_path;
sub mount_rootfs {
- die "$rootfs_path does not exist" unless $rootfs_path or
- -e $rootfs_path or -d $rootfs_path;
+ die "$rootfs_path does not exist" if !$rootfs_path || ! -e $rootfs_path || ! -d $rootfs_path;
system("guestmount -a $vm_img_path -m $cmd_opts{rootfs_path} $rootfs_path") == 0 or
die "failed to mount rootfs: $?";
}
@@ -485,7 +531,7 @@ sub setup_shared_dirs {
foreach (@dirs) {
my $path = abs_path($_);
- die "$_ does not exist" unless -e $path or -d $path;
+ die "$_ does not exist" if ! -e $path || ! -d $path;
my $tag = "__sharevh-" . sprintf "%d", rand(4096);
mkdir("$rootfs_path/share/" . basename($path));
@@ -509,9 +555,6 @@ sub setup_shared_dirs {
umount_rootfs();
}
-##
-## linux vms
-##
my $qemu_cmd = "/usr/bin/qemu-system-x86_64";
$qemu_cmd .= " $qemu_linux_opts{'mach'} $qemu_linux_opts{'cpu'}";
@@ -525,7 +568,7 @@ $qemu_cmd .= $user_hdds if $user_hdds;
setup_shared_dirs();
$qemu_cmd .= $qemu_linux_opts{'share'};
-create_tap_dev();
+setup_vm_net();
$qemu_cmd .= " " . sprintf $qemu_linux_opts{'net'}, get_vm_macaddr(), $tap_iface;
my $err;
@@ -535,7 +578,8 @@ if ($cmd_opts{kernel_path}) {
$err = "rootfs has not been specified";
goto OUT;
}
- unless (-e $cmd_opts{kernel_path} or -d $cmd_opts{kernel_path}) {
+
+ if (! -e $cmd_opts{kernel_path} || ! -d $cmd_opts{kernel_path}) {
$err = "$cmd_opts{kernel_path} does not exist";
goto OUT;
}
@@ -575,7 +619,7 @@ if ($cmd_opts{kernel_path}) {
}
my $linux_img = "$cmd_opts{kernel_path}/arch/x86/boot/bzImage";
- unless (-e $linux_img or -f $linux_img) {
+ if (! -e $linux_img || ! -f $linux_img) {
$err = "$linux_img does not exist";
goto OUT;
}
@@ -584,7 +628,7 @@ if ($cmd_opts{kernel_path}) {
$qemu_cmd .= " " . sprintf $qemu_linux_opts{'cmdline'}, $cmd_opts{rootfs_path};
$qemu_cmd .= " -nographic";
if ($cmd_opts{initrd_img}) {
- unless (-e $cmd_opts{initrd_img} or -f $cmd_opts{initrd_img}) {
+ if (! -e $cmd_opts{initrd_img} || ! -e $cmd_opts{initrd_img}) {
$err = "$cmd_opts{initrd_img} does not exist";
goto OUT;
}
@@ -599,7 +643,7 @@ $qemu_cmd .= " 2>/dev/null";
print "[*] $vm_name vm is up and running\n";
print "[*] ipaddr: " . resolve_name($vm_name) . "\n";
print "[*] macaddr: " . get_vm_macaddr() . "\n";
-print "[*] cmd: $qemu_cmd\n";
+print "[*] cmd: $qemu_cmd\n";
if (system($qemu_cmd)) {
$err = "failed to exec cmd: $qemu_cmd";
goto OUT;
@@ -608,7 +652,7 @@ print "[*] terminated\n";
OUT:
rem_shared_dirs();
-destroy_tap_dev();
+destroy_vm_net();
die "$err" if $err;
exit 0;