qm guest exec or the pvesh create /nodes/{node}/qemu/{vmid}/agent/exec how to send array

Craig St George

Well-Known Member
Jul 31, 2018
114
14
58
63
HI I m provisioning Mikrotik Routers and as there is No cloud-init M trying to use the guest exec
when I use guest exec by hand via socat I can get it to work below

But I m having a hell time with qm guest exec 689 or via the API or
pvesh create /nodes/{node}/qemu/{vmid}/agent/exec

basically I need to send no PATH just attributes called input-data

like

input-data ':ip address add address=192.168.201.100/24 interface=wan

OR maybe my question is HOW to pass a string that gets converted to an array as I see the work is done by
so how to pass that array

/usr/share/perl5/PVE/QemuServer/Agent.pm
sub qemu_exec {
my ($vmid, $cmd) = @_;


my $path = shift @$cmd;
my $arguments = $cmd;


Basically I have to send something like this as the final output e.g there is no PATH


in socat this works

{"execute": "guest-exec", "arguments": {"input-data": "OmlwIGFkZHJlc3MgYWRkIGFkZHJlc3M9MTkyLjE2OC4wLjEvMjQgaW50ZXJmYWNlPWV0aGVyMTs=" ,"capture-output": true } }

Thanks
 
OK I worked it out can do like -c stuff -c extra stuff BUT now I see the real problem


QemuServer/Agent.pm
it treats this as an Arg not a key called input-data and without hacking the Agent.pm I cant do it :-(

so will have to work on my plan C


'arg' =>

Command: guest-exec
Execute a command in the guest

Arguments:

path: string
path or executable name to execute

arg: array of string (optional)
argument list to pass to executable

env: array of string (optional)
environment variables to pass to executable

input-data: string (optional)
data to be passed to process stdin (base64 encoded)

capture-output: boolean (optional)
bool flag to enable capture of stdout/stderr of running process. defaults to false.
 
what command do you want to execute? the input data is not implemented in the api ( you can open a feature request though on bugzilla.proxmox.com )
for the api /pvesh you have to give the 'command' parameter again for each part e.g.
for '/bin/ping 8.8.8.8' you have to give

--command '/bin/ping' --command '8.8.8.8'

on the cli there is a shortcut for the current node with 'qm guest exec VMID -- /bin/ping 8.8.8.8'
 
yes I finally worked out the adding like --command '/bin/ping' --command '8.8.8.8'
Aculally what I m trying to do run a script on the Mikotick Router
https://wiki.mikrotik.com/wiki/Manual:CHR#KVM

To set the Interface IP address after I create the VM so that I can then finish the conf off automatically
Now I m trying the file upload method to see if I can work around that

And yes I will ask for the feature and thanks for your help
 
Hi,

you may try this crude shell script, depends on socat and jq, first argument/word is vm id, everything after space is command to vm. It is a little bit of work in progress, but maybe some code may help you somehow...
 

Attachments

Last edited:
I am working on something similar, however I would like to be able to configure CHR through the proxmox RESTAPI interface with agent sending these commands. How would I go about this?
 
I had to use the write file in the end and then run that script
maybe this will help




$data = array('content' => $file_content, 'file' => 'firstboot');
//this always fails we will catch it latter any way
$action = '/nodes/' . $server->hostname . '/' . $this->vtype . '/' . $spcobj->username . '/agent/file-write';
$ret = $this->_api_call($action, 'POST', $data);

//try to execute the script
$data = array();
$data['command'] = 'config-startup';
$action = '/nodes/' . $server->hostname . '/' . $this->vtype . '/' . $spcobj->username . '/agent/exec';
$ret = $this->_api_call($action, 'POST', $data);
 
Thank you very much! I will take a look at it and see what we can do with it.
Did you every inquiry into why that call always fails?
 
This is for some poor soul who like me came here looking for same thing but for API.
I'm currently implementing ansible modules for SDN. and dhcp-range parameter is an array in cluster/sdn/vnets/{vnet}/subnets for this you need to pass a list like this ["start-address=10.10.1.5,end-address=10.10.1.50", "start-address=10.10.1.100,end-address=10.10.1.150"]

For more reference this is coming from -> get_dhcp_ranges() -> parse_property_string() and pve-sdn-dhcp-range type
 
Last edited: