Merge branch 'master' of git.qubes-os.org:/var/lib/qubes/git/marmarek/core
Conflicts: version_vm
This commit is contained in:
commit
b76ead2cb2
1
Makefile
1
Makefile
@ -57,5 +57,6 @@ clean:
|
||||
(cd dom0/restore && make clean)
|
||||
(cd dom0/qmemman && make clean)
|
||||
(cd common && make clean)
|
||||
(cd u2mfn && make clean)
|
||||
make -C qrexec clean
|
||||
make -C vchan clean
|
||||
|
@ -5,9 +5,9 @@ dvm_file_editor: dvm_file_editor.o ../common/ioall.o
|
||||
$(CC) -pie -g -o $@ $^
|
||||
qfile-agent-dvm: qfile-agent-dvm.o ../common/ioall.o ../common/gui-fatal.o
|
||||
$(CC) -pie -g -o $@ $^
|
||||
qfile-agent: qfile-agent.o ../common/ioall.o ../common/gui-fatal.o copy_file.o crc32.o
|
||||
qfile-agent: qfile-agent.o ../common/ioall.o ../common/gui-fatal.o ../common/copy_file.o ../common/crc32.o
|
||||
$(CC) -pie -g -o $@ $^
|
||||
qfile-unpacker: qfile-unpacker.o ../common/ioall.o ../common/gui-fatal.o copy_file.o unpack.o crc32.o
|
||||
qfile-unpacker: qfile-unpacker.o ../common/ioall.o ../common/gui-fatal.o ../common/copy_file.o ../common/unpack.o ../common/crc32.o
|
||||
$(CC) -pie -g -o $@ $^
|
||||
|
||||
clean:
|
||||
|
@ -20,15 +20,15 @@
|
||||
#
|
||||
#
|
||||
|
||||
if [ x"$1" = "x--with-progress" ] ; then
|
||||
DO_PROGRESS=1
|
||||
if [ x"$1" = "x--without-progress" ] ; then
|
||||
DO_PROGRESS=0
|
||||
shift
|
||||
else
|
||||
DO_PROGRESS=0
|
||||
DO_PROGRESS=1
|
||||
fi
|
||||
|
||||
if [ $# -lt 2 ] ; then
|
||||
echo usage: $0 '[--with-progress] dest_vmname file [file]+'
|
||||
echo usage: $0 '[--without-progress] dest_vmname file [file]+'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -6,4 +6,4 @@ meminfo-writer: meminfo-writer.o
|
||||
xenstore-watch: xenstore-watch.o
|
||||
$(CC) -o xenstore-watch xenstore-watch.o -lxenstore
|
||||
clean:
|
||||
rm -f meminfo-writer *.o *~
|
||||
rm -f meminfo-writer xenstore-watch *.o *~
|
||||
|
@ -5,7 +5,16 @@
|
||||
# This creates dm-snapshot device on given arguments
|
||||
|
||||
dir=$(dirname "$0")
|
||||
. "$dir/block-common.sh"
|
||||
if [ "$1" = "prepare" ] || [ "$1" = "cleanup" ]; then
|
||||
. "$dir/xen-hotplug-common.sh"
|
||||
command=$1
|
||||
else
|
||||
. "$dir/block-common.sh"
|
||||
fi
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
HOTPLUG_STORE="/var/run/xen-hotplug/${XENBUS_PATH//\//-}"
|
||||
|
||||
get_dev() {
|
||||
dev=$1
|
||||
@ -89,7 +98,6 @@ create_dm_snapshot_origin() {
|
||||
|
||||
t=$(xenstore_read_default "$XENBUS_PATH/type" 'MISSING')
|
||||
|
||||
|
||||
case "$command" in
|
||||
add)
|
||||
case $t in
|
||||
@ -117,24 +125,81 @@ case "$command" in
|
||||
if [ "$t" == "snapshot" ]; then
|
||||
#that's all for snapshot, store name of prepared device
|
||||
xenstore_write "$XENBUS_PATH/node" "/dev/mapper/$dm_devname"
|
||||
echo "/dev/mapper/$dm_devname" > "$HOTPLUG_STORE-node"
|
||||
write_dev /dev/mapper/$dm_devname
|
||||
elif [ "$t" == "origin" ]; then
|
||||
# for origin - prepare snapshot-origin device and store its name
|
||||
dm_devname=origin-$(stat -c '%D:%i' "$base")
|
||||
create_dm_snapshot_origin $dm_devname "$base"
|
||||
xenstore_write "$XENBUS_PATH/node" "/dev/mapper/$dm_devname"
|
||||
echo "/dev/mapper/$dm_devname" > "$HOTPLUG_STORE-node"
|
||||
write_dev /dev/mapper/$dm_devname
|
||||
fi
|
||||
# Save domain name for template commit on device remove
|
||||
domain=$(xenstore_read_default "$XENBUS_PATH/domain" '')
|
||||
if [ -z "$domain" ]; then
|
||||
domid=$(xenstore_read "$XENBUS_PATH/frontend-id")
|
||||
domain=$(xl domname $domid)
|
||||
fi
|
||||
echo $domain > "$HOTPLUG_STORE-domain"
|
||||
|
||||
release_lock "block"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
prepare)
|
||||
t=$2
|
||||
case $t in
|
||||
snapshot|origin)
|
||||
p=$3
|
||||
base=${p/:*/}
|
||||
cow=${p/*:/}
|
||||
|
||||
if [ -L "$base" ]; then
|
||||
base=$(readlink -f "$base") || fatal "$base link does not exist."
|
||||
fi
|
||||
|
||||
if [ -L "$cow" ]; then
|
||||
cow=$(readlink -f "$cow") || fatal "$cow link does not exist."
|
||||
fi
|
||||
|
||||
# first ensure that snapshot device exists (to write somewhere changes from snapshot-origin)
|
||||
dm_devname=$(get_dm_snapshot_name "$base" "$cow")
|
||||
|
||||
claim_lock "block"
|
||||
|
||||
# prepare snapshot device
|
||||
create_dm_snapshot $dm_devname "$base" "$cow"
|
||||
|
||||
if [ "$t" == "snapshot" ]; then
|
||||
#that's all for snapshot, store name of prepared device
|
||||
echo "/dev/mapper/$dm_devname"
|
||||
elif [ "$t" == "origin" ]; then
|
||||
# for origin - prepare snapshot-origin device and store its name
|
||||
dm_devname=origin-$(stat -c '%D:%i' "$base")
|
||||
create_dm_snapshot_origin $dm_devname "$base"
|
||||
echo "/dev/mapper/$dm_devname"
|
||||
fi
|
||||
|
||||
release_lock "block"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
remove)
|
||||
remove|cleanup)
|
||||
if [ "$command" = "cleanup" ]; then
|
||||
t=$2
|
||||
else
|
||||
t=$(cat $HOTPLUG_STORE-type)
|
||||
fi
|
||||
case $t in
|
||||
snapshot|origin)
|
||||
node=$(xenstore_read "$XENBUS_PATH/node")
|
||||
if [ "$command" = "cleanup" ]; then
|
||||
node=$3
|
||||
else
|
||||
node=$(cat "$HOTPLUG_STORE-node")
|
||||
fi
|
||||
|
||||
if [ -z "$node" ]; then
|
||||
fatal "No device node to remove"
|
||||
@ -174,14 +239,16 @@ case "$command" in
|
||||
dmsetup remove $snap
|
||||
fi
|
||||
done
|
||||
# Commit template changes
|
||||
domain=$(xenstore_read "$XENBUS_PATH/domain")
|
||||
if [ "$domain" ]; then
|
||||
# Dont stop on errors
|
||||
/usr/bin/qvm-template-commit "$domain" || true
|
||||
if [ "$command" = "remove" ]; then
|
||||
# Commit template changes
|
||||
domain=$(cat "$HOTPLUG_STORE-domain")
|
||||
if [ "$domain" ]; then
|
||||
# Dont stop on errors
|
||||
/usr/bin/qvm-template-commit "$domain" || true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ -e $node ]; then
|
||||
log debug "Removing $node"
|
||||
dmsetup remove $node
|
||||
|
51
common/qubes_download_dom0_updates.sh
Executable file
51
common/qubes_download_dom0_updates.sh
Executable file
@ -0,0 +1,51 @@
|
||||
#!/bin/bash
|
||||
|
||||
DOM0_UPDATES_DIR=/var/lib/qubes/dom0-updates
|
||||
|
||||
DOIT=0
|
||||
GUI=1
|
||||
while [ -n "$1" ]; do
|
||||
if [ "x--doit" = "x$1" ]; then
|
||||
DOIT=1
|
||||
elif [ "x--nogui" = "x$1" ]; then
|
||||
GUI=0
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if ! [ -d "$DOM0_UPDATES_DIR" ]; then
|
||||
echo "Dom0 updates dir does not exists: $DOM0_UPDATES_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p $DOM0_UPDATES_DIR/etc
|
||||
cp /etc/yum.conf $DOM0_UPDATES_DIR/etc/
|
||||
|
||||
echo "Checking for updates..."
|
||||
PKGLIST=`yum --installroot $DOM0_UPDATES_DIR check-update -q | cut -f 1 -d ' '`
|
||||
|
||||
if [ -z $PKGLIST ]; then
|
||||
# No new updates
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$DOIT" != "1" ]; then
|
||||
zenity --question --title="Qubes Dom0 updates" \
|
||||
--text="Updates for dom0 available. Do you want to download its now?" || exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "$DOM0_UPDATES_DIR/packages"
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$GUI" = 1 ]; then
|
||||
( echo "1"
|
||||
yumdownloader --destdir "$DOM0_UPDATES_DIR/packages" --installroot "$DOM0_UPDATES_DIR" $PKGLIST
|
||||
echo 100 ) | zenity --progress --pulsate --auto-close --auto-kill \
|
||||
--text="Downloading updates for Dom0, please wait..." --title="Qubes Dom0 updates"
|
||||
else
|
||||
yumdownloader --destdir "$DOM0_UPDATES_DIR/packages" --installroot "$DOM0_UPDATES_DIR" $PKGLIST
|
||||
fi
|
||||
|
||||
# qvm-copy-to-vm works only from user
|
||||
su -c "qvm-copy-to-vm @dom0updates $DOM0_UPDATES_DIR/packages/*.rpm" user
|
2
common/qubes_network.rules
Normal file
2
common/qubes_network.rules
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
SUBSYSTEMS=="xen", KERNEL=="eth*", ACTION=="add", RUN+="/usr/lib/qubes/setup_ip"
|
1
common/qubes_trigger_sync_appmenus.action
Normal file
1
common/qubes_trigger_sync_appmenus.action
Normal file
@ -0,0 +1 @@
|
||||
*:any:/usr/lib/qubes/qubes_trigger_sync_appmenus.sh
|
7
common/qubes_trigger_sync_appmenus.sh
Executable file
7
common/qubes_trigger_sync_appmenus.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
UPDATEABLE=`/usr/bin/xenstore-read qubes_vm_updateable`
|
||||
|
||||
if [ "$UPDATEABLE" = "True" ]; then
|
||||
echo -n SYNC > /var/run/qubes/qrexec_agent
|
||||
fi
|
13
common/setup_ip
Executable file
13
common/setup_ip
Executable file
@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
ip=`/usr/bin/xenstore-read qubes_ip`
|
||||
netmask=`/usr/bin/xenstore-read qubes_netmask`
|
||||
gateway=`/usr/bin/xenstore-read qubes_gateway`
|
||||
secondary_dns=`/usr/bin/xenstore-read qubes_secondary_dns`
|
||||
if [ x$ip != x ]; then
|
||||
/sbin/ifconfig $INTERFACE $ip netmask 255.255.255.255
|
||||
/sbin/ifconfig $INTERFACE up
|
||||
/sbin/route add default dev $INTERFACE
|
||||
echo "nameserver $gateway" > /etc/resolv.conf
|
||||
echo "nameserver $secondary_dns" >> /etc/resolv.conf
|
||||
fi
|
@ -1,3 +1,4 @@
|
||||
#define _GNU_SOURCE /* For O_NOFOLLOW. */
|
||||
#include <errno.h>
|
||||
#include <ioall.h>
|
||||
#include <fcntl.h>
|
1
dom0/aux-tools/.gitignore
vendored
Normal file
1
dom0/aux-tools/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
qfile-dom0-unpacker
|
4
dom0/aux-tools/Makefile
Normal file
4
dom0/aux-tools/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
CC=gcc
|
||||
CFLAGS=-g -Wall -I../../common -fPIC -pie
|
||||
qfile-dom0-unpacker: qfile-dom0-unpacker.o ../../common/ioall.o ../../common/gui-fatal.o ../../common/copy_file.o ../../common/unpack.o ../../common/crc32.o
|
||||
$(CC) -pie -g -o $@ $^
|
@ -22,20 +22,29 @@
|
||||
|
||||
SRCDIR=$1
|
||||
VMNAME=$2
|
||||
VMDIR=/var/lib/qubes/appvms/$VMNAME
|
||||
VMTYPE=$3
|
||||
if [ -z "$VMTYPE" ]; then
|
||||
VMTYPE=appvms
|
||||
fi
|
||||
VMDIR=/var/lib/qubes/$VMTYPE/$VMNAME
|
||||
APPSDIR=$VMDIR/apps
|
||||
|
||||
if [ $# != 2 ]; then
|
||||
echo "usage: $0 <apps_templates_dir> <vmname>"
|
||||
if [ $# -lt 2 ]; then
|
||||
echo "usage: $0 <apps_templates_dir> <vmname> [appvms|vm-templates|servicevms]"
|
||||
exit
|
||||
fi
|
||||
mkdir -p $APPSDIR
|
||||
|
||||
if [ "$SRCDIR" != "none" ]; then
|
||||
echo "--> Converting Appmenu Templates..."
|
||||
find $SRCDIR -name "*.desktop" -exec /usr/lib/qubes/convert_apptemplate2vm.sh {} $APPSDIR $VMNAME $VMDIR \;
|
||||
if [ -r "$VMDIR/whitelisted-appmenus.list" ]; then
|
||||
cat $VMDIR/whitelisted-appmenus.list | xargs -I{} /usr/lib/qubes/convert_apptemplate2vm.sh $SRCDIR/{} $APPSDIR $VMNAME $VMDIR
|
||||
else
|
||||
find $SRCDIR -name "*.desktop" $CHECK_WHITELISTED -exec /usr/lib/qubes/convert_apptemplate2vm.sh {} $APPSDIR $VMNAME $VMDIR \;
|
||||
fi
|
||||
/usr/lib/qubes/convert_apptemplate2vm.sh /usr/share/qubes/qubes-appmenu-select.template $APPSDIR $VMNAME $VMDIR
|
||||
|
||||
/usr/lib/qubes/convert_dirtemplate2vm.sh $SRCDIR/qubes-vm.directory.template $APPSDIR/$VMNAME-vm.directory $VMNAME $VMDIR
|
||||
/usr/lib/qubes/convert_dirtemplate2vm.sh $SRCDIR/qubes-*.directory.template $APPSDIR/$VMNAME-vm.directory $VMNAME $VMDIR
|
||||
fi
|
||||
|
||||
echo "--> Adding Apps to the Menu..."
|
||||
|
86
dom0/aux-tools/qfile-dom0-unpacker.c
Normal file
86
dom0/aux-tools/qfile-dom0-unpacker.c
Normal file
@ -0,0 +1,86 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <ioall.h>
|
||||
#include <grp.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/fsuid.h>
|
||||
#include <gui-fatal.h>
|
||||
#include <errno.h>
|
||||
#include "filecopy.h"
|
||||
int prepare_creds_return_uid(char *username)
|
||||
{
|
||||
struct passwd *pwd;
|
||||
pwd = getpwnam(username);
|
||||
if (!pwd) {
|
||||
perror("getpwnam");
|
||||
exit(1);
|
||||
}
|
||||
setenv("HOME", pwd->pw_dir, 1);
|
||||
setenv("USER", username, 1);
|
||||
setgid(pwd->pw_gid);
|
||||
initgroups(username, pwd->pw_gid);
|
||||
setfsuid(pwd->pw_uid);
|
||||
return pwd->pw_uid;
|
||||
}
|
||||
|
||||
void wait_for_child(int statusfd)
|
||||
{
|
||||
int status;
|
||||
if (read(statusfd, &status, sizeof status)!=sizeof status)
|
||||
gui_fatal("File copy error: Internal error reading status from unpacker");
|
||||
errno = status;
|
||||
switch (status) {
|
||||
case LEGAL_EOF: break;
|
||||
case 0: gui_fatal("File copy: Connection terminated unexpectedly"); break;
|
||||
case EINVAL: gui_fatal("File copy: Corrupted data from packer"); break;
|
||||
case EEXIST: gui_fatal("File copy: not overwriting existing file. Clean ~/incoming, and retry copy"); break;
|
||||
default: gui_fatal("File copy");
|
||||
}
|
||||
}
|
||||
|
||||
extern void do_unpack(int);
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
char *incoming_dir;
|
||||
int pipefds[2];
|
||||
int uid;
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "Invalid parameters, usage: %s user dir\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pipe(pipefds);
|
||||
|
||||
uid = prepare_creds_return_uid(argv[1]);
|
||||
|
||||
incoming_dir = argv[2];
|
||||
mkdir(incoming_dir, 0700);
|
||||
if (chdir(incoming_dir))
|
||||
gui_fatal("Error chdir to %s", incoming_dir);
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
perror("fork");
|
||||
exit(1);
|
||||
case 0:
|
||||
if (chroot(incoming_dir)) //impossible
|
||||
gui_fatal("Error chroot to %s", incoming_dir);
|
||||
setuid(uid);
|
||||
close(pipefds[0]);
|
||||
do_unpack(pipefds[1]);
|
||||
exit(0);
|
||||
default:;
|
||||
}
|
||||
|
||||
setuid(uid);
|
||||
close(pipefds[1]);
|
||||
wait_for_child(pipefds[0]);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,14 +1,19 @@
|
||||
#!/bin/sh
|
||||
VMNAME=$1
|
||||
VMDIR=/var/lib/qubes/appvms/$VMNAME
|
||||
VMTYPE=$2
|
||||
if [ -z "$VMTYPE" ]; then
|
||||
VMTYPE=appvms
|
||||
fi
|
||||
VMDIR=/var/lib/qubes/$VMTYPE/$VMNAME
|
||||
APPSDIR=$VMDIR/apps
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo "usage: $0 <vmname>"
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "usage: $0 <vmname> [appvms|vm-templates|servicevms]"
|
||||
exit
|
||||
fi
|
||||
|
||||
if ls $APPSDIR/*.directory $APPSDIR/*.desktop > /dev/null 2>&1; then
|
||||
xdg-desktop-menu uninstall $APPSDIR/*.directory $APPSDIR/*.desktop
|
||||
rm -f $APPSDIR/*.desktop $APPSDIR/*.directory
|
||||
fi
|
||||
|
||||
|
10
dom0/aux-tools/sync_rpmdb_updatevm.sh
Executable file
10
dom0/aux-tools/sync_rpmdb_updatevm.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
UPDATEVM=`qvm-get-updatevm`
|
||||
|
||||
if [ -n "$UPDATEVM" ]; then
|
||||
qvm-run -u root --pass_io --localcmd='tar c /var/lib/rpm /etc/yum.repos.d' "$UPDATEVM" 'tar x -C /var/lib/qubes/dom0-updates'
|
||||
fi
|
||||
|
||||
# Ignore errors (eg VM not running)
|
||||
exit 0
|
@ -20,6 +20,7 @@
|
||||
start()
|
||||
{
|
||||
echo -n $"Executing Qubes Core scripts:"
|
||||
modprobe evtchn
|
||||
chgrp qubes /etc/xen
|
||||
chmod 710 /etc/xen
|
||||
chgrp qubes /var/run/xend
|
||||
@ -28,7 +29,21 @@ start()
|
||||
chmod 660 /var/run/xend/xen-api.sock /var/run/xend/xmlrpc.sock
|
||||
chgrp qubes /var/run/xenstored/*
|
||||
chmod 660 /var/run/xenstored/*
|
||||
xm sched-credit -d 0 -w 65535
|
||||
chgrp qubes /var/lib/xen
|
||||
chmod 770 /var/lib/xen
|
||||
chgrp qubes /var/log/xen
|
||||
chmod 770 /var/log/xen
|
||||
chgrp qubes /proc/xen/privcmd
|
||||
chmod 660 /proc/xen/privcmd
|
||||
chgrp qubes /dev/xen/evtchn
|
||||
chmod 660 /dev/xen/evtchn
|
||||
touch /var/run/qubes/xl-lock
|
||||
chgrp qubes /var/run/qubes/xl-lock
|
||||
chmod 660 /var/run/qubes/xl-lock
|
||||
|
||||
xenstore-write /local/domain/0/name Domain-0
|
||||
|
||||
xl sched-credit -d 0 -w 512
|
||||
cp /var/lib/qubes/qubes.xml /var/lib/qubes/backup/qubes-$(date +%F-%T).xml
|
||||
|
||||
/usr/lib/qubes/qmemman_daemon.py >/var/log/qubes/qmemman.log 2>/var/log/qubes/qmemman.errs &
|
||||
|
@ -22,10 +22,10 @@ NETVM=$(qvm-get-default-netvm)
|
||||
|
||||
get_running_netvms() {
|
||||
# Actually get running VMs with PCI devices attached
|
||||
RUNNING_VMS=`xm list --state=Running | tail -n +3 | cut -f 1 -d " "`
|
||||
RUNNING_VMS=`xl list | tail -n +3 | cut -f 1 -d " "`
|
||||
RUNNING_NETVMS=""
|
||||
for VM in $RUNNING_VMS; do
|
||||
if [ -n "`xm pci-list $VM`" ]; then
|
||||
if [ -n "`xl pci-list $VM`" ]; then
|
||||
echo "$VM"
|
||||
fi
|
||||
done
|
||||
|
3
dom0/misc/limits-qubes.conf
Normal file
3
dom0/misc/limits-qubes.conf
Normal file
@ -0,0 +1,3 @@
|
||||
# xl create needs to allocate and mlock all VM memory
|
||||
@qubes soft memlock unlimited
|
||||
@qubes hard memlock unlimited
|
10
dom0/misc/qubes-appmenu-select.template
Normal file
10
dom0/misc/qubes-appmenu-select.template
Normal file
@ -0,0 +1,10 @@
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Exec=qubes-appmenu-select %VMNAME%
|
||||
Icon=/usr/share/qubes/icons/qubes.png
|
||||
Terminal=false
|
||||
Name=%VMNAME%: Add more shortcuts...
|
||||
GenericName=%VMNAME%: Add more shortcuts...
|
||||
StartupNotify=false
|
||||
Categories=System;
|
5
dom0/misc/qubes-templatevm.directory.template
Normal file
5
dom0/misc/qubes-templatevm.directory.template
Normal file
@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Type=Directory
|
||||
Name=Template: %VMNAME%
|
||||
Icon=/usr/share/qubes/icons/template.png
|
5
dom0/misc/qubes-vm.directory.template
Normal file
5
dom0/misc/qubes-vm.directory.template
Normal file
@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Type=Directory
|
||||
Name=Domain: %VMNAME%
|
||||
Icon=%VMDIR%/icon.png
|
1
dom0/misc/qubes_sync_rpmdb_updatevm.action
Normal file
1
dom0/misc/qubes_sync_rpmdb_updatevm.action
Normal file
@ -0,0 +1 @@
|
||||
*:any:/usr/lib/qubes/sync_rpmdb_updatevm.sh
|
28
dom0/misc/vm-template.conf
Normal file
28
dom0/misc/vm-template.conf
Normal file
@ -0,0 +1,28 @@
|
||||
#
|
||||
# This is a Xen VM config file for Qubes VM
|
||||
# DO NOT EDIT - autogenerated by qubes tools
|
||||
#
|
||||
|
||||
kernel="{kerneldir}/vmlinuz"
|
||||
ramdisk="{kerneldir}/initramfs"
|
||||
extra="ro nomodeset xencons=hvc rd_NO_PLYMOUTH 3 {kernelopts}"
|
||||
root="/dev/mapper/dmroot"
|
||||
|
||||
memory = {mem}
|
||||
maxmem = {maxmem}
|
||||
name = "{name}"
|
||||
|
||||
disk = [ {rootdev}
|
||||
{privatedev}
|
||||
{volatiledev}
|
||||
]
|
||||
|
||||
vif = [ {netdev} ]
|
||||
|
||||
pci = [ {pcidev} ]
|
||||
|
||||
vcpus = {vcpus}
|
||||
|
||||
on_poweroff = 'destroy'
|
||||
on_reboot = 'destroy'
|
||||
on_crash = 'destroy'
|
@ -4,10 +4,10 @@
|
||||
|
||||
get_running_netvms() {
|
||||
# Actually get running VMs with PCI devices attached
|
||||
RUNNING_VMS=`xm list --state=Running | tail -n +3 | cut -f 1 -d " "`
|
||||
RUNNING_VMS=`xl list | tail -n +3 | cut -f 1 -d " "`
|
||||
RUNNING_NETVMS=""
|
||||
for VM in $RUNNING_VMS; do
|
||||
if [ -n "`xm pci-list $VM`" ]; then
|
||||
if [ -n "`xl pci-list $VM|tail -n +2`" ]; then
|
||||
echo "$VM"
|
||||
fi
|
||||
done
|
||||
|
@ -9,6 +9,7 @@ class DomainState:
|
||||
def __init__(self, id):
|
||||
self.meminfo = None #dictionary of memory info read from client
|
||||
self.memory_actual = None #the current memory size
|
||||
self.memory_maximum = None #the maximum memory size
|
||||
self.mem_used = None #used memory, computed based on meminfo
|
||||
self.id = id #domain id
|
||||
self.last_target = 0 #the last memset target
|
||||
@ -27,6 +28,7 @@ class SystemState:
|
||||
|
||||
def del_domain(self, id):
|
||||
self.domdict.pop(id)
|
||||
self.do_balance()
|
||||
|
||||
def get_free_xen_memory(self):
|
||||
return self.xc.physinfo()['free_memory']*1024
|
||||
@ -42,6 +44,9 @@ class SystemState:
|
||||
id = str(domain['domid'])
|
||||
if self.domdict.has_key(id):
|
||||
self.domdict[id].memory_actual = domain['mem_kb']*1024
|
||||
self.domdict[id].memory_maximum = self.xs.read('', '/local/domain/%s/memory/static-max' % str(id))
|
||||
if not self.domdict[id].memory_maximum:
|
||||
self.domdict[id].memory_maximum = domain['maxmem_kb']*1024
|
||||
|
||||
#the below works (and is fast), but then 'xm list' shows unchanged memory value
|
||||
def mem_set(self, id, val):
|
||||
@ -51,6 +56,7 @@ class SystemState:
|
||||
#can happen in the middle of domain shutdown
|
||||
#apparently xc.lowlevel throws exceptions too
|
||||
try:
|
||||
self.xc.domain_setmaxmem(int(id), val/1024 + 1024) # LIBXL_MAXMEM_CONSTANT=1024
|
||||
self.xc.domain_set_target_mem(int(id), val/1024)
|
||||
except:
|
||||
pass
|
||||
|
@ -60,8 +60,8 @@ def prefmem(domain):
|
||||
CACHE_FACTOR = 1.3
|
||||
#dom0 is special, as it must have large cache, for vbds. Thus, give it a special boost
|
||||
if domain.id == '0':
|
||||
return domain.mem_used*CACHE_FACTOR + 350*1024*1024
|
||||
return domain.mem_used*CACHE_FACTOR
|
||||
return min(domain.mem_used*CACHE_FACTOR + 350*1024*1024, domain.memory_maximum)
|
||||
return min(domain.mem_used*CACHE_FACTOR, domain.memory_maximum)
|
||||
|
||||
def memory_needed(domain):
|
||||
#do not change
|
||||
@ -104,8 +104,11 @@ def balloon(memsize, domain_dictionary):
|
||||
|
||||
#redistribute positive "total_available_memory" of memory between domains, proportionally to prefmem
|
||||
def balance_when_enough_memory(domain_dictionary, xen_free_memory, total_mem_pref, total_available_memory):
|
||||
donors_rq = list()
|
||||
acceptors_rq = list()
|
||||
print 'balance_when_enough_memory(', xen_free_memory, total_mem_pref, total_available_memory, ')'
|
||||
target_memory = {}
|
||||
# memory not assigned because of static max
|
||||
left_memory = 0
|
||||
acceptors_count = 0
|
||||
for i in domain_dictionary.keys():
|
||||
if domain_dictionary[i].meminfo is None:
|
||||
continue
|
||||
@ -114,10 +117,43 @@ def balance_when_enough_memory(domain_dictionary, xen_free_memory, total_mem_pre
|
||||
target_nonint = prefmem(domain_dictionary[i]) + scale*total_available_memory
|
||||
#prevent rounding errors
|
||||
target = int(0.999*target_nonint)
|
||||
#do not try to give more memory than static max
|
||||
if target > domain_dictionary[i].memory_maximum:
|
||||
left_memory += target-domain_dictionary[i].memory_maximum
|
||||
target = domain_dictionary[i].memory_maximum
|
||||
else:
|
||||
# count domains which can accept more memory
|
||||
acceptors_count += 1
|
||||
target_memory[i] = target
|
||||
# distribute left memory across all acceptors
|
||||
while left_memory > 0 and acceptors_count > 0:
|
||||
print ' left_memory:', left_memory, 'acceptors_count:', acceptors_count
|
||||
new_left_memory = 0
|
||||
new_acceptors_count = acceptors_count
|
||||
for i in target_memory.keys():
|
||||
target = target_memory[i]
|
||||
if target < domain_dictionary[i].memory_maximum:
|
||||
memory_bonus = int(0.999*(left_memory/acceptors_count))
|
||||
if target+memory_bonus >= domain_dictionary[i].memory_maximum:
|
||||
new_left_memory += target+memory_bonus - domain_dictionary[i].memory_maximum
|
||||
target = domain_dictionary[i].memory_maximum
|
||||
new_acceptors_count -= 1
|
||||
else:
|
||||
target += memory_bonus
|
||||
target_memory[i] = target
|
||||
left_memory = new_left_memory
|
||||
acceptors_count = new_acceptors_count
|
||||
# split target_memory dictionary to donors and acceptors
|
||||
# this is needed to first get memory from donors and only then give it to acceptors
|
||||
donors_rq = list()
|
||||
acceptors_rq = list()
|
||||
for i in target_memory.keys():
|
||||
target = target_memory[i]
|
||||
if (target < domain_dictionary[i].memory_actual):
|
||||
donors_rq.append((i, target))
|
||||
else:
|
||||
acceptors_rq.append((i, target))
|
||||
|
||||
# print 'balance(enough): xen_free_memory=', xen_free_memory, 'requests:', donors_rq + acceptors_rq
|
||||
return donors_rq + acceptors_rq
|
||||
|
||||
@ -140,7 +176,9 @@ def balance_when_low_on_memory(domain_dictionary, xen_free_memory, total_mem_pre
|
||||
for i in acceptors:
|
||||
scale = 1.0*prefmem(domain_dictionary[i])/total_mem_pref_acceptors
|
||||
target_nonint = domain_dictionary[i].memory_actual + scale*squeezed_mem
|
||||
acceptors_rq.append((i, int(target_nonint)))
|
||||
#do not try to give more memory than static max
|
||||
target = min(int(0.999*target_nonint), domain_dictionary[i].memory_maximum)
|
||||
acceptors_rq.append((i, target))
|
||||
# print 'balance(low): xen_free_memory=', xen_free_memory, 'requests:', donors_rq + acceptors_rq
|
||||
return donors_rq + acceptors_rq
|
||||
|
||||
@ -171,7 +209,7 @@ def balance(xen_free_memory, domain_dictionary):
|
||||
continue
|
||||
need = memory_needed(domain_dictionary[i])
|
||||
# print 'domain' , i, 'act/pref', domain_dictionary[i].memory_actual, prefmem(domain_dictionary[i]), 'need=', need
|
||||
if need < 0:
|
||||
if need < 0 or domain_dictionary[i].memory_actual >= domain_dictionary[i].memory_maximum:
|
||||
donors.append(i)
|
||||
else:
|
||||
acceptors.append(i)
|
||||
|
@ -29,10 +29,11 @@ class WatchType:
|
||||
class XS_Watcher:
|
||||
def __init__(self):
|
||||
self.handle = xen.lowlevel.xs.xs()
|
||||
self.handle.watch('/vm', WatchType(XS_Watcher.domain_list_changed, None))
|
||||
self.handle.watch('/local/domain', WatchType(XS_Watcher.domain_list_changed, None))
|
||||
self.watch_token_dict = {}
|
||||
|
||||
def domain_list_changed(self, param):
|
||||
time.sleep(0.05)
|
||||
curr = self.handle.ls('', '/local/domain')
|
||||
if curr == None:
|
||||
return
|
||||
|
5
dom0/qubes-cached.repo
Normal file
5
dom0/qubes-cached.repo
Normal file
@ -0,0 +1,5 @@
|
||||
[qubes-dom0-cached]
|
||||
name = Qubes OS Repository for Dom0
|
||||
baseurl = file:///var/lib/qubes/updates
|
||||
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-qubes-1-primary
|
||||
gpgcheck = 1
|
File diff suppressed because it is too large
Load Diff
@ -64,14 +64,6 @@ def main():
|
||||
qvm_collection.pop(vm.qid)
|
||||
exit (1)
|
||||
|
||||
try:
|
||||
vm.add_to_xen_storage()
|
||||
|
||||
except (IOError, OSError) as err:
|
||||
print "ERROR: {0}".format(err)
|
||||
qvm_collection.pop(vm.qid)
|
||||
exit (1)
|
||||
|
||||
qvm_collection.save()
|
||||
qvm_collection.unlock_db()
|
||||
|
||||
|
@ -164,7 +164,6 @@ def main():
|
||||
|
||||
try:
|
||||
vm.create_on_disk(verbose=options.verbose, source_template=template_vm)
|
||||
vm.add_to_xen_storage()
|
||||
|
||||
except (IOError, OSError) as err:
|
||||
print "ERROR: {0}".format(err)
|
||||
|
20
dom0/qvm-tools/qvm-dom0-upgrade
Executable file
20
dom0/qvm-tools/qvm-dom0-upgrade
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
UPDATEVM=`qvm-get-updatevm`
|
||||
if [ -z "$UPDATEVM" ]; then
|
||||
echo "UpdateVM not set, exiting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checking for dom0 updates"
|
||||
|
||||
# Start VM if not running already
|
||||
qvm-run -a $UPDATEVM true || exit 1
|
||||
/usr/lib/qubes/sync_rpmdb_updatevm.sh || exit 1
|
||||
qvm-run -u root --pass_io $UPDATEVM "/usr/lib/qubes/qubes_download_dom0_updates.sh --doit $@" || exit 1
|
||||
yum check-update
|
||||
if [ $? -ne 100 ]; then
|
||||
exit 0
|
||||
fi
|
||||
gpk-update-viewer
|
||||
|
39
dom0/qvm-tools/qvm-get-updatevm
Executable file
39
dom0/qvm-tools/qvm-get-updatevm
Executable file
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/python2.6
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from qubes.qubes import QubesVmCollection
|
||||
from optparse import OptionParser;
|
||||
|
||||
def main():
|
||||
qvm_collection = QubesVmCollection()
|
||||
qvm_collection.lock_db_for_reading()
|
||||
qvm_collection.load()
|
||||
qvm_collection.unlock_db()
|
||||
updatevm = qvm_collection.get_updatevm_vm()
|
||||
if updatevm is None:
|
||||
print ""
|
||||
else:
|
||||
print updatevm.name
|
||||
|
||||
|
||||
|
||||
main()
|
@ -21,6 +21,7 @@
|
||||
#
|
||||
|
||||
from qubes.qubes import QubesVmCollection
|
||||
from qubes.qubes import QubesHost
|
||||
from qubes.qubes import QubesException
|
||||
from optparse import OptionParser
|
||||
|
||||
@ -59,8 +60,8 @@ fields = {
|
||||
|
||||
"xid" : {"func" : "vm.get_xid() if vm.is_running() else '-'"},
|
||||
|
||||
"mem" : {"func" : "(str(vm.get_mem()/1024/1024) + ' MB') if vm.is_running() else '-'"},
|
||||
"cpu" : {"func" : "round (vm.get_cpu_total_load(), 1) if vm.is_running() else '-'"},
|
||||
"mem" : {"func" : "(str(vm.get_mem()/1024) + ' MB') if vm.is_running() else '-'"},
|
||||
"cpu" : {"func" : "round (cpu_usages[vm.get_xid()]['cpu_usage'], 1) if vm.is_running() else '-'"},
|
||||
"disk": {"func" : "str(vm.get_disk_utilization()/(1024*1024)) + ' MB'"},
|
||||
"state": {"func" : "vm.get_power_state()"},
|
||||
|
||||
@ -114,10 +115,14 @@ def main():
|
||||
|
||||
fields_to_display = ["name", "on", "state", "updbl", "type", "template", "netvm", "label" ]
|
||||
|
||||
cpu_usages = None
|
||||
|
||||
if (options.ids):
|
||||
fields_to_display += ["qid", "xid"]
|
||||
|
||||
if (options.cpu):
|
||||
qhost = QubesHost()
|
||||
(measure_time, cpu_usages) = qhost.measure_cpu_usage()
|
||||
fields_to_display += ["cpu"]
|
||||
|
||||
if (options.mem):
|
||||
|
@ -32,7 +32,7 @@ def do_list(vm):
|
||||
print fmt.format ("name", vm.name)
|
||||
print fmt.format ("label", vm.label.name)
|
||||
print fmt.format ("type", vm.type)
|
||||
if vm.is_appvm():
|
||||
if vm.template_vm is not None:
|
||||
print fmt.format ("template", vm.template_vm.name)
|
||||
if vm.netvm_vm is not None:
|
||||
print fmt.format ("netvm", vm.netvm_vm.name)
|
||||
@ -40,15 +40,18 @@ def do_list(vm):
|
||||
print fmt.format ("installed by RPM?", vm.installed_by_rpm)
|
||||
print fmt.format ("dir", vm.dir_path)
|
||||
print fmt.format ("config", vm.conf_file)
|
||||
print fmt.format ("pcidevs", vm.pcidevs)
|
||||
if not vm.is_appvm():
|
||||
print fmt.format ("root img", vm.root_img)
|
||||
if vm.is_template():
|
||||
print fmt.format ("root COW img", vm.rootcow_img)
|
||||
if vm.is_appvm():
|
||||
if vm.template_vm is not None:
|
||||
print fmt.format ("root img", vm.template_vm.root_img)
|
||||
print fmt.format ("root volatile img", vm.volatile_img)
|
||||
print fmt.format ("root volatile img", vm.volatile_img)
|
||||
|
||||
print fmt.format ("private img", vm.private_img)
|
||||
print fmt.format ("memory", vm.memory)
|
||||
print fmt.format ("maxmem", vm.maxmem)
|
||||
|
||||
|
||||
def set_label(vms, vm, args):
|
||||
@ -65,6 +68,23 @@ def set_label(vms, vm, args):
|
||||
vm.label = QubesVmLabels[label]
|
||||
subprocess.check_call (["ln", "-sf", vm.label.icon_path, vm.icon_path])
|
||||
|
||||
def set_memory(vms, vm, args):
|
||||
if len (args) != 1:
|
||||
print "Missing memory argument!"
|
||||
|
||||
vm.memory = int(args[0])
|
||||
|
||||
def set_maxmem(vms, vm, args):
|
||||
if len (args) != 1:
|
||||
print "Missing maxmem argument!"
|
||||
|
||||
vm.maxmem = int(args[0])
|
||||
|
||||
def set_pcidevs(vms, vm, args):
|
||||
if len (args) != 1:
|
||||
print "Missing memory argument!"
|
||||
|
||||
vm.pcidevs = args[0]
|
||||
|
||||
def set_netvm(vms, vm, args):
|
||||
if len (args) != 1:
|
||||
@ -151,8 +171,11 @@ def set_nonupdateable(vms, vm, args):
|
||||
properties = {
|
||||
"updateable": set_updateable,
|
||||
"nonupdateable": set_nonupdateable,
|
||||
"pcidevs": set_pcidevs,
|
||||
"label" : set_label,
|
||||
"netvm" : set_netvm,
|
||||
"maxmem" : set_maxmem,
|
||||
"memory" : set_memory,
|
||||
}
|
||||
|
||||
|
||||
|
140
dom0/qvm-tools/qvm-revert-template-changes
Executable file
140
dom0/qvm-tools/qvm-revert-template-changes
Executable file
@ -0,0 +1,140 @@
|
||||
#!/usr/bin/python2.6
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2011 Marek Marczykowski <marmarek@mimuw.edu.pl>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from qubes.qubes import QubesVmCollection
|
||||
from qubes.qubes import QubesException
|
||||
from optparse import OptionParser
|
||||
import subprocess
|
||||
import os
|
||||
import time
|
||||
import glob
|
||||
|
||||
def main():
|
||||
usage = "usage: %prog [options] <template-name>"
|
||||
parser = OptionParser (usage)
|
||||
parser.add_option ("--force", action="store_true", dest="force", default=False,
|
||||
help="Do not prompt for comfirmation")
|
||||
|
||||
(options, args) = parser.parse_args ()
|
||||
if (len (args) != 1):
|
||||
parser.error ("You must specify TemplateVM name!")
|
||||
vmname = args[0]
|
||||
|
||||
if os.geteuid() != 0:
|
||||
print "ERROR: This tool must be run as root!"
|
||||
exit(1)
|
||||
|
||||
qvm_collection = QubesVmCollection()
|
||||
qvm_collection.lock_db_for_reading()
|
||||
qvm_collection.load()
|
||||
qvm_collection.unlock_db()
|
||||
|
||||
vm = qvm_collection.get_vm_by_name(vmname)
|
||||
if vm is None:
|
||||
print "A VM with the name '{0}' does not exist in the system.".format(vmname)
|
||||
exit(1)
|
||||
|
||||
if not vm.is_template():
|
||||
print "A VM '{0}' is not template.".format(vmname)
|
||||
exit(1)
|
||||
|
||||
if vm.is_running():
|
||||
print "You must stop VM first."
|
||||
exit(1)
|
||||
|
||||
oldcow_img = vm.rootcow_img + '.old'
|
||||
oldcow_stat = os.stat(oldcow_img)
|
||||
oldcow_time_str = time.strftime("%F %T", time.gmtime(oldcow_stat.st_mtime))
|
||||
|
||||
root_stat = os.stat(vm.root_img)
|
||||
old_dmdev = "/dev/mapper/snapshot-{0:x}:{1}-{2:x}:{3}".format(
|
||||
root_stat[2], root_stat[1],
|
||||
oldcow_stat[2], oldcow_stat[1])
|
||||
|
||||
snapshots = glob.glob('/dev/mapper/snapshot-{0:x}:{1}-*'.format(root_stat[2], root_stat[1]))
|
||||
snapshot_present = False
|
||||
for dev in snapshots:
|
||||
if dev == old_dmdev:
|
||||
snapshot_present = True
|
||||
else:
|
||||
print "ERROR: You must shutdown all VMs running system older/newer than last good one."
|
||||
exit(1)
|
||||
|
||||
root_blocks = os.path.getsize(vm.root_img)/512
|
||||
if not snapshot_present:
|
||||
p = subprocess.Popen (["/etc/xen/scripts/block-snapshot", "prepare",
|
||||
"snapshot", "{0}:{1}".format(vm.root_img, oldcow_img)],
|
||||
stdout=subprocess.PIPE)
|
||||
result = p.communicate()
|
||||
if result[0].strip() != old_dmdev:
|
||||
print "ERROR: Cannot create snapshot device ({0} != {1})".format(
|
||||
result[0].strip(), old_dmdev)
|
||||
exit(1)
|
||||
|
||||
|
||||
print "INFO: Reverting template changes done at {0}".format(oldcow_time_str)
|
||||
if not options.force:
|
||||
prompt = raw_input ("Do you want to proceed? [y/N] ")
|
||||
if not (prompt == "y" or prompt == "Y"):
|
||||
exit (0)
|
||||
|
||||
p = subprocess.Popen(["/sbin/dmsetup", "table", old_dmdev], stdout=subprocess.PIPE)
|
||||
result = p.communicate()
|
||||
dm_table = result[0]
|
||||
dm_table_elements = dm_table.split(' ')
|
||||
if dm_table_elements[2] != 'snapshot':
|
||||
print "ERROR: Unexpected device-mapper type ({0}). Template changes reverting already running".format(dm_table_elements[2])
|
||||
exit(1)
|
||||
|
||||
dm_table_elements[2] = 'snapshot-merge'
|
||||
dm_table = ' '.join(dm_table_elements)
|
||||
subprocess.check_call(["/sbin/dmsetup", "reload", old_dmdev, "--table", dm_table])
|
||||
# Reload new table into LIVE slot
|
||||
subprocess.check_call(["/sbin/dmsetup", "suspend", old_dmdev])
|
||||
subprocess.check_call(["/sbin/dmsetup", "resume", old_dmdev])
|
||||
# Wait to snapshot merge completed
|
||||
while True:
|
||||
p = subprocess.Popen(["/sbin/dmsetup", "status", old_dmdev], stdout=subprocess.PIPE)
|
||||
result = p.communicate()
|
||||
status_details = result[0].split(' ')
|
||||
blocks_used = status_details[3].split('/')[0]
|
||||
if int(blocks_used) == int(status_details[4]):
|
||||
break
|
||||
print "\r-> Reverting template changes: {0} of {1} left".format(blocks_used, root_blocks),
|
||||
time.sleep(1)
|
||||
print "\r-> Reverting template changes: done ".format(blocks_used, root_blocks)
|
||||
|
||||
dm_table_elements[2] = 'snapshot'
|
||||
dm_table = ' '.join(dm_table_elements)
|
||||
subprocess.check_call(["/sbin/dmsetup", "reload", old_dmdev, "--table", dm_table])
|
||||
# Reload new table into LIVE slot
|
||||
subprocess.check_call(["/sbin/dmsetup", "suspend", old_dmdev])
|
||||
subprocess.check_call(["/sbin/dmsetup", "resume", old_dmdev])
|
||||
|
||||
subprocess.check_call(["/etc/xen/scripts/block-snapshot", "cleanup",
|
||||
"snapshot", old_dmdev])
|
||||
|
||||
os.rename(oldcow_img, vm.rootcow_img)
|
||||
exit(0)
|
||||
|
||||
|
||||
main()
|
@ -79,19 +79,19 @@ def vm_run_cmd(vm, cmd, options):
|
||||
if options.shutdown:
|
||||
if options.verbose:
|
||||
print "Shutting down VM: '{0}'...".format(vm.name)
|
||||
subprocess.call (["/usr/sbin/xm", "shutdown", vm.name])
|
||||
subprocess.call (["/usr/sbin/xl", "shutdown", vm.name])
|
||||
return
|
||||
|
||||
if options.pause:
|
||||
if options.verbose:
|
||||
print "Pausing VM: '{0}'...".format(vm.name)
|
||||
subprocess.call (["/usr/sbin/xm", "pause", vm.name])
|
||||
subprocess.call (["/usr/sbin/xl", "pause", vm.name])
|
||||
return
|
||||
|
||||
if options.unpause:
|
||||
if options.verbose:
|
||||
print "UnPausing VM: '{0}'...".format(vm.name)
|
||||
subprocess.call (["/usr/sbin/xm", "unpause", vm.name])
|
||||
subprocess.call (["/usr/sbin/xl", "unpause", vm.name])
|
||||
return
|
||||
|
||||
if options.verbose:
|
||||
@ -152,13 +152,13 @@ def main():
|
||||
help="Wait for the VM(s) to shutdown")
|
||||
|
||||
parser.add_option ("--shutdown", action="store_true", dest="shutdown", default=False,
|
||||
help="Do 'xm shutdown' for the VM(s) (can be combined this with --all and --wait)")
|
||||
help="Do 'xl shutdown' for the VM(s) (can be combined this with --all and --wait)")
|
||||
|
||||
parser.add_option ("--pause", action="store_true", dest="pause", default=False,
|
||||
help="Do 'xm pause' for the VM(s) (can be combined this with --all and --wait)")
|
||||
help="Do 'xl pause' for the VM(s) (can be combined this with --all and --wait)")
|
||||
|
||||
parser.add_option ("--unpause", action="store_true", dest="unpause", default=False,
|
||||
help="Do 'xm unpause' for the VM(s) (can be combined this with --all and --wait)")
|
||||
help="Do 'xl unpause' for the VM(s) (can be combined this with --all and --wait)")
|
||||
|
||||
parser.add_option ("--pass_io", action="store_true", dest="passio", default=False,
|
||||
help="Pass stdin/stdout/stderr from remote program")
|
||||
@ -166,6 +166,9 @@ def main():
|
||||
parser.add_option ("--localcmd", action="store", dest="localcmd", default=None,
|
||||
help="With --pass_io, pass stdin/stdout/stderr to the given program")
|
||||
|
||||
parser.add_option ("--force", action="store_true", dest="force", default=False,
|
||||
help="Force operation, even if may damage other VMs (eg shutdown of NetVM)")
|
||||
|
||||
(options, args) = parser.parse_args ()
|
||||
|
||||
|
||||
@ -218,8 +221,12 @@ def main():
|
||||
|
||||
# If stopping NetVM - stop connected VMs too
|
||||
if options.shutdown and vm.is_netvm():
|
||||
vms_list += [vm for vm in qvm_collection.get_vms_connected_to(vm.qid) if vm.is_running()]
|
||||
vms_list.reverse()
|
||||
connected_vms = [vm for vm in qvm_collection.get_vms_connected_to(vm.qid) if vm.is_running()]
|
||||
if connected_vms and not options.force:
|
||||
print "ERROR: There are other VMs connected to this VM, "
|
||||
print " shutdown them first or use --force option"
|
||||
print "VMs list: " + str([vm.name for vm in connected_vms])
|
||||
exit(1)
|
||||
|
||||
if takes_cmd_argument:
|
||||
cmd = "{user}:{cmd}".format(user=options.user, cmd=cmdstr)
|
||||
|
46
dom0/qvm-tools/qvm-set-updatevm
Executable file
46
dom0/qvm-tools/qvm-set-updatevm
Executable file
@ -0,0 +1,46 @@
|
||||
#!/usr/bin/python2.6
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from qubes.qubes import QubesVmCollection
|
||||
from optparse import OptionParser;
|
||||
|
||||
def main():
|
||||
usage = "usage: %prog <vm-name>"
|
||||
parser = OptionParser (usage)
|
||||
(options, args) = parser.parse_args ()
|
||||
if (len (args) != 1):
|
||||
parser.error ("Missing argument!")
|
||||
vmname = args[0]
|
||||
|
||||
qvm_collection = QubesVmCollection()
|
||||
qvm_collection.lock_db_for_writing()
|
||||
qvm_collection.load()
|
||||
vm = qvm_collection.get_vm_by_name(vmname)
|
||||
if vm is None or vm.qid not in qvm_collection:
|
||||
print "A VM with the name '{0}' does not exist in the system.".format(vmname)
|
||||
exit(1)
|
||||
|
||||
qvm_collection.set_updatevm_vm(vm)
|
||||
qvm_collection.save()
|
||||
qvm_collection.unlock_db()
|
||||
|
||||
main()
|
199
dom0/qvm-tools/qvm-sync-appmenus
Executable file
199
dom0/qvm-tools/qvm-sync-appmenus
Executable file
@ -0,0 +1,199 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2011 Marek Marczykowski <marmarek@mimuw.edu.pl>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import subprocess
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
import fnmatch
|
||||
import shutil
|
||||
from optparse import OptionParser
|
||||
from qubes.qubes import QubesVmCollection,QubesException
|
||||
from qubes.qubes import qrexec_client_path
|
||||
|
||||
# fields required to be present (and verified) in retrieved desktop file
|
||||
required_fields = [ "Name", "Exec" ]
|
||||
|
||||
# regexps for sanitization of retrieved values
|
||||
std_re = re.compile(r"^[/a-zA-Z0-9.,&() -]*$")
|
||||
fields_regexp = {
|
||||
"Name": std_re,
|
||||
"GenericName": std_re,
|
||||
"Comment": std_re,
|
||||
"Categories": re.compile(r"^[a-zA-Z0-9/.; -]*$"),
|
||||
"Exec": re.compile(r"^[a-zA-Z0-9%>/:.= -]*$"),
|
||||
}
|
||||
|
||||
def get_appmenus(xid):
|
||||
untrusted_appmenulist = []
|
||||
if xid == -1:
|
||||
untrusted_appmenulist = sys.stdin.readlines()
|
||||
else:
|
||||
p = subprocess.Popen ([qrexec_client_path, '-d', str(xid),
|
||||
'user:grep -H = /usr/share/applications/*.desktop'], stdout=subprocess.PIPE)
|
||||
untrusted_appmenulist = p.communicate()[0].split('\n')
|
||||
if p.returncode != 0:
|
||||
raise QubesException("Error getting application list")
|
||||
|
||||
row_no = 0
|
||||
appmenus = {}
|
||||
line_rx = re.compile(r"([a-zA-Z0-9-.]+.desktop):([a-zA-Z0-9-]+(?:\[[a-zA-Z@_]+\])?)=(.*)")
|
||||
ignore_rx = re.compile(r".*([a-zA-Z0-9-.]+.desktop):(#.*|\s+)$")
|
||||
for untrusted_line in untrusted_appmenulist:
|
||||
# Ignore blank lines and comments
|
||||
if len(untrusted_line) == 0 or ignore_rx.match(untrusted_line):
|
||||
continue
|
||||
# use search instead of match to skip file path
|
||||
untrusted_m = line_rx.search(untrusted_line)
|
||||
if untrusted_m:
|
||||
untrusted_key = untrusted_m.group(2)
|
||||
untrusted_value = untrusted_m.group(3)
|
||||
if fields_regexp.has_key(untrusted_key):
|
||||
if fields_regexp[untrusted_key].match(untrusted_value):
|
||||
# now values are sanitized
|
||||
key = untrusted_key
|
||||
value = untrusted_value
|
||||
filename = untrusted_m.group(1)
|
||||
|
||||
if not appmenus.has_key(filename):
|
||||
appmenus[filename] = {}
|
||||
|
||||
appmenus[filename][key]=value
|
||||
else:
|
||||
print >>sys.stderr, "Warning: ignoring key %s: %s" % (untrusted_key, untrusted_value)
|
||||
# else: ignore this key
|
||||
else:
|
||||
print >>sys.stderr, "Warning: ignoring line: %s" % (untrusted_line);
|
||||
|
||||
return appmenus
|
||||
|
||||
|
||||
def create_template(path, values):
|
||||
|
||||
# check if all required fields are present
|
||||
for key in required_fields:
|
||||
if not values.has_key(key):
|
||||
print >>sys.stderr, "Warning: not creating/updating '%s' because of missing '%s' key" % (path, key)
|
||||
return
|
||||
|
||||
desktop_file = open(path, "w")
|
||||
desktop_file.write("[Desktop Entry]\n")
|
||||
desktop_file.write("Version=1.0\n")
|
||||
desktop_file.write("Type=Application\n")
|
||||
desktop_file.write("Terminal=false\n")
|
||||
desktop_file.write("X-Qubes-VmName=%VMNAME%\n")
|
||||
desktop_file.write("Icon=%VMDIR%/icon.png\n")
|
||||
for key in ["Name", "GenericName" ]:
|
||||
if values.has_key(key):
|
||||
desktop_file.write("{0}=%VMNAME%: {1}\n".format(key, values[key]))
|
||||
|
||||
for key in [ "Comment", "Categories" ]:
|
||||
if values.has_key(key):
|
||||
desktop_file.write("{0}={1}\n".format(key, values[key]))
|
||||
|
||||
desktop_file.write("Exec=qvm-run -q --tray -a %VMNAME% '{0}'\n".format(values['Exec']))
|
||||
desktop_file.close()
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
env_vmname = os.environ.get("QREXEC_REMOTE_DOMAIN")
|
||||
usage = "usage: %prog [options] <vm-name>\n"\
|
||||
"Updates desktop file templates for given StandaloneVM or TemplateVM"
|
||||
|
||||
parser = OptionParser (usage)
|
||||
parser.add_option ("-v", "--verbose", action="store_true", dest="verbose", default=False)
|
||||
|
||||
(options, args) = parser.parse_args ()
|
||||
if (len (args) != 1) and env_vmname is None:
|
||||
parser.error ("You must specify at least the VM name!")
|
||||
|
||||
if env_vmname:
|
||||
vmname=env_vmname
|
||||
else:
|
||||
vmname=args[0]
|
||||
|
||||
qvm_collection = QubesVmCollection()
|
||||
qvm_collection.lock_db_for_reading()
|
||||
qvm_collection.load()
|
||||
qvm_collection.unlock_db()
|
||||
|
||||
vm = qvm_collection.get_vm_by_name(vmname)
|
||||
|
||||
if vm is None:
|
||||
print >>sys.stderr, "ERROR: A VM with the name '{0}' does not exist in the system.".format(vmname)
|
||||
exit(1)
|
||||
|
||||
if not vm.is_updateable():
|
||||
print >>sys.stderr, "ERROR: To sync appmenus for non-updateable VM, do it on template instead"
|
||||
exit(1)
|
||||
|
||||
if not vm.is_running():
|
||||
print >>sys.stderr, "ERROR: Appmenus can be retrieved only from running VM - start it first"
|
||||
exit(1)
|
||||
|
||||
new_appmenus = {}
|
||||
if env_vmname is None:
|
||||
# Get appmenus from VM
|
||||
xid = vm.get_xid()
|
||||
assert xid > 0
|
||||
|
||||
new_appmenus = get_appmenus(xid)
|
||||
else:
|
||||
options.verbose = False
|
||||
new_appmenus = get_appmenus(-1)
|
||||
|
||||
if len(new_appmenus) == 0:
|
||||
print >>sys.stderr, "ERROR: No appmenus received, terminating"
|
||||
exit(1)
|
||||
|
||||
if not os.path.exists(vm.appmenus_templates_dir):
|
||||
os.mkdir(vm.appmenus_templates_dir)
|
||||
if vm.is_template():
|
||||
shutil.copy('/usr/share/qubes/qubes-templatevm.directory.template', vm.appmenus_templates_dir)
|
||||
else:
|
||||
shutil.copy('/usr/share/qubes/qubes-vm.directory.template', vm.appmenus_templates_dir)
|
||||
|
||||
# Create new/update existing templates
|
||||
if options.verbose:
|
||||
print "--> Got {0} appmenus, storing to disk".format(str(len(new_appmenus)))
|
||||
for appmenu_file in new_appmenus.keys():
|
||||
if options.verbose:
|
||||
if os.path.exists(vm.appmenus_templates_dir + '/' + appmenu_file):
|
||||
print "---> Updating {0}".format(appmenu_file)
|
||||
else:
|
||||
print "---> Creating {0}".format(appmenu_file)
|
||||
create_template(vm.appmenus_templates_dir + '/' + appmenu_file, new_appmenus[appmenu_file])
|
||||
|
||||
# Delete appmenus of remove applications
|
||||
if options.verbose:
|
||||
print "--> Cleaning old files"
|
||||
for appmenu_file in os.listdir(vm.appmenus_templates_dir):
|
||||
if not fnmatch.fnmatch(appmenu_file, '*.desktop'):
|
||||
continue
|
||||
|
||||
if not new_appmenus.has_key(appmenu_file):
|
||||
if options.verbose:
|
||||
print "---> Removing {0}".format(appmenu_file)
|
||||
os.unlink(vm.appmenus_templates_dir + '/' + appmenu_file)
|
||||
|
||||
main()
|
@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
HOTPLUG_STORE="/var/run/xen-hotplug/${XENBUS_PATH//\//-}"
|
||||
|
||||
hd_arr[10]=a
|
||||
hd_arr[11]=b
|
||||
hd_arr[12]=c
|
||||
@ -38,6 +40,8 @@ process()
|
||||
xenstore-write "$XENBUS_PATH/node" "$dev" \
|
||||
"$XENBUS_PATH/physical-device" "7:"$HEXNUMBER \
|
||||
"$XENBUS_PATH/hotplug-status" connected
|
||||
echo "$dev" > "$HOTPLUG_STORE-node"
|
||||
echo "file" > "$HOTPLUG_STORE-type"
|
||||
}
|
||||
|
||||
#exec 2>>/tmp/block.$$
|
||||
|
@ -22,8 +22,13 @@
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import shutil
|
||||
import glob
|
||||
from qubes.qubes import QubesVmCollection
|
||||
|
||||
updates_dir = "/var/lib/qubes/updates"
|
||||
updates_rpm_dir = updates_dir + "/rpm"
|
||||
|
||||
def is_copy_allowed(vm):
|
||||
# if vm.copy_allowed:
|
||||
# return True
|
||||
@ -33,6 +38,36 @@ def is_copy_allowed(vm):
|
||||
retcode = subprocess.call(['/usr/bin/kdialog', '--yesno', q, '--title', 'File transfer confirmation'])
|
||||
return retcode == 0
|
||||
|
||||
def dom0updates_fatal(msg):
|
||||
print >> sys.stderr, msg
|
||||
shutil.rmtree(updates_rpm_dir)
|
||||
exit(1)
|
||||
|
||||
def handle_dom0updates(updatevm):
|
||||
source=os.getenv("QREXEC_REMOTE_DOMAIN")
|
||||
if source != updatevm.name:
|
||||
print >> sys.stderr, 'Domain ' + source + ' not allowed to send dom0 updates'
|
||||
exit(1)
|
||||
# Clean old packages
|
||||
if os.path.exists(updates_rpm_dir):
|
||||
shutil.rmtree(updates_rpm_dir)
|
||||
subprocess.check_call(["/usr/lib/qubes/qfile-dom0-unpacker", os.getlogin(), updates_rpm_dir])
|
||||
# Verify received files
|
||||
for f in os.listdir(updates_rpm_dir):
|
||||
if glob.fnmatch.fnmatch(f, "*.rpm"):
|
||||
p = subprocess.Popen (["/bin/rpm", "-K", updates_rpm_dir + "/" + f],
|
||||
stdout=subprocess.PIPE)
|
||||
output = p.communicate()[0]
|
||||
if p.returncode != 0:
|
||||
dom0updates_fatal('Error while verifing %s signature: %s' % (f, output))
|
||||
if output.find("pgp") < 0:
|
||||
dom0updates_fatal('Domain ' + source + ' sent not signed rpm: ' + f)
|
||||
else:
|
||||
dom0updates_fatal('Domain ' + source + ' sent unexpected file: ' + f)
|
||||
# After updates received - create repo metadata
|
||||
subprocess.check_call(["/usr/bin/createrepo", "-q", "/var/lib/qubes/updates"])
|
||||
exit(0)
|
||||
|
||||
def main():
|
||||
FILECOPY_VMNAME_SIZE = 32
|
||||
blob=os.read(0, FILECOPY_VMNAME_SIZE)
|
||||
@ -42,6 +77,11 @@ def main():
|
||||
qvm_collection.lock_db_for_reading()
|
||||
qvm_collection.load()
|
||||
qvm_collection.unlock_db()
|
||||
|
||||
if vmname == '@dom0updates':
|
||||
updatevm = qvm_collection.get_updatevm_vm()
|
||||
handle_dom0updates(updatevm)
|
||||
# handle_dom0updates never returns
|
||||
|
||||
vm = qvm_collection.get_vm_by_name(vmname)
|
||||
# we do not want to flood dom0 with error windows; so just log to stderr
|
||||
|
@ -31,6 +31,7 @@ from qubes.qubes import QubesDaemonPidfile
|
||||
from qubes.qmemman_client import QMemmanClient
|
||||
|
||||
current_savefile = '/var/run/qubes/current_savefile'
|
||||
current_dvm_conf = '/var/run/qubes/current_dvm.conf'
|
||||
notify_object = None
|
||||
|
||||
class QfileDaemonDvm:
|
||||
@ -58,6 +59,7 @@ class QfileDaemonDvm:
|
||||
return None
|
||||
retcode = subprocess.call(['/usr/lib/qubes/qubes_restore',
|
||||
current_savefile,
|
||||
current_dvm_conf,
|
||||
'-c', vm.label.color,
|
||||
'-i', vm.label.icon,
|
||||
'-l', str(vm.label.index)])
|
||||
@ -130,8 +132,8 @@ def main():
|
||||
lockf.close()
|
||||
if dispname is not None:
|
||||
subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', dispname, 'directly:user:/usr/lib/qubes/dvm_file_editor'])
|
||||
subprocess.call(['/usr/sbin/xm', 'destroy', dispname])
|
||||
subprocess.call(['/usr/sbin/xl', 'destroy', dispname])
|
||||
qfile.remove_disposable_from_qdb(dispname)
|
||||
|
||||
main()
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
get_encoded_script()
|
||||
{
|
||||
if ! [ -f "$1" ] ; then
|
||||
@ -42,22 +42,24 @@ if [ -n "$ENCODED_SCRIPT" ] ; then
|
||||
fi
|
||||
#set -x
|
||||
xenstore-write /local/domain/$ID/qubes_save_request 1
|
||||
xenstore-watch /local/domain/$ID/device/qubes_used_mem
|
||||
xenstore-watch-qubes /local/domain/$ID/device/qubes_used_mem
|
||||
xenstore-read /local/domain/$ID/qubes_gateway | \
|
||||
cut -d . -f 2 | tr -d "\n" > $VMDIR/netvm_id.txt
|
||||
xm block-detach $1 /dev/xvdb
|
||||
cut -d . -f 3 | tr -d "\n" > $VMDIR/netvm_id.txt
|
||||
xl block-detach $1 xvdb
|
||||
MEM=$(xenstore-read /local/domain/$ID/device/qubes_used_mem)
|
||||
echo "DVM boot complete, memory used=$MEM. Saving image..."
|
||||
QMEMMAN_STOP=/var/run/qubes/do-not-membalance
|
||||
touch $QMEMMAN_STOP
|
||||
xm mem-set $1 $(($MEM/1000))
|
||||
xl mem-set $1 $(($MEM/1000))
|
||||
sleep 1
|
||||
touch $2
|
||||
if ! xm save $1 $2 ; then
|
||||
if ! xl save $1 $2 ; then
|
||||
rm -f $QMEMMAN_STOP
|
||||
exit 1
|
||||
fi
|
||||
rm -f $QMEMMAN_STOP
|
||||
cd $VMDIR
|
||||
# Fix start memory
|
||||
sed -i -e "s/^memory.*/memory = $((MEM/1000))/" dvm.conf
|
||||
tar -Scvf saved_cows.tar volatile.img
|
||||
echo "DVM savefile created successfully."
|
||||
|
@ -12,95 +12,73 @@
|
||||
#include <syslog.h>
|
||||
#include <xs.h>
|
||||
|
||||
char xmlrpc_header[] =
|
||||
"POST /RPC2 HTTP/1.0\r\n"
|
||||
"Host: \r\n"
|
||||
"User-Agent: xmlrpclib.py/1.0.1 (by www.pythonware.com)\r\n"
|
||||
"Content-Type: text/xml\r\n" "Content-Length: %d\r\n" "\r\n";
|
||||
char xmlrpc_body_restore[] =
|
||||
"<?xml version='1.0'?>\n"
|
||||
"<methodCall>\n"
|
||||
"<methodName>xend.domain.restore</methodName>\n"
|
||||
"<params>\n"
|
||||
"<param>\n"
|
||||
"<value><string>%s</string></value>\n"
|
||||
"</param>\n"
|
||||
"<param>\n"
|
||||
"<value><boolean>0</boolean></value>\n"
|
||||
"</param>\n" "</params>\n" "</methodCall>\n";
|
||||
|
||||
char xmlrpc_body_setmem[] =
|
||||
"<?xml version='1.0'?>\n<methodCall>\n<methodName>xend.domain.setMemoryTarget</methodName>\n<params>\n<param>\n<value><string>%d</string></value>\n</param>\n<param>\n<value><int>%d</int></value>\n</param>\n</params>\n</methodCall>\n";
|
||||
|
||||
void send_raw(int fd, char *body)
|
||||
{
|
||||
char *header;
|
||||
asprintf(&header, xmlrpc_header, strlen(body));
|
||||
if (write(fd, header, strlen(header)) != strlen(header)) {
|
||||
perror("write xend");
|
||||
int restore_domain(char *restore_file, char *conf_file, char *name) {
|
||||
int pid, status, domid;
|
||||
int pipe_fd[2];
|
||||
char buf[256];
|
||||
char *endptr;
|
||||
switch (pid = fork()) {
|
||||
case -1:
|
||||
perror("fork");
|
||||
exit(1);
|
||||
}
|
||||
if (write(fd, body, strlen(body)) != strlen(body)) {
|
||||
perror("write xend");
|
||||
exit(1);
|
||||
}
|
||||
shutdown(fd, SHUT_WR);
|
||||
}
|
||||
|
||||
|
||||
void send_req_restore(int fd, char *name)
|
||||
{
|
||||
char *body;
|
||||
asprintf(&body, xmlrpc_body_restore, name);
|
||||
send_raw(fd, body);
|
||||
}
|
||||
|
||||
void send_req_setmem(int fd, int domid, int mem)
|
||||
{
|
||||
char *body;
|
||||
asprintf(&body, xmlrpc_body_setmem, domid, mem);
|
||||
send_raw(fd, body);
|
||||
}
|
||||
|
||||
char *recv_resp(int fd)
|
||||
{
|
||||
#define RESPSIZE 65536
|
||||
static char buf[RESPSIZE];
|
||||
int total = 0;
|
||||
int n;
|
||||
for (;;) {
|
||||
n = read(fd, buf + total, RESPSIZE - total);
|
||||
if (n == 0) {
|
||||
buf[total] = 0;
|
||||
close(fd);
|
||||
return buf;
|
||||
}
|
||||
if (n < 0) {
|
||||
perror("xend read");
|
||||
case 0:
|
||||
close(1);
|
||||
if (dup2(open("/dev/null", O_RDWR), 1)==-1) {
|
||||
perror("dup2 or open");
|
||||
exit(1);
|
||||
}
|
||||
total += n;
|
||||
execl("/usr/sbin/xl", "xl", "restore", conf_file, restore_file, NULL);
|
||||
perror("execl");
|
||||
exit(1);
|
||||
default:;
|
||||
}
|
||||
if (waitpid(pid, &status, 0) < 0) {
|
||||
perror("waitpid");
|
||||
exit(1);
|
||||
}
|
||||
if (status != 0) {
|
||||
fprintf(stderr, "Error starting VM\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// read domid
|
||||
if (pipe(pipe_fd)==-1) {
|
||||
perror("pipe");
|
||||
exit(1);
|
||||
}
|
||||
switch (pid = fork()) {
|
||||
case -1:
|
||||
perror("fork");
|
||||
exit(1);
|
||||
case 0:
|
||||
close(1);
|
||||
if (dup2(pipe_fd[1], 1) == -1) {
|
||||
perror("dup2");
|
||||
exit(1);
|
||||
}
|
||||
execl("/usr/sbin/xl", "xl", "domid", name, NULL);
|
||||
perror("execl");
|
||||
exit(1);
|
||||
default:;
|
||||
}
|
||||
read(pipe_fd[0], buf, sizeof(buf)-1);
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
domid = strtoul(buf, &endptr, 10);
|
||||
if (domid <= 0 || *endptr != '\n') {
|
||||
fprintf(stderr, "Cannot get DispVM xid\n");
|
||||
exit(1);
|
||||
}
|
||||
if (waitpid(pid, &status, 0) < 0) {
|
||||
perror("waitpid");
|
||||
exit(1);
|
||||
}
|
||||
if (status != 0) {
|
||||
fprintf(stderr, "Error getting DispVM xid\n");
|
||||
exit(1);
|
||||
}
|
||||
return domid;
|
||||
}
|
||||
|
||||
void bad_resp(char *resp)
|
||||
{
|
||||
fprintf(stderr, "Error; Xend response:\n%s\n", resp);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int parse_resp(char *resp)
|
||||
{
|
||||
char *domid;
|
||||
if (strstr(resp, "<fault>"))
|
||||
bad_resp(resp);
|
||||
if (!strstr(resp, "domid"))
|
||||
bad_resp(resp);
|
||||
domid = strstr(resp, "<int>");
|
||||
if (!domid)
|
||||
bad_resp(resp);
|
||||
return strtoul(domid + 5, NULL, 0);
|
||||
}
|
||||
|
||||
char *gettime()
|
||||
{
|
||||
@ -161,27 +139,6 @@ void preload_cache(int fd)
|
||||
}
|
||||
}
|
||||
|
||||
int xend_connect()
|
||||
{
|
||||
struct sockaddr_un server;
|
||||
int s;
|
||||
|
||||
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (s < 0) {
|
||||
perror("socket af_unix");
|
||||
exit(1);
|
||||
}
|
||||
server.sun_family = AF_UNIX;
|
||||
strcpy(server.sun_path, "/var/run/xend/xmlrpc.sock");
|
||||
if (connect
|
||||
(s, (struct sockaddr *) &server,
|
||||
strlen(server.sun_path) + sizeof(server.sun_family))) {
|
||||
perror("connext xend");
|
||||
exit(1);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void start_rexec(int domid)
|
||||
{
|
||||
int pid, status;
|
||||
@ -214,40 +171,13 @@ void start_guid(int domid, int argc, char **argv)
|
||||
guid_args[0] = "qubes_guid";
|
||||
guid_args[1] = "-d";
|
||||
guid_args[2] = dstr;
|
||||
for (i = 2; i < argc; i++)
|
||||
for (i = 3; i < argc; i++)
|
||||
guid_args[i + 1] = argv[i];
|
||||
guid_args[argc + 1] = NULL;
|
||||
execv("/usr/bin/qubes_guid", guid_args);
|
||||
perror("execv");
|
||||
}
|
||||
|
||||
// modify the savefile. fd = fd to the open savefile,
|
||||
// buf - already read 1st page of the savefile
|
||||
// pattern - pattern to search for
|
||||
// val - string to replace pattern with
|
||||
void fix_savefile(int fd, char *buf, char *pattern, char *val)
|
||||
{
|
||||
int i, len = strlen(val), origlen;
|
||||
char *bracket;
|
||||
char *loc = strstr(buf + 20, pattern) + strlen(pattern);
|
||||
if (!loc)
|
||||
return;
|
||||
bracket = index(loc, ')');
|
||||
if (!bracket)
|
||||
return;
|
||||
origlen = (long) bracket - (long) loc;
|
||||
if (origlen < len) {
|
||||
fprintf(stderr, "too long string %s\n", val);
|
||||
exit(1);
|
||||
}
|
||||
for (i = 0; i < origlen - len; i++)
|
||||
loc[i] = ' ';
|
||||
memcpy(loc + i, val, strlen(val));
|
||||
lseek(fd, (long) loc - (long) buf, SEEK_SET);
|
||||
write(fd, loc, origlen);
|
||||
}
|
||||
|
||||
|
||||
char *dispname_by_dispid(int dispid)
|
||||
{
|
||||
static char retbuf[16];
|
||||
@ -258,8 +188,7 @@ char *dispname_by_dispid(int dispid)
|
||||
char *build_dvm_ip(int netvm, int id)
|
||||
{
|
||||
static char buf[256];
|
||||
snprintf(buf, sizeof(buf), "10.%d.%d.%d", netvm, id / 254 + 200,
|
||||
(id % 254) + 1);
|
||||
snprintf(buf, sizeof(buf), "10.138.%d.%d", netvm, (id % 254) + 1);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -270,15 +199,17 @@ char *build_dvm_ip(int netvm, int id)
|
||||
// normally, it should be "templatename-dvm"
|
||||
char *get_vmname_from_savefile(int fd)
|
||||
{
|
||||
int buflen;
|
||||
static char buf[4096];
|
||||
char *name;
|
||||
char *slash;
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
|
||||
perror("read savefile");
|
||||
buflen = read(fd, buf, sizeof(buf) - 1);
|
||||
if (buflen < 0) {
|
||||
perror("read vm conf");
|
||||
exit(1);
|
||||
}
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
buf[buflen] = 0;
|
||||
name = strstr(buf + 20, NAME_PATTERN);
|
||||
if (!name) {
|
||||
fprintf(stderr,
|
||||
@ -296,25 +227,69 @@ char *get_vmname_from_savefile(int fd)
|
||||
return slash + 1;
|
||||
}
|
||||
|
||||
void fix_savefile_all(int fd, int dispid, int netvm_id)
|
||||
void fill_field(FILE *conf, char *field, int dispid, int netvm_id)
|
||||
{
|
||||
char val[256];
|
||||
char buf[4096];
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
|
||||
perror("read savefile");
|
||||
if (!strcmp(field, "NAME")) {
|
||||
fprintf(conf, "%s", dispname_by_dispid(dispid));
|
||||
} else if (!strcmp(field, "MAC")) {
|
||||
fprintf(conf, "00:16:3e:7c:8b:%02x", dispid);
|
||||
} else if (!strcmp(field, "IP")) {
|
||||
fprintf(conf, "%s", build_dvm_ip(netvm_id, dispid));
|
||||
} else if (!strcmp(field, "UUID")) {
|
||||
// currently not present in conf file
|
||||
fprintf(conf, "064cd14c-95ad-4fc2-a4c9-cf9f522e5b%02x", dispid);
|
||||
} else {
|
||||
fprintf(stderr, "unknown field in vm conf: %s\n", field);
|
||||
exit(1);
|
||||
}
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
snprintf(val, sizeof(val),
|
||||
"064cd14c-95ad-4fc2-a4c9-cf9f522e5b%02x", dispid);
|
||||
fix_savefile(fd, buf, "(uuid ", val);
|
||||
fix_savefile(fd, buf, "(name ", dispname_by_dispid(dispid));
|
||||
snprintf(val, sizeof(val), "00:16:3e:7c:8b:%02x", dispid);
|
||||
fix_savefile(fd, buf, "(mac ", val);
|
||||
fix_savefile(fd, buf, "(ip ", build_dvm_ip(netvm_id, dispid));
|
||||
}
|
||||
|
||||
// modify the config file. conf = FILE of the new config,
|
||||
// conf_templ - fd of config template
|
||||
// pattern - pattern to search for
|
||||
// val - string to replace pattern with
|
||||
void fix_conffile(FILE *conf, int conf_templ, int dispid, int netvm_id)
|
||||
{
|
||||
int buflen, cur_len = 0;
|
||||
char buf[4096];
|
||||
char *bufpos = buf;
|
||||
char *pattern, *patternend;
|
||||
|
||||
/* read config template */
|
||||
lseek(conf_templ, 0, SEEK_SET);
|
||||
while ((cur_len = read(conf_templ, buf+cur_len, sizeof(buf)-cur_len)) > 0) {
|
||||
buflen+=cur_len;
|
||||
}
|
||||
if (cur_len < 0) {
|
||||
perror("read vm conf");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while ((pattern = index(bufpos, '%'))) {
|
||||
fwrite(bufpos, 1, pattern-bufpos, conf);
|
||||
if (ferror(conf)) {
|
||||
perror("write vm conf");
|
||||
exit(1);
|
||||
}
|
||||
patternend = index(pattern+1, '%');
|
||||
if (!patternend) {
|
||||
fprintf(stderr, "Unmatched '%%' in VM config\n");
|
||||
exit(1);
|
||||
}
|
||||
*patternend = '\0';
|
||||
fill_field(conf, pattern+1, dispid, netvm_id);
|
||||
bufpos = patternend+1;
|
||||
}
|
||||
while ((cur_len = fwrite(bufpos, 1, buflen-(bufpos-buf), conf)) > 0) {
|
||||
bufpos+=cur_len;
|
||||
}
|
||||
if (ferror(conf)) {
|
||||
perror("write vm conf");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void unpack_cows(char *name)
|
||||
{
|
||||
char vmdir[4096];
|
||||
@ -355,6 +330,17 @@ void write_xs_single(struct xs_handle *xs, int domid, char *name,
|
||||
}
|
||||
}
|
||||
|
||||
void perm_xs_single(struct xs_handle *xs, int domid, char *name,
|
||||
struct xs_permissions *perms, int nperms)
|
||||
{
|
||||
char key[256];
|
||||
snprintf(key, sizeof(key), "/local/domain/%d/%s", domid, name);
|
||||
if (!xs_set_permissions(xs, XBT_NULL, key, perms, nperms)) {
|
||||
fprintf(stderr, "xs_set_permissions");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int get_netvm_id_from_name(char *name)
|
||||
{
|
||||
int fd, n;
|
||||
@ -377,6 +363,7 @@ void setup_xenstore(int netvm_id, int domid, int dvmid, char *name)
|
||||
{
|
||||
char val[256];
|
||||
struct xs_handle *xs = xs_daemon_open();
|
||||
struct xs_permissions perm[1];
|
||||
if (!xs) {
|
||||
perror("xs_daemon_open");
|
||||
exit(1);
|
||||
@ -385,12 +372,18 @@ void setup_xenstore(int netvm_id, int domid, int dvmid, char *name)
|
||||
write_xs_single(xs, domid, "qubes_ip",
|
||||
build_dvm_ip(netvm_id, dvmid));
|
||||
write_xs_single(xs, domid, "qubes_netmask", "255.255.0.0");
|
||||
snprintf(val, sizeof(val), "10.%d.0.1", netvm_id);
|
||||
snprintf(val, sizeof(val), "10.137.%d.1", netvm_id);
|
||||
write_xs_single(xs, domid, "qubes_gateway", val);
|
||||
snprintf(val, sizeof(val), "10.%d.255.254", netvm_id);
|
||||
snprintf(val, sizeof(val), "10.137.%d.254", netvm_id);
|
||||
write_xs_single(xs, domid, "qubes_secondary_dns", val);
|
||||
write_xs_single(xs, domid, "qubes_vm_type", "AppVM");
|
||||
write_xs_single(xs, domid, "qubes_restore_complete", "True");
|
||||
|
||||
perm[0].id = domid;
|
||||
perm[0].perms = XS_PERM_NONE;
|
||||
perm_xs_single(xs, domid, "device", perm, 1);
|
||||
perm_xs_single(xs, domid, "memory", perm, 1);
|
||||
|
||||
xs_daemon_close(xs);
|
||||
|
||||
}
|
||||
@ -437,46 +430,45 @@ void redirect_stderr()
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd, domid, dispid, netvm_id;
|
||||
char *resp;
|
||||
int conf_templ, domid, dispid, netvm_id;
|
||||
FILE *conf;
|
||||
char *name;
|
||||
if (argc < 2) {
|
||||
char confname[256];
|
||||
if (argc < 3) {
|
||||
fprintf(stderr,
|
||||
"usage: %s savefile [guid args] \n", argv[0]);
|
||||
"usage: %s savefile conf_templ [guid args] \n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
redirect_stderr();
|
||||
fprintf(stderr, "time=%s, starting\n", gettime());
|
||||
set_fast_flag();
|
||||
atexit(rm_fast_flag);
|
||||
fd = open(argv[1], O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open savefile");
|
||||
conf_templ = open(argv[2], O_RDONLY);
|
||||
if (conf_templ < 0) {
|
||||
perror("fopen vm conf");
|
||||
exit(1);
|
||||
}
|
||||
dispid = get_next_disposable_id();
|
||||
name = get_vmname_from_savefile(fd);
|
||||
name = get_vmname_from_savefile(conf_templ);
|
||||
netvm_id = get_netvm_id_from_name(name);
|
||||
fix_savefile_all(fd, dispid, netvm_id);
|
||||
snprintf(confname, sizeof(confname), "/tmp/qubes-dvm-%d.xl", dispid);
|
||||
conf = fopen(confname, "w");
|
||||
if (!conf) {
|
||||
perror("fopen new vm conf");
|
||||
exit(1);
|
||||
}
|
||||
fix_conffile(conf, conf_templ, dispid, netvm_id);
|
||||
close(conf_templ);
|
||||
fclose(conf);
|
||||
// printf("name=%s\n", name);
|
||||
unpack_cows(name);
|
||||
// no preloading for now, assume savefile in shm
|
||||
// preload_cache(fd);
|
||||
fd = xend_connect();
|
||||
send_req_restore(fd, argv[1]);
|
||||
resp = recv_resp(fd);
|
||||
domid = parse_resp(resp);
|
||||
domid=restore_domain(argv[1], confname, dispname_by_dispid(dispid));
|
||||
write_varrun_domid(domid, dispname_by_dispid(dispid), name);
|
||||
fprintf(stderr,
|
||||
"time=%s, created domid=%d, creating xenstore entries\n",
|
||||
gettime(), domid);
|
||||
#if 0
|
||||
fd = xend_connect();
|
||||
send_req_setmem(fd, domid, 400);
|
||||
resp = recv_resp(fd);
|
||||
// printf("%s\n", resp);
|
||||
fprintf(stderr, "time=%s, creating xenstore entries\n", gettime());
|
||||
#endif
|
||||
setup_xenstore(netvm_id, domid, dispid, name);
|
||||
fprintf(stderr, "time=%s, starting qubes_guid\n", gettime());
|
||||
rm_fast_flag();
|
||||
|
@ -40,12 +40,16 @@ if ! /usr/lib/qubes/qubes_prepare_saved_domain.sh \
|
||||
fi
|
||||
ROOT=/var/lib/qubes/dvmdata/savefile_root
|
||||
DEFAULT=/var/lib/qubes/dvmdata/default_savefile
|
||||
DEFAULTCONF=/var/lib/qubes/dvmdata/default_dvm.conf
|
||||
CURRENT=/var/run/qubes/current_savefile
|
||||
CURRENTCONF=/var/run/qubes/current_dvm.conf
|
||||
SHMDIR=/dev/shm/qubes
|
||||
SHMCOPY=$SHMDIR/current_savefile
|
||||
rm -f $ROOT $DEFAULT $CURRENT
|
||||
rm -f $ROOT $DEFAULT $CURRENT $DEFAULTCONF $CURRENTCONF
|
||||
ln -s "/var/lib/qubes/appvms/$DVMTMPL/dvm-savefile" $DEFAULT
|
||||
ln -s "/var/lib/qubes/vm-templates/$TEMPLATENAME/root.img" $ROOT
|
||||
ln -s $DVMTMPLDIR/dvm.conf $DEFAULTCONF
|
||||
ln -s $DVMTMPLDIR/dvm.conf $CURRENTCONF
|
||||
if [ -f /var/lib/qubes/dvmdata/dont_use_shm ] ; then
|
||||
ln -s $DEFAULT $CURRENT
|
||||
else
|
||||
|
@ -4,8 +4,13 @@
|
||||
struct xen_sysctl_physinfo xphysinfo;
|
||||
main()
|
||||
{
|
||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||
xc_interface *handle = xc_interface_open(NULL, NULL, 0);
|
||||
if (!handle) {
|
||||
#else
|
||||
int handle = xc_interface_open();
|
||||
if (handle == -1) {
|
||||
#endif
|
||||
perror("xc_interface_open");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -1,42 +0,0 @@
|
||||
<!DOCTYPE busconfig PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<busconfig>
|
||||
<!--
|
||||
WARNING: if running any D-Bus version prior to 1.2.6, you may be
|
||||
vulnerable to information leakage via the NM D-Bus interface.
|
||||
Previous D-Bus versions did not deny-by-default, and this permissions
|
||||
config file assumes that D-Bus will deny rules by default unless
|
||||
explicitly over-ridden with an <allow /> tag.
|
||||
-->
|
||||
|
||||
<policy user="root">
|
||||
<allow own="org.freedesktop.NetworkManagerUserSettings"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.NetworkManagerUserSettings"
|
||||
send_interface="org.freedesktop.NetworkManagerSettings"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.NetworkManagerUserSettings"
|
||||
send_interface="org.freedesktop.NetworkManagerSettings.Connection"/>
|
||||
|
||||
<!-- Only root can get secrets -->
|
||||
<allow send_destination="org.freedesktop.NetworkManagerUserSettings"
|
||||
send_interface="org.freedesktop.NetworkManagerSettings.Connection.Secrets"/>
|
||||
</policy>
|
||||
<policy user="user">
|
||||
<allow own="org.freedesktop.NetworkManagerUserSettings"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.NetworkManagerUserSettings"
|
||||
send_interface="org.freedesktop.NetworkManagerSettings"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.NetworkManagerUserSettings"
|
||||
send_interface="org.freedesktop.NetworkManagerSettings.Connection"/>
|
||||
</policy>
|
||||
<policy context="default">
|
||||
<allow send_destination="org.freedesktop.NetworkManagerUserSettings"
|
||||
send_interface="org.freedesktop.DBus.Introspectable"/>
|
||||
</policy>
|
||||
|
||||
<limit name="max_replies_per_connection">512</limit>
|
||||
</busconfig>
|
||||
|
@ -19,6 +19,9 @@ while true; do
|
||||
IPTABLES_SAVE=$(/sbin/iptables-save | sed '/^\*filter/,/^COMMIT/d')
|
||||
OUT=`echo -e "$RULES\n$IPTABLES_SAVE" | /sbin/iptables-restore 2>&1 || :`
|
||||
/usr/bin/xenstore-write $XENSTORE_ERROR "$OUT"
|
||||
if [ "$OUT" ]; then
|
||||
DISPLAY=:0 /usr/bin/notify-send -t 3000 "Firewall loading error ($HOSTNAME)" "$OUT" || :
|
||||
fi
|
||||
|
||||
if [[ -z "$OUT" ]]; then
|
||||
# If OK save it for later
|
||||
@ -29,5 +32,5 @@ while true; do
|
||||
fi
|
||||
|
||||
# Wait for changes in xenstore file
|
||||
/usr/bin/xenstore-watch $XENSTORE_IPTABLES
|
||||
/usr/bin/xenstore-watch-qubes $XENSTORE_IPTABLES
|
||||
done
|
||||
|
@ -24,8 +24,8 @@ while true; do
|
||||
/usr/bin/xenstore-write qubes_netvm_external_ip "$CURR_NETCFG"
|
||||
fi
|
||||
|
||||
/usr/bin/xenstore-watch /local/domain/$NET_DOMID/qubes_netvm_external_ip
|
||||
/usr/bin/xenstore-watch-qubes /local/domain/$NET_DOMID/qubes_netvm_external_ip
|
||||
else
|
||||
/usr/bin/xenstore-watch qubes_netvm_domid
|
||||
/usr/bin/xenstore-watch-qubes qubes_netvm_domid
|
||||
fi
|
||||
done
|
||||
|
@ -51,7 +51,8 @@ enum {
|
||||
|
||||
enum {
|
||||
QREXEC_EXECUTE_FILE_COPY=0x700,
|
||||
QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM
|
||||
QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM,
|
||||
QREXEC_EXECUTE_APPMENUS_SYNC
|
||||
};
|
||||
|
||||
struct server_header {
|
||||
|
@ -482,6 +482,9 @@ void handle_trigger_io()
|
||||
else if (!strcmp(buf, "DVMR"))
|
||||
s_hdr.client_id =
|
||||
QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM;
|
||||
else if (!strcmp(buf, "SYNC"))
|
||||
s_hdr.client_id =
|
||||
QREXEC_EXECUTE_APPMENUS_SYNC;
|
||||
if (s_hdr.client_id) {
|
||||
s_hdr.type = MSG_AGENT_TO_SERVER_TRIGGER_EXEC;
|
||||
write_all_vchan_ext(&s_hdr, sizeof s_hdr);
|
||||
|
@ -361,6 +361,10 @@ void handle_execute_predefined_command(int req)
|
||||
rcmd = "directly:user:/usr/lib/qubes/qfile-agent-dvm";
|
||||
lcmd = "/usr/lib/qubes/qfile-daemon-dvm";
|
||||
break;
|
||||
case QREXEC_EXECUTE_APPMENUS_SYNC:
|
||||
rcmd = "user:grep -H = /usr/share/applications/*.desktop";
|
||||
lcmd = "/usr/bin/qvm-sync-appmenus";
|
||||
break;
|
||||
default: /* cannot happen, already sanitized */
|
||||
fprintf(stderr, "got trigger exec no %d\n", req);
|
||||
exit(1);
|
||||
@ -402,7 +406,8 @@ void sanitize_message_from_agent(struct server_header *untrusted_header)
|
||||
case MSG_AGENT_TO_SERVER_TRIGGER_EXEC:
|
||||
untrusted_cmd = untrusted_header->client_id;
|
||||
if (untrusted_cmd != QREXEC_EXECUTE_FILE_COPY &&
|
||||
untrusted_cmd != QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM) {
|
||||
untrusted_cmd != QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM &&
|
||||
untrusted_cmd != QREXEC_EXECUTE_APPMENUS_SYNC) {
|
||||
fprintf(stderr,
|
||||
"received MSG_AGENT_TO_SERVER_TRIGGER_EXEC cmd %d ?\n",
|
||||
untrusted_cmd);
|
||||
|
@ -83,7 +83,11 @@ int buffer_space_vchan_ext()
|
||||
// if the remote domain is destroyed, we get no notification
|
||||
// thus, we check for the status periodically
|
||||
|
||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||
static xc_interface *xc_handle = NULL;
|
||||
#else
|
||||
static int xc_handle = -1;
|
||||
#endif
|
||||
void slow_check_for_libvchan_is_eof(struct libvchan *ctrl)
|
||||
{
|
||||
struct evtchn_status evst;
|
||||
@ -198,8 +202,13 @@ char *peer_client_init(int dom, int port)
|
||||
// now client init should succeed; "while" is redundant
|
||||
while (!(ctrl = libvchan_client_init(dom, port)));
|
||||
|
||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||
xc_handle = xc_interface_open(NULL, 0, 0);
|
||||
if (!xc_handle) {
|
||||
#else
|
||||
xc_handle = xc_interface_open();
|
||||
if (xc_handle < 0) {
|
||||
#endif
|
||||
perror("xc_interface_open");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ License: GPL
|
||||
URL: http://www.qubes-os.org
|
||||
Requires: /usr/bin/xenstore-read
|
||||
Requires: fedora-release
|
||||
Requires: yum-plugin-post-transaction-actions
|
||||
BuildRequires: xen-devel
|
||||
|
||||
%define _builddir %(pwd)/common
|
||||
@ -71,24 +72,76 @@ install -m 644 RPM-GPG-KEY-qubes* $RPM_BUILD_ROOT/etc/pki/rpm-gpg/
|
||||
mkdir -p $RPM_BUILD_ROOT/sbin
|
||||
cp qubes_serial_login $RPM_BUILD_ROOT/sbin
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||
cp xenstore-watch $RPM_BUILD_ROOT/usr/bin
|
||||
cp xenstore-watch $RPM_BUILD_ROOT/usr/bin/xenstore-watch-qubes
|
||||
mkdir -p $RPM_BUILD_ROOT/etc
|
||||
cp serial.conf $RPM_BUILD_ROOT/var/lib/qubes/
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/udev/rules.d
|
||||
cp qubes_network.rules $RPM_BUILD_ROOT/etc/udev/rules.d/
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp setup_ip $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp qubes_download_dom0_updates.sh $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/yum/post-actions
|
||||
cp qubes_trigger_sync_appmenus.action $RPM_BUILD_ROOT/etc/yum/post-actions/
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/lib/qubes
|
||||
cp qubes_trigger_sync_appmenus.sh $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/dom0-updates
|
||||
|
||||
%triggerin -- initscripts
|
||||
cp /var/lib/qubes/serial.conf /etc/init/serial.conf
|
||||
|
||||
%post
|
||||
|
||||
# Disable gpk-update-icon
|
||||
sed 's/^NotShowIn=KDE;$/\0QUBES;/' -i /etc/xdg/autostart/gpk-update-icon.desktop
|
||||
# disable some Upstart services
|
||||
for F in plymouth-shutdown prefdm splash-manager start-ttys tty ; do
|
||||
if [ -e /etc/init/$F.conf ]; then
|
||||
mv -f /etc/init/$F.conf /etc/init/$F.conf.disabled
|
||||
fi
|
||||
done
|
||||
|
||||
remove_ShowIn () {
|
||||
if [ -e /etc/xdg/autostart/$1.desktop ]; then
|
||||
sed -i '/^\(Not\|Only\)ShowIn/d' /etc/xdg/autostart/$1.desktop
|
||||
fi
|
||||
}
|
||||
|
||||
# don't want it at all
|
||||
for F in abrt-applet deja-dup-monitor imsettings-start krb5-auth-dialog pulseaudio restorecond sealertauto ; do
|
||||
if [ -e /etc/xdg/autostart/$F.desktop ]; then
|
||||
remove_ShowIn $F
|
||||
echo 'NotShowIn=QUBES' >> /etc/xdg/autostart/$F.desktop
|
||||
fi
|
||||
done
|
||||
|
||||
# don't want it in DisposableVM
|
||||
for F in gcm-apply ; do
|
||||
if [ -e /etc/xdg/autostart/$F.desktop ]; then
|
||||
remove_ShowIn $F
|
||||
echo 'NotShowIn=DisposableVM' >> /etc/xdg/autostart/$F.desktop
|
||||
fi
|
||||
done
|
||||
|
||||
# want it in AppVM only
|
||||
for F in gnome-keyring-gpg gnome-keyring-pkcs11 gnome-keyring-secrets gnome-keyring-ssh gnome-settings-daemon user-dirs-update-gtk gsettings-data-convert ; do
|
||||
if [ -e /etc/xdg/autostart/$F.desktop ]; then
|
||||
remove_ShowIn $F
|
||||
echo 'OnlyShowIn=GNOME;AppVM;' >> /etc/xdg/autostart/$F.desktop
|
||||
fi
|
||||
done
|
||||
|
||||
# remove existing rule to add own later
|
||||
for F in gpk-update-icon nm-applet ; do
|
||||
remove_ShowIn $F
|
||||
done
|
||||
|
||||
echo 'OnlyShowIn=GNOME;UpdateableVM;' >> /etc/xdg/autostart/gpk-update-icon.desktop || :
|
||||
echo 'OnlyShowIn=GNOME;NetVM;' >> /etc/xdg/autostart/nm-applet.desktop || :
|
||||
|
||||
usermod -p '' root
|
||||
if [ "$1" != 1 ] ; then
|
||||
# do this whole %post thing only when updating for the first time...
|
||||
exit 0
|
||||
fi
|
||||
|
||||
usermod -L root
|
||||
if ! [ -f /var/lib/qubes/serial.orig ] ; then
|
||||
cp /etc/init/serial.conf /var/lib/qubes/serial.orig
|
||||
fi
|
||||
@ -177,4 +230,9 @@ rm -rf $RPM_BUILD_ROOT
|
||||
/etc/yum.repos.d/qubes%{dist}.repo
|
||||
/etc/pki/rpm-gpg/RPM-GPG-KEY-qubes*
|
||||
/sbin/qubes_serial_login
|
||||
/usr/bin/xenstore-watch
|
||||
/usr/bin/xenstore-watch-qubes
|
||||
/etc/udev/rules.d/qubes_network.rules
|
||||
/usr/lib/qubes/setup_ip
|
||||
/etc/yum/post-actions/qubes_trigger_sync_appmenus.action
|
||||
/usr/lib/qubes/qubes_trigger_sync_appmenus.sh
|
||||
/usr/lib/qubes/qubes_download_dom0_updates.sh
|
||||
|
@ -39,8 +39,9 @@ URL: http://www.qubes-os.org
|
||||
BuildRequires: xen-devel
|
||||
Requires: python, xen-runtime, pciutils, python-inotify, python-daemon, kernel-qubes-dom0
|
||||
Conflicts: qubes-gui-dom0 < 1.1.13
|
||||
Requires: yum-plugin-post-transaction-actions
|
||||
Requires: NetworkManager >= 0.8.1-1
|
||||
Requires: xen >= 3.4.3-6
|
||||
Requires: xen >= 4.1.0-2
|
||||
%define _builddir %(pwd)/dom0
|
||||
|
||||
%description
|
||||
@ -50,6 +51,7 @@ The Qubes core files for installation on Dom0.
|
||||
python -m compileall qvm-core qmemman
|
||||
python -O -m compileall qvm-core qmemman
|
||||
make -C restore
|
||||
make -C aux-tools
|
||||
make -C ../common
|
||||
make -C ../vchan
|
||||
make -C ../u2mfn
|
||||
@ -89,17 +91,26 @@ cp aux-tools/convert_dirtemplate2vm.sh $RPM_BUILD_ROOT/usr/lib/qubes
|
||||
cp aux-tools/create_apps_for_appvm.sh $RPM_BUILD_ROOT/usr/lib/qubes
|
||||
cp aux-tools/remove_appvm_appmenus.sh $RPM_BUILD_ROOT/usr/lib/qubes
|
||||
cp aux-tools/reset_vm_configs.py $RPM_BUILD_ROOT/usr/lib/qubes
|
||||
cp aux-tools/sync_rpmdb_updatevm.sh $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp qmemman/server.py $RPM_BUILD_ROOT/usr/lib/qubes/qmemman_daemon.py
|
||||
cp ../common/meminfo-writer $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp ../qrexec/qrexec_daemon $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp ../qrexec/qrexec_client $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp aux-tools/qfile-dom0-unpacker $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
|
||||
cp restore/xenstore-watch restore/qvm-create-default-dvm $RPM_BUILD_ROOT/usr/bin
|
||||
cp restore/qvm-create-default-dvm $RPM_BUILD_ROOT/usr/bin
|
||||
cp restore/xenstore-watch $RPM_BUILD_ROOT/usr/bin/xenstore-watch-qubes
|
||||
cp restore/qubes_restore restore/xenfreepages $RPM_BUILD_ROOT/usr/lib/qubes
|
||||
cp restore/qubes_prepare_saved_domain.sh $RPM_BUILD_ROOT/usr/lib/qubes
|
||||
cp restore/qfile-daemon-dvm $RPM_BUILD_ROOT/usr/lib/qubes
|
||||
cp restore/qfile-daemon $RPM_BUILD_ROOT/usr/lib/qubes
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/yum.real.repos.d
|
||||
cp qubes-cached.repo $RPM_BUILD_ROOT/etc/yum.real.repos.d/
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/yum/post-actions
|
||||
cp misc/qubes_sync_rpmdb_updatevm.action $RPM_BUILD_ROOT/etc/yum/post-actions/
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes
|
||||
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/vm-templates
|
||||
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/appvms
|
||||
@ -108,8 +119,14 @@ mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/servicevms
|
||||
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/backup
|
||||
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/dvmdata
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/updates
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/share/qubes/icons
|
||||
cp icons/*.png $RPM_BUILD_ROOT/usr/share/qubes/icons
|
||||
cp misc/qubes-vm.directory.template $RPM_BUILD_ROOT/usr/share/qubes/
|
||||
cp misc/qubes-templatevm.directory.template $RPM_BUILD_ROOT/usr/share/qubes/
|
||||
cp misc/qubes-appmenu-select.template $RPM_BUILD_ROOT/usr/share/qubes/
|
||||
cp misc/vm-template.conf $RPM_BUILD_ROOT/usr/share/qubes/
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||
cp ../common/qubes_setup_dnat_to_ns $RPM_BUILD_ROOT/usr/lib/qubes
|
||||
@ -120,6 +137,8 @@ mkdir -p $RPM_BUILD_ROOT/etc/NetworkManager/dispatcher.d/
|
||||
cp ../common/qubes_nmhook $RPM_BUILD_ROOT/etc/NetworkManager/dispatcher.d/
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
|
||||
cp ../common/iptables $RPM_BUILD_ROOT/etc/sysconfig
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/security/limits.d
|
||||
cp misc/limits-qubes.conf $RPM_BUILD_ROOT/etc/security/limits.d/99-qubes.conf
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d
|
||||
cp pm-utils/01qubes-sync-vms-clock $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d/
|
||||
@ -150,6 +169,13 @@ fi
|
||||
|
||||
sed 's/^net.ipv4.ip_forward.*/net.ipv4.ip_forward = 1/' -i /etc/sysctl.conf
|
||||
|
||||
sed '/^autoballoon=/d;/^lockfile=/d' -i /etc/xen/xl.conf
|
||||
echo 'autoballoon=0' >> /etc/xen/xl.conf
|
||||
echo 'lockfile="/var/run/qubes/xl-lock"' >> /etc/xen/xl.conf
|
||||
|
||||
sed '/^reposdir=/d' -i /etc/yum.conf
|
||||
echo reposdir=/etc/yum.real.repos.d >> /etc/yum.conf
|
||||
|
||||
chkconfig --add qubes_core || echo "WARNING: Cannot add service qubes_core!"
|
||||
chkconfig --add qubes_netvm || echo "WARNING: Cannot add service qubes_netvm!"
|
||||
chkconfig --add qubes_setupdvm || echo "WARNING: Cannot add service qubes_setupdvm!"
|
||||
@ -158,6 +184,10 @@ chkconfig --level 5 qubes_core on || echo "WARNING: Cannot enable service qubes_
|
||||
chkconfig --level 5 qubes_netvm on || echo "WARNING: Cannot enable service qubes_netvm!"
|
||||
chkconfig --level 5 qubes_setupdvm on || echo "WARNING: Cannot enable service qubes_setupdvm!"
|
||||
|
||||
# Conflicts with libxl stack, so disable it
|
||||
service xend stop
|
||||
chkconfig --level 5 xend off
|
||||
|
||||
HAD_SYSCONFIG_NETWORK=yes
|
||||
if ! [ -e /etc/sysconfig/network ]; then
|
||||
HAD_SYSCONFIG_NETWORK=no
|
||||
@ -167,10 +197,7 @@ fi
|
||||
|
||||
# Load evtchn module - xenstored needs it
|
||||
modprobe evtchn
|
||||
|
||||
# Now launch xend - we will need it for subsequent steps
|
||||
service xenstored start
|
||||
service xend start
|
||||
|
||||
if ! [ -e /var/lib/qubes/qubes.xml ]; then
|
||||
# echo "Initializing Qubes DB..."
|
||||
@ -259,13 +286,20 @@ fi
|
||||
/usr/lib/qubes/meminfo-writer
|
||||
/usr/lib/qubes/qfile-daemon-dvm*
|
||||
/usr/lib/qubes/qfile-daemon
|
||||
/usr/lib/qubes/sync_rpmdb_updatevm.sh
|
||||
%attr(4750,root,qubes) /usr/lib/qubes/qfile-dom0-unpacker
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes/vm-templates
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes/appvms
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes/servicevms
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes/backup
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes/dvmdata
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes/updates
|
||||
%dir /usr/share/qubes/icons/*.png
|
||||
/usr/share/qubes/qubes-vm.directory.template
|
||||
/usr/share/qubes/qubes-templatevm.directory.template
|
||||
/usr/share/qubes/qubes-appmenu-select.template
|
||||
/usr/share/qubes/vm-template.conf
|
||||
/usr/lib/qubes/qubes_setup_dnat_to_ns
|
||||
/usr/lib/qubes/qubes_fix_nm_conf.sh
|
||||
/etc/dhclient.d/qubes_setup_dnat_to_ns.sh
|
||||
@ -274,7 +308,7 @@ fi
|
||||
/usr/lib64/pm-utils/sleep.d/01qubes-sync-vms-clock
|
||||
/usr/lib64/pm-utils/sleep.d/01qubes-suspend-netvm
|
||||
/usr/lib64/pm-utils/sleep.d/02qubes-pause-vms
|
||||
/usr/bin/xenstore-watch
|
||||
/usr/bin/xenstore-watch-qubes
|
||||
/usr/lib/qubes/qubes_restore
|
||||
/usr/lib/qubes/qubes_prepare_saved_domain.sh
|
||||
/etc/xen/scripts/block.qubes
|
||||
@ -288,5 +322,8 @@ fi
|
||||
%attr(770,root,qubes) %dir /var/run/qubes
|
||||
%{_libdir}/libvchan.so
|
||||
%{_libdir}/libu2mfn.so
|
||||
/etc/yum.real.repos.d/qubes-cached.repo
|
||||
/etc/sudoers.d/qubes
|
||||
/etc/xdg/autostart/qubes-guid.desktop
|
||||
/etc/security/limits.d/99-qubes.conf
|
||||
/etc/yum/post-actions/qubes_sync_rpmdb_updatevm.action
|
||||
|
@ -66,9 +66,6 @@ mkdir -p $RPM_BUILD_ROOT/var/run/qubes
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/xen/scripts
|
||||
cp ../common/vif-route-qubes $RPM_BUILD_ROOT/etc/xen/scripts
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/dbus-1/system.d
|
||||
cp ../netvm/dbus-nm-applet.conf $RPM_BUILD_ROOT/etc/dbus-1/system.d/qubes-nm-applet.conf
|
||||
|
||||
%post
|
||||
|
||||
# Create NetworkManager configuration if we do not have it
|
||||
@ -91,11 +88,6 @@ if [ "$1" = 0 ] ; then
|
||||
chkconfig qubes_core_netvm off
|
||||
fi
|
||||
|
||||
%triggerin -- NetworkManager
|
||||
# Fix PolicyKit settings to allow run as normal user not visible to ConsoleKit
|
||||
sed 's#<defaults>$#\0<allow_any>yes</allow_any>#' -i /usr/share/polkit-1/actions/org.freedesktop.NetworkManager.policy
|
||||
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
@ -108,4 +100,3 @@ rm -rf $RPM_BUILD_ROOT
|
||||
/etc/NetworkManager/dispatcher.d/qubes_nmhook
|
||||
/etc/NetworkManager/dispatcher.d/30-qubes_external_ip
|
||||
/etc/xen/scripts/vif-route-qubes
|
||||
/etc/dbus-1/system.d/qubes-nm-applet.conf
|
||||
|
42
vchan/init.c
42
vchan/init.c
@ -65,15 +65,25 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
|
||||
struct xs_handle *xs;
|
||||
char buf[64];
|
||||
char ref[16];
|
||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||
xc_evtchn *evfd;
|
||||
#else
|
||||
int evfd;
|
||||
#endif
|
||||
evtchn_port_or_error_t port;
|
||||
xs = xs_domain_open();
|
||||
if (!xs) {
|
||||
return ret;
|
||||
}
|
||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||
evfd = xc_evtchn_open(NULL, 0);
|
||||
if (!evfd)
|
||||
goto fail;
|
||||
#else
|
||||
evfd = xc_evtchn_open();
|
||||
if (evfd < 0)
|
||||
goto fail;
|
||||
#endif
|
||||
ctrl->evfd = evfd;
|
||||
// the following hardcoded 0 is the peer domain id
|
||||
port = xc_evtchn_bind_unbound_port(evfd, 0);
|
||||
@ -98,7 +108,11 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
|
||||
ret = 0;
|
||||
fail2:
|
||||
if (ret)
|
||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||
xc_evtchn_close(evfd);
|
||||
#else
|
||||
close(evfd);
|
||||
#endif
|
||||
fail:
|
||||
xs_daemon_close(xs);
|
||||
return ret;
|
||||
@ -152,10 +166,18 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno)
|
||||
int ret = -1;
|
||||
unsigned int len;
|
||||
struct xs_handle *xs;
|
||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||
xc_interface *xcfd;
|
||||
#else
|
||||
int xcfd;
|
||||
#endif
|
||||
char buf[64];
|
||||
char *ref;
|
||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||
xc_evtchn *evfd;
|
||||
#else
|
||||
int evfd;
|
||||
#endif
|
||||
int remote_port;
|
||||
xs = xs_daemon_open();
|
||||
if (!xs) {
|
||||
@ -181,23 +203,43 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno)
|
||||
if (!remote_port)
|
||||
goto fail;
|
||||
free(ref);
|
||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||
xcfd = xc_interface_open(NULL, NULL, 0);
|
||||
if (!xcfd)
|
||||
goto fail;
|
||||
#else
|
||||
xcfd = xc_interface_open();
|
||||
if (xcfd < 0)
|
||||
goto fail;
|
||||
#endif
|
||||
ctrl->ring = (struct vchan_interface *)
|
||||
xc_map_foreign_range(xcfd, domain, 4096,
|
||||
PROT_READ | PROT_WRITE, ctrl->ring_ref);
|
||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||
xc_interface_close(xcfd);
|
||||
#else
|
||||
close(xcfd);
|
||||
#endif
|
||||
if (ctrl->ring == 0 || ctrl->ring == MAP_FAILED)
|
||||
goto fail;
|
||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||
evfd = xc_evtchn_open(NULL, 0);
|
||||
if (!evfd)
|
||||
goto fail;
|
||||
#else
|
||||
evfd = xc_evtchn_open();
|
||||
if (evfd < 0)
|
||||
goto fail;
|
||||
#endif
|
||||
ctrl->evfd = evfd;
|
||||
ctrl->evport =
|
||||
xc_evtchn_bind_interdomain(evfd, domain, remote_port);
|
||||
if (ctrl->evport < 0 || xc_evtchn_notify(evfd, ctrl->evport))
|
||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||
xc_evtchn_close(evfd);
|
||||
#else
|
||||
close(evfd);
|
||||
#endif
|
||||
else
|
||||
ret = 0;
|
||||
fail:
|
||||
|
@ -149,7 +149,7 @@ int libvchan_close(struct libvchan *ctrl)
|
||||
/// The fd to use for select() set
|
||||
int libvchan_fd_for_select(struct libvchan *ctrl)
|
||||
{
|
||||
return ctrl->evfd;
|
||||
return xc_evtchn_fd(ctrl->evfd);
|
||||
}
|
||||
|
||||
/// Unmasks event channel; must be called before calling select(), and only then
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <xenctrl.h>
|
||||
typedef uint32_t VCHAN_RING_IDX;
|
||||
|
||||
/// struct vchan_interface is placed in memory shared between domains
|
||||
@ -37,7 +38,11 @@ struct libvchan {
|
||||
struct vchan_interface *ring;
|
||||
uint32_t ring_ref;
|
||||
/// descriptor to event channel interface
|
||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||
xc_evtchn *evfd;
|
||||
#else
|
||||
int evfd;
|
||||
#endif
|
||||
int evport;
|
||||
VCHAN_RING_IDX *wr_cons, *wr_prod, *rd_cons, *rd_prod;
|
||||
char *rd_ring, *wr_ring;
|
||||
|
@ -1 +1 @@
|
||||
1.5.26
|
||||
1.6.1
|
||||
|
@ -1 +1 @@
|
||||
1.5.28
|
||||
1.6.1
|
||||
|
Loading…
Reference in New Issue
Block a user