Quick VM restore support
This commit is contained in:
parent
172cc9a0e9
commit
793b7b2596
@ -8,7 +8,7 @@
|
||||
#
|
||||
/dev/mapper/dmroot / ext4 defaults,noatime 1 1
|
||||
/dev/mapper/dmswap swap swap defaults 0 0
|
||||
/dev/xvdb /rw ext4 defaults 0 0
|
||||
/dev/xvdb /rw ext4 noauto,defaults 0 0
|
||||
tmpfs /dev/shm tmpfs defaults 0 0
|
||||
devpts /dev/pts devpts gid=5,mode=620 0 0
|
||||
sysfs /sys sysfs defaults 0 0
|
||||
|
@ -14,6 +14,20 @@ start()
|
||||
echo "ERROR: /usr/bin/xenstore-read not found!"
|
||||
exit 1
|
||||
fi
|
||||
if xenstore-read qubes_save_request ; then
|
||||
dmesg -c >/dev/null
|
||||
# echo 1 >/proc/sys/vm/drop_caches
|
||||
# free | grep buffers/cache |
|
||||
# (read a b c d ; xenstore-write device/qubes_used_mem $c)
|
||||
free | grep Mem: |
|
||||
(read a b c d ; xenstore-write device/qubes_used_mem $c)
|
||||
echo "Waiting for restore"
|
||||
while ! dmesg -c | grep "using vcpu" ; do usleep 10 ; done
|
||||
while ! xenstore-read qubes_vm_type 2>/dev/null ; do
|
||||
usleep 10
|
||||
done
|
||||
echo Back to life.
|
||||
fi
|
||||
|
||||
name=$(/usr/bin/xenstore-read name)
|
||||
hostname $name
|
||||
@ -29,30 +43,36 @@ start()
|
||||
echo "nameserver $secondary_dns" >> /etc/resolv.conf
|
||||
fi
|
||||
|
||||
if ! [ -d /rw/home ] ; then
|
||||
echo
|
||||
echo "--> Virgin boot of the VM: Linking /home to /rw/home"
|
||||
mv /home /home.orig
|
||||
mkdir -p /rw/config
|
||||
mkdir -p /rw/home
|
||||
ln -s /rw/home/ /home
|
||||
cp -a /home.orig/user /home
|
||||
touch /rw/config/rc.local
|
||||
rm -fr /home.orig
|
||||
touch /var/lib/qubes/first_boot_completed
|
||||
fi
|
||||
if [ -e /dev/xvdb ] ; then
|
||||
mount /rw
|
||||
|
||||
if ! [ -L /home ] ; then
|
||||
mv /home /home.orig
|
||||
ln -s /rw/home /home
|
||||
fi
|
||||
if ! [ -L /usr/local ] ; then
|
||||
mv /usr/local /usr/local.orig
|
||||
ln -s /rw/usrlocal /usr/local
|
||||
fi
|
||||
if ! [ -d /rw/home ] ; then
|
||||
echo
|
||||
echo "--> Virgin boot of the VM: Linking /home to /rw/home"
|
||||
mv /home /home.orig
|
||||
mkdir -p /rw/config
|
||||
mkdir -p /rw/home
|
||||
ln -s /rw/home/ /home
|
||||
cp -a /home.orig/user /home
|
||||
touch /rw/config/rc.local
|
||||
rm -fr /home.orig
|
||||
touch /var/lib/qubes/first_boot_completed
|
||||
fi
|
||||
|
||||
if ! [ -L /home ] ; then
|
||||
mv /home /home.orig
|
||||
ln -s /rw/home /home
|
||||
fi
|
||||
if ! [ -L /usr/local ] ; then
|
||||
mv /usr/local /usr/local.orig
|
||||
ln -s /rw/usrlocal /usr/local
|
||||
fi
|
||||
#make it last, we want all above to work without /rw mounted
|
||||
if ! [ -d /rw/usrlocal ] ; then
|
||||
cp -a /usr/local.orig /rw/usrlocal
|
||||
if ! [ -d /rw/usrlocal ] ; then
|
||||
cp -a /usr/local.orig /rw/usrlocal
|
||||
fi
|
||||
else
|
||||
ln -sf /home_volatile /home
|
||||
fi
|
||||
|
||||
[ -x /rw/config/rc.local ] && /rw/config/rc.local
|
||||
|
2
appvm/qubes_timestamp
Executable file
2
appvm/qubes_timestamp
Executable file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
exec xenstore-write device/qubes_timestamp $(date +%s.%N)
|
@ -30,6 +30,8 @@ start()
|
||||
chgrp qubes /var/run/xenstored/*
|
||||
chmod 660 /var/run/xenstored/*
|
||||
xm sched-credit -d 0 -w 65535
|
||||
printf "\x00\x00\x00\x00" > /var/run/qubes/dispVM_seq
|
||||
xm mem-set 0 700
|
||||
cp /var/lib/qubes/qubes.xml /var/lib/qubes/backup/qubes-$(date +%F-%T).xml
|
||||
touch /var/lock/subsys/qubes_core
|
||||
success
|
||||
|
9
dom0/restore/Makefile
Normal file
9
dom0/restore/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
CC=gcc
|
||||
all: qubes_restore xenstore-watch
|
||||
qubes_restore: qubes_restore.o
|
||||
$(CC) -o qubes_restore qubes_restore.o -lxenstore
|
||||
|
||||
xenstore-watch: xenstore-watch.o
|
||||
$(CC) -o xenstore-watch xenstore-watch.o -lxenstore
|
||||
clean:
|
||||
rm -f *.o *~ qubes_restore xenstore-watch
|
54
dom0/restore/block.qubes
Executable file
54
dom0/restore/block.qubes
Executable file
@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
|
||||
hd_arr[10]=a
|
||||
hd_arr[11]=b
|
||||
hd_arr[12]=c
|
||||
hd_arr[13]=d
|
||||
hd_arr[14]=e
|
||||
hd_arr[15]=f
|
||||
|
||||
hexdigit()
|
||||
{
|
||||
if [ $1 -lt 10 ] ; then
|
||||
RET=$1
|
||||
else
|
||||
RET=${hd_arr[$1]}
|
||||
fi
|
||||
}
|
||||
|
||||
hexnumber()
|
||||
{
|
||||
hexdigit $(($1/16))
|
||||
ret2=$RET
|
||||
hexdigit $(($1%16))
|
||||
HEXNUMBER="$ret2"$RET
|
||||
}
|
||||
|
||||
|
||||
process()
|
||||
{
|
||||
if ! [ "x""$1" = "xfile" ] ; then
|
||||
exec /etc/xen/scripts/block "$@"
|
||||
fi
|
||||
while true ; do
|
||||
dev=$(losetup -f --show $2)
|
||||
if [ -n "$dev" ] ; then break ; fi
|
||||
done
|
||||
hexnumber ${dev:9:70}
|
||||
xenstore-write "$XENBUS_PATH/node" "$dev" \
|
||||
"$XENBUS_PATH/physical-device" "7:"$HEXNUMBER \
|
||||
"$XENBUS_PATH/hotplug-status" connected
|
||||
}
|
||||
|
||||
#exec 2>>/tmp/block.$$
|
||||
#set -x
|
||||
export PATH="/sbin:/bin:/usr/bin:/usr/sbin:$PATH"
|
||||
|
||||
XENBUS_PATH="${XENBUS_PATH:?}"
|
||||
if ! [ "$1" = "add" ] || ! [ -f /var/run/qubes/fast_block_attach ] ; then
|
||||
exec /etc/xen/scripts/block "$@"
|
||||
fi
|
||||
|
||||
vars=$(xenstore-read "$XENBUS_PATH/type" "$XENBUS_PATH/params")
|
||||
process $vars
|
||||
exit 0
|
42
dom0/restore/qubes_prepare_saved_domain.sh
Executable file
42
dom0/restore/qubes_prepare_saved_domain.sh
Executable file
@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
if ! [ $# = 2 ] ; then
|
||||
echo usage: $0 domainname savefile_to_be_created
|
||||
exit 1
|
||||
fi
|
||||
VMDIR=/var/lib/qubes/appvms/$1
|
||||
if ! [ -d $VMDIR ] ; then
|
||||
echo $VMDIR does not exist ?
|
||||
exit 1
|
||||
fi
|
||||
if ! qvm-start $1 --no-guid ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ID=none
|
||||
for i in $(xenstore-list /local/domain) ; do
|
||||
name=$(xenstore-read /local/domain/$i/name)
|
||||
if [ "x"$name = "x"$1 ] ; then
|
||||
ID=$i
|
||||
fi
|
||||
done
|
||||
set -x
|
||||
if [ $ID = none ] ; then
|
||||
echo cannot get domain id
|
||||
exit 1
|
||||
fi
|
||||
echo domainid=$ID
|
||||
xenstore-write /local/domain/$ID/qubes_save_request 1
|
||||
xenstore-watch /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
|
||||
MEM=$(xenstore-read /local/domain/$ID/device/qubes_used_mem)
|
||||
echo MEM=$MEM
|
||||
xm mem-set $1 $(($MEM/1000))
|
||||
sleep 1
|
||||
touch $2
|
||||
xm save $1 $2
|
||||
cd $VMDIR
|
||||
tar -Scvf saved_cows.tar root-cow.img swap-cow.img
|
||||
|
||||
|
406
dom0/restore/qubes_restore.c
Normal file
406
dom0/restore/qubes_restore.c
Normal file
@ -0,0 +1,406 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.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");
|
||||
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");
|
||||
exit(1);
|
||||
}
|
||||
total += n;
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
static char retbuf[60];
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
snprintf(retbuf, sizeof(retbuf), "%lld.%lld",
|
||||
(long long) tv.tv_sec, (long long) tv.tv_usec);
|
||||
return retbuf;
|
||||
}
|
||||
|
||||
int actually_do_unlink = 1;
|
||||
#define FAST_FLAG_PATH "/var/run/qubes/fast_block_attach"
|
||||
void set_fast_flag()
|
||||
{
|
||||
int fd = open(FAST_FLAG_PATH, O_CREAT | O_RDONLY, 0600);
|
||||
if (fd < 0) {
|
||||
perror("set_fast_flag");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void rm_fast_flag()
|
||||
{
|
||||
if (actually_do_unlink)
|
||||
unlink(FAST_FLAG_PATH);
|
||||
}
|
||||
|
||||
#define BUFSIZE (512*1024)
|
||||
void do_read(int fd)
|
||||
{
|
||||
static char buf[BUFSIZE];
|
||||
int n;
|
||||
while ((n = read(fd, buf, BUFSIZE))) {
|
||||
if (n < 0) {
|
||||
perror("read savefile");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void preload_cache(int fd)
|
||||
{
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
perror("fork");
|
||||
exit(1);
|
||||
case 0:
|
||||
actually_do_unlink = 0;
|
||||
do_read(fd);
|
||||
fprintf(stderr, "time=%s, fs cache preload complete\n",
|
||||
gettime());
|
||||
exit(0);
|
||||
default:
|
||||
close(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_guid(int domid, int argc, char **argv)
|
||||
{
|
||||
char dstr[40];
|
||||
snprintf(dstr, sizeof(dstr), "%d", domid);
|
||||
if (argc == 2)
|
||||
execl("/usr/bin/qubes_guid", "guid", "-d", dstr, "-c",
|
||||
"red", "-i", "red", NULL);
|
||||
else
|
||||
execl("/usr/bin/qubes_guid", "guid", "-d", dstr, "-c",
|
||||
"red", "-i", "red", "-e", argv[2], NULL);
|
||||
perror("execl");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define NAME_PATTERN "/root-cow.img"
|
||||
char *fix_savefile_and_get_vmname(int fd, int dispid)
|
||||
{
|
||||
static char buf[4096];
|
||||
char *name;
|
||||
char *slash;
|
||||
char val[256];
|
||||
if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
|
||||
perror("read savefile");
|
||||
exit(1);
|
||||
}
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
snprintf(val, sizeof(val),
|
||||
"064cd14c-95ad-4fc2-a4c9-cf9f522e5b%02x", dispid);
|
||||
fix_savefile(fd, buf, "(uuid ", val);
|
||||
snprintf(val, sizeof(val), "disp%02d", dispid);
|
||||
fix_savefile(fd, buf, "(name ", val);
|
||||
snprintf(val, sizeof(val), "00:16:3e:7c:8b:%02x", dispid);
|
||||
fix_savefile(fd, buf, "(mac ", val);
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
name = strstr(buf + 20, NAME_PATTERN);
|
||||
if (!name) {
|
||||
fprintf(stderr,
|
||||
"cannot find 'root-cow.img' in savefile\n");
|
||||
exit(1);
|
||||
}
|
||||
*name = 0;
|
||||
slash = name - 1;
|
||||
while (slash[0] && slash[0] != '/')
|
||||
slash--;
|
||||
if (!*slash) {
|
||||
fprintf(stderr, "cannot find / in savefile\n");
|
||||
exit(1);
|
||||
}
|
||||
return slash + 1;
|
||||
}
|
||||
|
||||
void unpack_cows(char *name)
|
||||
{
|
||||
char vmdir[4096];
|
||||
char tarfile[4096];
|
||||
int status;
|
||||
snprintf(vmdir, sizeof(vmdir), "/var/lib/qubes/appvms/%s", name);
|
||||
snprintf(tarfile, sizeof(tarfile),
|
||||
"/var/lib/qubes/appvms/%s/saved_cows.tar", name);
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
fprintf(stderr, "fork");
|
||||
exit(1);
|
||||
case 0:
|
||||
execl("/bin/tar", "tar", "-C", vmdir, "-Sxf",
|
||||
tarfile, NULL);
|
||||
perror("execl");
|
||||
exit(1);
|
||||
default:
|
||||
wait(&status);
|
||||
if (WEXITSTATUS(status)) {
|
||||
fprintf(stderr, "tar exited with status=0x%x\n",
|
||||
status);
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stderr, "time=%s, cows restored\n", gettime());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void write_xs_single(struct xs_handle *xs, int domid, char *name,
|
||||
char *val)
|
||||
{
|
||||
char key[256];
|
||||
snprintf(key, sizeof(key), "/local/domain/%d/%s", domid, name);
|
||||
if (!xs_write(xs, XBT_NULL, key, val, strlen(val))) {
|
||||
fprintf(stderr, "xs_write");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setup_xenstore(int domid, char *name)
|
||||
{
|
||||
char val[256];
|
||||
char netvm_id_path[256];
|
||||
int fd, n;
|
||||
char netvm_id[256];
|
||||
struct xs_handle *xs = xs_daemon_open();
|
||||
if (!xs) {
|
||||
perror("xs_daemon_open");
|
||||
exit(1);
|
||||
}
|
||||
snprintf(netvm_id_path, sizeof(netvm_id_path),
|
||||
"/var/lib/qubes/appvms/%s/netvm_id.txt", name);
|
||||
fd = open(netvm_id_path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror("open netvm_id");
|
||||
exit(1);
|
||||
}
|
||||
n = read(fd, netvm_id, sizeof(netvm_id) - 1);
|
||||
close(fd);
|
||||
netvm_id[n] = 0;
|
||||
|
||||
snprintf(val, sizeof(val), "10.%s.%d.%d", netvm_id,
|
||||
domid / 254 + 200, (domid % 254) + 1);
|
||||
write_xs_single(xs, domid, "qubes_ip", val);
|
||||
write_xs_single(xs, domid, "qubes_netmask", "255.255.0.0");
|
||||
snprintf(val, sizeof(val), "10.%s.0.1", netvm_id);
|
||||
write_xs_single(xs, domid, "qubes_gateway", val);
|
||||
snprintf(val, sizeof(val), "10.%s.255.254", netvm_id);
|
||||
write_xs_single(xs, domid, "qubes_secondary_dns", val);
|
||||
write_xs_single(xs, domid, "qubes_vm_type", "AppVM");
|
||||
xs_daemon_close(xs);
|
||||
|
||||
}
|
||||
|
||||
int get_next_disposable_id()
|
||||
{
|
||||
int seq = 0;
|
||||
int fd = open("/var/run/qubes/dispVM_seq", O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open dispVM_seq");
|
||||
exit(1);
|
||||
}
|
||||
read(fd, &seq, sizeof(seq));
|
||||
seq++;
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
write(fd, &seq, sizeof(seq));
|
||||
close(fd);
|
||||
return seq;
|
||||
}
|
||||
|
||||
void write_varrun_domid(int domid)
|
||||
{
|
||||
FILE *f = fopen("/var/run/qubes/dispVM_xid", "w");
|
||||
if (!f) {
|
||||
perror("fopen dispVM_xid");
|
||||
exit(1);
|
||||
}
|
||||
fprintf(f, "%d", domid);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd, domid, dispid;
|
||||
char *resp;
|
||||
char *name;
|
||||
if (argc != 2 && argc != 3) {
|
||||
fprintf(stderr, "usage: %s savefile\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
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");
|
||||
exit(1);
|
||||
}
|
||||
dispid = get_next_disposable_id();
|
||||
name = fix_savefile_and_get_vmname(fd, dispid);
|
||||
// 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);
|
||||
write_varrun_domid(domid);
|
||||
fprintf(stderr,
|
||||
"time=%s, created domid=%d, executing set_mem 400\n",
|
||||
gettime(), domid);
|
||||
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());
|
||||
setup_xenstore(domid, name);
|
||||
fprintf(stderr, "time=%s, starting qubes_guid\n", gettime());
|
||||
rm_fast_flag();
|
||||
start_guid(domid, argc, argv);
|
||||
return 0;
|
||||
}
|
28
dom0/restore/xenstore-watch.c
Normal file
28
dom0/restore/xenstore-watch.c
Normal file
@ -0,0 +1,28 @@
|
||||
#include <sys/types.h>
|
||||
#include <xs.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct xs_handle *xs;
|
||||
unsigned int count;
|
||||
char **vec;
|
||||
char dummy;
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s xenstore_path\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
xs = xs_daemon_open();
|
||||
if (!xs) {
|
||||
perror("xs_daemon_open");
|
||||
exit(1);
|
||||
}
|
||||
if (!xs_watch(xs, argv[1], &dummy)) {
|
||||
perror("xs_watch");
|
||||
exit(1);
|
||||
}
|
||||
vec = xs_read_watch(xs, &count);
|
||||
free(vec);
|
||||
vec = xs_read_watch(xs, &count);
|
||||
free(vec);
|
||||
}
|
@ -60,7 +60,7 @@ mkdir -p $RPM_BUILD_ROOT/etc/init.d
|
||||
cp qubes_core $RPM_BUILD_ROOT/etc/init.d/
|
||||
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||
cp qubes_add_pendrive_script qubes_penctl qvm-copy-to-vm qvm-copy-to-vm.kde $RPM_BUILD_ROOT/usr/bin
|
||||
cp qubes_timestamp qubes_add_pendrive_script qubes_penctl qvm-copy-to-vm qvm-copy-to-vm.kde $RPM_BUILD_ROOT/usr/bin
|
||||
mkdir -p $RPM_BUILD_ROOT/%{kde_service_dir}
|
||||
cp qvm-copy.desktop $RPM_BUILD_ROOT/%{kde_service_dir}
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/udev/rules.d
|
||||
@ -77,6 +77,9 @@ cp ../common/qubes_serial_login $RPM_BUILD_ROOT/sbin
|
||||
mkdir -p $RPM_BUILD_ROOT/etc
|
||||
cp ../common/serial.conf $RPM_BUILD_ROOT/var/lib/qubes/
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/home_volatile/user
|
||||
chown 500:500 $RPM_BUILD_ROOT/home_volatile/user
|
||||
|
||||
%triggerin -- initscripts
|
||||
cp /var/lib/qubes/serial.conf /etc/init/serial.conf
|
||||
|
||||
@ -186,3 +189,6 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%dir /mnt/removable
|
||||
/etc/yum.repos.d/qubes.repo
|
||||
/sbin/qubes_serial_login
|
||||
/usr/bin/qubes_timestamp
|
||||
%dir /home_volatile
|
||||
%attr(700,user,user) /home_volatile/user
|
||||
|
@ -46,6 +46,7 @@ The Qubes core files for installation on Dom0.
|
||||
%build
|
||||
python -m compileall qvm-core
|
||||
python -O -m compileall qvm-core
|
||||
make -C restore
|
||||
|
||||
%install
|
||||
|
||||
@ -57,6 +58,12 @@ mkdir -p $RPM_BUILD_ROOT/usr/bin/
|
||||
cp qvm-tools/qvm-* $RPM_BUILD_ROOT/usr/bin
|
||||
cp clipboard_notifier/qclipd $RPM_BUILD_ROOT/usr/bin
|
||||
cp pendrive_swapper/qfilexchgd $RPM_BUILD_ROOT/usr/bin
|
||||
cp restore/xenstore-watch $RPM_BUILD_ROOT/usr/bin
|
||||
cp restore/qubes_restore $RPM_BUILD_ROOT/usr/bin
|
||||
cp restore/qubes_prepare_saved_domain.sh $RPM_BUILD_ROOT/usr/bin
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/xen/scripts
|
||||
cp restore/block.qubes $RPM_BUILD_ROOT/etc/xen/scripts
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT%{python_sitearch}/qubes
|
||||
cp qvm-core/qubes.py $RPM_BUILD_ROOT%{python_sitearch}/qubes
|
||||
@ -99,6 +106,9 @@ 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/
|
||||
cp pm-utils/02qubes-pause-vms $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d/
|
||||
|
||||
%triggerin -- xen-runtime
|
||||
sed -i 's/\/block /\/block.qubes /' /etc/udev/rules.d/xen-backend.rules
|
||||
|
||||
%post
|
||||
|
||||
if [ -e /etc/yum.repos.d/qubes-r1-dom0.repo ]; then
|
||||
@ -167,6 +177,7 @@ if [ "$1" = 0 ] ; then
|
||||
chgrp root /etc/xen
|
||||
chmod 700 /etc/xen
|
||||
groupdel qubes
|
||||
sed -i 's/\/block.qubes /\/block /' /etc/udev/rules.d/xen-backend.rules
|
||||
fi
|
||||
|
||||
%files
|
||||
@ -202,3 +213,7 @@ fi
|
||||
/etc/sysconfig/iptables
|
||||
/usr/lib64/pm-utils/sleep.d/01qubes-sync-vms-clock
|
||||
/usr/lib64/pm-utils/sleep.d/02qubes-pause-vms
|
||||
/usr/bin/xenstore-watch
|
||||
/usr/bin/qubes_restore
|
||||
/usr/bin/qubes_prepare_saved_domain.sh
|
||||
/etc/xen/scripts/block.qubes
|
||||
|
Loading…
Reference in New Issue
Block a user