From 951b771b9c9278b7d78e97f6082ae2c9b7e7e0bf Mon Sep 17 00:00:00 2001 From: Pragmatic Software Date: Tue, 15 Feb 2022 11:28:47 -0800 Subject: [PATCH] pbot-vm: vm-exec can now select VM; can be configured by vm-exec.json file The vm-exec command now recognizes the following options: -vm-serial -vm-heart -vm-cid -vm-vport -vm The -vm option accepts a name and configures the serial, heart, cid and vport appropriately. The vm-exec command can be configured by /host/config/vm-exec.json. --- applets/pbot-vm/README.md | 2 +- applets/pbot-vm/host/bin/vm-exec | 97 +++++++++++++++++++++--- applets/pbot-vm/host/config/vm-exec.json | 21 +++++ 3 files changed, 108 insertions(+), 12 deletions(-) create mode 100644 applets/pbot-vm/host/config/vm-exec.json diff --git a/applets/pbot-vm/README.md b/applets/pbot-vm/README.md index b7f01d90..9dc20ad5 100644 --- a/applets/pbot-vm/README.md +++ b/applets/pbot-vm/README.md @@ -1,3 +1,3 @@ PBot can interact with a virtual machine to safely execute arbitrary user-submitted system commands and code. -For installation and usage instructions, see [the documentation.](../../doc/VirtualMachine.md) +For installation and usage instructions, see [the PBot Virtual Machine documentation.](../../doc/VirtualMachine.md) diff --git a/applets/pbot-vm/host/bin/vm-exec b/applets/pbot-vm/host/bin/vm-exec index 7d10fe63..24d03255 100755 --- a/applets/pbot-vm/host/bin/vm-exec +++ b/applets/pbot-vm/host/bin/vm-exec @@ -108,9 +108,11 @@ sub make_context_from_args(@args_in) { } } - # parse -lang option - if ($context->{code} =~ s/^-lang=([^ ]+)\s+//) { - $context->{lang} = lc $1; + # parse options specific to vm-exec + while ($context->{code} =~ s/^-(lang|vm-cid|vm-vport|vm-serial|vm)=([^ ]+)\s+//) { + my ($option, $value) = ($1, $2); + print STDERR "Overriding `$option` to `$value`.\n"; + $context->{$option} = lc $value; } return $context; @@ -148,9 +150,90 @@ sub load_language($context) { return "Languages::$language"->new(%$context); } +sub load_config($file) { + open my $fh, '<', $file or die "load config: could not open $file: $!\n"; + local $/ = undef; + my $json = <$fh>; + close $fh; + return decode_json($json); +} + +sub config_get_machine($config, $machine) { + # check if machine is an alias and update to actual machine + if (exists $config->{aliases}->{$machine}) { + $machine = $config->{aliases}->{$machine}; + } + + # return pointer to config entry + return $config->{machines}->{$machine}; +} + +sub list_machines($config) { + my @machines; + + # quick-and-easy: just list the aliases + foreach my $alias (keys %{$config->{aliases}}) { + push @machines, $alias; + } + + return join ', ', sort @machines; +} + +sub configure_context($context, $config) { + if (exists $context->{vm}) { + # -vm option was passed, forcibly override machine + my $machine = $context->{vm}; + + # point at config entry + my $entry = config_get_machine($config, $machine); + + if (not defined $entry) { + my $machines = list_machines($config); + print "Unknown machine '$machine'; available machines are: $machines\n"; + exit 1; + } + + # override values + $context->{'vm-serial'} = $entry->{'serial'}; + $context->{'vm-heart'} = $entry->{'heart'}; + $context->{'vm-cid'} = $entry->{'cid'}; + $context->{'vm-vport'} = $entry->{'vport'}; + } else { + # otherwise configure any undefined values as default machine + my $machine = $config->{'default-machine'}; + + # point at config entry + my $entry = config_get_machine($config, $machine); + + if (not defined $entry) { + my $machines = list_machines($config); + print "Unknown machine '$machine'; available machines are: $machines\n"; + exit 1; + } + + # update any undefined values, preserving any existing values + $context->{'vm-serial'} //= $entry->{'serial'}; + $context->{'vm-heart'} //= $entry->{'heart'}; + $context->{'vm-cid'} //= $entry->{'cid'}; + $context->{'vm-vport'} //= $entry->{'vport'}; + } + + # set any undefined values to default values + $context->{nick} //= 'vm'; + $context->{channel} //= 'vm'; + $context->{lang} //= 'c11'; + $context->{'vm-serial'} //= SERIAL; + $context->{'vm-cid'} //= CID; + $context->{'vm-vport'} //= VPORT; +} + sub main() { my $context = make_context_from_args(@ARGV); + my $config = load_config("$RealBin/../config/vm-exec.json"); + + configure_context($context, $config); + if (not length $context->{code}) { if (exists $context->{usage}) { print "$context->{usage}\n"; @@ -160,14 +243,6 @@ sub main() { exit 1; } - # set any missing fields to default values - $context->{nick} //= 'vm'; - $context->{channel} //= 'vm'; - $context->{lang} //= 'c11'; - $context->{'vm-serial'} //= SERIAL; - $context->{'vm-cid'} //= CID; - $context->{'vm-vport'} //= VPORT; - my $lang = load_language($context); $lang->process_interactive_edit; diff --git a/applets/pbot-vm/host/config/vm-exec.json b/applets/pbot-vm/host/config/vm-exec.json new file mode 100644 index 00000000..9261bef7 --- /dev/null +++ b/applets/pbot-vm/host/config/vm-exec.json @@ -0,0 +1,21 @@ +{ + "machines" : { + "pbot-vm" : { + "serial" : 5555, + "heart" : 5556, + "cid" : 7, + "vport" : 5555 + }, + "pbot-test-vm" : { + "serial" : 7777, + "heart" : 7778, + "cid" : 42, + "vport" : 5555 + } + }, + "aliases" : { + "fedora-amd64" : "pbot-vm", + "test" : "pbot-test-vm" + }, + "default-machine" : "fedora-amd64" +}