feat: netvm push/pull support, fixed run, and lots of cleanup
This commit is contained in:
parent
18fa25b87e
commit
ea07569187
|
@ -55,7 +55,7 @@ qemu_ga() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function start(){
|
function cmd_start(){
|
||||||
[ ! -f "${LOCKFILE}" ] || { echo "Error: Netvm already running"; exit 1; }
|
[ ! -f "${LOCKFILE}" ] || { echo "Error: Netvm already running"; exit 1; }
|
||||||
echo "Starting netvm";
|
echo "Starting netvm";
|
||||||
qemu-system-x86_64 -m 512M \
|
qemu-system-x86_64 -m 512M \
|
||||||
|
@ -72,21 +72,53 @@ function start(){
|
||||||
echo $! > "${LOCKFILE}"
|
echo $! > "${LOCKFILE}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function stop(){
|
function cmd_stop(){
|
||||||
pkill -F "${LOCKFILE}" && rm "${LOCKFILE}"
|
pkill -F "${LOCKFILE}" && rm "${LOCKFILE}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function status(){
|
function cmd_status(){
|
||||||
qemu_ga guest-get-host-name "{}" | jq -r '."host-name"'
|
qemu_ga guest-get-host-name "{}" | jq -r '."host-name"'
|
||||||
pid=$(qemu_ga guest-exec '{"path": "uptime", "capture-output": true}' | jq -r '.pid')
|
pid=$(qemu_ga guest-exec '{"path": "uptime", "capture-output": true}' | jq -r '.pid')
|
||||||
out=$(qemu_ga guest-exec-status "$(jq -n --argjson pid "$pid" '{pid: $pid }')" \
|
out=$(qemu_ga guest-exec-status "$(jq -n --argjson pid "$pid" '{pid: $pid }')" \
|
||||||
| jq -r '."out-data"' \
|
| jq -r '."out-data"' \
|
||||||
| base64 -d \
|
| base64 -d \
|
||||||
)
|
)
|
||||||
echo $out
|
echo $out
|
||||||
}
|
}
|
||||||
|
|
||||||
function run(){
|
function cmd_push(){
|
||||||
|
local source="${COMMAND[1]}"
|
||||||
|
local dest="${COMMAND[2]}"
|
||||||
|
fo_request=$(jq -n --arg dest "$dest" '{"path": $dest, "mode": "w" }')
|
||||||
|
handle=$(qemu_ga guest-file-open "$fo_request")
|
||||||
|
bufb64=$(base64 "$source")
|
||||||
|
count=$(cat "$source" | wc -c)
|
||||||
|
fw_request=$(jq -n \
|
||||||
|
--argjson handle $handle \
|
||||||
|
--argjson count $count \
|
||||||
|
--arg bufb64 "$bufb64" \
|
||||||
|
'{handle: $handle, "buf-b64": $bufb64, count: $count }' \
|
||||||
|
)
|
||||||
|
qemu_ga guest-file-write "$fw_request"
|
||||||
|
fh_request=$(jq -n --argjson handle $handle '{handle: $handle}' )
|
||||||
|
qemu_ga guest-file-flush "$fh_request"
|
||||||
|
qemu_ga guest-file-close "$fh_request"
|
||||||
|
}
|
||||||
|
|
||||||
|
function cmd_pull(){
|
||||||
|
local source="${COMMAND[1]}"
|
||||||
|
local dest="${COMMAND[2]}"
|
||||||
|
fo_request=$(jq -n --arg source "$source" '{"path": $source}')
|
||||||
|
handle=$(qemu_ga guest-file-open "$fo_request")
|
||||||
|
fr_request=$(jq -n \
|
||||||
|
--argjson handle $handle \
|
||||||
|
'{handle: $handle, count: 48000000 }' \
|
||||||
|
)
|
||||||
|
out=$(qemu_ga guest-file-read "$fr_request")
|
||||||
|
echo $out | jq -r '."buf-b64"' | base64 -d > $dest
|
||||||
|
}
|
||||||
|
|
||||||
|
function cmd_run(){
|
||||||
[ -z "${COMMAND[1]}" ] && { echo "Error: missing command"; exit 1; }
|
[ -z "${COMMAND[1]}" ] && { echo "Error: missing command"; exit 1; }
|
||||||
[ -f "${LOCKFILE}" ] || { echo "Error: Netvm is not running"; exit 1; }
|
[ -f "${LOCKFILE}" ] || { echo "Error: Netvm is not running"; exit 1; }
|
||||||
[ -S "${QGA_SOCKET}" ] || { echo "Error: Netvm QGA socket is missing"; exit 1; }
|
[ -S "${QGA_SOCKET}" ] || { echo "Error: Netvm QGA socket is missing"; exit 1; }
|
||||||
|
@ -107,25 +139,48 @@ function run(){
|
||||||
"capture-output": true
|
"capture-output": true
|
||||||
}' \
|
}' \
|
||||||
)
|
)
|
||||||
|
pid=$(qemu_ga guest-exec "$request" | jq -r '.pid')
|
||||||
pid=$(qemu_ga guest-exec "$request" | jq -r '.pid')
|
local exited=false
|
||||||
out=$(qemu_ga guest-exec-status "$(jq -n --argjson pid "$pid" '{pid: $pid }')" \
|
until [ "$exited" == "true" ]; do \
|
||||||
| jq -r '."out-data"' \
|
out=$(qemu_ga guest-exec-status "$(jq -n --argjson pid "$pid" '{pid: $pid }')" )
|
||||||
)
|
exited=$(echo $out | jq -r '.exited')
|
||||||
sleep 1
|
if $exited && jq -r 'has("out-data")' >/dev/null < <(echo $out); then
|
||||||
echo $out
|
echo "$out" | jq -r '."out-data"' | base64 -d
|
||||||
echo $out | base64 -d
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
function help(){
|
cmd_usage() {
|
||||||
echo "Valid operations: start, stop, run, help"
|
cat <<-_EOF
|
||||||
|
netvm
|
||||||
|
|
||||||
|
Control network vm headlessly via QMP protocol
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
netvm start
|
||||||
|
Start headless network vm in the background
|
||||||
|
netvm stop
|
||||||
|
Stop headless network vm
|
||||||
|
netvm status
|
||||||
|
Get hostname and uptime from running network vm
|
||||||
|
netvm push <local-path> <remote-path>
|
||||||
|
Push a local file to the network VM
|
||||||
|
netvm pull <remote-path> <local-path>
|
||||||
|
Pull a file from the network VM
|
||||||
|
netvm run "<command>"
|
||||||
|
Run a command in network vm and get stdout
|
||||||
|
_EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
case "${COMMAND[0]}" in
|
case "$1" in
|
||||||
status) status ;;
|
status) shift; cmd_status $@ ;;
|
||||||
start) start ;;
|
start) shift; cmd_start $@ ;;
|
||||||
stop) stop ;;
|
stop) shift; cmd_stop $@ ;;
|
||||||
run) run ;;
|
push) shift; cmd_push $@ ;;
|
||||||
help) help ;;
|
pull) shift; cmd_pull $@ ;;
|
||||||
*) help ;;
|
run) shift; cmd_run $@ ;;
|
||||||
|
help) shift; cmd_usage $@ ;;
|
||||||
|
*) cmd_usage $@ ;;
|
||||||
esac
|
esac
|
||||||
|
|
Loading…
Reference in New Issue