* [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
@ 2007-12-10 8:28 Yuval Kashtan
2007-12-10 20:51 ` Blue Swirl
2007-12-11 14:53 ` Daniel P. Berrange
0 siblings, 2 replies; 37+ messages in thread
From: Yuval Kashtan @ 2007-12-10 8:28 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1.1: Type: text/plain, Size: 3035 bytes --]
Hello All,
Attached is a proposed patch which adds DBus support to QEMU. DBus is a
standard message bus for linux (
http://www.freedesktop.org/wiki/Software/dbus )
The idea behind this is to allow for external programs such as controlling
GUI or HyperVisors to communicate and control QEMU, in a standard manner.
Although it is possible to connect to the monitor, an API is more standard,
theres no need to parse texts and error messages, no internationalization
problems and in general is a much better idea.
Implementation:
This is done by creating a DBus server from QEMU which raise signals and act
upon methods.
Methods mainly implement same logic as the current command line options and
monitor does.
How to use:
To enable DBus support you'll have to add --enable-dbus when you execure
configure script.
Then when you execute QEMU, you'll have to add -dbus-service <service_name>
where service_name follows the DBus naming convention ( xxx.xxx.xxx....)
To support QEMU configuration through DBus, you'll also have to add
-dbus_configuration which will cause QEMU to wait until ConfigDone is called
through the DBus interface. this allows external programs time to call DBus
methods starting with Config_ which changes configuration (just as the CLI
does) thus enabling invocation of QEMU without parameters (beside the DBus
ones).
With that, we have implemented a nice python script that reads VM's
configuration from INI file.
To compile this you will also have to compile the attached
freedesktop.orgdsrv library (it is also attach for those who can't
handle GIT) from:
git://people.freedesktop.org/~shaharf/dsrv
Features:
Currently support was added to all important CLI configuration and some
online monitor functions (such as connecting and disconnecting usb devices).
configuration methods begins with Config_ prefix and monitor ones with
Monitor_.
For a complete list you can just execute qemu and connect with dbus-viewer
to see what is supported.
All the dbus handling routines can be found in dbus-monitor.c.
I have two different implementations of this:
1) A single threaded version. which comply to the qemu standard of not
opening additional threads.
2) A multi threaded version which open an additional, single, thread which
handles all the DBus load. I actually believe this version is better as it
allows QEMU to continue execution of guest operations even when there are
DBus methods/signals to handle, whereas in the first option, DBus is
integrated into QEMU mainloop. Also this makes it possible to monitor even
during long operations (like monitoring the progress of savevm)
Please comment both on the idea of management API and the proposed
implementation.
Attached are:
RFC-QEMU-Dbus.patch - patch file including all necessary changes to qemu.
was made against QEMU HEAD as of 23/9 morning.
RFC-QEMU-Dbus-Interface.xml - the xml description of the DBus interface that
I suggest.
dsrv.tar.gz.txt - the dbus server library.
BR,
Yuval Kashtan,
Qumranet Development Team.
[-- Attachment #1.2: Type: text/html, Size: 3442 bytes --]
[-- Attachment #2: RFC-QEMU-DBus.patch --]
[-- Type: application/octet-stream, Size: 72699 bytes --]
diff -Naur /yuval/Dev/qemu-cvs/qemu/configure /yuval/Dev/qemu-dbus/qemu/configure
--- /yuval/Dev/qemu-cvs/qemu/configure 2007-09-22 18:49:14.000000000 +0200
+++ /yuval/Dev/qemu-dbus/qemu/configure 2007-09-23 12:59:54.000000000 +0200
@@ -102,6 +102,8 @@
darwin_user="no"
build_docs="no"
uname_release=""
+dbus="yes"
+dbus_service="org.qemu"
# OS specific
targetos=`uname -s`
@@ -291,6 +293,12 @@
;;
--enable-uname-release=*) uname_release="$optarg"
;;
+ --disable-dbus) dbus="no"
+ ;;
+ --enable-dbus) dbus="yes"
+ ;;
+ --dbus-service=*) dbus_service="$optarg"
+ ;;
--sparc_cpu=*)
sparc_cpu="$optarg"
case $sparc_cpu in
@@ -391,6 +399,9 @@
echo " --fmod-lib path to FMOD library"
echo " --fmod-inc path to FMOD includes"
echo " --enable-uname-release=R Return R for uname -r in usermode emulation"
+echo " --enable-dbus enable DBus monitor service"
+echo " --disable-dbus disable DBus monitor service"
+echo " --dbus-service=service set the dbus service name"
echo " --sparc_cpu=V Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9"
echo ""
echo "NOTE: The object files are built at the place where configure is launched"
@@ -714,6 +725,7 @@
echo "Target Sparc Arch $sparc_cpu"
fi
echo "kqemu support $kqemu"
+echo "DBUS support $dbus"
echo "Documentation $build_docs"
[ ! -z "$uname_release" ] && \
echo "uname -r $uname_release"
@@ -888,6 +900,11 @@
echo "CONFIG_VNC_TLS_LIBS=$vnc_tls_libs" >> $config_mak
echo "#define CONFIG_VNC_TLS 1" >> $config_h
fi
+if test "$dbus" = "yes" ; then
+ echo "CONFIG_DBUS=yes" >> $config_mak
+ echo "#define CONFIG_DBUS 1" >> $config_h
+ echo "#define DBUS_SERVICE \"$dbus_service\"" >> $config_h
+fi
qemu_version=`head $source_path/VERSION`
echo "VERSION=$qemu_version" >>$config_mak
echo "#define QEMU_VERSION \"$qemu_version\"" >> $config_h
diff -Naur /yuval/Dev/qemu-cvs/qemu/dbus/monitor-dbus.c /yuval/Dev/qemu-dbus/qemu/dbus/monitor-dbus.c
--- /yuval/Dev/qemu-cvs/qemu/dbus/monitor-dbus.c 1970-01-01 02:00:00.000000000 +0200
+++ /yuval/Dev/qemu-dbus/qemu/dbus/monitor-dbus.c 2007-09-23 13:00:47.000000000 +0200
@@ -0,0 +1,1506 @@
+/*
+ * Example/Unit-test D-Bus server code.
+ * Written by Shahar Frank <shaharf@qumranet.com>
+ *
+ * This code has been released into the Public Domain.
+ * You may do whatever you like with it.
+ */
+#include <dsrv.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "vl.h"
+#include "error.h"
+#include "monitor.h"
+#include "monitor-dbus.h"
+
+pthread_t dbus_thread;
+char g_Devices[3][6]; //tmp
+
+static volatile int configured = 0;
+
+pthread_mutex_t conf_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t conf_cond = PTHREAD_COND_INITIALIZER;
+
+//
+// Debug interface functions
+//
+
+char *SetLogLevel(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nLogLevel;
+
+ dsrv_method_arg(method, "LogLevel", &nLogLevel);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%c) method called",
+ method->name,
+ nLogLevel
+ );
+
+ dsrv_log_level = nLogLevel;
+
+ return NULL;
+}
+
+//
+// Configuration interface functions
+//
+
+char *Config_boot(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nRC = 0;
+ int nDeviceLetter;
+
+ dsrv_method_arg(method, "DeviceLetter", &nDeviceLetter);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%c) method called",
+ method->name,
+ nDeviceLetter
+ );
+
+ if (
+ boot_device != 'a' &&
+#if defined(TARGET_SPARC) || defined(TARGET_I386)
+ // Network boot
+ boot_device != 'n' &&
+#endif
+ boot_device != 'c' &&
+ boot_device != 'd'
+ ) {
+ nRC = 1;
+ } else {
+ boot_device = nDeviceLetter;
+ }
+
+ dsrv_method_return(method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+char *Monitor_usb_add(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nRC;
+ char *szDevName;
+
+ dsrv_method_arg(method, "DeviceName", &szDevName);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szDevName
+ );
+
+ nRC = usb_device_add(szDevName);
+
+ dsrv_method_return(method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+char *Monitor_usb_del(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nRC;
+ char *szDevName;
+
+ dsrv_method_arg(method, "DeviceName", &szDevName);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szDevName
+ );
+
+ nRC = usb_device_del(szDevName);
+
+ dsrv_method_return(method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+char *Config_usb(DSrvMethod * method, DBusMessage * msg, void *user) {
+// int nState;
+ bool fUSB;
+
+ dsrv_method_arg(method, "State", &fUSB);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ fUSB ? "True" : "False"
+ );
+
+ usb_enabled = (int) fUSB;
+
+ return NULL;
+}
+
+char *Monitor_ListUsbDevices(DSrvMethod * method, DBusMessage * msg, void *user) {
+ USBDevice *dev;
+ USBPort *port;
+ const char *speed_str;
+ int n = 10;
+
+ DSrvArray *array;
+ char szUsbDevice[256];
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s() method called",
+ method->name
+ );
+
+ if (!(array = dsrv_method_basic_array_return (method, "Info", NULL, &n)))
+ DSRV_PANIC (NULL, "dsrv_method_basic_array failed");
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s - after dsrv_method_basic_array_return",
+ method->name
+ );
+
+ if (!usb_enabled) {
+ return NULL;
+ }
+
+ for (
+ port = used_usb_ports;
+ port;
+ port = port->next
+ ) {
+ dev = port->dev;
+ if (!dev) {
+ continue;
+ }
+
+ switch(dev->speed) {
+ case USB_SPEED_LOW:
+ speed_str = "1.5";
+ break;
+ case USB_SPEED_FULL:
+ speed_str = "12";
+ break;
+ case USB_SPEED_HIGH:
+ speed_str = "480";
+ break;
+ default:
+ speed_str = "?";
+ break;
+ }
+
+ snprintf (
+ szUsbDevice,
+ 256,
+ " Device %d.%d, Speed %s Mb/s, Product %s\n",
+ 0,
+ dev->addr,
+ speed_str,
+ dev->devname
+ );
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s - adding info: %s",
+ method->name,
+ szUsbDevice
+ );
+
+ dsrv_array_append_basic (array, szUsbDevice);
+ }
+
+ return NULL;
+}
+
+char *Monitor_ListNetworkDevices(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int n = 10;
+ VLANState *vsFirstVLAN;
+ VLANState *vlan;
+ VLANClientState *vc;
+
+ DSrvArray *array;
+ char szBuf[256];
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s() method called",
+ method->name
+ );
+
+ if (!(array = dsrv_method_basic_array_return (method, "Info", NULL, &n)))
+ DSRV_PANIC (NULL, "dsrv_method_basic_array failed");
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s - after dsrv_method_basic_array_return",
+ method->name
+ );
+
+ vsFirstVLAN = get_first_vlan();
+
+ for(vlan = vsFirstVLAN; vlan != NULL; vlan = vlan->next) {
+ for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
+ snprintf (
+ szBuf,
+ 256,
+ "VLAN %d: %s",
+ vlan->id,
+ vc->info_str
+ );
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s - adding info: %s",
+ method->name,
+ szBuf
+ );
+
+ dsrv_array_append_basic (array, szBuf);
+ }
+ }
+
+ return NULL;
+}
+
+char *Config_SetLocaltime(DSrvMethod * method, DBusMessage * msg, void *user) {
+// int nState;
+ bool fUTC;
+
+ dsrv_method_arg(method, "IsUTC", &fUTC);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ fUTC ? "True" : "False"
+ );
+
+ rtc_utc = (int) fUTC;
+
+ return NULL;
+}
+
+char *Config_SetFullScreen(DSrvMethod * method, DBusMessage * msg, void *user) {
+// int nState;
+ bool fIsFullScreen;
+
+ dsrv_method_arg(method, "IsFullScreen", &fIsFullScreen);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ fIsFullScreen ? "True" : "False"
+ );
+
+ full_screen = (int) fIsFullScreen;
+
+ return NULL;
+}
+
+char *Config_Set_std_vga(DSrvMethod * method, DBusMessage * msg, void *user) {
+// int nState;
+ bool fIsSTDVGA;
+
+ dsrv_method_arg(method, "Is_std_vga", &fIsSTDVGA);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ fIsSTDVGA ? "True" : "False"
+ );
+
+ cirrus_vga_enabled = (int) fIsSTDVGA;
+
+ return NULL;
+}
+
+char *Config_SetNoACPI(DSrvMethod * method, DBusMessage * msg, void *user) {
+// int nState;
+ bool fIsNoACPI;
+
+ dsrv_method_arg(method, "IsNoACPI", &fIsNoACPI);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ fIsNoACPI ? "True" : "False"
+ );
+
+ acpi_enabled = (int) fIsNoACPI;
+
+ return NULL;
+}
+
+char *Config_SetNoQuit(DSrvMethod * method, DBusMessage * msg, void *user) {
+// int nState;
+ bool fIsNoQuit;
+
+ dsrv_method_arg(method, "IsNoQuit", &fIsNoQuit);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ fIsNoQuit ? "True" : "False"
+ );
+
+ no_quit = (int) fIsNoQuit;
+
+ return NULL;
+}
+
+char *Config_SetNoGraphic(DSrvMethod * method, DBusMessage * msg, void *user) {
+// int nState;
+ bool fIsNoGraphic;
+
+ dsrv_method_arg(method, "IsNoGraphic", &fIsNoGraphic);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ fIsNoGraphic ? "True" : "False"
+ );
+
+ nographic = (int) fIsNoGraphic;
+
+ return NULL;
+}
+
+char *Config_daemonize(DSrvMethod * method, DBusMessage * msg, void *user) {
+// int nState;
+ bool fIsDaemonize;
+
+ dsrv_method_arg(method, "IsDaemonize", &fIsDaemonize);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ fIsDaemonize ? "True" : "False"
+ );
+
+ daemonize = (int) fIsDaemonize;
+
+ return NULL;
+}
+
+char *Config_SetNoReboot(DSrvMethod * method, DBusMessage * msg, void *user) {
+// int nState;
+ bool fIsNoReboot;
+
+ dsrv_method_arg(method, "IsNoReboot", &fIsNoReboot);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ fIsNoReboot ? "True" : "False"
+ );
+
+ no_reboot = (int) fIsNoReboot;
+
+ return NULL;
+}
+
+char *Config_SetNoFDBootCheck(DSrvMethod * method, DBusMessage * msg, void *user) {
+// int nState;
+ bool fIsNoFDBootCheck;
+
+ dsrv_method_arg(method, "IsNoFDBootCheck", &fIsNoFDBootCheck);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ fIsNoFDBootCheck ? "True" : "False"
+ );
+
+ fd_bootchk = (int) fIsNoFDBootCheck;
+
+ return NULL;
+}
+
+char *Config_snapshot(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nState;
+
+ dsrv_method_arg(method, "State", &nState);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%d) method called",
+ method->name,
+ nState
+ );
+
+ snapshot = nState;
+
+ return NULL;
+}
+
+char *Config_monitor(DSrvMethod * method, DBusMessage * msg, void *user) {
+ char *szDeviceName;
+
+ dsrv_method_arg(method, "DeviceName", &szDeviceName);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szDeviceName
+ );
+
+ pstrcpy(monitor_device, sizeof(monitor_device), szDeviceName);
+
+ return NULL;
+}
+
+char *Monitor_AddSerial(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nRC = 0;
+ char *szDeviceName;
+
+ dsrv_method_arg(method, "DeviceName", &szDeviceName);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szDeviceName
+ );
+
+
+ if (serial_device_index >= MAX_SERIAL_PORTS) {
+ nRC = 1;
+ } else {
+ const char *devname;
+ if (devname[0] != '\0') {
+ //Close device before creating and opening a new one.
+ }
+
+ pstrcpy (
+ serial_devices[serial_device_index],
+ sizeof(serial_devices[0]),
+ optarg
+ );
+ devname = serial_devices[serial_device_index];
+
+ serial_hds[serial_device_index] = qemu_chr_open(devname);
+ if (!serial_hds[serial_device_index]) {
+ nRC = 2;
+ } else {
+ if (!strcmp(devname, "vc")) {
+ qemu_chr_printf(serial_hds[serial_device_index], "serial%d console\r\n", serial_device_index);
+ }
+ serial_device_index++;
+ }
+ }
+
+ dsrv_method_return (method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+char *Monitor_RemoveSerial(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nIndex;
+
+ dsrv_method_arg(method, "DeviceID", &nIndex);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%d) method called",
+ method->name,
+ nIndex
+ );
+
+ qemu_chr_close(serial_hds[nIndex]);
+
+ return NULL;
+}
+
+char *Monitor_AddParallel(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nRC = 0;
+ char *szDeviceName;
+
+ dsrv_method_arg(method, "DeviceName", &szDeviceName);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szDeviceName
+ );
+
+
+ if (parallel_device_index >= MAX_SERIAL_PORTS) {
+ nRC = 1;
+ } else {
+ const char *devname;
+ if (devname[0] != '\0') {
+ //Close device before creating and opening a new one.
+ }
+
+ pstrcpy (
+ parallel_devices[parallel_device_index],
+ sizeof(parallel_devices[0]),
+ optarg
+ );
+ devname = parallel_devices[parallel_device_index];
+
+ parallel_hds[parallel_device_index] = qemu_chr_open(devname);
+ if (!parallel_hds[parallel_device_index]) {
+ nRC = 2;
+ } else {
+ if (!strcmp(devname, "vc")) {
+ qemu_chr_printf(parallel_hds[parallel_device_index], "parallel%d console\r\n", parallel_device_index);
+ }
+ parallel_device_index++;
+ }
+ }
+
+ dsrv_method_return (method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+char *Monitor_RemoveParallel(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nIndex;
+
+ dsrv_method_arg(method, "DeviceID", &nIndex);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%d) method called",
+ method->name,
+ nIndex
+ );
+
+ qemu_chr_close(parallel_hds[nIndex]);
+
+ return NULL;
+}
+
+char *Config_ramsize(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nRC = 0;
+ unsigned nSize;
+
+ dsrv_method_arg(method, "MegaBytes", &nSize);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%d) method called",
+ method->name,
+ nSize
+ );
+
+ if ((int)(nSize * 1024 * 1024) > PHYS_RAM_MAX_SIZE) {
+ nRC = 1;
+ } else {
+ ram_size = nSize * 1024 * 1024;
+ }
+
+ dsrv_method_return (method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+char *Config_smp(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nRC = 0;
+ unsigned nCPUs;
+
+ dsrv_method_arg(method, "CPUs", &nCPUs);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%d) method called",
+ method->name,
+ nCPUs
+ );
+
+ if (
+ nCPUs < 1 ||
+ nCPUs > MAX_CPUS
+ ) {
+ nRC = 1;
+ } else {
+ smp_cpus = nCPUs;
+ }
+
+ dsrv_method_return (method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+#ifdef HAS_AUDIO
+char *Config_SoundHWState(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nRC = 0;
+ char *szName;
+ int nState;
+ struct soundhw *c;
+
+ dsrv_method_arg(method, "Name", &szName);
+ dsrv_method_arg(method, "State", &nState);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s,%d) method called",
+ method->name,
+ szName,
+ nState
+ );
+
+ if (!strcmp (szName, "all")) {
+ for (c = soundhw; c->name; ++c) {
+ c->enabled = nState;
+ }
+ } else {
+ for (c = soundhw; c->name; ++c) {
+ if (!strncmp (c->name, szName, c->name > szName ? sizeof(szName) : sizeof(c->name))) {
+ c->enabled = nState;
+ }
+ }
+ if (!c->name) {
+ nRC = 1;
+ }
+ }
+
+ dsrv_method_return (method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+#endif // HAS_AUDIO
+char *MonitorSetFloppy(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nRC = 0;
+ int nIndex;
+ char *szImageName;
+
+ dsrv_method_arg(method, "Index", &nIndex);
+ dsrv_method_arg(method, "ImageName", &szImageName);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%d,%s) method called",
+ method->name,
+ nIndex,
+ szImageName
+ );
+
+ if (nIndex > MAX_FD) {
+ nRC = 1;
+ } else {
+ if (fd_table[nIndex]) {
+ bdrv_close(fd_table[nIndex]);
+ }
+
+ bdrv_set_type_hint(fd_table[nIndex], BDRV_TYPE_FLOPPY);
+
+ if (
+ bdrv_open (
+ fd_table[nIndex],
+ szImageName,
+ snapshot ? BDRV_O_SNAPSHOT : 0
+ ) < 0
+ ) {
+ nRC = 2;
+ }
+ }
+
+ dsrv_method_return (method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+char *Config_SetCdrom(DSrvMethod *method, DBusMessage *msg, void *user) {
+ int nRC = 0;
+ char *szImageName;
+
+ dsrv_method_arg(method, "ImageName", &szImageName);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szImageName
+ );
+
+ if (cdrom_index >= 0) {
+ hd_filename[cdrom_index] = szImageName;
+ }
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s return = %d",
+ method->name,
+ nRC
+ );
+ dsrv_method_return (method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+char *Monitor_SetBlockDevice(DSrvMethod *method, DBusMessage *msg, void *user) {
+ int nRC = 0;
+ int nIndex;
+ char *szImageName;
+
+ dsrv_method_arg(method, "Index", &nIndex);
+ dsrv_method_arg(method, "ImageName", &szImageName);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%d,%s) method called",
+ method->name,
+ nIndex,
+ szImageName
+ );
+
+ if (nIndex > MAX_DISKS) {
+ nRC = 1;
+ } else {
+ hd_filename[nIndex] = szImageName;
+ if (nIndex == cdrom_index) {
+ cdrom_index = -1;
+ }
+ }
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s return = %d",
+ method->name,
+ nRC
+ );
+ dsrv_method_return (method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+char *Config_AddNet(DSrvMethod *method, DBusMessage *msg, void *user) {
+ int nRC = 0;
+ char *szParameters;
+
+ dsrv_method_arg(method, "Parameters", &szParameters);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szParameters
+ );
+
+ if (nb_net_clients >= MAX_NET_CLIENTS) {
+ nRC = 1;
+ } else {
+ pstrcpy(
+ net_clients[nb_net_clients],
+ sizeof(net_clients[0]),
+ szParameters
+ );
+
+ nb_net_clients++;
+ }
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s return = %d",
+ method->name,
+ nRC
+ );
+ dsrv_method_return (method, "ReturnCode", &nRC);
+
+ return NULL;
+
+}
+
+char *Config_BIOSDir(DSrvMethod *method, DBusMessage *msg, void *user) {
+ int nRC = 0;
+ char *szDirectory;
+
+ dsrv_method_arg(method, "Directory", &szDirectory);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szDirectory
+ );
+
+ bios_dir = szDirectory;
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s return = %d",
+ method->name,
+ nRC
+ );
+ dsrv_method_return (method, "ReturnCode", &nRC);
+
+ return NULL;
+
+}
+
+char *Monitor_LoadVM(DSrvMethod * method, DBusMessage * msg, void *user) {
+ char *szFilename;
+
+ dsrv_method_arg(method, "Filename", &szFilename);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szFilename
+ );
+
+ do_loadvm(szFilename);
+
+ return NULL;
+}
+
+char *Config_vnc(DSrvMethod * method, DBusMessage * msg, void *user) {
+ char *szDisplay;
+
+ dsrv_method_arg(method, "Display", &szDisplay);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szDisplay
+ );
+
+ vnc_display = szDisplay;
+
+ return NULL;
+}
+
+char *Monitor_commit(DSrvMethod * method, DBusMessage * msg, void *user) {
+ char *szDeviceName;
+
+ dsrv_method_arg(method, "DeviceName", &szDeviceName);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szDeviceName
+ );
+
+ do_commit(szDeviceName);
+
+ return NULL;
+}
+
+char *Monitor_quit(DSrvMethod * method, DBusMessage * msg, void *user) {
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s() method called",
+ method->name
+ );
+
+ exit(0);
+
+ return NULL;
+}
+
+char *Monitor_eject(DSrvMethod * method, DBusMessage * msg, void *user) {
+ int nForce;
+ char *szFilename;
+
+ dsrv_method_arg(method, "Force", &nForce);
+ dsrv_method_arg(method, "Filename", &szFilename);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%d,%s) method called",
+ method->name,
+ nForce,
+ szFilename
+ );
+
+ do_eject(nForce, szFilename);
+
+ return NULL;
+}
+
+char *Monitor_change(DSrvMethod * method, DBusMessage * msg, void *user) {
+ char *szDeviceName;
+ char *szFilename;
+
+ dsrv_method_arg(method, "DeviceName", &szDeviceName);
+ dsrv_method_arg(method, "Filename", &szFilename);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s,%s) method called",
+ method->name,
+ szDeviceName,
+ szFilename
+ );
+
+ do_change(szDeviceName, szFilename);
+
+ return NULL;
+}
+
+char *Monitor_savevm(DSrvMethod * method, DBusMessage * msg, void *user) {
+ char *szDeviceName;
+ int nRC;
+
+ dsrv_method_arg(method, "DeviceName", &szDeviceName);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szDeviceName
+ );
+
+ nRC = mgmt_savevm(szDeviceName);
+
+ if (nRC != 0) {
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_ERROR,
+ "%s failed: %s",
+ method->name,
+ GetLastError()
+ );
+ }
+
+ dsrv_method_return(method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+char *Monitor_loadvm(DSrvMethod * method, DBusMessage * msg, void *user) {
+ char *szDeviceName;
+ int nRC;
+
+ dsrv_method_arg(method, "DeviceName", &szDeviceName);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szDeviceName
+ );
+
+ nRC = mgmt_loadvm(szDeviceName);
+
+ if (nRC != 0) {
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_ERROR,
+ "%s failed: %s",
+ method->name,
+ GetLastError()
+ );
+ }
+
+ dsrv_method_return(method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+char *Monitor_delvm(DSrvMethod * method, DBusMessage * msg, void *user) {
+ char *szDeviceName;
+ int nRC;
+
+ dsrv_method_arg(method, "DeviceName", &szDeviceName);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szDeviceName
+ );
+
+ nRC = mgmt_delvm(szDeviceName);
+
+ if (nRC != 0) {
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_ERROR,
+ "%s failed: %s",
+ method->name,
+ GetLastError()
+ );
+ }
+
+ dsrv_method_return(method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+char *Monitor_send_key(DSrvMethod * method, DBusMessage * msg, void *user) {
+ char *szKeys;
+ int nRC = 0;
+
+ dsrv_method_arg(method, "Keys", &szKeys);
+
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s(%s) method called",
+ method->name,
+ szKeys
+ );
+
+ do_send_key(szKeys);
+
+ if (nRC != 0) {
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_ERROR,
+ "%s failed: %s",
+ method->name,
+ GetLastError()
+ );
+ }
+
+ dsrv_method_return(method, "ReturnCode", &nRC);
+
+ return NULL;
+}
+
+char *Monitor_system_reset(DSrvMethod * method, DBusMessage * msg, void *user) {
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s() method called",
+ method->name
+ );
+
+ qemu_system_reset_request();
+
+ return NULL;
+}
+
+char *Monitor_system_powerdown(DSrvMethod * method, DBusMessage * msg, void *user) {
+ DSRV_LOG (
+ dsrv_method_server(method),
+ DSRV_LOG_VERBOSE,
+ "%s() method called",
+ method->name
+ );
+
+ qemu_system_powerdown();
+
+ return NULL;
+}
+
+char *ConfigDone(DSrvMethod * method, DBusMessage * msg, void *user) {
+ pthread_mutex_lock(&conf_mutex);
+ configured = 1;
+ pthread_mutex_unlock(&conf_mutex);
+
+ pthread_cond_signal(&conf_cond);
+
+ return NULL;
+}
+
+void *dbus_main(void *arg)
+{
+ DSrvServer *server;
+ DSrvObject *object;
+ DSrvInterface *interface;
+ DSrvMethod *method;
+ char *err;
+ char szServiceName[256];
+
+ dsrv_log_level = DSRV_LOG_WARN;
+
+ // Create service name.
+ if (szDBusServiceName == NULL) {
+ snprintf (
+ szServiceName,
+ 256,
+ "qemu.org.%d",
+ getpid()
+ );
+ } else {
+ strncpy (szServiceName, szDBusServiceName, 256);
+ }
+
+ // Initialize the server structure
+ if (!(server = dsrv_server_new(szServiceName)))
+ DSRV_PANIC(server, "can't setup a server");
+
+ // Initialize an object - this is optional, interafaces can use rootobject
+ if (!(object = dsrv_object_new(server, NULL, "/Management")))
+ DSRV_PANIC(server, "can't alloc an object");
+
+ // Debug interface
+ if (!(interface = dsrv_interface_new(object, "org.qemu.Debug")))
+ DSRV_PANIC(server, "can't create Debug interface");
+
+ // SetLogLevel declaration and params
+ if (!(method = dsrv_method_new(interface, "SetLogLevel", SetLogLevel, NULL)))
+ DSRV_PANIC(server, "can't create SetLogLevel method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("LogLevel", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Capture interface
+ if (!(interface = dsrv_interface_new(object, "org.qemu.Configuration")))
+ DSRV_PANIC(server, "can't create Capture interface");
+
+ // ConfigDone declaration and params
+ if (!(method = dsrv_method_new(interface, "ConfigDone", ConfigDone, NULL)))
+ DSRV_PANIC(server, "can't create ConfigDone method");
+
+ // ConfigDone declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_UsbState", Config_usb, NULL)))
+ DSRV_PANIC(server, "can't create Config_SetUsbState method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("State", 'b', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // ConfigDone declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_SetLocaltime", Config_SetLocaltime, NULL)))
+ DSRV_PANIC(server, "can't create Config_SetUsbState method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("IsUTC", 'b', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // ConfigDone declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_SetFullScreen", Config_SetFullScreen, NULL)))
+ DSRV_PANIC(server, "can't create Config_SetFullScreen method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("IsFullScreen", 'b', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Config_Set_std_vga declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_Set_std_vga", Config_Set_std_vga, NULL)))
+ DSRV_PANIC(server, "can't create Config_Set_std_vga method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("Is_std_vga", 'b', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Config_Set_std_vga declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_SetNoACPI", Config_SetNoACPI, NULL)))
+ DSRV_PANIC(server, "can't create Config_SetNoACPI method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("Is_NoACPI", 'b', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Config_SetNoQuit declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_SetNoQuit", Config_SetNoQuit, NULL)))
+ DSRV_PANIC(server, "can't create Config_SetNoQuit method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("IsNoQuit", 'b', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Config_SetNoFDBootCheck declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_SetNoFDBootCheck", Config_SetNoFDBootCheck, NULL)))
+ DSRV_PANIC(server, "can't create Config_SetNoFDBootCheck method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("IsNoFDBootCheck", 'b', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Config_SetNoGraphic declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_SetNoGraphic", Config_SetNoGraphic, NULL)))
+ DSRV_PANIC(server, "can't create Config_SetNoGraphic method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("IsNoGraphic", 'b', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Config_SetNoReboot declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_SetNoReboot", Config_SetNoReboot, NULL)))
+ DSRV_PANIC(server, "can't create Config_SetNoReboot method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("IsNoReboot", 'b', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Config_daemonize declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_daemonize", Config_daemonize, NULL)))
+ DSRV_PANIC(server, "can't create Config_daemonize method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("IsDaemnoize", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // ConfigDone declaration and params
+ if (!(method = dsrv_method_new(interface, "usb_add", Monitor_usb_add, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_usb_add method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("DeviceName", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // ConfigDone declaration and params
+ if (!(method = dsrv_method_new(interface, "usb_del", Monitor_usb_del, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_usb_add method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("DeviceName", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // ConfigDone declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_boot", Config_boot, NULL)))
+ DSRV_PANIC(server, "can't create Config_boot method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("DeviceLetter", 'y', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // ConfigDone declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_snapshot", Config_snapshot, NULL)))
+ DSRV_PANIC(server, "can't create Config_snapshot method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("State", 'u', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // ConfigDone declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_ramsize", Config_ramsize, NULL)))
+ DSRV_PANIC(server, "can't create Config_snapshot method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("MegaBytes", 'u', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // ConfigDone declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_smp", Config_smp, NULL)))
+ DSRV_PANIC(server, "can't create Config_smp method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("CPUs", 'u', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+#ifdef HAS_AUDIO
+ // Config_SoundHWState declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_SoundHWState", Config_SoundHWState, NULL)))
+ DSRV_PANIC(server, "can't create Config_SoundHWState method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("Name", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("State", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+#endif //HAS AUDIO
+
+ // MonitorSetFloppy declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_SetFloppy", MonitorSetFloppy, NULL)))
+ DSRV_PANIC(server, "can't create MonitorSetFloppy method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("Index", 'u', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("ImageName", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_SetBlockDevice declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_SetBlockDevice", Monitor_SetBlockDevice, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_SetBlockDevice method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("Index", 'u', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("ImageName", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Config_SetCdrom declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_SetCdrom", Config_SetCdrom, NULL)))
+ DSRV_PANIC(server, "can't create Config_SetCdrom method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("ImageName", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Config_AddNet declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_AddNet", Config_AddNet, NULL)))
+ DSRV_PANIC(server, "can't create Config_AddNet method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("Parameters", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Config_BIOSDir declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_BIOSDir", Config_BIOSDir, NULL)))
+ DSRV_PANIC(server, "can't create Config_BIOSDir method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("Directory", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Config_monitor declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_monitor", Config_monitor, NULL)))
+ DSRV_PANIC(server, "can't create Config_monitor method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("DeviceName", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_AddSerial declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_AddSerial", Monitor_AddSerial, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_AddSerial method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("DeviceName", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_AddSerial declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_RemoveSerial", Monitor_RemoveSerial, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_RemoveSerial method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("DeviceID", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_AddParallel declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_AddParallel", Monitor_AddParallel, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_AddParallel method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("DeviceName", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_AddParallel declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_RemoveParallel", Monitor_RemoveParallel, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_RemoveParallel method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("DeviceID", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_LoadVM declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_LoadVM", Monitor_LoadVM, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_LoadVM method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("Filename", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Config_vnc declaration and params
+ if (!(method = dsrv_method_new(interface, "Config_vnc", Config_vnc, NULL)))
+ DSRV_PANIC(server, "can't create Config_vnc method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("Display", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_commit declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_commit", Monitor_commit, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_commit method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("DeviceName", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_quit declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_quit", Monitor_quit, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_quit method");
+
+ // Monitor_eject declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_eject", Monitor_eject, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_eject method");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("Force", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("Filename", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_change declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_change", Monitor_change, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_change method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("DeviceName", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("Filename", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_savevm declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_savevm", Monitor_savevm, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_savevm method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("DeviceName", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_loadvm declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_loadvm", Monitor_loadvm, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_loadvm method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("DeviceName", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_delvm declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_delvm", Monitor_delvm, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_delvm method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("DeviceName", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_send_keys declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_send_key", Monitor_send_key, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_send_key method");
+ if ((err = dsrv_method_arg_add(method, dsrv_param_new("Keys", 's', NULL, 256))))
+ DSRV_PANIC(server, "can't add method param");
+ if ((err = dsrv_method_return_add (method, dsrv_param_new("ReturnCode", 'i', NULL, 0))))
+ DSRV_PANIC(server, "can't add method param");
+
+ // Monitor_system_reset declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_system_reset", Monitor_system_reset, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_system_reset method");
+
+ // Monitor_system_powerdown declaration and params
+ if (!(method = dsrv_method_new(interface, "Monitor_system_powerdown", Monitor_system_powerdown, NULL)))
+ DSRV_PANIC(server, "can't create Monitor_system_reset method");
+
+
+ // Connect to bus daemon
+ if ((err = dsrv_server_connect(server, 1)))
+ DSRV_PANIC(server, "connect failed: %s", err);
+
+ DSRV_LOG(server, DSRV_LOG_INFO, "DBus server is connected");
+
+ // start the main loop
+ dsrv_server_serve(server);
+
+ return 0;
+}
+
+
+void dbus_monitor_wait(void)
+{
+ pthread_mutex_lock(&conf_mutex);
+ while (!configured) {
+ pthread_cond_wait(&conf_cond, &conf_mutex);
+ }
+ pthread_mutex_unlock(&conf_mutex);
+}
+
+void dbus_monitor_init(void)
+{
+ if (pthread_create(&dbus_thread, NULL, dbus_main, NULL))
+ perror("dbus thread create failed");
+}
diff -Naur /yuval/Dev/qemu-cvs/qemu/dbus/monitor-dbus.h /yuval/Dev/qemu-dbus/qemu/dbus/monitor-dbus.h
--- /yuval/Dev/qemu-cvs/qemu/dbus/monitor-dbus.h 1970-01-01 02:00:00.000000000 +0200
+++ /yuval/Dev/qemu-dbus/qemu/dbus/monitor-dbus.h 2007-09-23 13:00:47.000000000 +0200
@@ -0,0 +1,60 @@
+#ifndef __monitor_dbus_h
+#define __monitor_dbus_h
+
+#include "vl.h"
+
+void dbus_monitor_init(void);
+void dbus_monitor_wait(void);
+
+//migration function declaration
+void mgmt_migrate_set_speed(uint32_t nBytes);
+void do_migrate_set_speed(const char *value);
+void do_migrate_cancel(void);
+int mgmt_migrate(int detach, const char *uri);
+
+// External variables, definded in vl.c and we need to use.
+extern int usb_enabled;
+extern USBPort *used_usb_ports;
+extern int boot_device;
+extern int snapshot;
+extern int ram_size;
+extern int smp_cpus;
+#ifdef HAS_AUDIO
+extern struct soundhw soundhw[];
+#endif
+extern BlockDriverState *fd_table[MAX_FD];
+/* Note: bs_table[MAX_DISKS] is a dummy block driver if none available
+ to store the VM snapshots */
+extern BlockDriverState *bs_table[MAX_DISKS + 1];
+extern char *hd_filename[MAX_DISKS];
+extern char *fd_filename[MAX_FD];
+extern int cyls;
+extern int heads;
+extern int secs;
+extern int translation;
+extern int rtc_utc;
+extern int full_screen;
+extern int win2k_install_hack;
+extern char net_clients[MAX_NET_CLIENTS][256];
+extern int nb_net_clients;
+extern int cirrus_vga_enabled;
+extern int acpi_enabled;
+extern int time_drift_fix;
+extern int use_rtc;
+extern int no_quit;
+extern int fd_bootchk;
+extern int nographic;
+extern char monitor_device[128];
+extern char serial_devices[MAX_SERIAL_PORTS][128];
+extern int serial_device_index;
+extern char parallel_devices[MAX_PARALLEL_PORTS][128];
+extern int parallel_device_index;
+extern int no_reboot;
+extern const char *vnc_display;
+extern int daemonize;
+extern USBPort *used_usb_ports;
+extern const char *szDBusServiceName;
+extern int cdrom_index;
+
+#endif // __monitor_dbus_h
+
diff -Naur /yuval/Dev/qemu-cvs/qemu/error.c /yuval/Dev/qemu-dbus/qemu/error.c
--- /yuval/Dev/qemu-cvs/qemu/error.c 1970-01-01 02:00:00.000000000 +0200
+++ /yuval/Dev/qemu-dbus/qemu/error.c 2007-09-23 13:00:08.000000000 +0200
@@ -0,0 +1,27 @@
+#include "error.h"
+#include "vl.h"
+
+char g_szLastError[1024];
+
+void SetLastError(char *szErrorMsg) {
+ strcpy (g_szLastError,szErrorMsg);
+}
+
+void SetLastError_vprintf(const char *fmt, va_list ap)
+{
+ char buf[4096];
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ SetLastError(buf);
+}
+
+void SetLastError_printf(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ SetLastError_vprintf(fmt, ap);
+ va_end(ap);
+}
+
+const char *GetLastError() {
+ return g_szLastError;
+}
diff -Naur /yuval/Dev/qemu-cvs/qemu/error.h /yuval/Dev/qemu-dbus/qemu/error.h
--- /yuval/Dev/qemu-cvs/qemu/error.h 1970-01-01 02:00:00.000000000 +0200
+++ /yuval/Dev/qemu-dbus/qemu/error.h 2007-09-23 13:00:08.000000000 +0200
@@ -0,0 +1,27 @@
+#include "error.h"
+#include "vl.h"
+
+char g_szLastError[1024];
+
+void SetLastError(char *szErrorMsg) {
+ strcpy (g_szLastError,szErrorMsg);
+}
+
+void SetLastError_vprintf(const char *fmt, va_list ap)
+{
+ char buf[4096];
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ SetLastError(buf);
+}
+
+void SetLastError_printf(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ SetLastError_vprintf(fmt, ap);
+ va_end(ap);
+}
+
+const char *GetLastError() {
+ return g_szLastError;
+}
diff -Naur /yuval/Dev/qemu-cvs/qemu/Makefile.target /yuval/Dev/qemu-dbus/qemu/Makefile.target
--- /yuval/Dev/qemu-cvs/qemu/Makefile.target 2007-09-16 23:07:47.000000000 +0200
+++ /yuval/Dev/qemu-dbus/qemu/Makefile.target 2007-09-23 15:29:52.000000000 +0200
@@ -368,6 +368,19 @@
# must use static linking to avoid leaving stuff in virtual address space
VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o loader.o isa_mmio.o
+ifdef CONFIG_DBUS
+CPPFLAGS+=-I$(SRC_PATH)/dbus
+VL_OBJS+=/usr/local/lib/dsrv.o
+
+DBUS_SERVER := monitor-dbus
+DBUS_SERVOBJ :=$(DBUS_SERVER).o
+VL_OBJS+=$(DBUS_SERVOBJ)
+
+error.o: error.c
+ $(CC) $(OP_CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+VL_OBJS+=error.o
+endif
VL_OBJS+=cutils.o
VL_OBJS+=host-utils.o
VL_OBJS+=block.o block-raw.o
@@ -659,6 +672,27 @@
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
+ifdef CONFIG_DBUS
+
+PKGCONF ?= pkg-config
+BINDTOOL ?= dbus-binding-tool
+
+DBUS_CFLAGS +=-I$(SRC_PATH)/dbus/
+DBUS_CFLAGS += $(shell $(PKGCONF) --cflags dbus-1)
+DBUS_LDFLAGS += $(shell $(PKGCONF) --libs dbus-1)
+LIBS += $(DBUS_LDFLAGS)
+
+DBUS_SERVOBJECT := qemu_mon
+VL_OBJS+=$(DBUS_SERVOBJ)
+
+$(DBUS_SERVOBJ): dbus/monitor-dbus.c $(DBUS_SERVHDR)
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(DBUS_CFLAGS) -c -o $@ $<
+
+#$(DBUS_SERVHDR): dbus/$(DBUS_SERVER).xml
+# $(BINDTOOL) --prefix=$(DBUS_SERVOBJECT) --mode=glib-server --output=$@ $<
+
+endif
+
%.o: %.S
$(CC) $(CPPFLAGS) -c -o $@ $<
diff -Naur /yuval/Dev/qemu-cvs/qemu/monitor.c /yuval/Dev/qemu-dbus/qemu/monitor.c
--- /yuval/Dev/qemu-cvs/qemu/monitor.c 2007-09-19 07:49:13.000000000 +0200
+++ /yuval/Dev/qemu-dbus/qemu/monitor.c 2007-09-23 13:00:07.000000000 +0200
@@ -199,7 +199,7 @@
help_cmd(name);
}
-static void do_commit(const char *device)
+void do_commit(const char *device)
{
int i, all_devices;
@@ -378,7 +378,7 @@
return 0;
}
-static void do_eject(int force, const char *filename)
+void do_eject(int force, const char *filename)
{
BlockDriverState *bs;
@@ -420,7 +420,7 @@
}
}
-static void do_change(const char *device, const char *target)
+void do_change(const char *device, const char *target)
{
if (strcmp(device, "vnc") == 0) {
do_change_vnc(target);
@@ -873,7 +873,7 @@
return -1;
}
-static void do_send_key(const char *string)
+void do_send_key(const char *string)
{
char keybuf[16], *q;
uint8_t keycodes[16];
diff -Naur /yuval/Dev/qemu-cvs/qemu/monitor.h /yuval/Dev/qemu-dbus/qemu/monitor.h
--- /yuval/Dev/qemu-cvs/qemu/monitor.h 1970-01-01 02:00:00.000000000 +0200
+++ /yuval/Dev/qemu-dbus/qemu/monitor.h 2007-09-23 13:00:07.000000000 +0200
@@ -0,0 +1,10 @@
+#ifndef __monitor_h
+#define __monitor_h
+
+void do_commit(const char *device);
+void do_eject(int force, const char *filename);
+void do_change(const char *device, const char *filename);
+void do_send_key(const char *string);
+
+#endif // __monitor_h
+
diff -Naur /yuval/Dev/qemu-cvs/qemu/vl.c /yuval/Dev/qemu-dbus/qemu/vl.c
--- /yuval/Dev/qemu-cvs/qemu/vl.c 2007-09-17 23:25:20.000000000 +0200
+++ /yuval/Dev/qemu-dbus/qemu/vl.c 2007-09-23 15:29:47.000000000 +0200
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include "vl.h"
+#include "error.h"
#include <unistd.h>
#include <fcntl.h>
@@ -125,6 +126,7 @@
//#define DEBUG_UNUSED_IOPORT
//#define DEBUG_IOPORT
+#define DEBUG_ACPI
#define PHYS_RAM_MAX_SIZE (2047 * 1024 * 1024)
@@ -150,11 +152,18 @@
/* Note: bs_table[MAX_DISKS] is a dummy block driver if none available
to store the VM snapshots */
BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD];
+char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
+int cyls, heads, secs, translation;
BlockDriverState *pflash_table[MAX_PFLASH];
BlockDriverState *sd_bdrv;
BlockDriverState *mtd_bdrv;
/* point to the block driver where the snapshots are managed */
BlockDriverState *bs_snapshots;
+char serial_devices[MAX_SERIAL_PORTS][128];
+int serial_device_index;
+char parallel_devices[MAX_PARALLEL_PORTS][128];
+int parallel_device_index;
+char monitor_device[128];
int vga_ram_size;
static DisplayState display_state;
int nographic;
@@ -190,13 +199,6 @@
static VLANState *first_vlan;
int smp_cpus = 1;
const char *vnc_display;
-#if defined(TARGET_SPARC)
-#define MAX_CPUS 16
-#elif defined(TARGET_I386)
-#define MAX_CPUS 255
-#else
-#define MAX_CPUS 1
-#endif
int acpi_enabled = 1;
int fd_bootchk = 1;
int no_reboot = 0;
@@ -216,6 +218,13 @@
unsigned int nb_prom_envs = 0;
const char *prom_envs[MAX_PROM_ENVS];
#endif
+int snapshot;
+int nb_net_clients;
+char net_clients[MAX_NET_CLIENTS][256];
+int cdrom_index;
+#ifdef CONFIG_DBUS
+const char *szDBusServiceName = NULL;
+#endif
#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
@@ -459,6 +468,77 @@
abort();
}
+#ifdef DEBUG_ACPI
+#define DBG_ACPI_MSG(buff, len) { \
+ fprintf(stderr,"HOST acpid: "); \
+ write(2, buff, len); \
+ fprintf(stderr,"\n"); \
+ }
+#else
+#define DBG_ACPI_MSG(buff, len) { }
+#endif
+
+
+void acpid_channel_event(void *dummy, int event)
+{
+ // printf("acpid_channel_event: event=%d\n", event);
+ return;
+}
+int acpid_channel_ready(void *dummy)
+{
+ //printf("acpid_channel_ready ... \n");
+ return 1024;
+}
+
+uint8_t acpi_lid_sts = 0;
+uint8_t acpi_adp_sts = 0;
+
+void acpid_channel_handler(void *dummy, const uint8_t *buff, int len)
+{
+ static int event_flag=0; // remove!!!
+
+ DBG_ACPI_MSG(buff, len);
+/*
+ if (strstr(buff,"lid") != NULL) {
+ // We need to read real LID status open/close
+ // and after that update the acpi_lid_sts
+ if (!(event_flag & (1<<0))) {
+ event_flag |= (1<<0);
+ acpi_lid_sts = 0x5a;
+ cpu_outw(NULL,0xb00c,(1 << 11)); // LID_STS
+ }else {
+ event_flag &= ~(1<<0);
+ }
+ DBG_ACPI_MSG("It's a LID event.",strlen("It's a LID event."));
+ }else
+*/
+ if (strstr(buff,"ac_adapter") != NULL) {
+ // We need to read real AC adapter status on/off
+ // and after that update the acpi_adp_sts
+ if (!(event_flag & (1<<1))) {
+ event_flag |= (1<<1);
+ acpi_adp_sts = 0xa5; // AC offline
+ }else {
+ event_flag &= ~(1<<1);
+ acpi_adp_sts = 0x5a; // AC online
+ }
+ DBG_ACPI_MSG("It's a ADP event.",strlen("It's a ADP event."));
+ }else{
+ DBG_ACPI_MSG("It's unknown event.",strlen("It's unknown event."));
+ }
+}
+
+
+void acpi_lid_status(uint8_t status)
+{
+ DBG_ACPI_MSG("It's a real LID event.",strlen("It's a real LID event."));
+ if (status) {
+ acpi_lid_sts = 0x5a;
+ cpu_outw(NULL,0xb00c,(1 << 11)); // LID_STS
+ }
+}
+
+
/***********************************************************/
/* keyboard/mouse */
@@ -3276,6 +3356,9 @@
break;
}
}
+#ifdef DEBUG_ACPI
+ printf("connected(ret=%d) to fd %d (look at /proc/%d/fd/%d)\n",ret, fd, getpid(),fd);
+#endif
s->fd = fd;
socket_set_nodelay(fd);
if (s->connected)
@@ -4670,6 +4753,10 @@
return ret;
}
+VLANState *get_first_vlan (void) {
+ return first_vlan;
+}
+
void do_info_network(void)
{
VLANState *vlan;
@@ -4685,7 +4772,7 @@
/***********************************************************/
/* USB devices */
-static USBPort *used_usb_ports;
+USBPort *used_usb_ports;
static USBPort *free_usb_ports;
/* ??? Maybe change this to register a hub to keep track of the topology. */
@@ -4699,7 +4786,7 @@
free_usb_ports = port;
}
-static int usb_device_add(const char *devname)
+int usb_device_add(const char *devname)
{
const char *p;
USBDevice *dev;
@@ -4748,7 +4835,7 @@
return 0;
}
-static int usb_device_del(const char *devname)
+int usb_device_del(const char *devname)
{
USBPort *port;
USBPort **lastp;
@@ -5498,14 +5585,14 @@
return ret;
}
-void do_savevm(const char *name)
-{
+int mgmt_savevm(const char *name) {
BlockDriverState *bs, *bs1;
QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
int must_delete, ret, i;
BlockDriverInfo bdi1, *bdi = &bdi1;
QEMUFile *f;
int saved_vm_running;
+ int nRC = 0;
#ifdef _WIN32
struct _timeb tb;
#else
@@ -5515,7 +5602,7 @@
bs = get_bs_snapshots();
if (!bs) {
term_printf("No block device can accept snapshots\n");
- return;
+ return 1;
}
/* ??? Should this occur after vm_stop? */
@@ -5553,22 +5640,25 @@
sn->vm_clock_nsec = qemu_get_clock(vm_clock);
if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
- term_printf("Device %s does not support VM state snapshots\n",
+ SetLastError_printf("Device %s does not support VM state snapshots\n",
bdrv_get_device_name(bs));
+ nRC = 2;
goto the_end;
}
/* save the VM state */
f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 1);
if (!f) {
- term_printf("Could not open VM state file\n");
+ SetLastError("Could not open VM state file\n");
+ nRC = 3;
goto the_end;
}
ret = qemu_savevm_state(f);
sn->vm_state_size = qemu_ftell(f);
qemu_fclose(f);
if (ret < 0) {
- term_printf("Error %d while writing VM\n", ret);
+ SetLastError_printf("Error %d while writing VM\n", ret);
+ nRC = 4;
goto the_end;
}
@@ -5580,35 +5670,50 @@
if (must_delete) {
ret = bdrv_snapshot_delete(bs1, old_sn->id_str);
if (ret < 0) {
- term_printf("Error while deleting snapshot on '%s'\n",
+ SetLastError_printf("Error while deleting snapshot on '%s'\n",
bdrv_get_device_name(bs1));
+ nRC = 5;
}
}
ret = bdrv_snapshot_create(bs1, sn);
if (ret < 0) {
- term_printf("Error while creating snapshot on '%s'\n",
+ SetLastError_printf("Error while creating snapshot on '%s'\n",
bdrv_get_device_name(bs1));
+ nRC = 6;
}
}
}
the_end:
- if (saved_vm_running)
+ if (saved_vm_running) {
vm_start();
+ }
+ return (nRC);
+}
+
+void do_savevm(const char *name) {
+ int nRC;
+
+ nRC = mgmt_savevm(name);
+
+ if (nRC != 0) {
+ term_printf("%s",GetLastError());
+ }
}
-void do_loadvm(const char *name)
+int mgmt_loadvm(const char *name)
{
BlockDriverState *bs, *bs1;
BlockDriverInfo bdi1, *bdi = &bdi1;
QEMUFile *f;
int i, ret;
int saved_vm_running;
+ int nRC = 0;
bs = get_bs_snapshots();
if (!bs) {
- term_printf("No block device supports snapshots\n");
- return;
+ SetLastError_printf("No block device supports snapshots\n");
+ return 1;
}
/* Flush all IO requests so they don't interfere with the new state. */
@@ -5622,76 +5727,114 @@
if (bdrv_has_snapshot(bs1)) {
ret = bdrv_snapshot_goto(bs1, name);
if (ret < 0) {
- if (bs != bs1)
- term_printf("Warning: ");
switch(ret) {
case -ENOTSUP:
- term_printf("Snapshots not supported on device '%s'\n",
- bdrv_get_device_name(bs1));
+ SetLastError_printf(
+ "%sSnapshots not supported on device '%s'\n",
+ (bs != bs1) ? "Warning: " : "",
+ bdrv_get_device_name(bs1)
+ );
break;
case -ENOENT:
- term_printf("Could not find snapshot '%s' on device '%s'\n",
- name, bdrv_get_device_name(bs1));
+ SetLastError_printf(
+ "%sCould not find snapshot '%s' on device '%s'\n",
+ (bs != bs1) ? "Warning: " : "",
+ name,
+ bdrv_get_device_name(bs1)
+ );
break;
default:
- term_printf("Error %d while activating snapshot on '%s'\n",
- ret, bdrv_get_device_name(bs1));
+ SetLastError_printf(
+ "%sError %d while activating snapshot on '%s'\n",
+ (bs != bs1) ? "Warning: " : "",
+ bdrv_get_device_name(bs1)
+ );
break;
}
/* fatal on snapshot block device */
- if (bs == bs1)
+ if (bs == bs1) {
+ nRC = 2;
goto the_end;
+ }
}
}
}
if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
- term_printf("Device %s does not support VM state snapshots\n",
+ SetLastError_printf("Device %s does not support VM state snapshots\n",
bdrv_get_device_name(bs));
- return;
+ return 3;
}
/* restore the VM state */
f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0);
if (!f) {
- term_printf("Could not open VM state file\n");
+ SetLastError_printf("Could not open VM state file\n");
+ nRC = 4;
goto the_end;
}
ret = qemu_loadvm_state(f);
qemu_fclose(f);
if (ret < 0) {
- term_printf("Error %d while loading VM state\n", ret);
+ SetLastError_printf("Error %d while loading VM state\n", ret);
+ nRC = 5;
}
the_end:
if (saved_vm_running)
vm_start();
+ return (nRC);
}
-void do_delvm(const char *name)
+int mgmt_delvm(const char *name)
{
BlockDriverState *bs, *bs1;
int i, ret;
+ int nRC = 0;
bs = get_bs_snapshots();
if (!bs) {
- term_printf("No block device supports snapshots\n");
- return;
+ SetLastError_printf("No block device supports snapshots\n");
+ return 1;
}
+ SetLastError("");
for(i = 0; i <= MAX_DISKS; i++) {
bs1 = bs_table[i];
if (bdrv_has_snapshot(bs1)) {
ret = bdrv_snapshot_delete(bs1, name);
if (ret < 0) {
- if (ret == -ENOTSUP)
- term_printf("Snapshots not supported on device '%s'\n",
+ if (ret == -ENOTSUP) {
+ SetLastError_printf("%sSnapshots not supported on device '%s'\n",
+ GetLastError(),
bdrv_get_device_name(bs1));
- else
- term_printf("Error %d while deleting snapshot on '%s'\n",
+ nRC = 2;
+ } else {
+ SetLastError_printf("%sError %d while deleting snapshot on '%s'\n",
+ GetLastError(),
ret, bdrv_get_device_name(bs1));
+ nRC = 3;
+ }
}
}
}
+
+ return (nRC);
+}
+
+void do_delvm(const char *name) {
+ int nRC = 0;
+ nRC = mgmt_delvm(name);
+
+ if (nRC != 0) {
+ term_printf ("%s", GetLastError());
+ }
+}
+void do_loadvm(const char *name) {
+ int nRC;
+ nRC = mgmt_loadvm(name);
+ if (nRC != 0) {
+ term_printf ("%s", GetLastError());
+ }
}
void do_info_snapshots(void)
@@ -7067,6 +7210,10 @@
"-kernel-kqemu enable KQEMU full virtualization (default is user mode only)\n"
"-no-kqemu disable KQEMU kernel module usage\n"
#endif
+#ifdef CONFIG_DBUS
+ "-dbus-service name Set dbus service name and enables DBus support\n"
+ "-dbus-disable-configuration do not wait for dbus configuration\n"
+#endif
#ifdef USE_CODE_COPY
"-no-code-copy disable code copy acceleration\n"
#endif
@@ -7185,6 +7332,10 @@
QEMU_OPTION_prom_env,
QEMU_OPTION_old_param,
QEMU_OPTION_clock,
+#ifdef CONFIG_DBUS
+ QEMU_OPTION_dbus_service,
+ QEMU_OPTION_dbus_disable_configuration,
+#endif
};
typedef struct QEMUOption {
@@ -7248,6 +7399,10 @@
{ "no-kqemu", 0, QEMU_OPTION_no_kqemu },
{ "kernel-kqemu", 0, QEMU_OPTION_kernel_kqemu },
#endif
+#ifdef CONFIG_DBUS
+ { "dbus_service", HAS_ARG, QEMU_OPTION_dbus_service },
+ { "dbus_disable_configuration", 0, QEMU_OPTION_dbus_disable_configuration },
+#endif
#if defined(TARGET_PPC) || defined(TARGET_SPARC)
{ "g", 1, QEMU_OPTION_g },
#endif
@@ -7524,26 +7679,18 @@
int use_gdbstub;
const char *gdbstub_port;
#endif
- int i, cdrom_index, pflash_index;
- int snapshot, linux_boot;
+ int i, pflash_index;
+ int linux_boot;
const char *initrd_filename;
- const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
const char *pflash_filename[MAX_PFLASH];
const char *sd_filename;
const char *mtd_filename;
const char *kernel_filename, *kernel_cmdline;
DisplayState *ds = &display_state;
- int cyls, heads, secs, translation;
- char net_clients[MAX_NET_CLIENTS][256];
- int nb_net_clients;
int optind;
const char *r, *optarg;
CharDriverState *monitor_hd;
- char monitor_device[128];
- char serial_devices[MAX_SERIAL_PORTS][128];
- int serial_device_index;
- char parallel_devices[MAX_PARALLEL_PORTS][128];
- int parallel_device_index;
+ CharDriverState *acpid_conn;
const char *loadvm = NULL;
QEMUMachine *machine;
const char *cpu_model;
@@ -7552,6 +7699,10 @@
int fds[2];
const char *pid_file = NULL;
VLANState *vlan;
+#ifdef CONFIG_DBUS
+ int dbus_allowed = 0;
+ int dbus_wait = 1;
+#endif
LIST_INIT (&vm_change_state_head);
#ifndef _WIN32
@@ -8005,6 +8156,15 @@
kqemu_allowed = 2;
break;
#endif
+#ifdef CONFIG_DBUS
+ case QEMU_OPTION_dbus_service:
+ dbus_allowed = 1;
+ szDBusServiceName = optarg;
+ break;
+ case QEMU_OPTION_dbus_disable_configuration:
+ dbus_wait = 0;
+ break;
+#endif
case QEMU_OPTION_usb:
usb_enabled = 1;
break;
@@ -8076,6 +8236,17 @@
}
}
+#ifdef CONFIG_DBUS
+ // The DBus service should be initalized here, after CLI is read and BEFORE it is manipulated / acted upon.
+ if (dbus_allowed) {
+ dbus_monitor_init();
+
+ if (dbus_wait) {
+ dbus_monitor_wait();
+ }
+ }
+#endif
+
#ifndef _WIN32
if (daemonize && !nographic && vnc_display == NULL) {
fprintf(stderr, "Can only daemonize if using -nographic or -vnc\n");
@@ -8388,6 +8559,15 @@
}
}
+ if (acpi_enabled) {
+ acpid_conn = qemu_chr_open("unix:/var/run/acpid.socket");
+ if (!acpid_conn)
+ fprintf(stderr, "qemu: could not connect to acpid");
+ else {
+ qemu_chr_add_handlers(acpid_conn, acpid_channel_ready, acpid_channel_handler, acpid_channel_event, NULL);
+ }
+ }
+
machine->init(ram_size, vga_ram_size, boot_device,
ds, fd_filename, snapshot,
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
diff -Naur /yuval/Dev/qemu-cvs/qemu/vl.h /yuval/Dev/qemu-dbus/qemu/vl.h
--- /yuval/Dev/qemu-cvs/qemu/vl.h 2007-09-20 15:24:53.000000000 +0200
+++ /yuval/Dev/qemu-dbus/qemu/vl.h 2007-09-23 12:59:39.000000000 +0200
@@ -38,6 +38,19 @@
#include <fcntl.h>
#include <sys/stat.h>
+#define PHYS_RAM_MAX_SIZE (2047 * 1024 * 1024)
+
+#define MAX_NET_CLIENTS 32
+
+#if defined(TARGET_SPARC)
+#define MAX_CPUS 16
+#elif defined(TARGET_I386)
+#define MAX_CPUS 255
+#else
+#define MAX_CPUS 1
+#endif
+
+
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
@@ -329,6 +342,7 @@
QEMUBH *bh;
} CharDriverState;
+void qemu_chr_close(CharDriverState *chr);
CharDriverState *qemu_chr_open(const char *filename);
void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
@@ -412,6 +426,7 @@
void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size);
void qemu_handler_true(void *opaque);
+VLANState *get_first_vlan (void);
void do_info_network(void);
/* TAP win32 */
@@ -549,6 +564,9 @@
void cpu_save(QEMUFile *f, void *opaque);
int cpu_load(QEMUFile *f, void *opaque, int version_id);
+int mgmt_savevm(const char *name);
+int mgmt_loadvm(const char *name);
+int mgmt_delvm(const char *name);
void do_savevm(const char *name);
void do_loadvm(const char *name);
void do_delvm(const char *name);
@@ -1158,6 +1176,8 @@
#include "hw/smbus.h"
+void acpi_lid_status(uint8_t status);
+
/* acpi.c */
extern int acpi_enabled;
i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base);
@@ -1384,6 +1404,8 @@
#define VM_USB_HUB_SIZE 8
+int usb_device_add(const char *devname);
+int usb_device_del(const char *devname);
void do_usb_add(const char *devname);
void do_usb_del(const char *devname);
void usb_info(void);
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: RFC-QEMU-DBus-Interface.xml --]
[-- Type: text/xml; name=RFC-QEMU-DBus-Interface.xml, Size: 8325 bytes --]
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg name="xml" type="s" direction="out"/>
</method>
</interface>
<interface name = "org.qemu.Configuration">
<method name = "Monitor_system_powerdown">
</method>
<method name = "Monitor_system_reset">
</method>
<method name = "Monitor_send_key">
<arg name = "Keys" type = "s" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Monitor_delvm">
<arg name = "DeviceName" type = "s" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Monitor_loadvm">
<arg name = "DeviceName" type = "s" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Monitor_savevm">
<arg name = "DeviceName" type = "s" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Monitor_change">
<arg name = "DeviceName" type = "s" direction = "in" />
<arg name = "Filename" type = "s" direction = "in" />
</method>
<method name = "Monitor_eject">
<arg name = "Filename" type = "s" direction = "in" />
<arg name = "Force" type = "i" direction = "out" />
</method>
<method name = "Monitor_quit">
</method>
<method name = "Monitor_commit">
<arg name = "DeviceName" type = "s" direction = "in" />
</method>
<method name = "Config_vnc">
<arg name = "Display" type = "s" direction = "in" />
</method>
<method name = "Monitor_LoadVM">
<arg name = "Filename" type = "s" direction = "in" />
</method>
<method name = "Monitor_RemoveParallel">
<arg name = "DeviceID" type = "i" direction = "in" />
</method>
<method name = "Monitor_AddParallel">
<arg name = "DeviceName" type = "s" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Monitor_RemoveSerial">
<arg name = "DeviceID" type = "i" direction = "in" />
</method>
<method name = "Monitor_AddSerial">
<arg name = "DeviceName" type = "s" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Config_monitor">
<arg name = "DeviceName" type = "s" direction = "in" />
</method>
<method name = "Config_BIOSDir">
<arg name = "Directory" type = "s" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Config_AddNet">
<arg name = "Parameters" type = "s" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Config_SetCdrom">
<arg name = "ImageName" type = "s" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Monitor_SetBlockDevice">
<arg name = "Index" type = "u" direction = "in" />
<arg name = "ImageName" type = "s" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Monitor_SetFloppy">
<arg name = "Index" type = "u" direction = "in" />
<arg name = "ImageName" type = "s" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Config_SoundHWState">
<arg name = "Name" type = "s" direction = "in" />
<arg name = "State" type = "i" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Config_smp">
<arg name = "CPUs" type = "u" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Config_ramsize">
<arg name = "MegaBytes" type = "u" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Config_snapshot">
<arg name = "State" type = "u" direction = "in" />
</method>
<method name = "Config_boot">
<arg name = "DeviceLetter" type = "y" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "usb_del">
<arg name = "DeviceName" type = "s" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "usb_add">
<arg name = "DeviceName" type = "s" direction = "in" />
<arg name = "ReturnCode" type = "i" direction = "out" />
</method>
<method name = "Config_daemonize">
<arg name = "IsDaemnoize" type = "s" direction = "in" />
</method>
<method name = "Config_SetNoReboot">
<arg name = "IsNoReboot" type = "b" direction = "in" />
</method>
<method name = "Config_SetNoGraphic">
<arg name = "IsNoGraphic" type = "b" direction = "in" />
</method>
<method name = "Config_SetNoFDBootCheck">
<arg name = "IsNoFDBootCheck" type = "b" direction = "in" />
</method>
<method name = "Config_SetNoQuit">
<arg name = "IsNoQuit" type = "b" direction = "in" />
</method>
<method name = "Config_SetNoACPI">
<arg name = "Is_NoACPI" type = "b" direction = "in" />
</method>
<method name = "Config_Set_std_vga">
<arg name = "Is_std_vga" type = "b" direction = "in" />
</method>
<method name = "Config_SetFullScreen">
<arg name = "IsFullScreen" type = "b" direction = "in" />
</method>
<method name = "Config_SetLocaltime">
<arg name = "IsUTC" type = "b" direction = "in" />
</method>
<method name = "Config_UsbState">
<arg name = "State" type = "b" direction = "in" />
</method>
<method name = "ConfigDone">
</method>
</interface>
<interface name = "org.qemu.Debug">
<method name = "SetLogLevel">
<arg name = "LogLevel" type = "i" direction = "in" />
</method>
</interface>
</node>
[-- Attachment #4: dsrv.tar.gz.txt --]
[-- Type: text/plain, Size: 33892 bytes --]
BZh91AY&SYÀOúM\0ùÿ®ÿý!\0\x7fÿÿÿÿÿÿþÿÿÿÿ\x02\0 \0\0\x02\x01\0\0\b`¹}ô\0*ÇwhûϾó©Rç\x0f½÷\v§ÏIw{\x1ew\aw\x13ÚñÆ»ÙÚ7×·v^ãÝ^ñî{çg3·»×=m²ÞaErúvFî:À=ë}>.´ti÷c\x05W'G$%\x1fMU\x1eèh\a/¶\x04öß`ÔÓ×Óîû\x1eîoo\b;:_]{\x0fªè\x15Ó×¾\x0e¼yíì4;¬Z\x19¸ºã\x16°Þûß+víÝÔ=ó¹£Öí =·ÜãÏo¥sï¾÷¸^[»××¶_3n÷wm¯µõ×}ÝÞû»>·\v}µ·tßsw¾ûïëÛÝõòû·Û{Ü[§¯¥¶RîùN÷Ûæ]½ç²ì\x15ÞÏC£\x13zÔ§u¶¶í³.»cû×»®ì\x17U\x15
ÞÇ[éx\a×Á[ì)×ÖZ¢ûR{ïkÕ%{Þ«Öû¼÷sè¥y÷ÝÝ·wV^®ÍuJ5·-Ê]\0\0)w]¾í«lÇÇ\x1dÕ\x14C3íK»r>;\x0f+,7w\0»\r|Ú(¦çÜùÀTªØ\x06OmÎhª;»ØÛëq{^[(\0\02âÉ1nI\x03]ê)ò4}>ö\x15óçÛä[¸\x136}íï]òÛ@\x1aöÔw¹×»è}æùK ¥÷3¤RC{nîny+Ý!)¢\x04\0\x10! \0)úSÈ\x05OÉOÐ
6P0\a©ÐÐJh\x10B\b\bÒimSÉ6¤ÓhmF\x01 4\0\0\0\0H$D\bSÒdM¤Ê\x13õ6SÑ¥7\x19F \x19\0\x03@\x01µ\0\x04)\x12\b\b\01O MOM5OÓTý\x14Úi{DÔ~©M¢\x1ayG¨h\x18D ¦S\x01\x02©þ¦h\x02y)ù¤èÓM¤Ó(x¦!µ4b4È\0a\x12B\bh!\x1a24 ©±\x1574ö
SÊ^[Hôj\0\x1a=5\04^[ûÄÿÿ»üÏÜ\x7fuþëûÿW?¤NUÔLÎDØ\0Ev ¿\r?5|mò¿ÊÙz\x04\r+!4\x13A4\x13ñt#5®²DW¨1 *\aY\x042Es\x11\x0eÁ1]\x14DÈ@Âb
\x02@ L\bP\x1f³Aè1\x11Ä\x12U\x19TW¸Eû$@?\x7fѨs\fo½°\x0e&"I"¦ HüñÄI\x04Q\x14CD\x10Erã.\x13#í`lÁÉH\\b`rVÃ\0j)%`¢(B¤ 8¤¢ª\x0e# 22j®ry\x05¤ÂH³¨#Xà@\r!,Ì\x12Ò£ÿ,S
"\x02&\0ÿ^[\x10\x7fæòÿ\x0fè×ùoÁEÿt'æFT4µøD\x1fIqK¥¯àQþÒéB4G\v\x03ÐÀýÃ\0ÿå6\x1fâIÑà13Dÿ4¢\x02oû¿ô\x1dÄ"HHËãÊç°Y5"C\x1fQî2Rÿ&L ÇGxÙÊLÿV'ϼ|±Ä¦¼\x10æ·¶ª\x02ØA¾\x17Ç îAòÊ\x1fÛë6êb¼úøhÜ M\x01C@%òF¤¥RkçÌ\x1a\x04¼0L*
ªNË >oöv\x7f]
ë÷ý0Óeu×(áK\x1aü.c^[1Ƥú¥(1ÈäxÈW\x1cnOÜuýRF\x13\a\x1fO¢»,âÞó'Á\x1aúðÙs$«gM~7ñû"¢«¹ä©\x15vn\x1cy\x7f³\x7fbI/@¨ÁF`ô!\x03\x04ç\x03(Gé¥ú m\x13çú \x13:\aõ@\x14uÖ\x14(ú'üo¼K¸\x0f\x0f,øGñëXceº>ììüO3#ÈR½°Lb$×T\x13B\x02w7ÇB\x1f£÷H ¦0V%û=\x1dMyõøºÐeW_êåi&ë`]_ höH<2D50Rj_lõÏïôao\x1dº\x16\vÄd] \x01%ºDMcPUÉ÷4;³u\x14`n"\f̾$ØÓ\x0e"Ý1[bCgº\x11m\rµ
:ÐM1Rf¡\fF\x01ÐåÜâK\|}\x19¾¶÷ù¡_áù{>SÙccÐíÀõ\ç\x1e16µ\a\x10\x0e¨¢C(6L\x1a\x0f5î·%4¶ðȦ¤¦y
¬(Ö¢ÐUäÃ
<½5¢n,\x1aàöjëDDÉF1Ù¸¨7¼¡¡ãÆGxÚÖ³7ÚÒzç-áÙÄTL^\x16\x11\x12e4Â1\x1f#\x14yÛ1\x1e,ÐÆ1» 5¦DÄñÀ\x1d}£Ë\x02\x1d\x1e¼wÔËOB UUÒ0"OýÜÊNsSA\x19DAÆy(È\x1c³XÈÆ
ÞcòLF©?:y/KÌq\x03á\x12¸Å\x14\x12Ò\x14ÎÛ_\fvUÊåj'ËÖ\x15óxcã·\x0etõñÑÈÓ=l¯¥¶1µ\x06$j16\x1e\x18dLY¢\\b ÉÎQ\x04oh
æ\x13f9A\x11\e1\x15UQ\x01UN#\x19Pdj\v\x12\x192\x10"ÉÆDU;+'a $/TgKú`T°LQ\x1e¦\X\x13¾<3<ù±&}\rÏßÈ£6\x7f\r½6\x05-)\x10\x1aCÁIJpcÞ8RÂacMk\x11 ¾\x06[\x0euiAÃM½BÙ¶[Ë+LC³Z÷
>Q\b`i\x1f¿
ÏZ\r«L¾>=û^}"±\x1aÌʱ̧²}>Î~cÚ\a|ÍøS\x04úcÚÃÝ\x1f\x18Ô=Ø
4¹\x14\a)ÒÑ2
Ð3ç²$yÙR¼äG
$\x13|\x04$\x10Û\x14NØ\bÔU^ØqÞ½ÔØÚxݯ\x1fD\x1c\x12eÞ\x03&\vwPä'zg*÷E&ÞÆ¶¦±\x12H*ò\b\a¯JPä3&F3\f K\x14={É@üä§ë\vêúìSÂ\x0eD\x0f|+º<¾6î$æ@Ð}
»ô¼D(`\x0f\x10*\f²iÊý$|墼æ\x1d\x13Å\x12¥\x06C:xÏHO³gi\aB^[ jñ1mÙhYsèQ(aPipº\x1a\x17» \x13\0ìPô\x10\x13H¯Ãªë®ÜrÈ$-)\f¹\x057ÍðW/Ïâã4Ä&?@\x7f\x1f¬J\x05Azö|Ýh\x1f\x1eìûO{ñüØöø·Ûª´¸é7Ãñ;\x01^ËsgÔ~Xf\8ÎÂ:Váµ¹ÇÜ~'¬<Õ©y×·j-8¨Á\x1dWÕø\x1cßý¯Î÷|µ9Ðøt»\x1a\x0e*\x15ÖûÔò
}"òOE\x1cçq\x03ÚgM/²\x7fS^[÷Cy£öêMaý{<7=íkvu³ud*î¼yçµ+UÄÝ×ß\x1f7_«GDn.6¸YïïØkS\x02k\bu¸ÿ²^\x13áù\r® íøH{©_þx\x04rÚ\r¤VþëuÒ²¼x/ÂD+\v§qSYy#UòäÎc£,J\x17]\x13Lkåzì-]3?ÕW¾\x17ÓÒ\aÃÑ@¨ \x04\x01\vAA\x17ke¥À?2§´3_gÄõ|,z;üÞOéÅe»p¨À\x1d°5\x17è0ÈkPdQõÁ\x15¹ö)û:·Ùûõ \x04#*\x1cØf!û?³?ùç\9s7ôêÑSQBQ@9U0"É ",éèé\r'JÙµùt¼¡I5veG\x15)däÑA¨a\x0f¤³ÚDq×\b]Úß~\x01
.«Ùýu7ßAôï¼yJÔý½u®fêÿ>ý¨ÒÆ\x12w\x7fè½²±§þe
CÏøYY¸í·N\x17ào5ï;Ï\x01 Þî=üôy\x0eRHhA#\x01Ö£þ\x18g
S¼¤\x18\x02$Dúâµ&\x11òèÀ\x03dS@#¹0!\vÐ;dt` \x0fL)Ä«\x12 RÒ\beW±@Eiå= H^ÉQ\bD]m¬/³ÿOß(ù½°õ|>÷ã?ü[ó_Ù¾Ð\f>ºC¦9\x12rg?I\fl¯w_\x11Úá\x05¯E@±ýK.^¾\x1f¨ÐÀ|ñ.lÒA\x14¨`Þ\x1e§ìâPF_o\x15%CÍ\x14Ý»¥
48¡Ò\x17ÞQT\x02\fbE@Î\x03¯àw\aõd3²_ÒITþ_ñýM+¯MºÚæÍª\x01M\x1e$èrî\x13H\x14^[\x1f¤¡÷ìQ¬Ñé\x1esx"r`ý ²?r\x03Iðj1Äog\x10_âëc§fB5\x03\x19¿Üý¥ðî^Cú+]ñ\rØ2»'\x17²\x12(\x1aÂD|ð
Ð)^[:6zªý,Ç \x18C£njN¼³!\x13¾ì0ìÙß SXcî¢V\x19\rvG©D;zà)g«éýðb\x7fl3I8`
ADN\0P¸\x18¤Kz|?ÞtDÛø&1B\x10tNtf\0ÇD66H*jC\x0e1s\a^ÒU³CbP Ü`Q:øÃ¼e¥Ç÷\x1dÈþ¶»ÛzÀh-¿¹Ò±à\x12\x14 èg\f½4·ñ\x1eô¤öAÞðë¡\x1a#5R9\x10qÙØ¿åìß´pü@qÙÒÎqg»0#\x13q\x05§ÊãóÔ¨Üë·_C´±ÂɾiMÇK§àeJX,ûç^ëørS;·+´z\x02Q*oÝôrþ³3¦T°FHiÄF\x19\x1d¹N½Bb\x13\x0e34«p»8\x18'w
S_¶ÅØõ 0Ý7ÁrÉ¿ü¢S«YäOÂȶ2Øê\x19Í{\x03\x1cç%ü\b1¡Vô(>kK[°\x16¼,¢uèE6\x14\f¦¬§\a]\x16HBåÍ3NÖ\ròÂÕºðãã¬ï\x14ÜØGÑæ47â@8êq¢°Ç\x14¹Þ\x1d(S87\x1fH\x05H\x7f\r¹áãCÑ\x0eoc8tl Þ³^[Ö\x7fO¶Ø9Ëï×÷w°ÌÂi¥ß7Pï Q´i7\0µ!øÁ!¿\a"=TÃ#±±¾$z^ZÄ\x1cD\x7f\x1a£\x1c\x16øG=\x7f0d &I\bß+©Ê\x1eᢪ]|e»eÓ\x0f\x17~ÿ)F4{öÓ¦?:r<*¶H\x12\alEaMUàL·&ñ&ë\x11¼ 8@|O+~Ø]Q^[Á\x06E^[+´Z̶¹Ö4Rh¥¬ \x14©oµVÁÔt2ñ4\acføMvdá\x11O@*E :Î\x04qéëÃ3\x15'À\x1aÃÇû}Þç¿þO¼²ç|¸é.?_ãÒ[t~w~\x1d׳1 Í,X\vxÿ#\x10⺡#æ<ùÛðóÂÈyú¥Ó°°nOZ¹\x06[xuðäl¬"\x06Ä66´2oT \x15ô©m\x01EÑúù\x05ã\x03C\x15@Ï+nÒÆà2#k\x0eíV\x1cÌ~÷\x05\a
St\x1fÊÊç±\x06^KÀÍ!õÛ«xmðîfw:ÆÖpGØ÷/ÀÅØ\x0e\x05è/\x1c&6\x18û
\x1c%Dîôz\x1a<ìçzsü\x10ÕlþìYNäêÞS³Q\x1e\x1e¡xÄÚ×Ï%SÚ]`9UÆÅ©úÆ'åÇIÿ,°ùiÞ^##\x10Z+H9AHŰÃçôe÷á\b5\x12°útÔÐ÷b£7è\x134ç¸\x15§\x02¶c£Oúâüè#\x1d,\av\O³±öüO\x03Úßyªów¢AõGݯ:WZýçfñ(ß\x06þ
Ø»i 9¥~/u_qúïá}wuKçøvkü\x1cÂ]éB\x17)¤\x17wnõé¹<\x146¿@ô $Å#¤OqsÑ÷ÓÑ8 ÀÍÑ#j§Î\x11\x0e½¨±\f\f³\x0e2\x17\v2\x11¤gÍðÃ
øÏ\x02jò¤Ç.àTÇÇz~^[FÎë¬/i±Á\x1a~g Q#¢$¸a§ì\x13ø1ÒÁßD2ÆGoqöÙ3Ʀ,ÞGisÑv\x16up\x06ÿîrÞJd;tÆ%¤¶MÁYmO¦iðã;#Lé-U%i=~Å`ù¿\x19á\x7f\x18¯¤æÀêëuòìÌ_7/ <ý\aï\x1e&à"ÇÊu¸=é\bbæø<þsçVmtöùà¼\x16©g¼»¹\x1a>\x18§²_Ø&ng\x13\x19qÉ õm)³KP£G¸Á|dÃÇîÕ÷ýÙ}t
\x1c\x1aæ¼\x16ñ@S!ä8Ôû ùn\0#@-
\x01Ð\x01\x11¾\x16X Bce\x1fìÀËò\vQ$8ÒÎ\x1fÚN´µþ\x1a䥶K·þì\f\vy4¸Ü[\x17%Òàw¸CÆhÃ\x16\x1fÂ\x0exðø>»àf³MÍÆÞL²O£klt;û:÷¾\x1d2K]æM{\x19! ³vBâÔN\x11p~(®KºdqdÄDxç\x16îù÷Q§9Tò¼sSÜ{60ÈÑ`\x19eÕ0ëÍ[Dê8EvuÉú¨Ç\x0ey\x11t¦ðå?Ò±<*@¯
Zq8¶\x1dÞ\x1e«t/y\bD$xNÓÃèáÀÏd\x04TU\rI%\x04\f0 \x18\0\x16ÎRÓr~èòêôùIÖ%°»\x1eò:ß\rïMVÃ\\f~1=w«ýJã>\x069ö>t\0èZ!À}\x12D6\x13`}ÇBû<Ý;\x16§ªÂ\x1e\x11\x14ç\x11:i¡Ìd\x060·s¹29¤\x15yÌð8^[tl\x1d¢;\x13\x11à4ôaoîÝ©zû«üÄèÜ£Thdo/ñqì\x17&ÑÉ&"Å\x0f·|åT\x12M!Ƚ%zFzÝs\x17¸çuñò^[\x13{Ê
6oò\x1cc)é\x1cSæXÀ\x0fA\x14z0Û¾GÜ\x11YÝuÉä~C¸÷\x1eF\x1a^[O:\x19W+DSX,d(#\x1f\v$ ò¹dîÔ\x11;°Ì0 ËÖ_.£·^åiz¢FB¥ãCÈGµÁÐ\v}\x1f&rãT\x1e¤SÄ\x04 *\x06{\fÍ\x18¦ïa:\bf@4ýßÁö¸\x1f¬Ì\x1aíäs)¡\fé *^[ .sh×Ùë&éêzàÌF^[\x1fLH\aÐPñ\x0e\x11\x040BIfF\aY~¡âîß\x7fPÝ̼ÌJío8_\x06[/Ûò;gäi$¿,ëW\x01loÅÌê1\x03¾\x13s\x0eèú\x06gªÑ¬1ë:_±4Ëôú\x1ec43\x16bd¥Ó\x04c«Ó~¡36¿YJý1βgÄÛ\x1dLîÓRx[3\x02\x04ÔÅé\x14ôñã´¦*»\x1e+>\aÜ&îùºéÃ3\rX%J§4|\x11qb
ûìkT[-òù\x13YQÓȨÿ1¶Ñ<ñ¶¯hJ_¯|\x03¶S¼fó 4ÊNÕ\x18úgá¾1H\¼\x12ìøâ\x1cÔøïf¥\x0f¹ªc\x1c-mestê
zW\x1d\x15_LÏ¿î§ìÞk¤?§Ôÿ7»å¤¾q}nmozÈ +°{öã£À2AÆò¯\x19a;©j?*Å÷ßÝh³ \x1fTR<>Ô±\x062W¾VbÈ¡ö¢µ"-ü"åS9\x1dmÞ¯è&¾£DĦÞ!ÜÆÞ¸f\x1dx&\x1a|7ÄË~JL`âw«ºP\a4!x\x10^=iÑ\x13t%|-!i\x14ÉÅ2ÛÕÛ˨Ðvit¶\b<Þ¯^µ×®üwÊ«\x16´\{0íÊ_<Óß`\x13ç\kF»<I^=/»B´iµ*+5ef¯\f}ýY=_¯ÆûYiþ%J?-¨aúL«ó\x18W\x1dÎ;¤né¨vRÏæÚAK·nDå~\x10Æ\b\fO©\§ÝWtw\x13)á¤þ\x19ê¹|Gïð\bÔ\x1dáâ©möÃ\x1d<ú 8¹_Z`{¨òÓHJ^Q*¢Jó0±éÜxÁ¼a\x1amjµÚjE¦ôj¤õ\x14yC*¹Ôd\x01°\x03I "\x1a\x13Y%9Øé¥Ôö·×Õ¼¹rvQ^[h\x043Ësò]¡³t²?:¾×X\x13|8\8Ev§á;eNÜÌhÇ´µðø]L\fw@a\x17=Ð<²!A
äÍ\b9&'à\x0e/ ·\x18\x14Ïsºù\x03S{\x15~è̦^>׳
>ñÝ0\x06\x10ßi\x06&þîy\x04\x1fa,C#MÕ.K'é¹U\CÍôßÉ\x06OÁàõÀËÎV¡^àU!^\x12r\x1dæiª¤\x03\x13\f°ÈHxÇ\r.\x033cG\x18:ͺ\x1dq^ö¿®4Ç· aÒsÓ1ùø\v¤V¯Éø\x1cn´ÉV\x14\÷Vi<÷±ÃʦÆá\x06Ť`ª·2\x0fÖ¦Èùrª3´Ùå\x16¼7\x03Ñ\x17#\x15ö{>ÿqià'Sd±Ø\x7fqän
õ¼a{×c¼Èf\x1f¯\x03¸Â¬±u)\x11 jø æÂ@G \x1d:5ßoÚb6^{Ûëþ|våµ%/\x1f±³Q\x1cä9GF\x0fXüY~ÂiÎjGï~»=C,Ã%mϨ\x0fPSJT\bú\7Ý»?«ÀGFMä@ç!"Ç\x12\x1eøXÙM0'¦Ê\x04òû?'«ý%);¤ýëËÞº"hÞb^[\x7f8f\x02¥ÐF°ñrh#\a}¦¼R§Kïs¹\x7fMÃ$ztê«ÃZ6.ï>JÛ\x15ÚÛlñôXo³Ð\x16o©\x13Y8
m\x01
Jä;§D\x05í2]¸fEgÜa,ß\x19ÒòmÏ\x01áÃä÷}³÷í¤&ÊÏòpÙ\b\x14&ÎÎMNnê6rY¸$a\x0eë(vJ\x1dúB.¬Hy\x1c¨nS'¿uò&%Öqë öH3ß".\x16V\x0eu׺æ2ïRÄ\x17PíÜãÜÎNR
GèDZ
ÃO¥/î\x03D\x7f\x02\ar\x18\x7f\rHïÖH
4Á\x1cÝP®£\x0fÁ¨i\x01\r-#\x14Û·O=¦u9\x01ʨ`* vl0·h¨Þ*¨67\x04Á:þ\x1eÿ&}¨ì5È>h'§'\x02ÌãNxÐá¤íì9ªµ×Ù½)½/bùȸpìl\x14\x14dó¯\x12\x06\0ã:zç¢Ç|;¹æÌ½K\x03é"\x0e\x02+¤ÆÙ*Æ«mK³ÉèÛ·$
Ü¡µ\x041\x06PÁ9-\r\x1f\x06Cç02Åê;\0m·ÒMǸôå(ÊúÁÔÕ}PùªÌ ÔÆ\x1eòÅ÷É\x06¨v©\x1f3Q±TgßÒF~
\x7f?]+>×\x17|3¸D\x1a<¡Jå':ö<ãJË\x1f[J4Î*ÐOÈùeNìÕå,êO\x1dkÉgGI¥Öq$ÞJÐ\x11t÷\x13µeqwkÓLKÛ¤JG\a%Qü}\fpáÁ\r\x7fÃáùT3<×Üi\x05y\x13\x12õ°4Û¦\x15ÉðD¸ù}ÌUªì<½Z&ÌußJzÊØþJü.:,0#¥e½ÇÚëCâfDµ§3\x19uâ¯%ö¦*¡þ:c\x7f\fßQÃ÷¸hd,{äu×× îWȼG\x19nä¸\v\x7f5u\x18\x1aßIW´µÄ?=õÂòx\x18¼ó¾_ñ¯\x1col\x11ëÓ}ô¶i}<÷7åíÁÀD ä$¸ðïÑ<&EJ.jME=ÎÆõ\b¨&ò¼(²
jRq\x1cÈ8Z\x19ÄèMËÓõ'$gÛ5\x11µs\x1cQF/6Sjtà½\x1e\bÔA©;zÇ.V÷>¦jHr[kÝ8ÞûÅÊøåìvé¦Tc2áøöf\f¯¨¬t;îÒTÒ1Òó7üþϵ\x1cìYéÂ
ôî(á\v«
\x19ÀQ\x04I\x14£/ÙöðóÚzé¾^=xvfå«ói
!åuûKl¾¬\x1f\b9p¹\x0f®e÷:X Ú)gî¢Tóö\x1a\x12Ø¢èÍïf³6¤ê\v4ÕMÅO.O69¹l\x1far«¥ç<#Y´¡0éQÇ\f8ô©.Îòa\x10¨Y KÍaLÈ\x1f\x06C×[P\x1cÝ'/30@ \x06Ù^#\x03*U¼´#+ê¿|8ãÌi\x1eu¨?¦Ñ\x19n¢h¬¶¤çWt`-ïízK_î³<lr0\x0fª\x0fÑ\rÒ\x12 \b1\x05\x020NÔ§ÿ\x0eÂQ¦»C³½õ\x18ÐëØ¯\x16êfì±=Ë\x04ã u\x10ËãàÌ5S{ãmbI\b|ø»^TìO¢)EiXVÀl\x1e\x13U=\x14DUû^üd³ÅKá÷>\x12Äoî\x10_JIÒ8xý>£aL/ÎKö¿\x148¾ª=\x13N®\x03\x7fã/÷(ÕÅê^[ÜI¾1ⱬf\x13yL\f$\x1e?+°$\rùN89×\x14ð©añ\x1cV}QüUd·ÅÓÆ\x135ÿ¯zlnAI(Ü篽ËwäCÈ9\x10;ö£¨\x15s{;¶Ü|u\x11çuúîÇÖLvò7Ö\x15ð´0%æT¦6î£\x1erf\x10 1'ôÚ|I±zctüç¥
¥ñw\vär·ò¬}uÓqêú\x15GGÿhè0\x0eͬ@ áwöËiÎä¡4\b\x11f\x1d¢¯%7»
63á]?^ÿN\x16¸ÂÙaGúçm%t~Ök\x06¿\x1eóQļ¿/\x06Ð)PÊì²G\SM¨Ï¥ÞHø½öQ|G=L?^14[6Ù¾?½Ê«;,*OÔ÷\x06*s»ôû'\r½5\x139Jí\x058ò&ç¬å
\x1fË4è^sùÑ7öf#âü Ö|^ºfV¹, ׬8Íb\v¯~ij0º\x7fM²¿½wÛo\x14r¨Í÷íßjjö{¢ç»¢£«@Ãg<ÓËny\x02e\x05ì\x18
÷3ò\x14\÷ß±°µ~q/z@
.=vÝÕO»Ó)ÞãµXr%+!Û`ëÞíâ¡HŬåÜjü\vÙ\ba!&\x13\0õÛºçÝS\v¬ÜñçO\x1f*\x7f< qNFÝ\0Õä\aÑ\x11õDÑ/_õþ=AË /\fc»¤Ç¼âÇ,¨jø`âP0&\x1au>\x0føé\x12(o¼q¬\r,¤Ç½
I¹%G1OXS¼2Ú`¦\x0eÌ&¥§³ÜI¯®^^[Aýo\x1eÿgÑYÇ8\x14>¯~0v«FÐfe ìc} ;o|¼õ¼&ãW ï¥&\x05Ú¦eà_ZõRÁ~YÃçñÅÐ}øåÒÑø¦ç\x7fßÎ]7®{£\f(ÃÔÔ\x10äì-²@ÇHç7¨ì®,^-yΨÃ<\{\x18_\x11X¥\x0eWèáì<ÁkèCV\x1fwôµJIÄ_Û\x132Áf¼Ô±nàÓF\x0fªêõUâµÃ°áó\x1d÷Ì|\x04Ò\x1d=p®©ámâ\x19/WìïZx\x18
\x04Â\x18ú{Ù\x1fC3 Íï\x1c-6Ì:ß0hÕé"W\x13iýºFöZk^[xWüpô¦Å\x1aö-\aÇîð? ¸pô&eÇÏ|Úm+Ü\x1a<Ór\béþ_\x1e^¶WÙf`È´Z-ÿËõO°g°ô¯}yû0GSÈo\x1câ¾ç£c|¼g{ñõ1
ýáÐY4Ù²\vcéüä~¨O¥ BòýZʨi"fuº=³\x1eB2|~U¿\x19´\x7f\x04Þ}~eãÔ\x1c5\x1ajúåº~\x02$Ù§e©Nãÿ_ÕÝtþ6Þxcy.H(ì\x7f?\x18\vê\x03ÔÀ>½°¯ÄÎIk³¸Éñ\x17mÍz§æfçÓ¸Jwóhòð¾Ó\x02SºO»Ã81\x1cp¼-M±=\x1cü{P9óé7éx^[ñظéÌ~«ÝòíuíÃò|\x1fiD}²-
.é7ìÅ
\x031p¸ç\x12Üø`ïË\÷*n*Ô97^[d·GÂ*T©o\x1dÖÑí\b\a\x15M\r\x04\x1fShc,ÓM%r ¼Lf"\x05÷±\x19O\x01ÌôÕ3}Y\caÇIwòw#óùÇS¥Þ`x;õæbYÍF\f|\v\\v]>\ö9\x12d\x1cÇvX9W`2¢\x1að_¡\ôº6\rS$Zý\r\x1dâß&M\x06}ÛfÔ¢Jì©i\x14ÒÔ¾á1*Ö¨ÞÎébݽ7ÆXà´±\x02mø¶Þ\x1aRã\réËk\x1dûõðÛ¸(SÂ\0t
Hµ¨\x11fv2Ñ \x04È=ÕNMtDtMç\x146¯º$«ç\vi-ááìÄfmx\x17\x1e
´ÓâTÖ©ïx±3@f#ØH¿êÆ\x12ébÑ\fJP\x18µ" p«÷[_\x19½'FÅaçx]~,ÃS¬,?$â;}^\x1aÃVÖ4ÝãÌ=ÑáçàÁÝ"h\x12fI*&w2p`ÆN®P`12ÀC\x18\x12?\x7fǾÛð÷\x16¡¦¶¹\x11\x17¢Éÿi±;*éØÕ5h]i\x1a¦û}<ÌòÀ{í{~6³Vθ»÷úË^ê:ô;øÅöCÅ\x1cw©ÄÈfÕ:I #Àqå\x7f9hJQb¥l7A}vÏýS`2ëoN\x05·\x1eÖy\x12}õêíe»KãµàÑtÞrêqXs.Ì.¶ÀRAd-(Nð°\x1a5\x19n®É¨j`FGH=>SOuר¡tíö×}^[ئ&ÛÝK°ÝÇñ÷Y\x1aØ\0Í\fNq±Å8~Ù¯:·LÛ\x15Ê8|ú[O>YKtãºaV/æá¿\x10å ¾[óSK÷\x14ï±r\0£\x1d»c^[^òã\f\x14\x15ÃðöÒ¸ùQ»gÞºfÕ èÝ\x19\x13Cwbm¹æîk´Kq6ìÞRMÚuñm¾-¾S;¶»ü\x7f£YJ\x7f
ÄwÌ|\x02&ÌÄu\f\x15^[à7,.\x1a£=ÙÕ°ñ\x12\ù]+Áú\TÒ>*$fÖ?W\x19ãjý
\x7f¯öiöü\x0fx/Ü÷%:'&Äÿ/ß;\x16i~R3ÆfÓâæ\b§~O9ÖÓé\x17ðQ£úßÌêµ_gòzP~b5Öª,ÞÜ¿äþ
ó^Ë(oðÎæ\x7fÁ\x12\x10J\x0f\x18Ôû0§¸[\b߯7¨¤2¸å+®
ý°«¦iv\jz]èïÿ/H\x15hx\x1f7ç}\x16µ\x11d\QÇϼöâÁ~Õr/¯\x06ißå\x0féFª\x13~ìâ\x7fJ:D\x1aZõ»ì\x1aNîêSõâ_vìxã-\vã)ÎÜ3\vhàä$ÄçÔì\x123qQ\fg#áQ"iéμg5M^[\x1dª<Æ¡»T°£\x10\x1c,¦=cs¡Êf¯G4ßÂùàðx\ìÏmëy<Ä~{kɽq8ñ¼í7)×g."×òâ)ºt2íkQÜ0Ó:Öº\x06m
Î4¬mð¸C\x0eº×gSÙG8ÖªÁ»\x1eGéë*®áÞc\x1eÑÁÛàÛ¿6q\x0eýrér&áîDJ¶Ä»Á7ªûÎ×\x05q^[ßl{'Ó·èäÏ#ö,×\x1dSÛî%ºê(ªmvãk¿ãÖ¶\x1cuÛà\rÇ]®ÜQîñÍyá£Í_\x06§xr}(ªÉï®ËÈrpF¹&¦æ¬Íb\x1fôuÄ+V°þ:_ÍÐùÁÈû·¯\x14±`´ã\x1c7¤³£Ë\x1c\x055ïÇ5\x13S½ó³dQó9ìfÏ\+^\x12ºù±ïb¬ëM¡â{¥·]°¿1$#'4»t^[^Ö6Ï\x11\x18ÈfZS3~^[ÅÖÎÞ껾Ø|ºñï\x1fãïm×}%Ä>Äy.Vì¾{ûY5fyÄ%r;C`Cþ¸ê"64^[\x14Ìb&&îH#A\x04\x01HY2/¾á\x13×ÓÕÜOàªâ!Ú[f\a>Éòl\x16Úpq\v?GSų¿\x0evïÏj§Î#_õ\x1eo#ðcWâ\x061¬ôU9Ä3bÆ0CÚ\x18-\x16\b\x02:"¤øW\x11.øPºv£çÅqô>\f\x0eé°#t1ÊU\x18G2ìföHF©é¢S²IçKt¤ç\v|OÁíSkv¢[~\x02\x03Íôë±n?\x17º¶Õcògû4îþÕüÞÅü¦NÁ3$ÙÛ÷-q;=k\x01Ëkv-%¢\x1339cl\x14\x19þ#Çòþ\x1fNí\x01^ïuNËn\7TÚþü(S0yaßÉñóCØd»SÂa6Z8ÎÒqè\x0f\x10Ø(d§G!¦HyF{¬¤7-\x16e;È·»uèâ|.6\x11!Þ]à¤\x18»\x1c\v»×£~Q¾Ø\x0fo½{¦n¥Wìн³êÁ¨I°Ù_påNlsbÍè&¥gIÊ\x0eBkôa\x1d®Ae&iÑ6ÖÁd¸>èzç?\r3ß5¦ºåðQÁ\x18\x19M«Ýå\x1a¹¦ãÛ}¹\x17Ç»~ð\x0eoéæÐHH ´×ÄÏg&ËET$ËiÇ\x0e^[¡ªþûÛ¥d[a,Ã1DâêeGCöÎVQ"~À8\x01MÔ.\x1f½OWb]èËÕ#ÂKéÒ\x1czþò5=!Ë£;N}pÖjS\x06\x0f4îw/eì</cÞ¾ûí®;k3^\x1c(©Ò%£\x029¦\x10N¢dËÚLþ\x13²ìRùwh@cr·<Ëù¦{IP9IÉå,G0¥£Õèãóe÷\x17[*+ÝÌØòä'Ø,_6Ì;¼]®J²\x0fv§íf\x047*ÌÕú\x1fG?»Ë|\x7f\x1fýXo[Î\x18\x12\x06\x19%Ì@\x0eÜÐ<BA$VDÌà~~uc`Àþ[óʹ3*Î\Æ\x17´ó\x0f?§ö9\x1eϧáÌ\zýU`ÖrwÿM'ÞB\x01q"bp*Gdi<«ÛznÂxê"Tf,>ýí¹\x01ÓñJSõtÎ\x0f¯òôñ ¦Ò!ë\0ÔG\x05Ì_êÆsVÏ?®£\v¦û·\\x1a\x06gèÃß3_ðÂFZÙÛŤâaXt ¯ªViÉ\x157¸Ø(ºÁ\x1c\x15/öýßwÇóý=ñshÚ78\0\x12cs4à5rehRêh7\x10\x1a¾\h>ãÔÃ=nk\¿Å×îöýý¦z«\x12Ïà ÔKêí\IdJãRt'<¨Ð¡Eùá÷g\x1f"ö¯ëBAåk8{ÏÛìåÎz\f#Ö2À¤
¤u\x04Ù\x11?XÁ6T\x10VªLʱ¡i\x0fÞÞ´\x14<a7îÊäZ \x19"Y%¦\x0fÌA\x13JHLAPrÔ:&"i¤fÔç,27\x1fØ\x03ÿô¨ùU0Ò\x1ciAÉ\x16:Ó\x06J}n\x18\x1ddQ+áyç%Oz\x12AÓö¸\x0e\x04ÉL\x1f4\x1c¡
´\x10d/³1\x0f¼ú\vùtërtÄu0L=íÒ;1¿j¸Ò\x12¯òÚôI\x14\x01é
q\b\x1a\x18ï\x0f»Ç&@&d
#ØÈ_d¤G¢\x7faä©ùG\x1e\x16¨\fq>×&¸êfJÿ_¶ñÒHoæïñÝ\x0e_\x0f§¥×0!\0L\b\x1aä\x17òÿ\x1eó®í}÷nRúyrC#ýG\x1e|wôéÝÕûc.Ùw^\x19S§^Ýwrã×nÜw \x1cÓ»»ÿÞ<BtîwqÝØn\0¢\x13º3ü÷\x7fDÏ»WÛHj4¢^¨îÐ.ÿ<à@,Ê\b$rFÜ@\aÑ?9\b\x1fÁ \x1fdþ8\x14ï²Tû\x02\x1fÉ*'£æ©äyÐóGìCê6zõ D\x01oM°ºªº\x1cØ;(ì^[\x14\x05;©\x1fò"d\x016X"øCì-(B^[ ?xþý8Ì\x7f##\x12Ò\aôüp\x10ð!O0Ð\aáé¢ÐM å\x16jïÅ\x17B{"8eL*\x19Â\0øËACÆuÆ\x14ÊÀ\x06\x11\x0fÊ¥+tµÅ©c¾\0¯t^¸\x1f\0\fA^[\x01\x1ecAú3ôTµ\b¶Ý!\x18\aÞ]\x02ÂBz`°æ\x05¶ßÜXO´25<ÿNÆÙº\x10ç±c"òµ«»»»½×\^T,\x18\x19f`\x0e\x13²
bz
Â'\x18\x14Ä\x19ɤÜeø»\x7fód\aØE3$² µ\x14:úé\x0f\x12\a\x13]ÿ±\x10?ßõøºúýÈ}\x05!Ðõ\x1f\x12È]åÄø¶i·úÌ\x1e\x06C9ô×çD^[Ðíæ'´XqÍ2\x1cÀI\x02U=\x0e\x19ïŻۮíìôض¹±ÐÈ\x0e
±`þ'Ýù\x7fjMåÅM¦\x1ec¡îß\x12BÁèeÃÄÚ£D\bEÊËópsfs¤Gñpºw\òá\x01¾\x1a«*$\x1eÇ\x1dú\x02_Få9wÓØm½\x1f'ë!s¥}%|>ÈDxzÚi4Òò¿BôY^4ã[ÑÜ¢ÖõeÆ·:)|°FÙ %±á%ú\x1aA¯\x03Ö¬mq\r*ÊS\x1cAEL\x1c¨&ÕK}ª\x16ñXmèФ¿ÒèÆ´°aÚïßGMÇh'\x13É/\x1aûÇS¦¼îgÞuCf\r$ßúøô§DÕ×û¿\x0eö)ð«\x7f\x14Y\x12Ò# Fñ´:I\x14ò\x154'<7
b\x16þÊ;\vq\x7f^\x1f
êOòñçö5L±~i}Îopí±)¤LEEÎL0\x1dQæÉ¿j0]^[áì¡ò&( f\x17W|\\b÷ó %)C¢Né^ÈKÇÊÑ/lÈDñqÒÍË·1|\x13 ÞÐÃ\x01³V^[]v"Ý-E?\x04Æ\x18KpÎ)\x1fCÈM_M
JÛmºÜìtÆù[\aÞz0?®;âÿÕL!\x12$ I²+×ã×(ªá¦\a\x04ÒjÚé\x1dSÞåF/b·p²ýWße47§Æºµ*g^[¹"É6Å´ïKë\x15æÔò\x04Mò|oJ¯·ë÷¶Hv§<\x7fß
:EìÖÚþçÊÜ.*pa¬!ÙqÇ44\x11Ïé>oWDG´Ë¶9dbðé£LBðÎ\x19ÆÏÍüÔ¯³\rÓïÕZ:û\x12%\x13dÂGg=×Ȩ\x1cJÂ,¡æ¥10¹\x0f·x´õÃýö=\x036\x1fnâ$KpIlâè-¥o»Þ\x7fc2YM#´Ö»Õ§sçOÝÜÎ\bE2ÂCÔ\x03ûêåÂgÛMcÑAÜóSÞAFai/GïyÇY¥à«lõáÜz\x1db¨ï},óÃÜDDâ=.R5)#h\x19°aT&}õD=ñ
ê&Jwm?~s[¥Û¹-Ü´OÔ.®~\a^fë§Të̦ͻËÇê̤#Ý¢¦]xüé§t¥\x16Ê:广Æ&Ó\x03ݱd6ýÓÃO½¿ýDbXûD&\x044*ðÿ£f¨\x01\x1e$r)\x03\0r\x04¥¥ZiR!\x14\x14*i
\x06¿õàsbb=\x12A;\x04\x13i8?°Þ!¨\x156ÏÞr\x14`:\x12\bjP¶$V
S\x12üí\b
Ä3 ÐGj
1¥zÆE. ÈJ\x03rk³\x10Íâz±Ð)bPHÀ\x0f\x0f³ßÜu}\x0fyë\beA<
Zî»nàÈ \x0fzø^[H)§·\x1e\x19 \x12çB^[Kq«f\x19æ|\x0fwËáô\x03\x1c´0fE4\x0f÷ªAHdnøê}\x01\x1aèÃk\bî&íÏb\bÞâBÚ\v\x10\x1f¾\fiÚIûa¹Û´Ó?K*\x17ëøßWÑÐä\ra·±ò·PÝùò)ÃßÌïEûøÞ¿í÷»7\x11vr³7ØÎ\x1dæ®dB\x19ìØ\vgXiÂd\x13\x02)*ï\r@\x1a\x19\x12®µ6¿Q\x0fhѤS«TL" ìÊJS±¹Ã&h»²,}© Ò~}Xm^[÷øNYJ]pû=-æ\x0eÿz\f÷ܹg,ËÓ\x04!®¶t8Ph)\x05=ÍdÀ7\x17\x0e\blËH:uõúúP:òCnÇ#¶¡i\x1eÎwuNéºqiJP\bû]¡ÜCê\x1d]ǧ<&¹y \x12¹\x1aR\x1eBÞûliöW¨éê-Kö\x10 \rH\x12ÐCùèQ\0;óS p©¸@íV)÷ö´ýR$Nãä¦\x18½gÁ?\x16=ÂåÇ«\x038x/8\x06-
ëm§.'ù¼åOÄò2=ç>Æ:¯ÿ4ãñ^+nZÞF¼%ò¬õ+\x01ß¹¥D3¹Vk]ʵsçó¥,ùV7Ï<\ñ÷ÜË\x7fnNn'¨3ö `f4¸\x1aMr³é\x1c\r:\bíàç6=XLPxv¸{õ=¿\x12j7e¦apÆÉ©ûO¼h\x1dºÃû\x10>ñ7-\x1eV¿ÈfLL;ëÑ\x19âJ\aì ÃÉW£ß\x1f¤cuac\a,Njáĸ*#b94á0íàÜO\óð\x12z\x11¯ög^[P±¿\x16ÕÝ\x1f«ïñ,Ö»jT¸åÎ$C\f¹5üom´öõh«LëØïí'w
¥ª³Sx\x1aìΩévi
\x11Ë\as¹T\x1dà²OÃP~_»®µçh}Ñ]\x15Ý%A\Ì¢~È/@!H~Âd6¸Ù6ÿÑ1ïÇ©á\x04olûÏku^×^¿so\x06\x14=P;³sÍÀï1\a\x06¾\x12ÏÓ/]=\x11ÿ|\x1aßäÅM!ª°\a^`QvwÃmóôN\x18¸ÒòâÎlR±Ù;9îcÐ\x0fT#*·«··N\x1dóX\vÜrº&$Ô§Þ;\x14XÖ©\x115ú^[}Y\x0fK[s\x13múvæM+õá\x02E\x02\x01\rRã?XB\a( `ØfÞ$5z.I-T\x1cA)Rá\x03Ê%4\x05¬µ#Y,\\x1cSî\x04Úm\flÞjñÅ~µ%®\5½T=Ö½mMyôÉ%Á\x10÷[y"fan\x7f\x0f\fPi¤bðî¤ý¥m4\x19F9^ÇË'C¯FÂÔÙz¥Ùc$ÃB\x1d\x0eEÍ)\a½«\0Q'ÛÕ¨hYîË×0öþ{1~+^[² F;e*Èw Wãñù\x17ßSà[ÝAòRNº+\x17Ó¬Z\¥óN±C¥e93\x05LL'JR\x1cå/{þEû'Y¸¤X¡ÏÇ[Ïä1=G\x1eÄð¹âñÂl"ñ§ÿÄâµj«÷²R?_Cåú«ôUS×/Ú5¥>BüWÄ{j^[ïGÐ\x06\x05^[¼iO¸µñ Í
2Bʺé»-0<μhºGêGB.ªd¬|´cmا+:ËWÀéçbXÝj]¥,ÔqáåÀÝuv·8ÇODýß7£v®\x06÷\x1dlxô¯J/ëÍÅ÷?qñG|O'á¾ÚÿF'5´\x05\x1ckàÍ8cxñÜ}Ù\_Þ)GÄ¢àôjµå5Æå4·¢S«|\Æ?\fâjÿ\x02¨çsHDHó¨ö}Æ2MÐÄbB\x18Mé©xð÷
w8O\bõÇ7ç
6öqÅ7\ró\x11ÃÝOb"=è¸Çôú¾\x06ÐåL\x12È\x0fîO$uBNK'â0)üýôýØÚ}»ø÷½\x03è\x1dÅ\aØGêc\x18¹Ä#¹ 8}º\x17>Ç/Ì=\x03A;Õ.$MÎ\x01ßsÌfäí\x1dÁÑõ/À\x0f\x0f\x7fYdÍò\x0eån\x1as7§^C` û\x03àÉhr4ùáØÞa\x03\x04Ù6ým¼L¨îCHçZ\0¹ÿEÖIKªÁ£\Fí~jëS^[CxÑERU\x06húäE\x0eqTø>wÜ\x1e&ÌOçl\x7f¦Ö T±P*\x14AGòg{À)
\x10¦XªI\bý\x12dµQ0`Ȥ\x03÷o¦>ìº\x1e\x17-\x0e\x1f&»{3\x1c\x1e3iw×ÿ õÜ=[\x161z0\v&ÙdsüiüØìã\x1f\x0föwãÍ\x02oãòñöm?ðB\x02_Ç8\x7fhQO\CúàÂ`Gê\bl\x04\0OÙüÿøßÅú¿F\x1eñ]OÀ a8¾( %ÎÎ<OÝ¢ÿÛþS\x1aÇA
ÃÝà|W÷ñ±ï_µÊ|ßç8$×!è'\x13åÄÓYéµÂäZÛ-éd°\x10èCöñ¤ä\fu\x18m\fò\Èn]=1TÒì1¸ýâ½!¶\Ö(Pîân°3_»z\x1eŸqzË, Ns\x1cyXO\0NÖz\x16\x14½òúmS\x02JOA:
!\fð˾»®n]\r_t±VçèBë}Ã\x14c&4YéF$Ôÿ䮬ÕôFÛ¬ÉîñÆGG\a\a71µµ\x01\x13ÈG>ËXµD|ù\x18Æ\x05?®ì{/\x121×\x160¥\r©\x18·e\W\x1eÓ\x06!\fF\x06939\x18߯\x11\x1a)p<\x04Ôû\x13\x1e\x02n\x13RÇ^[1ÏBV ÌÐÈ{Êiú\x1a\aû\x0fà\0ßôp§s]Fýg÷C\x18¬+Îf?w\x17óÍ=Þ\x1a^[LC~I¦×\x12·\x03ãz%8gAü\x0f?×Ï\x18ÅÈ\õî¬úÍ
ò·Ùâ¸ct^\x13\x10;â
ÌÄ÷#ô,¿÷¾\x18^øm(DýÁ\x1cªY>\x0e=×ÞÑ&¯ýR+CúPÖB\x13\x1dí´è\x7f\x1a\x0em8Á^[dú\x1c\\x18ÀL͹\x06©¼P\x17¦?ÃN6Ê\x1foM
+¯i-\x03Æõ²a64\x13m!Õ1NEvعpLÚarî¤äÝ\x13£5¹N\x1c(áé3\x12\x06\x13\x05¦±\x1d©ÈZü®`Àì\x1cwØß¿-ê!Q ã¥6Ë\x0f^[¥q(ýÒD;¸CÙfÁcO®\x1d\a6@\x13rݾcd»G{Ç\x05ei³Rõ¯U'ªv\x13¾¼¿Á\x1d¸¬1;CO¦áì#æÌ\x15^\x11t\x16¯\x1cçÉîîêQ¸&bI®÷p\x0fvcs°>^[æRe)÷w\x19S4¾^ÛÜåk<øß\x19S"Så#e¥s»EÔ\x10ªÜ*êÚ&\x14fk/ßaÍG~.\x0eK;I[\x0ePÍr\x19 ¾ÉvªjFfo\x14ÞªÕD5W5Êa& XQÀö´;öq&\x05[¡´@ÆÉQͰÄPx¦)ι¾ û¹¨»xÀ´/NJ¤m"ZK\x1c§âoR\x06\x1d\fK
ÙceC\x16}Öá5ÆX7ã¼pAù59æõfì¨ãyq»6\x10Ée\x04¦bR!Z78'¹¯§¾5¸8\x17gx¬9UPCÂX(·ö³;îH:äP»q\x0f×Ë\0ûáüµ(wÿ¨¹Z Ö\0fV\x0eÔéZH>Õþoú\x7fÚs\x7f/æþkúòñÌ×ë9þk®ß¯¾úoZGN\x0f¬þ0õ£\x1a
¸ãûÏ{o~\x18cG[
ÌnI'v\x1dÿ7üÝ,j»s\x11ü7^cÔU V¼WÆ#Xñ;Õ¸ç8¬`Ýíó\ÍszÛ\x1do±Ö¡õ<> Xâ°ó¿~íjw\x0eïxËæ\x06a¾?Îöò¢\x1dd \x10|QW?À
\x13H\bº*k¦ý´0\x1c8R\x1e8\rà¿j\x02ø¥\x03$A7\ *7÷aéæ\0Ò\x0f\x19^Ïm±ç\x03äÀ\x1d¾EÌ\x1d¯Ë\0³f\x16Ñ(õÝrýS\x1ai÷Û\x16Ó5EOü¹÷z¸ÑSùþÞÓ=2
(R\x04\x1fÅr\x10\x7f»þxægÕþ\x0fÒ\x7fiGüO\að/íÿ¸Þ?¤Þ\x7f¤¹\x06\x11ý q5?þ\x19jUPl\x1e,Ø\x12c'\a&Æp\v\Ì\x0fþ³aÁÚ{8îASï®F\x02\f\x1fø\x1dE*CòXÙ¥\x11y\x11Tnl@ä`2\x1c\x17\x11ÈÉõ\\Ì\x10?xؾƤ\x03Q¦^bju7lhÌX¨_¼?÷"æ©QRî´
\x01´:\x11N*\x1cÅÜãHÈ\x180NÇa\x03ú ;r\x1ee<NB«Ú~ýô0?:\x01$\x02/ð|q%¢]ÔÜhÿ¤À¾\x02ݹ\x03\x1fM)Èb/¯{Jyr1\x13Ð\x16½ :\x10¹ûE)\x14²\x17>,~äP \Û·×[!ºG\x18ƹ_¾\x15WË9\x1ev\x0f°]ãi4.#d\x16Ñàû\x0e\x040áá\v,æÇ? :^ÂàÃa¸7\x0f è`ÍÑCZn7\x0fô¨\x1dPÊdä]Om\x1aé\x06\x1d\0\x05§\x11\f\baPÃ@&\x1f8Ô\x1f\x01û\x7f<IòÐþx\x7f\_È\x1a\f\0©luç¤~È Ó\x7f\x1f·)äúãØ\x7f/ýò~v\v\x12øù¤Å"\x14ýP\x04ÏÜã\x19ô\x10ç`\rènÍa$$\va\aV>\x18\v'~¹!¸ÀjB\x04HÂ\x0fY¨@ËG1c\x02q×Û\x02\x17\a\x16\x17÷$\x12!Ä\x12b\x01çfUVÏÜZ\0óÞI\x01¡(JJ¡WéÄú}yì))¡\x02\x13|\0 ¢yGqhÞ"m"#¸y«"EêÒ\x1a43«M\x06@.f\x1at \x11¸ÒÑ\x1a%H1Áf0 HÅ\x18Á)§t\x04'Bô§cc¢SAE\x04:\x05X!`aÌÜp³½rÿ\x10qWî9}/ëöùNK^êËþu{XcÒ=G\x03\fsõ³^ù~::\æ&{vÔ\bf\x1d\x03k¡Û Xa§uE(\x12ìÃ\x01_Ý\b;ìc¤ßA\x02J;6(6Ö\x17I!!\x0e\x02\x1a\x05%Î\x18?Q\x149C¼\vuóÄ\x0f\x03\x02\x1a\x14\x198èÓ\x18ô\x17cÚ9Ù\x01ر\x02\x16Í\x1dª¢N{ÌØÊ²!b8I\x14ØÍ\x10¤Wü@cPæ-(jv@\0ÔÕaª.ÂÉað#^òM\aø\x18\x06¼û?o\b~}*füÓå$L\x19$q\x03c\x0fU39'¥ä\x19\baKdälL=\x04{lHùôhq6\v½ÜheÚvî\x18\x1dNæ¢jõò*ª«ÒæS\x12yMj¢(®\x0e"Ëåó(H\x1c^[ÑÐô[Ä>\a\v4 ,A$%\x06´/`Ê\x1dÐ餳Á\x03>ÑMFM\x1aI\x13\x06R Ĺ¯TNÈð'' '`\x04×Ð\x06^d8U5ÆÃÛïòú{§ \x1cðò\x11\x13\x04ö\x11Æ^[\x15\x1a\x12©!¢\ag\x18GvTl\x19\x1a!\x03¨¹¥\09=Ç^[u5M\x1dÆ?Á$ù¢>ñ\x03Pè
sSp#IO´¸\x16îºV\x15HÑîy<O7mQ\x15%UUUU\x12h`zÈ%\x119¦f{#22zÅ×\x14'k_8\x11\x1d
[cJØb\a" 9ÓUfdv\x1e÷\x15Q\x15$\x10ùZqá ³ÀÌs\x06.l|à \y>Óvì^[[BªBJ,6\x1c
ÙÆ\x1dH\x0frrxA¯t`ôÊI%b\x02Õb\x01Ù;H1;y.Ú\x06\rpóê8ÌG4\x11ð¨ÔI
Ô§6\x19W fh\x1d\fƨh\x1d¦#{1»l\bo\0;2fc\x13¸ \x0eàÖ¸6h$ü®Ô\x06É|\fî@çÔ\x7f¨vnÂ7\x1dpZ\fã\x12\x03²fäeÛ\x04&ÃB$"v\x15O'\rUPÐk3\a»§J*Jb"\x04Â\x18°Ú\0T\x11"ñÒ/:\x13(\x19\x1a\v¦©©p¢æAsDñoß}H¿|>ý³Ò\x18aÛRÄ#)û\0}=\r/ë\x0f:+!aõ\x1f@|®ÏQí\x13\x1fYë'a\x1e·\x17 B\x10¬µ
\x15@.T# sö!Ôð=%!IhÍûdI1ú\0Ü_{íN,v£k©D~â\f<v
(B\aº\x0f9Üm\r¶1B \x185Mo\x02nFí}G¢!è\\x164\x13$BL\x10<\x188õ\x03ª(ùÇkÈä@\x18\x1cÕ.ê^[«i\x02/""BaA¡v\x19\a]Øb\a<çGm\x16\x11\x12a\x11 %$
Õ½äd#\x01Ìà\x1c¨\fŹ0¡\x1d³Ú=ß\x12 ¤ªH*\x13ÐlÃL\x1cÉR$17Â\r\x06¹.ev»õ£\rr7æ%\x15úàûÐ\x1f\x04A¿z\x0fÃ×V«YÏ)ó\x14»\x1c\x13o"Qa j\x16$z\x0fzPÁê\x04÷.\r\0Ð\fõ\0!9\a\x12T\x062\x18U¡ÞPûpQÚbQ,@\x14\x11DlhXBQ\x01ó\x17]ð£qTÃ\x10qÈ¡êõ¨5a^[pÑ\x1cùd\x10!\x19\x06`ë\b§S!éתlÙ°Ù\x10a\x18u0ÑÆÇJd \x13¹\0>eî%ÉHH_xw)³
¯;C\x144Aæ\f|áqóxÀ$"\x1a\x01Ä>\x1eÕPØCR"°9óu8\x06N(
\x0eù7aÌ(ºBÎ3`ldM\f\x12q\x18\x13\a\x06q·\x1c±,ÊéÈlR^[0#Ã4LX±±r! Á\f\x01¸Mç1+1 ªÁh\x19]ö\rÇz!çóû_E\x0fN\x1erRy^[Ï\0\x11D`rÙ`nó\x04\0^[\x180\x10AGô\x15j\x13'4IüI ²Ah]\x1eØ&ãìõ9 ;¹\x162ð0l\x1c¹8\aa^[Õ<@ÑðOjIK\f6<LH0ê;S!3"mG¤\x03iRà&I\f\x10\x1er0¡34ÚÔ\x11\x06\x10\x15Ü\x01£èHL8\r\bì\ad¯\x06Çȯ\x01!1\aÛÔq:\x0f0g\x1dª\\rá{\x12$@H^[\x03EQ%\x02Aöpc\rXo¬¦ù\x18(\vq2\v°]Ù%À,0Å.&'\x0e\x02o38¨\7\x1a
è$T\x0e\aªÄ-\x19d Â]æf\x04'BI4.\x06Êã0O22\x10¾!â1)K§ÄEÁØÀ\x067J2GÈ^[U1Oµ)\x1e\x0fçN\x16xøðç¨ÒF\aÙÕÒ\r\a¡¡ìÃ\r\x10øL¬å\x05/ç¦jâàu\x02@ºwÚÂïO':V|¾W¬ b\x19ò(Ð".²£ÀÜrÇa*B±G|\x11õXrÐè|K§\x02 \x18#ãñÈà0BÖ÷\x06 Ü\b½±¶\x1cÈ`A\x17S¾¤$`¹êG6Aà
ÌqY$©¢æDUMC²&Á\x12&ð3\x17¾C\x05ì@7^I) \0ɨ;2
K\x19´l,àr¦\x03³ JVôô\x12BzJ\x15=2ÊûU\v{Û)¡îI>\x14\0 Æ
°MóÈâ îÙÄ8;¸\bãËFߦÚÂ
)ysD\x05\x7f¤8¼/Îå"\x13\x17p"¶Ô\bÃç¯Ù>!°p\x1a
4-=ww\x12/¯µ<¯\x19 çb\x10ó£aÜ{ɦ(£°\x14òèG°¿_w2ÀZ¡©\b@Ì9êhzóhÝÜs8\x06\x0f\x16Ôô\b2HA(²ó@s:N&ûIá,\m
5:\v\bå´\x02ä\x1cªg)(\adh÷\x0f\x04Ø2u\x03@¢G uRàÑÚ\x18Th¤!Ä(ÀàÌ
ï<¸K<ÇÃZ36\x1aqEó\x10ÐÒû£Gì=§dö½ç0è=Ê\x0fꯡ\x04¢v\x17Ô\x04^çÚ\x0eH×IJ`\a`9\x10;\0æ(\x02%Ì`1\a#³*´\bp1È0L=¥M(lõ°}v\x03NóÌ$9ÄMù\x18Dí&\0Ì\x1fN|\b\x17\x14\x01ù^[;nøjm¦5U$H¤,9:¶
Ͼ\f\bÑøñy°ó%\x01Ô¢rT´uáHçU¥Ca\f\x04\x11\x1fGg\x7f¬#ZÈxÂÝÉ@\x0f¸2®ßaçpè\x10\x0f¨ß3¯®+ÌuóÈy@*\x7f]H\x19ôþÃô¯á«Ý³)m
ª×ç\f[f¿&¦Ì/ ppoÁ\x13\fù\x1eë\x10O¬X·ý9¸/øÝ0µÉ½KYitßú`ý?\fÄÁÕ½Èî =Ñ\x14þ`_¾þ`üÿÉIY²Uð3Ý\x12B\x11Kǰîþoèûþ£öþ'ÇîËôgPïI\x0fÍGzÃý&Usù=¢\x1fÝû\x12Ýçü2&N\x01ûd0x&okþ°ÿoü-R«o÷È? 9¬¥/÷òùþø²\x0f
ô\x1erÀó\x0fÖ|Ïá,uâZ° R¥\x16Ä\x1f`áJdVd?AEþ1}\x1c\x0e{\x1c´\x0fæt\\r§ócø÷ã%{Ñ;ø?Îèg²\x7fAúNb¤$å' ÙB/UÏW98lØéÜduÂp(!! àP\x0ezð^[°\r^JçS¼QY4\x04È&n^[
rg Æ¡\P9\x16?e¬éÄï\x199\r\x1a\x1c*0Þh\x18\x16åjO\aqÐÚ¨Hfn\a2dëH\r'\x14´/\r³&XÓ¶Æ60ÍDht'o\x0eìãácöI¯"\x02C¾/-Um\x03\x13qô 8ä纥ZÍåe\bÄ<l\x1e\x12Aص%ÊB|xxV/80Cd\x11À\x18\x10\x10ÞOã$äÜ¡\fxl·\a\x1d\x12ã!ÔC0Ó\x01¤äP÷®\x01\x12vø
l d\x14\r\aQpóýg´ûDë\x1dãüD!\x03ë!ðõ¥__¸ròeäR(3\x10\0P¤¨£èúGì\x19<M2¿Ï\x7fbÚÀ\x06θDíB¢ #°ÿ\r\x04T²ÎøpícX\x06ÔU`÷ûÒJ¡F\x04!ÝËË$¦ÅÀi\x15ÁÅs\x7fý~jª¯éÌhª¢ª«Y¶2¤Öa\x7fÛYe5Yæe\x15UIM\x15TÒOµ"B\x06Äämnè\x7f}%C`ØuõÄò¤=\x14\x1eÍ2dz^[obÇ87±%ärgc°¤
PéNC\x16êM.JÜ$1p\r³\x12Å\x04&\x12Qc1lÄ\x03w ÅÐ3\ak´d¢;Ó+m
K\x1cc\vlê\0#Ð\x03kÀ45NDD7¸i"\fME\x14§SfB\x1a4f\f@Ý\x19¤i\x18£AY e\x06*EÂ\x11"½"¸L\0õó
QKKñ&~\x1c#|ÒwÁÈH\x05iÝë\x02\x16\x04Lè\x05sc\x02d\0`¶¹8"`Ô\x19ÎÆC\x11ÐmÏ\x1cÉîz
u\bÖ¦Nªq#"\x1aë'\af¤a©s©\r\aªH²òIöüÒ\x04û F¦;ÎÊ¡à\x06\x05XvàB\x10\rdçQÀÈ\x05\aPù\x04ßáMn¡¬\x05º©.^\x1f¶2]B´¡\x1e\x112\x12¨V5Ò\x14>y@¿Çñ\x0ebv$w@d\x14S\x1c\x06\x01@}hÁ?¢×Ûõ/\x19n°î\x0eds3±%\x10oxK/]\x14Ãp\x13phÛ"!ôl6\x17¼G§¤_`\x7fP\aÂ\0ih(ºX´¢4£âi0tD\x11\x15'±_«å12 ï\x1eû\x1d}!Û\x01³¦ù¹c@Mo\f!\fú\x04\x13VýÁ>ìøG;ô¦ÏN׿È\x12PP ÔAS]ÝÒ.\x17þ~\x06Íæö@^[mïyLmÛ Q\x12\0o$¬>:eV\x13Úøô\x1d\vQ7°\r{C~¡¤bV:0t,\x12С1Y\x02ñ|leÁ\fW ôAOz l \x0eD\x06\x043ÅTÊ\aLâ\x01/%ç#¼\x14E\x05qÐΤ`ÕÒS2:\N÷=b; \x14äO"SP)Ôó\x1f×l»ægoAr¬¦\x018\x1f,-m
Ý5"|åé\f9ÔS`Î\x12\x06¼ü´¸8~\x01A)ñÒxÁÆff½²\x18=É\x04\x1f4¦\x0fÈB Xz\x14\x05\x0e\x04öÀ%\x13dR(´¨~\x12\aI\x14¡(0Bÿ$\v ^[t.q HÔd"\b[º¬\x1aÃ\x05ÅÂÌÞbý^[ÀTôò}¹5ByÀë¼Nd±\aô¤\vó@9%\x01E\x03\x04Û\vé
Ô§\x1dÎ$hx6þI\x04.²Á¢Öðöÿ.\x1f~4`¤#9 Ã'ã|QÄù73±£¾É"\x1f¹¶¹ \x18L'Î=\x1ahÐÍîÜ%\x109n¡\r®\b¥])
tHÁ¿ØCB°¨CTª4D4(/\x11ÀÝÖN¾\x1f\a²4çÞ3ôîi\fB\vâ\x11\x16+dK\x06+\x12ß@-,ø\x12\x17§ÚOå\f÷C°m\0õ-E\x19ýrS,\x10Jv¹Øõ#úÔË%\x0fÜØY A¿&Ä4Ì2ó
rSÚÒpÜó\x03Ý\x1eLá\b|&À ÁĤ4¹\x02$<Mð:KòXD6`aùã!àÌúìã<¶58ÈtAʧrË\x13\x12Ø»m\bfvª¼¨óv\x1e~HÉØÀ Ñð\x7f\x06óïÉAGT=EupiøÞï>ôÄQp÷Ú\aW)\x0fí¥¹`e`V;λ-l»¨\aôÅ\x10Îiòàt\x1eϺÂç\x0eȶÕRzþ;æ\v{ G¦\0\f\x1cËQSJ\r°=jêÆÙ(B\x01Ch
3[\x06¢\x10/4ý\x1dþ\a o\x010è\x04àF3Î\f"$¯¥"`(9Á/\x04XÓllmÒBO$À·KË8ß7Û\?4K(öîU4çàèum÷Ýgýp[\x044Æã1Òd\x19b´ÁsÖ\x1d¤\rJI Ù#îåùGMÀb"I\b$2\x02MDì\x05vóGãþ\x10h:/ ¨¹Â\x11\x14ê\x11|ó\x1dA ¥ófDQH\x05\r¬\0B Óù÷A\x17¸Üú}Y\x05\x03ßâ4\x0e\x10÷1ºOT-M>©\x05 ®ÙJMzµÔÕ\0"Ûx\x16¥°ÝÂÞ¦î¢\x1f)\x14\b¬âa@¡@´\x01¥\x1e\x049ËÄ&\f\x18an\x10ÒÉ\x11°)évüÁ°ÒAsWà¾ÓÕ\x7fûÄvÀ2Ê)cFîÏyéMaòì¢Î%¡ ¢\x18±\x04AF\x11\x06\x17cMÑÈ\x0eÁéGl8¡KY\x14ÈÈ%\x1fP÷R¤"pÅ
¬¡`\x025\x17 A\0Ðì7äüÆe!-\x05\x05\x0eþç Ú\a \x7fñ\x15|Q
\a\x05zqùÝ5\f³4 µ\0=~&6΢'\x16CC2V#\x15:ÈÓ CÊ('\x11!\x06 gJ{\x12}BÇäq¡½^[66\x02ìí\x03e\x10\x01ê'¶\x028Ýáçó½RyÈgiÔ\x19¦êf\x16ÌLr\b"«Dk{Í
¹-°ÀÈ¡*832 JüAÔYÖ\a\Øø\x18c\x1c!\x1eÚ®ÈVwF!t±çîß~jE"£%hR\x15«b¬Á\x0f\v\x15$0Tu» \x7f³péi
\x1aTÈ.\v@Ê~[å\bWu!!\x0e¡\x1f÷Í&ä 8!xÕ+BáR'¤nÃÄõâ\x06è~t\x15IªúÅÉ\x15°<áÁÈáÀ \x05]:\x15\x02T¥`PP.G!¾è3\x1a(\x12BI1ÌG°Ì\x04\b7nϲ\0\x10dd\0^[\x19\x19Ô¸¦\x03j\x0eSr9=\x0eR!^[Pþ\x02\õG'ÁL\x0eÆ\^[R.ø!Ó{ÖU£e,[\x14Å¡~Û\x01JÑ\x1c¥zB^[¨uEæç\aI©\x06=±Ã\x01Ñ \x1cDÃsÍÂõA\x05ã@þÇ$FÇ\x064ù\x0f&ò¡ ûHè\bò\x7f\0rGËswså<æ
IEIÈÌ¥\x18\b\x02`HJ\x12\x1a*
\x18¨"\x1aDu4°°ÒÒ1\x04\x12Y\x14\x11\f,&¥ë\x11jS\b¦¨¦\x1aià°¡¢\ap\x19\x11'\x1aE8¡3\x15K\x1a¥É×F¦¹´6غVdoêj'$\x01'æéFØÏ¤z63\x16fx&\x1f@mlr\x19
ÈÕ\a` 79ÕÎ\x1e\ri²Ó§{y2(B\x1a \f\x10Ù$
¸3\x18j\x01 \x04\x1cÒâY\bÄÆÐÆ9ÉDU:%¬W\r²\x1a$\x18\a\x10MC
&^[\x18¦Z0ÈsÔ À\x18ÅÊ\x1alç¨åna\x1cµ³0Ô\r\x15\x14ÄDA5tÞ(ÍB&cj3bB¥MÍBn)¸pŤh|HG\x1d[H#\x04\rÐDo\x15D+\x1eÝccÖ*Ðï\x11g\x11[tlÞ\x06\x1c6F®A\x06Mg9SD"Ò\x141ÒEÜÓl\x06ÅdA\x01\f!t$¦´c!Ø\x1d\x16³¤jMW4ÄW§\x11¾fÇrÞ"á\x03%\x18¨P&1Jæ`\vÄ\x04°f\x1er\x19R\x1aIË\b2\x1a\x02có&ö¸\x12@ç\x03å1Ù\b¯c\fÙ\b60BäÔ"\x11àÔÙ\x06b-Rvâb)T"°²S\rÃ\x1c\x03ÍÛæº\x17·ç%\x17Nèb\x06A\x12^Öeo\rdûÄ\a˼t¢£ZÓ\x1fIIKipÑ·59kx8DÔ¸l&(¤:y\x14\x13á\x13*½Ìd¹æ÷\x05
¸PQ\x10Ðf\x19dPfUwb\x1d\x05}\x1eG>vÏlÔS\x02æ&ë|Â1\bÈÂ\x0eíTñoóV\x0f¢I~é\x0e½ýÏ
hÚýrx!xAí(!\f;J/²ü*²WzÅß\aË$\x1f.Äz/úý¦\b\x03cÛ£Å\x1dxyñNxQ}á°)H\x1e\x10ç\0¨$tàX5Ȭ(Ç\x0fS¿wW^[
\x06óphX}%fä@y\x12$'Úb\x1f~D\x0eP1\x02wÆ õ@\x15ê8_vë*^[uÖ<{wHÔyI[ÍcÊC¶rg\x12\x15\x1aÈI.\x0e?(ÿ÷öÿǪú\x7fÓíÿ§ý9üòìÒËò[k\f\fʪ\x1aûS\x1eeDjM,çÜ«®=\fQ»\x12\[A\x1a\x05/½i\x13K&9c>ÁË\x13\x03
ts2É\x13
¹\x18ÚlN\x10AsRUm\x12 \x12`¤©È/i¥sê(k-2à¨iD>F\fi-4(ÐkPZ\x02ÚQ_¯\x04f±U-M¦Õ m\x1a¶">0EÌRB«o\x04´\x1cAà m-¥\fQf@ÂÚ\x14köÉó0/Ì\x02~|(ßÂÕ/áõ\x1eãê)ý\x1fE$¬\x0fu¦\<
D\x7f§?)\x7f\x15ÍZ°cFçàíNÉïëê¸k,ìÎ:»Q1§¨Ú^±ÒçU&m˳ѽ)²ñ^[Óg|¶\x7fª~!¥Ï y$k´\x17\x0fæ]µ-Ó$\x02í\x06$ Á>EsL\x1dñ\x19ÝÃXå?¥zn°i2Ö\x18é\frì®Âd±©Ï\bÞqÓXÑ~a ZçóÛc531ä"\x01¡ °r; ø9½îÌó»\x0f?A6:\v¥6¢V\x06ó\x05ã*Q0@£,Éè)\x18ôÍ;\x17àÎ26\x12F s ;\x04BÓ6Üâ\x06Ä\x01Î
r\x1dðÂ!x\x05ãþ-\b£ \x06¨\x10Ð/ÐDi@teºM¤e\x0eá\x11<u¶(9Ëѱ¼'Åq¹Ûfu5kFÙ\x1391ݺ2@.\x13ð&øÂ~\x1aÞÜënÁ¨ï\x0f;ÕlãVdLc\x06`óÆðßkÞ3¶Ct»ùÁ\x062ðØqØ»=(+p£®eqÃ\x1a^\x13Rî1³4ªBÔji§\x0f\¸U\x0f$Ý®HÚ\x06hP){µ1~\x06-\x05¦T
©\x1e1µ)¶pÎr¹8LévòÝ\x0ev]Û|Ñj.úæ¡Ey\x12W¸ýuÃS:.YÛ²ÖCÅÛQß¡âÀ½Ö\rÌÌc¸è\x14ÎpÇ[»0\rCÀªK¬v\̶îýãyq.âĹw í¶5BvnÖä \x1d\x15
D~L^MV&H\x1aãV\x128\x06\x02\x1a\r]Ghv÷¾Ï9î»ä hc\x17&îÔ\b¬ìÇcxcñÚÛ
8ç"fØØäâCÑ+³ °Ê0À×1+gÆ/×\x122\x06\x06\x10ì\'\x12«ßÃÂ\x0e\0AÚÄrcë\x103áºN&ã\x18¼qÒ·Ó¨D5_Y\x12b,\x0f\ræv¶ d\x18Bmj¥ÓíI
\x16\f¢g±Ì5\x16v:@îÌÂ\x13MÚhÜK§^*Ç^[;rX\x0eñ\r̰C Hß(Õ\0ñÛ\x04\x01®ùÝ;÷)â°ýáã\x0eíxï\ôü
õ¾s\x15[ÄÏo\r\x1c£¤R\x1dݺÚt\x189ð*Ï6µ\x1dâ\x13c\x13dy 宿>üܵ\bcHC`6\x1cpv`lB\x06Ë\x18\x19Î\x13J¶'Qã>7ÙWu®[\x04l]ª8\x129á\f¹<\x0eixÇiÎ]¥ê\x18 I\x14i*Ð6ºÙû\vg4èkµ6*v=¹8CÑçj/e# äG\x14zñ¹Úù^[×\x19\x05ZdËË!)
Péc÷?wz\x11®°1!÷\x10WMãG`ØÆG%!CPÆlk@M\x19E&M2\x04kR&ÄÝ\x04N¹0\r&ùû\x14H½)IËl\x12ü\x0f\a´X\v½9\x12LÇ¢ò>Ì43¥æzNF±±®\x1cqkPP¼×ÀÊ©\x1c!ßGUqÐèrS¤4\b\x01Y®l\x18¤z³,[n^[mÃ\x16¶ã9[C\x0fK§éÌ\x18À\x11\x0eFÛ3È¥èå Äjäf5¬[ä±\x0f(ôzuK¡µ Pp9^q«óg]]ÀÕ¼\v»zn\x12²\x14:\x1diCµ±
A
\x0e>ÖfÚ\x11\btz;T0p\x1e%"\x0f"^[Øÿ\x1a³&|hÉäÒ\x17$b9\x04\bD³ÊB\vA½Ñ,Ò¦j`LÍa6±q@\x1eÅ)ª-B÷ Õ6:ÍRaqj\x12^µÔÎÁß\a>9º6¶·ý$ÀçHU`!bm
RbÍ4
°Ã·x$CÄ
ä\x012èÚQÚOd Fá$\x01\v¬\x11ñ0A\x12¨À\x0fmóÇwÄBo1 ËÍÑ/9\x14°ÌFÚ8âNÜæ\x0f\x18F^[£HÎ\x05zé d¾Ç\x1c\x165S¡\x02^[\x10ùÏ<°å\0ã#á@اHý:)Ó¨øÍß\x11(>TQ-
I]\x19ã#iuv®52Hý`·ªêÁé\x0e_\f^¬ùÇ"^[\b6|1\x18¤3\x048Î(@àY¸f7svÍ\x18½¾²!ûíh!BÜâ¢&cç®\x1cnFmèó\x1cØÍ[±B¯Êľ \x14&^]ã¼bN:©¦L7CÝ3Ì\x18¾#2´µ<R\a}Xûà\x05âÀAàKózY{iâÛNæ\x1cìiÑ+¤\x03 i\bJ\x14"\x19Bx÷1Ì6¢}\=éEv¡,nl®./VÒ³²n\x1d{Ò\x03±\0Þǽñ\x1fº?Ãç'4´£\x06\x1e\x1c(¶`al\vU$^[.\0Ghl\x7f{¨î:7\aù ¦ÂÛÁáñuF@\x7fp·^Ò >e#¶\x15¶\x01?\x1cTîE\x1câ§?¨ßðñ%vöÒÑ
²X¶kô¦íð\rSw«]v^[ýBÔ\r¨Æ-CúÌ\x10´^X7èxmm5¢\x12G>pe\x1cchSåu
Ì~®ì.TN½0³³,ÌD»³T\fýÛÄÈ!p§\x0e!颸öÂÛ¨£2®!øýÔbN}\x01±£jçq¤679ëlò6"Põ(!\x06 Ó\x1f\x1d)ÑòôÛmêÅÅd"ËDÓ!\x15Ìà ÂA×z(6\x1cä\x1eÂ\bn|r4Øöó¶wÂ\x1cîÈ\a$
W¬¨Ú\x04\x1ecgÒ|\x14^îýs©Þ¾úP(Ì D \rl³Ñ\x13¡\ræÌ¦èí\x0f,éòØ¡\x14¥\x17LÊÈ\x12\x13Õ)"^[\x11QR\x17\f\x06ɺC®ß|G-µ8tcdW
'î!&A¯\x18yvMa³DiÁвïyÍ&r\x14\x18j¬Ù9PrZf\x19¢5\x03NëLºGFkYª\x06µB¬k\x04Û^[\x1a³|ôÒ3°¸´\x1aáûÓ\#Ã,i\x06I\x0efA\x06i Òf&0fN.^[2ƾýfKZ^[\x0eÌò\f;'N4ð`³Q\x05æ\x05mf\x19q\x1aX£Ì¬¥á\x04
\x18(Á\x15<ÈÒ\x01\x04 +,g\x19 LÎZÈbå\x1a§@9N]qcÇ{,Ñ\x16GÊfl²ÙÍH2,a8F\x1c\x1aµ©ek\aLBsõ§\x14\x13¶`ß;\x10Õ\x0e\x11 \x03áÚE\fP ¹\x19v`ncE+ùRB=÷[\x16
\x05äùèáü'?÷}Þ÷\x1fx\x16?\x1f\0oN#cB\x17Ùu¬9Ïéª5 \x1c"PbXïÙñÒ\x14D[õà}H³¥%\x0fÏM\x04\aXhN¾DßTNú½\x1d·5ïÐ\x1f£\r fáûÜ iokèu&<"ÈH\x11\x02«B!Áu\x17\x03·íÆPn~ç)H¸Ãó<fsSIø0>1¯ÛÅ~l\î^[- çbe Ù\v\x12;\x0f¿õ0ÝwÉýµº_Ü\x17·\x1a)ËQ/\x02ó&Q}ñnaßÍ÷ç^\x13H¶d4\x14wYë\x16G¹ÔªvÜ<Tg>Tw}IëÓ\£\x1dÜtpéä
¶wtOdx+\x15c\x1cÞfx»ºåwÖ\\v¢9\x0e\x11¯N«\x1c»ã\x19\x1ci¨dÐÜÑ\x0e(jò®§VKÕÀ\fc´ÌL\x11Ò\x1f\x16\x01 \x177Qà\a¤Ääý±8É\x11²\x16¼+jq´ûx=o}5"""*¦âÚn¯7=vq²ÑpjƺÂbÕ9ay¨\b¾\x17¡¤\f`!aÓø×\x06'lP¦'Í\âchi4\x7fÙXÚ\x02"""\b¦\x10¨½w \x1dJs\f¢¡qrHôÅ\x01\x05"ÑJ\x15\f\0²H «Hª\x1dË«ú,ç¦\x14W $ 8¢\x19: VÙªFÖ\x1ai,ßJÙ\x01\x0eè*H\x1fÀY \x1cu ìZ¬É\x131z\x1fý\0GÝ ûHu<ç5.+ϪTHC\x16l^[v\x066¾û¬\r$#$B%ÂÅ`'+\x13\r¸¸\x1c²\r\x05F\x11 ¬Q?ç þ&A*qÿ>bi\f.\x1a¥ÑDC\x19dhäDª Èe@³&$£åTÅ
5¼[bÔ\x06Vå"t\x03\x18ºSzÒmBb X ,\x0fà
±FV7`ÈÂ+Uu;»V\r8ÔùNªòÅ\x1cB $
$\x188Îr\x01ë
ß©x0\x11\x10OÓRA\x13¸\x15Ø;Òô\x02ÝP\x1d©ýg.HOiAФv\x10è²ÀyG|-\x03Æ\bT\x10ÿÖ\x03-\Aú¸ô*%^$öG\x1eâþv\x04û±Ô \x11\r\x03? ÒV\x10ªÑç#
R`¡]ó&\x1fTåÊ~²"\x05à\x10ô\; äJµ#´ \x05ÏÒ\x7f\x1eûÕ%\x15\x17úëöA6ö\x10\x0e!ç¾\v\x11i\x18\x1c¢\tH§ÚA>Â<"99sU=\x05W
!Õã\b,\x0f\r~Ë\b#ÌÈ\0Á²³\x1c¶\x044±\x0e\x03\x1e$8-¨0M\x04XÑ¢Ä&B9A°i5Æ\b\x145h4ÔfV~eÁÀk\x146Ó$¶\x05M cfdUI\x18ÒQÖEɦdK\x18G?v#)
\x01û×\x1eIîKBÛHlüÇÆ©Êmlf-¸\x13\x18ª\x10ì\x128ãÑEiçìà\rJ¼\x175\x02ÐDPö(\x0eh(Ms3\x1f<Y\0¿j2·DïO¥};ªò\x1a\x05pæö\x16cØ®¸VãÔRÀÜ.)I\x1a|
ɺ¨'f¾Hø'§¿¤3l|ßw\x04Ü\x01¿YöÅRo¾Nh\x19"a)\fCXãb9\x02D%\bd&\a |ÞSb\x0fB|y_?Ñ\bDS Ã=ÑfoëÍL´±$k\x1c¢6XV\x18å,A&Q\x15,f\x05£\´kA
-$E,Q¢2()Þa\x19f´ë\a$¤Èr-U&Pd[1\x1cjvaQ:[ìN\x17aêñ\x1fc\x0fÝÌÌ\x1crW&øÆ\x04\x0fEP\x0f2HM:\r)ÑQýRû'Aæáaåä ~v\x15ª¦"X¨*\x06X¤¦©bfb
¡ª"F&\x02*B$"Uf\x11(\x11¢
iJ¡B¨P¥ ¡F\x10¡\x02ZD¥b\x15¤\x1eÞ\x04¤ê?ÔÄÄËܸL0N \x1f1.øíîÊhC Ì\a¸( Ï\x0eY8\a\x01Ë\x10¨õ©Ã\x1c°$q1J\ré\(f'ñA.\x01º!t\rs\x1dÊ;b\bj¨¦`dB$¨©"b\x0e5Û\x06\x15]1Ü2¡\vUì\x12#HLâzâ\x1afã\x10¤4Æ×T¸\x1eF?ÿJ_´Ü\x1eõØîÖ{=NÜýFi\x02ÛC+D´üÁ\aÞ\x10à\x190\x19§Íiåê·¼\x0ey\x1fJ:%ú\x1d\0¡\0]AU^[\x01« üùiR\x02; pòÍPz\x0fµåZ\x0eÀX±,ë÷l¼\x0eBC
\0§Ó©=ÖL·8/_k©\x06-Ùgâ'^[q|É\x044®\x1e uCɯH:³AÊìóHhRp\a¸y`¼CõËy05RQ¡l¨²ç1P¤6O\x17~À\x1fK\x05HEíøbê£þ0äÔI\x12[l\x10Ù\x0e¦ÉÇ& Wù`\ j(>²}0ò*
÷ص6÷\a\0µàxL\0üGÐòë¨õ\x0fº
\x17ãó QE\x02y\x13áå>1¼p¡éÈÈRÄ4ÓKKLB!J\0F\bZ(ñ\x1d\x04:½Yä!³¨{\x13³cê\b}Ä´`)¤öJd)Ã\x0eB\x06)\x01¸§[ ¿É¡¥¢-AV\x10P(ÔoC¡¸
W\û¹¯+=ta9ñgªP¿=á¢\x0f¨1í|ä-.>ÿÁ§'R$\x15!tÌOí¶Üñ¬¡\x02Ô$q¤lüÒ®ç,\x0fwãÏ2gdjT\05v£<¸øÙw
Õ\x13ê^÷|sV25ÕM¡\x0f (,CÆ\x01{Þ©oá:\x18m<¯Û\a&G(±\x16! "}¢o¼ÄXãn\a'|»Þegî§Ó¨Í\x0e°?ÔKîÿiEÐ9¥8Ó½§$\x11\x19c©÷q&áú\x19.\x1að¨ÓÍ\x1aÍ&Ñ5Öb½q\x02@¬°\x12 ëUÍ|±ì\x1eϵBÁÙ\x0eràìºÿ-}ß0}\x18Gî À\x109\x10Ð(WX\x0fÙ\x1f
jÙÊ(|\x06\x05â\x0fÛ!Ð\b\x0eO½Ã\x06S\x13°×¦Z)ºÅÈød\0?T´6!Ç$µcqD¤7Oæ,qd`$8\içi4Aa\x06Ð@¹ú\x7f\x01H[\x19eÁ¶QoAGÊ\x01 êë#\x1f^\|\a4¿(i\x17稡BBe&\x12
R¾|2B JH(
J\x12 _¼v/²Xt¤L\x13ÔÆ\x19´\x156úGħØÈE
\x16&$"i\x0fú¤2\x02X&\x02\b\x18 J`
\x18\b$)\x01("BRB¨\x1aC q¦|q÷ð¿$\r\x14õ®\x1cèàIzh
wì*@º'Ó\x101H/Å\v\x14QV6a¦CyòÎáÝ\x10)z\x1d,¦JXØÁØÜÆ!
\x06-Ð(Þ\x14¢
I¼\x1e(\x05ÌQOõæ¯n°Á²rX\x10êèW\a\x1cÊÙ²ÄM5&Crò0á
5®!2åÃ|¿\x06wx·î\0#\bÀCh¢â~\x10xßP«Q\x05$@Ä\bÐ\v\x10¾OW\x7f NãÍ#æébÀÙ'>ª\x02 ú`Å^[5\x14a$D÷u°Ñj\x0e<MÙê\x1fÓ\x1cHBiêQ\x1cÎm«³»\x03\x12\x1ak\x1flj;ãq¥¹1¾\x1d¶\x01Óy\x04a~3ð\x18+å÷sÙÎ
f&%\x04»H2"¦)f*íwË\b\x114\x1c\x01±¡Â@°ld¯C\x10S3Ià³CG+
"BY!\x10icÈj0á¨\x18Ö©3vÔ©Ðê]¶ÏhûXu½1\x1cQ¬\x10"
à0Ë1IÄ\x1câ¶<ÿ
ñ°[\x04\x06øê\x14\x1d\aµR\x18ü±NÕ\x1e^[\x12v(Ý*ZsÜ\x01(5ûË\x19á\x03^[ø&©
rJL\x1eçð÷á_\x02B\f\fC^[µM8¬º\f¸6ñí6ôÈôÉdé sxhg\x038ÓSz\x1emTn]\x06´(Ú0pu`Õ¹1`P\x12RpÊv
v8N»y\x06U\x180¶8b;}\x12/Ô2}üA§"µN°
\0
05Ñѽî:Åó\x1c¤É ÄÒôÆh\fè\x14\x05+HdÙ%44SG0
,ÃÔ\x14VòþGC9gNby}¡L
B»àUÅ{¹\0[;Ón±Cݹ;´(K? Þ\x10HU=UÄ&Ò\v©©V,Ôâ¨öðÄw&gv)!]§\x1c
Ñ:1\x12\x04^\0½6\b8gÅgb"1m!Ù
H\x14
b\0uUDT\x01R
U)D\x15\x05\x195\x12\x14\x7f×
:\ráBâð\x18SB·\bp\x04RR £\he8½\0\x1eä?gÙÝEI\x018Ä\x1f\vÛ^[E\x03¡69ì[øÍç9\b\x16R\x03¨µ$XMĵX²h,ÄX|²yA^ \x1dN)Ã}A\x12\0)\x15îZ\x13È^[°p=á©AÚöÞ\x06zYìÔfý\fä0¼cF`AÙ\fÉË
Óv ̾éti\a »\x01T¥ø¢\x14bm"AGßì¤\x1c7ÅÌ:\x14ô éxÑ2\x19F\x1e\x11¹uï8°L9\0lmJ®ZÔ@å`AÒqÉ\x03z1\0Ù\x02Ð\x1as\x1e!ÍaS9f\x06\x03BRCÐH ñ\x0e¤& æ$\x0f¸\ù\x06ªÒ9\x186\x7f:adM|¥:h貤\x0e¨\x1fæh-à[\x1dg²\x06©ðB\x14&·±È\x17<9ü\x12×ʳ\x1d«°èq/z«ß®Å\x03¯gVÂ\x1cïÁ=AÔ¯|ìÅ\x05\f±\x14 %Q$T3U\x04Á(C?Oûã\x04Gh=°\x05\vKÊ\«ÈÁ:!i ¤F\x06\x10\x18J\x05d
*z%®êôm_,侬\x0f½\b~_YX>îÏÈîtTE k<\bà
Ü4
ÒÒP±\x17aË&B^p\x193\x05*_<c\x1aË0[,\x06\x02\vj(*,-`:\x11BËÆ"vF
H%\x18ìÞàXìN|ªT\x01À\x10?¤Qõ\x06ñn1ç \x17\x10JP20\x06ab\x14\x1dá,¤ýÐÆ3÷õ^¡5\x04V%Ø\x11È \x1f¾Q\0.±KÓÔ!âv\x0e,\x0fãµ\x17jÅ-\ag6Èò>døð\v¸N)}\x7f/hzÆ\x02ú\x13\x13¿\x13Þ§wKª¦ø;
dgù\x12
\fØ©A¨Û\x1cMS>1ÔôGÈùðòo,Ë'2\f-\x19³JîPÝ¿^e7%ç\v¸4¾Î\x17ÒwçÈéõA\x1dCY¢f\r×&óÒ3ÝJiy\x1d§²ÀâCkÊ\x023\x04î¹ÓK0D¡ b!&e׿©%;
Ç×zQ¦:0W´Æ®\x18Ô¤×/:~\x190"Z\x1daº`H\beo\x18èce¹3>ÌÁã.4\vÄæ$Un§F\0ð ôq[ãVì\ràYA\x05="4X\0oE \a¥Þb¬£M\x13\x19\bÁ\x10uµ§¸M\bÓ6È=êÂ4[R-±`X0×&F&ß\x1f\x1e:/\x02\x1c\x10kÃ:«TL
ÜÈc2ªk\fdY.³L\x04úCb+\bÓ`£\x12!lM¢8ãWú°Æ²\x10^[#\x1c\x17W^[\x18Øõ×¥±(Cf¬\x06Àh\bÌ3Ûú\x03ËâJG<~£\rjbHE\x18Ó_U8\x19ǯ´õϰßÀc¨ÎFö¸ßâ\x155í9[È(ÔilÜmf9ÊÓ:s5ð$#¦ÆGaÐY8\x15Í\x18¦§?Q`êZÞÊ\x1cr°êÀ#ö5Y\x1a8Y\x03a\x0f7\x0eâa²¦\x0e\x18§líÕ\x03È`ßÕODv¬3â BÀ9Ü\rP¥õíCP;L\x10\x1eP\x0e2ãáXX1´¥¹Y ÐL\x02¡Ø}Âr\x0eù~ðÒÌh>ÄÀ%Ñüa0z\x10\ajÛ&b°@_^[.3Ul\x18ÌXÃliã±ä\x06ªG¬A^[FA\Í\x16&Á?%ØJ§\x11\v\0Á¸h6,@ú"\x18ÄþØ.÷ºuõ¨&HbX¤\x18&L\x1eçÁdÃäË0øÆ©h
\x10rIä¢iÞ\f\x06A
d\x069 Ò\x06E6c
9$ÁH\x14\x06§RAJ\x16¨À¢ \aJ`ëNWåÑ¥çÃÆ×\x14:\x10p2p\x17\0¡ÂbïC¨Ó²P"¨¥hÔeFñÂê{ÔLï;\x14É\f\bÃÆª\b\x02Jáûzð>05
K@%êIÎ]×Ozõª\x01=²H¤>ÔÏN!í\b»;ñà\vHQ¨\x15\x11ûB\x1d5x\x16\x14õ9P-) §Gìç\rvuÑ6UK±4[á,Y.¹0\x03´b\x06\x1c"d1&Ã\x162ítÀ½bj×SEæ±åI·Ï~Ú¤¼]£\aÝ- \x06\x10Ü0Däá¬ÙjtF¯¨$ó\x17èO\x04ø A\x0e<@\x1a\vŨÓ\x02¡ÊÔ#hZ7\x11]±\x1d\x16(ÐlBÖ6°\x1c\x03\0beôXÄq\x1cNRD+jq\x022É&%¨"H´X\x18´%¢ÄbhÈC"scí524Û5£Ue!$2\f\f\x02'\fq«\x04Â"\x03\bdg"1Àª\x10 |R\x15à·µIC&E¢NP\x12!HË%\x10BHÒ£IFJ6èO\x18à ¦6¦\x06 \x02\x04lH'#\v\x0e·=ìâÙ}\x1eyIÎ$\x12\x04±\x02ÈQ\x06Ã\Õå½úݼ§ípµ;âÜZ\x0eï\r*Äú£¤£ÉÌM9®Cý2\x1fÀAÄ\x19£\x7f1\x16µt/Þ½¸\aÓ\x13tVø¤oªVd1\x14\fAi(¥\x10d\x12K5A@|în9\x06W=Å\b?\x17éÇ\x13Îr Lþ+ê\b¤ôî ò\x12 0ËWhA40\x1a²0##\r4,ÆF\rVh\x04ãE\x0fÃzÕßúÐ\x12(\x11 \x02×\x03`7a\x142\x1fh*ÖA\x01\x0f´^© |Ñ£áÝW.\x1dÔ6p?y½ôó\x06\x02\x02D%)é$À¢`_ÒYö8yß@°îñÈ~\x02\x03õñ?*E\x1c#Úä4R¡\x0eÊMºõý·Àd{\x16ªÒ¹!¼ã\x03R\v\asû0éq\x04\x0eÒ^[1\x14?\x18\fX\fu>)ÊD½Ù3Ò@D¬êW!N.@qeA¼TÆiS 4G \f(
8r\x1eÆAæÊ\x17]qtj\x16¾\x05©6r\x17Â*.G
mWJ¼ 8a "\x7fUÖ \v ¸d4*íð\x1fÐh¡òKI öÁ$sÒÊ{\b\x0f[[=8yP»{E¶ÐùQÓ\x1f§ Râ,
\x04i\x0e\x04,[H\x04\x11×(ólpJV\x02-½`E@LÕ`êC\våþ<\x1dr
®\x188\x151&\x18q¬lCIñÜÇ&ª*9\r\x064¨0\=d2qÎ"¦Èì\x06¨\÷þ¼Ó
*b$ D{Ëv'Íã\x1e°\x0eM©çÌi\x1d]æP\bpí\x03¾!Dh§È§E\x10Ö\x0f£§g?4?vp\b»\x13¡æëTê<'\x7f¾¾nÝ\x03÷I\rËA²RÈ#²qu-A\x05gNFJ\x1d\x1fÒ\a/hz\x17\x10nì\x17\x1dy\x7fIûå4T\x06nFþ¸vF¢\x05FAè&øÙ
ÁxøÐ
ÕÚzø#] 16ïúðÉ(i"ÐaMDù zÙ.C3ÒY \x1abQÇâ\v(Ï\x0eÃc:ùÀâ
@`xll\x19úäÄ®\x1dµ\aÈï\x06\x18\x06uúð ¨ ©¤f\x02\x1a¢Iû>Pì<¿9ÇÉ\x0e\x10$dB\f bîn"Hö \x10*Àw£¾\x14\x04%\x1a\x1an2ÈÆU>[©\x1c¬«\x10{ÄÕó¢\x19 L9|²ÆêNúS½/¶ïK~Ü\\x16
5C¢ÈèÈ\x18\x19\x1cé\x03ñ³ë~\x16-öÏ@ö\x15\x18HB+úO9Ø[BÄ\x10 DD¤Á,R\aæÁ\x17'iæ²Ï\vÏ
ÅÒÏì\0¢\x0fäü¦=e7\x06£Ðê\x06í)\x05ó¼§;z¢iT \r³\x1d@8³Ø\x04ve²øºÖ\x7f&*\x11¹\x10VÞºa(òYw)d,Ñ
|+³?G\x1e8YgÍ:ÿmõ¨\x1f$"|\x19A(AùSÈ\0\x1eè\x1aKZØyô%!,^~,ñ\x1dyi-\x1d\x0f>\x1dH9ËÉt\x05(Hòé'%Á`wd\x01Ô!·ª\x1a\x06é\x02qü2±ì $\rä! \x04C=3aÐ\x1aÕKE\r\0\x0f¦ &iÅ\x0eë\x16\f\f\x02UBu?6Ö\0î©PÅb-×ùh\x02ç4Î\x0få\x05èZ!ÈÐ\x0e¨Ãowä GÔ/×Vf\b¤PòÀì û·EöqJåsBE\avJªIp°\x03þÂ2Vçpò}}\bd\x0f\x05<0b$
QA\x0e\f\x18)6w>1 H6>'\x04&ÉÏ|\x1d$`:ÞG³iÛ\x14å\b¤ª)Á+\x03\re\x01©ÑxáE\x11dYÀ\x194f\x1aD5 J\x06I£\vH\x05\x01@\x05\b¤0\x04\x16Á)¢(7\x19Äb\x03«\x19\vIa¸á,G2ÄÆ*°N3\x02\flÓfaL3Ù/fbÅ0@\x1512\x10\x1eb2Üí0QLN³' ÖöêZ*""Ø!29¨Ö%¦Âp
\x12
sNo\fvB^[u\x14h\x06(²\x1c,K1(*¦¦*
"mFY19*a\bä\x19\x043Æ´Z¥È2©3\x1eR\r/\x1e\x0e#Á¶é¨¢
Sy§,\r\x12`f\x1a´\x04L_N.TÏ\x18åL4Q Ì0¦³\x1809\x03
50P¥1 Èë ØB䣺%w\và^[vZ\b9dàå6`åV\x1a×H-¥c\x066\x16\0\x1a
\b4b¦\x06|úöm}Ïg\aì\aH~yB\x06
\x11h\x10 \x18\x018B¤`\x1d§wð'£<\x0fô~µ`m\x04(¢n\x04¬¯Eé[yRÅ5!Ä\x05\x13ôÑç¹\x1c
ç\x01G0t\r¢Sh`áVv
Å"&\x04)l\x19\x12#^æªÔ\b8Ö2
¥\x18ÓµºFâ"vÛ\x17"\x05$ÓT#²F5\x19\x01$$2\0¥\x13ÆÞ"¢5Ü>5ë\x16Tm\x1fq¹
33ó:ùÁ\aÏYmÞP!\x10\x1dÖÒÙBp±(jÒ¡}{$\x19ÑÌ\aw\aÏ%c\x1d¬\x1dð¶F¿\x0fßË\rYöæl|\x10÷ǯ6Fa\x18@d4F=¯\bfE\x1c\aL\x12å¢eÇx\x06.Þd$õ\x14hBÆÞ\x16Õ\x1f+ ã|=Ï\x12Ë*£PAhGctU¸\x15b¬lX1ZPT BÖÝ\x13µ7. ®$\x06\x03BÀÈÙ£\x04B´80®2Å\x14eO\x04ã1
\x102>ñÆÖ\x01O5syª\v\x05Np\x11\x03\x10\x03´ ÷a
@
TLHy».Í\x01ójºD\x0f Ê\x10«þ\x184O,\x10©¾\0^[\b´\x14.\aÜ)\b~LtÏv Ñ#^Lv@1\bP\b<f"4¢\x14\x03\0p\x06\bfÃÉ£*¶gm\x04Z¢hsõP.ø60<llPóWÀ;ð\x11\r\x1dñWî\x04ìyÌExY\vP\x19>0£H-DÄT¾Ä¡$JR\x02©Be&!dH\x14bBCÊù@ôp¡þ`\0×\x18¼\x10÷ÈjÔ!M\r*eZtX·)Èd¼º\x1c0\x14ë\x17\x12f0ÀÈ\x1cÉòÏÌ86S\aE\x05>#Ü@,3Ü|Ð\0b \x02/2^Â' '\bÌ9\x06µ Á*\x19Kô÷±ó9ÏÂ\bâïa´+êÆñÇ2/#Éd©¯|TýýøåR8u®¢\x16W\b©yA\x1fº í¤TÄÑÕ\x14÷¼ì6kM&z þÌ^[C©9®»ó\x18¸r<}0M gÛ\x1có\x1e\ab\r¯!·¹ìÆ=\x19Ìyö\b=]Ç%p¥Ê±V¥']qÓt)²!1sjv'IèÐôÆ´Ö¤ÆßS\x12é!ÇÁ `Ò-ÚøgÍ&|núÁ\rÊ\x13VÏnõ\x7fKí{.)ü;u"óÐUÓÐ=ê\bQc\a\x01ÇnÕi¾|zM5\x1c\x1e^DÌãlÓG\x16ؤE
í\x7fÎ'¥WD)(ʰáVC¬ÖÎûsrÔmö\x15wQ\x10µ·; \x12\a\x18ãªu·uÇ\x1a!È}b\x0f\x1dó0\x12¤LûÃÛ´³&í\x10É\x01±\v/´Q\x1e3£ºÈË\x0euvÒÝH\Ü\0ü5é¹\0°ç>n¦ÚgT
\f\x17¶Ï.êðL!\x10\x1eW´èòÃõÏvØûax¸bþ{@´ÌÞ±½6Ú^[\vX°\x01Z4? eµ\x03g˵,Æå3^[<#Â\rmøD¡ò8p%ÂtÄâ\x10T;Q\x16¬Ü¶±váw\x06È£\x13dâ*qæqĶ{µÃ\x10+®_+Ñì^´þ
\x1aÝÏlzó\x0eîÝ®J7ç¼z\x1a:Þ¢\x19\x06 \x04ÛÉ\x19- 6\x1cUdÒ¬\x18<Nè-\x0eØë¶ø\x1a8Ód«Mùi,X"¬cJ_¥ÿ\x03K$Ê\x02\x1a\x13$S6+²½,\x03Õ²îÎvV1 (£1$R\x18q0d¸\x04\x18tÑíç(õM\x13{Ô7C±îMz¸!óyÓ»%ïP²Áñ03q.\x18ÇxÒÚ?5>Bý04Â\x1cÊÏÓQñ³Ý\f>3fnbbD0>qÏ\x17û\x1f\rï¿M\x0e£M#dâiL?\vÖRó^kä¥:N;»ÊîÞ"]KL£xv*\x06ù>$\x1a× Õû`wÞ¤!\x10+I0\x01)ϵQÔ \x05\x1f'<>Øë\x12¯°¸h_'\x17Î g£D\x15_ÅÍ7;»wI·9\r4£ÝÛ1ë&ëS2£\x18oHã^[Ô¸¹g\x04¾±´\x06M`Ñ\rÑ\rÓ4Î7ECK¹\x1cë>ÙcìÚ\x1d®\x1e\x1f ±\b\b\x10l\x14Q\b\x114ód=.Hqc¼ :â(\x15\x10.ø\x10¢ÄåÀSq\0¼\x03êp^æ&DÖ±Ïlá(¬!\f
C\x12\x064Æ«\0ÏÍÁÐ:Éè"°Ëâ\x02@\0 \aèõª§n95\x02\x01÷<L\a:Ðð¤Cñ»g\x06R [«\x1dÝv¸:κ¢Ò4wZΨÛrÑb
ùsOâ@Ãó§áFý©M¤zãòHñ è²5\x17àÇ\a8ðÌ\x1df\x15ùc% »ì¢ìÃA\x0fNc¿',\0Ðò/èf\x03jS\x0fñA£{y\x15l&²\x15RLHõAæÐ\x15AïÚàØ\x1f\x7fÞi¡\x1f¾
Rg(\x18/~ötpù-tqÁIÖ&r9Py»S\x19óN \x12\x0fÂAÿ\®äî¶u,C¨ªÏò
G?[L\x18Æ^[Ï*;¼¡â¸'}Ã!U\b÷yíP\aá#\x12\x10g'¥ÅÙ\x01Mà×\x10nÉ
í\x0e>ïÇÞ-\x02\býo\x03¦ ª¦f ²Lí,\x10â(\x184\x03×cÞî 0\x1cH4ýù¤kHÞµ\x11½\fÛÈl?g\x06n\x1d\vÅ{4\x05ø\x0eâá\x18¡\f\x02ùü¦ä)¤ê0¡4
ÖÕµ%\vØh'FëÖ*Q0\x1e²w'yÎ\ab^[{ ¾Î\x1ab«ãã\x12ôTAr\x13Í\x05\x1a`ú1s^[aóñ\x11sA ͨ\x11\x\x1e³\x13Pà4QÜÈüÌÕ!½Ç¥!àMßdÇ| ü<´IÕ:ªªªÔd\x1d¤\x10Oò\WËÈô\vÕÖ@cñ\x13p^[ný3ü\x7f\b»V0;+\x16ô úb®pMF\x0f/£ªÅr\x1a\x1d
¨ôsÔä^Ö)m)Wí¡¥ìh10ûì]F¼4nlÒ~BôhÈ\x18¢W©eÉ¿\vKgì£\x1fG\x03/¼ÎÆQ#\x7f!Qcú4ý ï8ffÐ\x18MÄ Â¹\x1c(û\t\b\x10Q§3±\x0f«p!LHØjQâ¥;Ê\x06-#\b\x15\x1dªÕgbôLé!ÙE:+_^u4¿\x195Ëþ\TÈs\x14\x05\x1f{3\r¾ø£ZvÙRøÚ%\x03@:ÌUa+\x13\x11$×\rÂä/Ãwø `ß*Kr4IYdS Ìô\fѹ®øÎº)\x1d\x13vÖÚO\b©D°Û¢[\x0fn5²n\fr¹\x10\x16Ìo\x13mãÛ\x02\a\x12©bx\x7f\x101v`wáç\r§7±Ý¡#\x03\rÃýø%i4[\x11 *YÍ^£8@§GG\x14±ªx®!¨Ã\x12K&f\x165hè¨Unôöa\x1cÓâiXÂæ*\vx}ÌF¹ye Êá5¢ Í&lÁs6Ü\x0eãëQ'ao\pɸÛêñFÈxá%Ã:tÖüBqjÖÎöp®iK4ÆÇÔ»ñSTæ0Î\x05#HÅ$@hÔ8æ\0\x18\0ùUg.TôÊ\x1cEÏ8k
ÚÆ¶2=k\x1aaÓ²Z
\x15\x15ée@,¼@ëdf&\x14p¯vÌ3]\x14à\x19ÀTèB
"9;JTMÂf\r#ѽ\x0eMö:\0¡û\f±\x14#â>\x02
¿¢\x06!Q½ÈÜÒlÙ;ØÚz\b7¡\x11XáºWxÝÖzsR$(L$\x0epT\x1cQ!ÿ\x0f\x01\x14a \x18\bcg$jÝÁö Ç5Vd'C\x19Iv£^[£Dg8Ø6Û0ÂæFã6Ï??%6µ¼á\x06\rw]ëu¾ª=JÖ!\x16\x1f9`iÌj\a\x11\b^[\x05à\x0e\x0e9 ±1BàÀð`a\x05#r("((¬\x04ÁX\x1d®&È]\x0f¡Qíà7"¡@}$rXæ>2\x1f\¬Juõô\rÀ@üñWNi´^¸
è dr¥[\x01¤Õ\0Úâ\x11\b¯\x164¨b\x03It\x06¹e©°ÓB\x06Ñ`¡\v\x14ÆG\x190EBH!Çé`üØþ¸°`&äÄyáMsÎw^[Ç'8k7¹ÃÓ\x05¶\x1c0¼7±X·Yt\x17n±êîåù½\fÄ,pLËÀ1Â\x06À9P\x03úwfeÞè²Y\x16ÂÎ\x1cQûQ5H-¬ÑV·5r.S¥ðg &D\x12ñ\x1c²*\x12\x04ÈB\x06Ì{r\x1a5wÓüP]£"AÄÑÒ\x11\x16¹Ó¾Ö\x15\x14\x11r´\b$Uá)% J\x19c&µ÷°î0gêäÍ|£êL ·óDDõGú°(ä\x17?\0
)ìäR\aãî02\5&3$~\x14óf^[3%\x18b)îZC
ü¤¨¯Ü$Èe\x02@R¾üaE\x14h\x05Ù¤:F\x14\x10¯ÈÐ\!IJh?M\v\rb¹u@UpÙã\x14e2\v[·\x10\x16âf4MÉpÞV\x03Îw9îyã\x1eOU\x1c-\x18MýMg:3aIºÐü®âhx\x02®c\x02\x1d
\x1d9\x06DÐÚ²\x05N)\x1a²ÖÈØ\x10`\fc\x1aW"Å\x1eB1ÒÊÇ4ZË\rJg\x18^[«U%MY\x12^[\rC\x04Ú5a-W#¬
¶Þåcq!¸[e\x19NE½´]i ô\x15ã\x1ae
êoÚb\0~¹_\x04Fd_D§|&.
¦l\a\b
÷\x0e£Ød÷ç\x1aPù¯\aè´\aâÓ ú¥\x13¯Ç°À \x12\x12A>â\x14ÀÒ>Q\x02\x13!@¥"bBJ$h\x05¤] ô\0õÎí!@WªíM\x188A»W¶zÚ \f\vÅÖ.§D.¤\x02$¤)&\x02©9k¼-\"7"H\x05 M\x12ò\x04\x13¿f«¹¦Ò\x02 iiI¡(Z\x19©"\0÷4\b âÈ´Ö É\x1ald\x1aÉÊ«x8\x1d~öïv\x10\x069¯ºÈ?!-äkLß[#íwÔâÍDeJ\x1d$¤¥gIÒs¬ÖÛÔÀ!\x1cQðÕHã6Q50:3¢\x17¢\x06O\x13\x10ví? ²\aw~\x028\x0f\x06+ñ\x14.wÙ}á³8\x14B\x1cévÄæµÖ{?öõiHpõé¥\x1akìߢ(q\x7f\x10wX#àþ®Z=¤oÞ §PDPìIE\x02B*¼Ù^[%\vÒ¼¹G¤Üõý͹\x01æù´4ùúÛ\aÅÕ\x7fxu\x1eBo:o\x049ô\x19ôr\x7f§Ë{²\x1aJ\x1a\x11:¹\x1fÐV/2\x19L6\x06/²"
"f¢$õéP0;Ð<R \x11®ýÜN/\09ý<\x16Ã\0OË\x0e¿«\x14kÍüÿ;¾\x0fyÎ\x02l>¨4U/Î\x16ÇE\x1d\x1aò\x1eoÊ\x04q!$W\x01¤´9é1×3ä\r¥\x01´é ë¯`\0õ_bH<¤\x11Á!T\x1fI<Üh>SA\x19\x05-\x17¿A¦üAÄ! â\0f\x02/yÎ\x0f\x03ðÎ\x12¯Â|eA>\aêPÊ
`ÈÞD¡ÆqX\x061r\x0fÓä¿ \x7f(%=\x04OèÃË£$ i\v
ÄÈ2Ä\b\x06Bþ<T;Ý^[»Mö¿ß!dG\x14ï\x7f|\x13ËâO³ë|[-¬R\x02\0^[NÆä
¦$\x12\x06,w\x10ô\x02~\x04ÈÓï¸$EwþÏ\a-â°9ùL2\x058a*÷½éêðÔNì\fF32¥þ8×z¦\x13\x06cãÍÔ 2ABÐ1\r5C¬Ç\x19rh \x14ZA¥^[@Á EͤF~bf=Îí;Â\x1eÅ`»mOuÌOo\x04£ïwTH~âT-Ø©¨R#Ác \x02\x1då\x15\x05K 7üD
¼¾ £ADÃ6\x1f^-á½8FÖ+å\x04\x0f÷±UKú\x02Èã\x15r\x13\x05>h\x1a\x03½4¬ì-?(\x06HhA8{î?¢\x01ê0Äõ\a²0ê²Ð\x13Ö\x14É>&lº§ëÎ:\&`kC#ÿC \x10@:J¸@sÜ\x1d7ÐipÁ\03»ní:\x04÷îù\x04à{Ï~úìõ×<òW\x183QDTÅN4\x18?ÆÚNHt¢ax:2mòTF¾O*ÑDjÕ\x14ó@÷TÏ\x12Ç\b$hq;^[\x14saEÔÉ'rH½Üà[ó#¨\x11,èÜbá¶%'ö\x04ø{\FÌF3:ÀÒÆæTvÍÝWÃdµ$8×%µ¨ÛZYT¸qÊ\x19øËàI!1ð5¼Ð\4! \x03\x1a\bÄ\x1c5tÄ\x02q5»{⨣ É\x04>44\x02õñ@s¶àzr\x04.uTt ©³PÌÄÚ\x1d
:±?\x0f¨OÿÜ*\x1f¶\0\a#õW\x0eïz\x1a\x06Q\x05ý\x1eá\x16ÑD!éÉ\x10~á!O\x1dÌu0(RH¢Pk^[
XoV\ÿÃû\x17ó8¹\x14\x0fò\x17rE8PÀOúM
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-10 8:28 [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API Yuval Kashtan
@ 2007-12-10 20:51 ` Blue Swirl
2007-12-11 7:16 ` Yuval Kashtan
2007-12-11 14:53 ` Daniel P. Berrange
1 sibling, 1 reply; 37+ messages in thread
From: Blue Swirl @ 2007-12-10 20:51 UTC (permalink / raw)
To: qemu-devel
On 12/10/07, Yuval Kashtan <yuvalkashtan@gmail.com> wrote:
> Hello All,
> Attached is a proposed patch which adds DBus support to QEMU. DBus is a
> standard message bus for linux
> (http://www.freedesktop.org/wiki/Software/dbus )
> The idea behind this is to allow for external programs such as controlling
> GUI or HyperVisors to communicate and control QEMU, in a standard manner.
> Although it is possible to connect to the monitor, an API is more standard,
> theres no need to parse texts and error messages, no internationalization
> problems and in general is a much better idea.
>
> Implementation:
> This is done by creating a DBus server from QEMU which raise signals and act
> upon methods.
> Methods mainly implement same logic as the current command line options and
> monitor does.
>
> How to use:
> To enable DBus support you'll have to add --enable-dbus when you execure
> configure script.
> Then when you execute QEMU, you'll have to add -dbus-service <service_name>
> where service_name follows the DBus naming convention ( xxx.xxx.xxx....)
> To support QEMU configuration through DBus, you'll also have to add
> -dbus_configuration which will cause QEMU to wait until ConfigDone is called
> through the DBus interface. this allows external programs time to call DBus
> methods starting with Config_ which changes configuration (just as the CLI
> does) thus enabling invocation of QEMU without parameters (beside the DBus
> ones).
> With that, we have implemented a nice python script that reads VM's
> configuration from INI file.
>
> To compile this you will also have to compile the attached freedesktop.org
> dsrv library (it is also attach for those who can't handle GIT) from:
> git://people.freedesktop.org/~shaharf/dsrv
>
> Features:
> Currently support was added to all important CLI configuration and some
> online monitor functions (such as connecting and disconnecting usb devices).
> configuration methods begins with Config_ prefix and monitor ones with
> Monitor_.
> For a complete list you can just execute qemu and connect with dbus-viewer
> to see what is supported.
>
>
> All the dbus handling routines can be found in dbus-monitor.c.
> I have two different implementations of this:
> 1) A single threaded version. which comply to the qemu standard of not
> opening additional threads.
> 2) A multi threaded version which open an additional, single, thread which
> handles all the DBus load. I actually believe this version is better as it
> allows QEMU to continue execution of guest operations even when there are
> DBus methods/signals to handle, whereas in the first option, DBus is
> integrated into QEMU mainloop. Also this makes it possible to monitor even
> during long operations (like monitoring the progress of savevm)
>
>
> Please comment both on the idea of management API and the proposed
> implementation.
>
>
> Attached are:
> RFC-QEMU-Dbus.patch - patch file including all necessary changes to qemu.
> was made against QEMU HEAD as of 23/9 morning.
> RFC-QEMU-Dbus-Interface.xml - the xml description of the DBus interface that
> I suggest.
> dsrv.tar.gz.txt - the dbus server library.
I have no idea if this is useful. I would have tried the patch, but it
does not apply to current CVS. Other comments:
When configure is invoked with --enable-dbus, it should check for DBUS
libraries and abort if not found.
The coding style in monitor-dbus.c is different from what is commonly
used in Qemu. Some long lines could be shortened.
Enabling of DEBUG_ACPI and other ACPI changes are probably not
directly needed so they should be in separate patches.
Only commands are included, how about reading values and statistics?
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-10 20:51 ` Blue Swirl
@ 2007-12-11 7:16 ` Yuval Kashtan
2007-12-11 9:10 ` Fabrice Bellard
2007-12-11 15:44 ` Daniel P. Berrange
0 siblings, 2 replies; 37+ messages in thread
From: Yuval Kashtan @ 2007-12-11 7:16 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 4827 bytes --]
Some answers:
- If there is interest I can re-create the patch so it will work against the
current head. I thought to receive some comments about it first..
- thanks for the styling and configuration remarks, I will certainly fix
these. But before I invest more time in it, I would like to hear what ppl
think in general of management API? How do you like DBus as the
infrastructure for that? and what do you think of the proposed
implementation?
- Currently only commands are implemented (with very few getters), but of
course this can be further extended to include values reading and
statistics.
- This is very useful when you want to manage and control QEMU, for instance
developing a GUI to attach and detach usb devices or controlling more than
one instance of QEMU from a single management point, receiving parameters
externally and more.
On Dec 10, 2007 10:51 PM, Blue Swirl <blauwirbel@gmail.com> wrote:
> On 12/10/07, Yuval Kashtan < yuvalkashtan@gmail.com> wrote:
> > Hello All,
> > Attached is a proposed patch which adds DBus support to QEMU. DBus is a
> > standard message bus for linux
> > ( http://www.freedesktop.org/wiki/Software/dbus )
> > The idea behind this is to allow for external programs such as
> controlling
> > GUI or HyperVisors to communicate and control QEMU, in a standard
> manner.
> > Although it is possible to connect to the monitor, an API is more
> standard,
> > theres no need to parse texts and error messages, no
> internationalization
> > problems and in general is a much better idea.
> >
> > Implementation:
> > This is done by creating a DBus server from QEMU which raise signals and
> act
> > upon methods.
> > Methods mainly implement same logic as the current command line options
> and
> > monitor does.
> >
> > How to use:
> > To enable DBus support you'll have to add --enable-dbus when you execure
>
> > configure script.
> > Then when you execute QEMU, you'll have to add -dbus-service
> <service_name>
> > where service_name follows the DBus naming convention ( xxx.xxx.xxx....)
> > To support QEMU configuration through DBus, you'll also have to add
> > -dbus_configuration which will cause QEMU to wait until ConfigDone is
> called
> > through the DBus interface. this allows external programs time to call
> DBus
> > methods starting with Config_ which changes configuration (just as the
> CLI
> > does) thus enabling invocation of QEMU without parameters (beside the
> DBus
> > ones).
> > With that, we have implemented a nice python script that reads VM's
> > configuration from INI file.
> >
> > To compile this you will also have to compile the attached
> freedesktop.org
> > dsrv library (it is also attach for those who can't handle GIT) from:
> > git://people.freedesktop.org/~shaharf/dsrv
> >
> > Features:
> > Currently support was added to all important CLI configuration and some
> > online monitor functions (such as connecting and disconnecting usb
> devices).
> > configuration methods begins with Config_ prefix and monitor ones with
> > Monitor_.
> > For a complete list you can just execute qemu and connect with
> dbus-viewer
> > to see what is supported.
> >
> >
> > All the dbus handling routines can be found in dbus-monitor.c.
> > I have two different implementations of this:
> > 1) A single threaded version. which comply to the qemu standard of not
> > opening additional threads.
> > 2) A multi threaded version which open an additional, single, thread
> which
> > handles all the DBus load. I actually believe this version is better as
> it
> > allows QEMU to continue execution of guest operations even when there
> are
> > DBus methods/signals to handle, whereas in the first option, DBus is
> > integrated into QEMU mainloop. Also this makes it possible to monitor
> even
> > during long operations (like monitoring the progress of savevm)
> >
> >
> > Please comment both on the idea of management API and the proposed
> > implementation.
> >
> >
> > Attached are:
> > RFC-QEMU-Dbus.patch - patch file including all necessary changes to
> qemu.
> > was made against QEMU HEAD as of 23/9 morning.
> > RFC-QEMU-Dbus-Interface.xml - the xml description of the DBus interface
> that
> > I suggest.
> > dsrv.tar.gz.txt - the dbus server library.
>
> I have no idea if this is useful. I would have tried the patch, but it
> does not apply to current CVS. Other comments:
>
> When configure is invoked with --enable-dbus, it should check for DBUS
> libraries and abort if not found.
>
> The coding style in monitor-dbus.c is different from what is commonly
> used in Qemu. Some long lines could be shortened.
>
> Enabling of DEBUG_ACPI and other ACPI changes are probably not
> directly needed so they should be in separate patches.
>
> Only commands are included, how about reading values and statistics?
>
>
>
--
Sincerly,
Yuval Kashtan
[-- Attachment #2: Type: text/html, Size: 5638 bytes --]
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 7:16 ` Yuval Kashtan
@ 2007-12-11 9:10 ` Fabrice Bellard
2007-12-11 9:23 ` Laurent Vivier
2007-12-11 11:05 ` Avi Kivity
2007-12-11 15:44 ` Daniel P. Berrange
1 sibling, 2 replies; 37+ messages in thread
From: Fabrice Bellard @ 2007-12-11 9:10 UTC (permalink / raw)
To: qemu-devel
Hi,
At this point I am not interested in integrating it into QEMU as it is
one more API level to maintain in addition to the command line monitor.
However, I can change my mind if several projects insists to have a
similar interface.
Regards,
Fabrice.
Yuval Kashtan wrote:
> Some answers:
> - If there is interest I can re-create the patch so it will work against
> the current head. I thought to receive some comments about it first..
> - thanks for the styling and configuration remarks, I will certainly fix
> these. But before I invest more time in it, I would like to hear what
> ppl think in general of management API? How do you like DBus as the
> infrastructure for that? and what do you think of the proposed
> implementation?
> - Currently only commands are implemented (with very few getters), but
> of course this can be further extended to include values reading and
> statistics.
> - This is very useful when you want to manage and control QEMU, for
> instance developing a GUI to attach and detach usb devices or
> controlling more than one instance of QEMU from a single management
> point, receiving parameters externally and more.
>
>
> On Dec 10, 2007 10:51 PM, Blue Swirl <blauwirbel@gmail.com
> <mailto:blauwirbel@gmail.com>> wrote:
>
> On 12/10/07, Yuval Kashtan < yuvalkashtan@gmail.com
> <mailto:yuvalkashtan@gmail.com>> wrote:
> > Hello All,
> > Attached is a proposed patch which adds DBus support to QEMU.
> DBus is a
> > standard message bus for linux
> > ( http://www.freedesktop.org/wiki/Software/dbus )
> > The idea behind this is to allow for external programs such as
> controlling
> > GUI or HyperVisors to communicate and control QEMU, in a standard
> manner.
> > Although it is possible to connect to the monitor, an API is more
> standard,
> > theres no need to parse texts and error messages, no
> internationalization
> > problems and in general is a much better idea.
> >
> > Implementation:
> > This is done by creating a DBus server from QEMU which raise
> signals and act
> > upon methods.
> > Methods mainly implement same logic as the current command line
> options and
> > monitor does.
> >
> > How to use:
> > To enable DBus support you'll have to add --enable-dbus when you
> execure
> > configure script.
> > Then when you execute QEMU, you'll have to add -dbus-service
> <service_name>
> > where service_name follows the DBus naming convention (
> xxx.xxx.xxx....)
> > To support QEMU configuration through DBus, you'll also have to add
> > -dbus_configuration which will cause QEMU to wait until
> ConfigDone is called
> > through the DBus interface. this allows external programs time to
> call DBus
> > methods starting with Config_ which changes configuration (just
> as the CLI
> > does) thus enabling invocation of QEMU without parameters (beside
> the DBus
> > ones).
> > With that, we have implemented a nice python script that reads VM's
> > configuration from INI file.
> >
> > To compile this you will also have to compile the attached
> freedesktop.org <http://freedesktop.org>
> > dsrv library (it is also attach for those who can't handle GIT) from:
> > git://people.freedesktop.org/~shaharf/dsrv
> >
> > Features:
> > Currently support was added to all important CLI configuration
> and some
> > online monitor functions (such as connecting and disconnecting
> usb devices).
> > configuration methods begins with Config_ prefix and monitor ones
> with
> > Monitor_.
> > For a complete list you can just execute qemu and connect with
> dbus-viewer
> > to see what is supported.
> >
> >
> > All the dbus handling routines can be found in dbus-monitor.c.
> > I have two different implementations of this:
> > 1) A single threaded version. which comply to the qemu standard
> of not
> > opening additional threads.
> > 2) A multi threaded version which open an additional, single,
> thread which
> > handles all the DBus load. I actually believe this version is
> better as it
> > allows QEMU to continue execution of guest operations even when
> there are
> > DBus methods/signals to handle, whereas in the first option, DBus is
> > integrated into QEMU mainloop. Also this makes it possible to
> monitor even
> > during long operations (like monitoring the progress of savevm)
> >
> >
> > Please comment both on the idea of management API and the proposed
> > implementation.
> >
> >
> > Attached are:
> > RFC-QEMU-Dbus.patch - patch file including all necessary changes
> to qemu.
> > was made against QEMU HEAD as of 23/9 morning.
> > RFC-QEMU-Dbus-Interface.xml - the xml description of the DBus
> interface that
> > I suggest.
> > dsrv.tar.gz.txt - the dbus server library.
>
> I have no idea if this is useful. I would have tried the patch, but it
> does not apply to current CVS. Other comments:
>
> When configure is invoked with --enable-dbus, it should check for DBUS
> libraries and abort if not found.
>
> The coding style in monitor-dbus.c is different from what is commonly
> used in Qemu. Some long lines could be shortened.
>
> Enabling of DEBUG_ACPI and other ACPI changes are probably not
> directly needed so they should be in separate patches.
>
> Only commands are included, how about reading values and statistics?
>
>
>
>
>
> --
> Sincerly,
> Yuval Kashtan
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 9:10 ` Fabrice Bellard
@ 2007-12-11 9:23 ` Laurent Vivier
2007-12-11 10:06 ` Brad Campbell
` (3 more replies)
2007-12-11 11:05 ` Avi Kivity
1 sibling, 4 replies; 37+ messages in thread
From: Laurent Vivier @ 2007-12-11 9:23 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 749 bytes --]
Le mardi 11 décembre 2007 à 10:10 +0100, Fabrice Bellard a écrit :
> Hi,
Hi,
> At this point I am not interested in integrating it into QEMU as it is
> one more API level to maintain in addition to the command line monitor.
> However, I can change my mind if several projects insists to have a
> similar interface.
perhaps the DBUS interface can replace the command line monitor ?
We have just to move the command line interface to a client speaking to
qemu through the DBUS interface.
I guess Yuval will be very happy to make this work :-D
Regards,
laurent
--
------------- Laurent.Vivier@bull.net --------------
"Any sufficiently advanced technology is
indistinguishable from magic." - Arthur C. Clarke
[-- Attachment #2: Ceci est une partie de message numériquement signée --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 9:23 ` Laurent Vivier
@ 2007-12-11 10:06 ` Brad Campbell
2007-12-11 10:07 ` Dor Laor
` (2 subsequent siblings)
3 siblings, 0 replies; 37+ messages in thread
From: Brad Campbell @ 2007-12-11 10:06 UTC (permalink / raw)
To: qemu-devel
Laurent Vivier wrote:
> Le mardi 11 décembre 2007 à 10:10 +0100, Fabrice Bellard a écrit :
>> Hi,
>
> Hi,
>
>> At this point I am not interested in integrating it into QEMU as it is
>> one more API level to maintain in addition to the command line monitor.
>> However, I can change my mind if several projects insists to have a
>> similar interface.
>
> perhaps the DBUS interface can replace the command line monitor ?
> We have just to move the command line interface to a client speaking to
> qemu through the DBUS interface.
>
Nooooooooooooooooooooooooooooo!!!!!
The command line monitor is one of QEMU's greatest strengths! Don't replace it and for the love of
Pete, don't force another library dependency on us!
Add an optional interface, sure.. but don't go making it mandatory.. pretty please with sugar!
--
"Human beings, who are almost unique in having the ability
to learn from the experience of others, are also remarkable
for their apparent disinclination to do so." -- Douglas Adams
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 9:23 ` Laurent Vivier
2007-12-11 10:06 ` Brad Campbell
@ 2007-12-11 10:07 ` Dor Laor
2007-12-11 14:51 ` Anthony Liguori
2007-12-11 10:20 ` Andreas Färber
2007-12-11 10:21 ` Heikki Lindholm
3 siblings, 1 reply; 37+ messages in thread
From: Dor Laor @ 2007-12-11 10:07 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1635 bytes --]
Laurent Vivier wrote:
> Le mardi 11 décembre 2007 à 10:10 +0100, Fabrice Bellard a écrit :
>
>> Hi,
>>
>
> Hi,
>
>
>> At this point I am not interested in integrating it into QEMU as it is
>> one more API level to maintain in addition to the command line monitor.
>> However, I can change my mind if several projects insists to have a
>> similar interface.
>>
>
> perhaps the DBUS interface can replace the command line monitor ?
> We have just to move the command line interface to a client speaking to
> qemu through the DBUS interface.
>
>
This is a valid option but the problem is that local user will have to
use another tool (client) to
send commands. Another option is to have a common backend with machine &
user interfaces.
For example, if we use dbus as the backend, monitor commands will just
be translated into dbus.
The opposite option is also valid.
Anyway, the motivation behind a new interface is that the monitor
interface is not good enough for automation:
There are not return status for commands, no option for async
notifications, no option for parallel actions in case
a command takes long time to complete (like snapshot).
So we either a new interface is added or the existing one will be enhanced.
Since Qemu/KVM will be used in production its highly important to have a
reliable channel to connects with mgmt daemons.
Dbus is a common practice for communication and used in Linux, libvirt,
etc. The question is whether to add a dbus server to Qemu or
a client is sufficient.
Regards,
Dor.
> I guess Yuval will be very happy to make this work :-D
>
> Regards,
> laurent
>
[-- Attachment #2: Type: text/html, Size: 2263 bytes --]
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 9:23 ` Laurent Vivier
2007-12-11 10:06 ` Brad Campbell
2007-12-11 10:07 ` Dor Laor
@ 2007-12-11 10:20 ` Andreas Färber
2007-12-11 10:29 ` Laurent Vivier
2007-12-11 10:21 ` Heikki Lindholm
3 siblings, 1 reply; 37+ messages in thread
From: Andreas Färber @ 2007-12-11 10:20 UTC (permalink / raw)
To: qemu-devel
Am 11.12.2007 um 10:23 schrieb Laurent Vivier:
> perhaps the DBUS interface can replace the command line monitor ?
> We have just to move the command line interface to a client speaking
> to
> qemu through the DBUS interface.
That would work for few platforms only!
Andreas
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 9:23 ` Laurent Vivier
` (2 preceding siblings ...)
2007-12-11 10:20 ` Andreas Färber
@ 2007-12-11 10:21 ` Heikki Lindholm
3 siblings, 0 replies; 37+ messages in thread
From: Heikki Lindholm @ 2007-12-11 10:21 UTC (permalink / raw)
To: qemu-devel
Laurent Vivier kirjoitti:
> Le mardi 11 décembre 2007 à 10:10 +0100, Fabrice Bellard a écrit :
>> Hi,
>
> Hi,
>
>> At this point I am not interested in integrating it into QEMU as it is
>> one more API level to maintain in addition to the command line monitor.
>> However, I can change my mind if several projects insists to have a
>> similar interface.
>
> perhaps the DBUS interface can replace the command line monitor ?
> We have just to move the command line interface to a client speaking to
> qemu through the DBUS interface.
That would pretty much ruin the Mac OS X port and maybe others that
haven't got dbus in a "default" installation.
-- Heikki Lindholm
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 10:20 ` Andreas Färber
@ 2007-12-11 10:29 ` Laurent Vivier
2007-12-11 10:50 ` Andreas Färber
0 siblings, 1 reply; 37+ messages in thread
From: Laurent Vivier @ 2007-12-11 10:29 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 657 bytes --]
Le mardi 11 décembre 2007 à 11:20 +0100, Andreas Färber a écrit :
> Am 11.12.2007 um 10:23 schrieb Laurent Vivier:
>
> > perhaps the DBUS interface can replace the command line monitor ?
> > We have just to move the command line interface to a client speaking
> > to
> > qemu through the DBUS interface.
>
> That would work for few platforms only!
Linux, windows, freebsd, netbsd, macos...
And all platforms with a working GNOME (Solaris, HPUX, AIX, I guess too)
Laurent
--
------------- Laurent.Vivier@bull.net --------------
"Any sufficiently advanced technology is
indistinguishable from magic." - Arthur C. Clarke
[-- Attachment #2: Ceci est une partie de message numériquement signée --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 10:29 ` Laurent Vivier
@ 2007-12-11 10:50 ` Andreas Färber
0 siblings, 0 replies; 37+ messages in thread
From: Andreas Färber @ 2007-12-11 10:50 UTC (permalink / raw)
To: qemu-devel
Am 11.12.2007 um 11:29 schrieb Laurent Vivier:
> Le mardi 11 décembre 2007 à 11:20 +0100, Andreas Färber a écrit :
>> Am 11.12.2007 um 10:23 schrieb Laurent Vivier:
>>
>>> perhaps the DBUS interface can replace the command line monitor ?
>>> We have just to move the command line interface to a client speaking
>>> to
>>> qemu through the DBUS interface.
>>
>> That would work for few platforms only!
>
> Linux, windows, freebsd, netbsd, macos...
> And all platforms with a working GNOME (Solaris, HPUX, AIX, I guess
> too)
(Recent) Linux and Solaris certainly yes.
However, Windows is a fork in progress, and Mac OS X does not ship D-
Bus to my knowledge. Requiring installation of such a system-level
component, likely requiring administrative priviledges, does not seem
like a good idea to me. I am okay with using it where it is available
though.
Andreas
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 9:10 ` Fabrice Bellard
2007-12-11 9:23 ` Laurent Vivier
@ 2007-12-11 11:05 ` Avi Kivity
2007-12-11 14:43 ` Anthony Liguori
2007-12-11 14:56 ` Daniel P. Berrange
1 sibling, 2 replies; 37+ messages in thread
From: Avi Kivity @ 2007-12-11 11:05 UTC (permalink / raw)
To: qemu-devel
Fabrice Bellard wrote:
> Hi,
>
> At this point I am not interested in integrating it into QEMU as it is
> one more API level to maintain in addition to the command line
> monitor. However, I can change my mind if several projects insists to
> have a similar interface.
>
I think that many projects now want to control qemu programatically.
The monitor is not a good interface since it is text-based, hard to
parse, and liable to change without notice when new features are added.
However, I agree that having many similar constructs is not a good
thing, and that we should retain the monitor for non-programmatic control.
What do you say to implementing the qemu interface as a plugin API, and
implementing the monitor on top of this API? e.g.:
qemu loads /usr/local/lib/qemu/libmonitor.so, which uses the API to
export the good old qemu monitor interface. If it finds
/usr/local/lib/qemu/libdbus.so, it loads an additional dbus interface.
If libvirt wants to drop a libvirtapi.so into that directory, it can
control qemu through that.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 11:05 ` Avi Kivity
@ 2007-12-11 14:43 ` Anthony Liguori
2007-12-11 14:56 ` Daniel P. Berrange
1 sibling, 0 replies; 37+ messages in thread
From: Anthony Liguori @ 2007-12-11 14:43 UTC (permalink / raw)
To: qemu-devel
Avi Kivity wrote:
> Fabrice Bellard wrote:
>> Hi,
>>
>> At this point I am not interested in integrating it into QEMU as it
>> is one more API level to maintain in addition to the command line
>> monitor. However, I can change my mind if several projects insists to
>> have a similar interface.
>>
>
> I think that many projects now want to control qemu programatically.
> The monitor is not a good interface since it is text-based, hard to
> parse, and liable to change without notice when new features are
> added. However, I agree that having many similar constructs is not a
> good thing, and that we should retain the monitor for non-programmatic
> control.
>
> What do you say to implementing the qemu interface as a plugin API,
> and implementing the monitor on top of this API? e.g.:
>
> qemu loads /usr/local/lib/qemu/libmonitor.so, which uses the API to
> export the good old qemu monitor interface. If it finds
> /usr/local/lib/qemu/libdbus.so, it loads an additional dbus
> interface. If libvirt wants to drop a libvirtapi.so into that
> directory, it can control qemu through that.
Why not just improve the monitor interface? Half the internet is based
on human-readable text protocols.
I don't think there would be a lot of objections to adding a status
field with each monitor command. It could even be done in a way that
was backwards compatible. For instance:
(qemu) info kqemu
kqemu support is not compiled in
(qemu) verbosity status
(qemu) info kqemu
-38: kqemu support is not compiled in
The other two things to add to the monitor are support for multiple
simultaneous connections and some sort of select command.
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 10:07 ` Dor Laor
@ 2007-12-11 14:51 ` Anthony Liguori
2007-12-11 15:00 ` Daniel P. Berrange
` (2 more replies)
0 siblings, 3 replies; 37+ messages in thread
From: Anthony Liguori @ 2007-12-11 14:51 UTC (permalink / raw)
To: dor.laor, qemu-devel
Dor Laor wrote:
> Laurent Vivier wrote:
>> Le mardi 11 décembre 2007 à 10:10 +0100, Fabrice Bellard a écrit :
>>
>>> Hi,
>>>
>>
>> Hi,
>>
>>
>>> At this point I am not interested in integrating it into QEMU as it is
>>> one more API level to maintain in addition to the command line monitor.
>>> However, I can change my mind if several projects insists to have a
>>> similar interface.
>>>
>>
>> perhaps the DBUS interface can replace the command line monitor ?
>> We have just to move the command line interface to a client speaking to
>> qemu through the DBUS interface.
>>
>>
> This is a valid option but the problem is that local user will have to
> use another tool (client) to
> send commands. Another option is to have a common backend with machine
> & user interfaces.
> For example, if we use dbus as the backend, monitor commands will just
> be translated into dbus.
> The opposite option is also valid.
>
> Anyway, the motivation behind a new interface is that the monitor
> interface is not good enough for automation:
> There are not return status for commands, no option for async
> notifications, no option for parallel actions in case
> a command takes long time to complete (like snapshot).
All of these are valid, and addressable. Return statuses can just be
added to the beginning of the output of each command (similar to how
POP3 works). Async notification can be made to work by add support to
the monitor for a "select" command. Semantically, select would block
the monitor and then output events. For this to work really well, you
would have to support multiple simultaneous monitor sessions. The
parallel options for long running commands is already address in KVM
with the migration command. We just have to rework the snapshotting to
be properly asynchronous.
>
> So we either a new interface is added or the existing one will be
> enhanced.
> Since Qemu/KVM will be used in production its highly important to have
> a reliable channel to connects with mgmt daemons.
> Dbus is a common practice for communication and used in Linux,
> libvirt, etc. The question is whether to add a dbus server to Qemu or
> a client is sufficient.
The main objection I have to dbus is that it's very heavy weight. It
implies a rather fat infrastructure and it not very suitable for
embedding. QEMU has very few dependencies and that is a strength ATM.
People interested in embedding QEMU still want a good management
interface so enhancing the monitor seems more preferable to me than
adding a dbus dependency.
Regards,
Anthony Liguori
> Regards,
> Dor.
>> I guess Yuval will be very happy to make this work :-D
>>
>> Regards,
>> laurent
>>
>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-10 8:28 [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API Yuval Kashtan
2007-12-10 20:51 ` Blue Swirl
@ 2007-12-11 14:53 ` Daniel P. Berrange
1 sibling, 0 replies; 37+ messages in thread
From: Daniel P. Berrange @ 2007-12-11 14:53 UTC (permalink / raw)
To: qemu-devel
On Mon, Dec 10, 2007 at 10:28:01AM +0200, Yuval Kashtan wrote:
> Hello All,
> Attached is a proposed patch which adds DBus support to QEMU. DBus is a
> standard message bus for linux (
> http://www.freedesktop.org/wiki/Software/dbus )
> The idea behind this is to allow for external programs such as controlling
> GUI or HyperVisors to communicate and control QEMU, in a standard manner.
> Although it is possible to connect to the monitor, an API is more standard,
> theres no need to parse texts and error messages, no internationalization
> problems and in general is a much better idea.
>
> Implementation:
> This is done by creating a DBus server from QEMU which raise signals and act
> upon methods.
> Methods mainly implement same logic as the current command line options and
> monitor does.
>
> How to use:
> To enable DBus support you'll have to add --enable-dbus when you execure
> configure script.
> Then when you execute QEMU, you'll have to add -dbus-service <service_name>
> where service_name follows the DBus naming convention ( xxx.xxx.xxx....)
> To support QEMU configuration through DBus, you'll also have to add
> -dbus_configuration which will cause QEMU to wait until ConfigDone is called
> through the DBus interface. this allows external programs time to call DBus
> methods starting with Config_ which changes configuration (just as the CLI
> does) thus enabling invocation of QEMU without parameters (beside the DBus
> ones).
> With that, we have implemented a nice python script that reads VM's
> configuration from INI file.
Frankly this is complete & utter overkill. QEMU needs a configuration file
for machines, but writing a configuration file in an external app and then
sending that over DBus to QEMU is just insane, when QEMU can simply implement
a config file directly. Spawning QEMU then just becomes 'qemu -config foo.cfg'
instead of a mass of DBus calls. Having QEMU do the config file directly
is also portable to all operating systems and simpler to maintain, and easier
to deploy since it does not mandate a depedancy on a message bus.
> Currently support was added to all important CLI configuration and some
> online monitor functions (such as connecting and disconnecting usb devices).
>
> configuration methods begins with Config_ prefix and monitor ones with
> Monitor_.
> For a complete list you can just execute qemu and connect with dbus-viewer
> to see what is supported.
The style of the DBus API does not make any sense & does not follow the common
recommended approach for dbus services.
The idea of well-known bus names is that they are well-known. Passing in the
DBus well-known name as a --service command line arg is non-sensical because
then it ceases to be well-known since it can change at the whim of the app /
admin running QEMU.
Simply exporting a single object having populating that with a flat set of
methods mapping 1-1 onto the monitor commands is a bad idea. THis has been
done before and is very much unliked & discouraged (eg the Skype dbus control
API which maps DBus methods straight onto the SKype monitor). The idea with
DBus is to provide a tree of objects mapping to objects managed within the
application, and then provide contextually relevant methods.
So for a virtual machine management application you might have a main manager
object (eg '/qemu/Manager') which provides a way to list virtual machines. Each
virtual machine might then be its own object (eg '/qemu/Machines/<name>'). From
a machine one might have methods to list devices, and add & remove devices. Each
device though would be an object '/qemu/Machines/<name>/Devices/<device>'. The
device objects would implement different interfaces depending on the type of
device being managed. eg, you might have a qemu.Device.Disk interface, a
qemu.Device.USB interface, etc, etc, and each interface would have methods
relevant to that type of device.
Which dovetails into the next point - having a DBus API for a single VM is not
really much use. To be generally useful it needs to have a single DBus service
to control all virtual machines (ie QEMU instances). This implies that any DBus
service doesn't belong in the QEMU process itself.
You're now back to square one - the DBus control service needs to spawn QEMU
instances and talk to the QEMU monitor.
IMHO, the entire idea of bolting DBus into QEMU to provide a control API is
just fundamentally flawed.
Looking at what you're trying to address I see two core problems
- Interacting with QEMU at runtime to change various configs
- Configuring QEMU at startup
For the first, we currently have the monitor. As you noted this is hard to
interact with programatically since it involves parsing & formating strings.
The way to deal with this problem is to provide a 'libqemumonitor.so' which
exposes a formal C api for the various runtime control needs. Internally
this library would talk to the monitor. This ensures that all the string
parsing & formatting is isolated in a single source, trivially usable by any
application. Such a library would be easily cross-OS portable and not impose
unneccessary infrastructure on applications using it.
For the second problem of configuring QEMU, we're back at the often raised
point of QEMU needing a configuration file so applications don't need to build
up giant command line args. Once QEMU had a configuration file, one might
want to provide a library API 'libqemuconfig.so' to let both QEMU itself, and
applications using QEMU read and write the config files with well define APIs.
Again this is portable and does not impose unneccessary infrastructure.
One might even combine the libqemuconfig & libqemumonitor into a single
general purpose libqemucontrol.so library for apps to use.
> All the dbus handling routines can be found in dbus-monitor.c.
> I have two different implementations of this:
> 1) A single threaded version. which comply to the qemu standard of not
> opening additional threads.
> 2) A multi threaded version which open an additional, single, thread which
> handles all the DBus load. I actually believe this version is better as it
> allows QEMU to continue execution of guest operations even when there are
> DBus methods/signals to handle, whereas in the first option, DBus is
> integrated into QEMU mainloop. Also this makes it possible to monitor even
> during long operations (like monitoring the progress of savevm)
The multi-threaded version will be very hard todo safely. Any monitor command
would need to lock any data structures it touched from access by the main QEMU
thread to avoid data integrity issues. Likewise operations in the main thread
would need to lock data structures against the monitor. So you don't really
solve the problem you think you do.
This question of single vs multi threaded again demonstrates to me that embedding
DBus in QEMU is the wrong solution. If there is a need for a DBus control API
for QEMU, it needs to be higher up the stack, in a separate QEMU management
service independant of the main QEMU emulator processses. I've written such a
DBus api in the past - see the 'perl-QEMU-Manager' RPM here which provides a
DBus API for qemu written in Perl, and the 'qemu-admin' app which provides a
python GUI using the DBus API:
http://people.redhat.com/berrange/olpc/sdk/SRPMS/
Since writing that code though, I came to the conclusion the idea was flawed in
many ways. Using DBus was one flaw. Targetting only QEMU was the second. Instead
I now work on libvirt which provides a formal C API for controlling virtual machines,
one which is able to support QEMU, Xen, KVM, etc, etc. So any GUI management app
can work with any virtualization technology.
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 11:05 ` Avi Kivity
2007-12-11 14:43 ` Anthony Liguori
@ 2007-12-11 14:56 ` Daniel P. Berrange
2007-12-11 15:57 ` Avi Kivity
1 sibling, 1 reply; 37+ messages in thread
From: Daniel P. Berrange @ 2007-12-11 14:56 UTC (permalink / raw)
To: qemu-devel
On Tue, Dec 11, 2007 at 01:05:38PM +0200, Avi Kivity wrote:
> Fabrice Bellard wrote:
> >Hi,
> >
> >At this point I am not interested in integrating it into QEMU as it is
> >one more API level to maintain in addition to the command line
> >monitor. However, I can change my mind if several projects insists to
> >have a similar interface.
> >
>
> I think that many projects now want to control qemu programatically.
> The monitor is not a good interface since it is text-based, hard to
> parse, and liable to change without notice when new features are added.
> However, I agree that having many similar constructs is not a good
> thing, and that we should retain the monitor for non-programmatic control.
>
> What do you say to implementing the qemu interface as a plugin API, and
> implementing the monitor on top of this API? e.g.:
>
> qemu loads /usr/local/lib/qemu/libmonitor.so, which uses the API to
> export the good old qemu monitor interface. If it finds
> /usr/local/lib/qemu/libdbus.so, it loads an additional dbus interface.
> If libvirt wants to drop a libvirtapi.so into that directory, it can
> control qemu through that.
To be honest this is overkill. IMHO, there should simply be a client side
'libqemumonitor.so' which provides a formal C API for applications to use.
This C api would then talk to the QEMU monitor, thus isolating all the
string parsing & formatting in one place. Behind the scenes I could imagine
dropping in an alternative QEMU monitor impl which used an XDR serialization
format for the args & reply to avoid the string parsing/formatting, but this
is a minor detail, compared to the big picture, which is that applications
would benefit from a simply C api implementing the monitor commands. I'd
be interested in using such an API in libvirt, since I could remove the
string parsing/formatting code I currently have. Having libvirt drop a
custom .so into the QEMU process just feels horribly wrong.
Regards,
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 14:51 ` Anthony Liguori
@ 2007-12-11 15:00 ` Daniel P. Berrange
2007-12-11 15:21 ` Yuval Kashtan
2007-12-11 15:02 ` Daniel P. Berrange
2007-12-11 15:17 ` Jean-Christian de Rivaz
2 siblings, 1 reply; 37+ messages in thread
From: Daniel P. Berrange @ 2007-12-11 15:00 UTC (permalink / raw)
To: qemu-devel
On Tue, Dec 11, 2007 at 08:51:32AM -0600, Anthony Liguori wrote:
> Dor Laor wrote:
> >Laurent Vivier wrote:
> >>Le mardi 11 décembre 2007 à 10:10 +0100, Fabrice Bellard a écrit :
> >>
> >>>Hi,
> >>>
> >>
> >>Hi,
> >>
> >>
> >>>At this point I am not interested in integrating it into QEMU as it is
> >>>one more API level to maintain in addition to the command line monitor.
> >>>However, I can change my mind if several projects insists to have a
> >>>similar interface.
> >>>
> >>
> >>perhaps the DBUS interface can replace the command line monitor ?
> >>We have just to move the command line interface to a client speaking to
> >>qemu through the DBUS interface.
> >>
> >>
> >This is a valid option but the problem is that local user will have to
> >use another tool (client) to
> >send commands. Another option is to have a common backend with machine
> >& user interfaces.
> >For example, if we use dbus as the backend, monitor commands will just
> >be translated into dbus.
> >The opposite option is also valid.
> >
> >Anyway, the motivation behind a new interface is that the monitor
> >interface is not good enough for automation:
> >There are not return status for commands, no option for async
> >notifications, no option for parallel actions in case
> >a command takes long time to complete (like snapshot).
>
> All of these are valid, and addressable. Return statuses can just be
> added to the beginning of the output of each command (similar to how
> POP3 works). Async notification can be made to work by add support to
> the monitor for a "select" command. Semantically, select would block
> the monitor and then output events. For this to work really well, you
> would have to support multiple simultaneous monitor sessions. The
> parallel options for long running commands is already address in KVM
> with the migration command. We just have to rework the snapshotting to
> be properly asynchronous.
>
> >
> >So we either a new interface is added or the existing one will be
> >enhanced.
> >Since Qemu/KVM will be used in production its highly important to have
> >a reliable channel to connects with mgmt daemons.
> >Dbus is a common practice for communication and used in Linux,
> >libvirt, etc. The question is whether to add a dbus server to Qemu or
> >a client is sufficient.
>
> The main objection I have to dbus is that it's very heavy weight. It
> implies a rather fat infrastructure and it not very suitable for
> embedding. QEMU has very few dependencies and that is a strength ATM.
> People interested in embedding QEMU still want a good management
> interface so enhancing the monitor seems more preferable to me than
> adding a dbus dependency.
It is also not so easily portable to other OS like Windows & Mac OS, who
will still be lacking a decent control API. As I mentioned in my other
thread, embedding a DBus in each individual QEMU process is not the right
way to write DBus services either. If you want DBus (which is questionable
in itself), then you want to have a single service which manages all a QEMU
VMs. This mandates that the DBus service be outside the context of the QEMU
process itself.
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 14:51 ` Anthony Liguori
2007-12-11 15:00 ` Daniel P. Berrange
@ 2007-12-11 15:02 ` Daniel P. Berrange
2007-12-11 15:15 ` Anthony Liguori
2007-12-11 15:17 ` Jean-Christian de Rivaz
2 siblings, 1 reply; 37+ messages in thread
From: Daniel P. Berrange @ 2007-12-11 15:02 UTC (permalink / raw)
To: qemu-devel
On Tue, Dec 11, 2007 at 08:51:32AM -0600, Anthony Liguori wrote:
> Dor Laor wrote:
> >Laurent Vivier wrote:
> >>Le mardi 11 décembre 2007 à 10:10 +0100, Fabrice Bellard a écrit :
> >>
> >>>Hi,
> >>>
> >>
> >>Hi,
> >>
> >>
> >>>At this point I am not interested in integrating it into QEMU as it is
> >>>one more API level to maintain in addition to the command line monitor.
> >>>However, I can change my mind if several projects insists to have a
> >>>similar interface.
> >>>
> >>
> >>perhaps the DBUS interface can replace the command line monitor ?
> >>We have just to move the command line interface to a client speaking to
> >>qemu through the DBUS interface.
> >>
> >>
> >This is a valid option but the problem is that local user will have to
> >use another tool (client) to
> >send commands. Another option is to have a common backend with machine
> >& user interfaces.
> >For example, if we use dbus as the backend, monitor commands will just
> >be translated into dbus.
> >The opposite option is also valid.
> >
> >Anyway, the motivation behind a new interface is that the monitor
> >interface is not good enough for automation:
> >There are not return status for commands, no option for async
> >notifications, no option for parallel actions in case
> >a command takes long time to complete (like snapshot).
>
> All of these are valid, and addressable. Return statuses can just be
> added to the beginning of the output of each command (similar to how
> POP3 works). Async notification can be made to work by add support to
> the monitor for a "select" command. Semantically, select would block
> the monitor and then output events. For this to work really well, you
> would have to support multiple simultaneous monitor sessions. The
> parallel options for long running commands is already address in KVM
> with the migration command. We just have to rework the snapshotting to
> be properly asynchronous.
Or have 2 monitor interaction modes. One mode uses the command line style
suitable for people / scripting languages. The other umode ses a binary XDR
protocol for serializing the args & returns values for formal control
APIs to use in a easy manner. It ought to be reasonably straightforward to
add a binary serialization format for all existing commands
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:02 ` Daniel P. Berrange
@ 2007-12-11 15:15 ` Anthony Liguori
2007-12-11 15:40 ` Richard W.M. Jones
0 siblings, 1 reply; 37+ messages in thread
From: Anthony Liguori @ 2007-12-11 15:15 UTC (permalink / raw)
To: Daniel P. Berrange, qemu-devel
Daniel P. Berrange wrote:
> On Tue, Dec 11, 2007 at 08:51:32AM -0600, Anthony Liguori wrote:
>
>> Dor Laor wrote:
>>
>>> Laurent Vivier wrote:
>>>
>>>> Le mardi 11 décembre 2007 à 10:10 +0100, Fabrice Bellard a écrit :
>>>>
>>>>
>>>>> Hi,
>>>>>
>>>>>
>>>> Hi,
>>>>
>>>>
>>>>
>>>>> At this point I am not interested in integrating it into QEMU as it is
>>>>> one more API level to maintain in addition to the command line monitor.
>>>>> However, I can change my mind if several projects insists to have a
>>>>> similar interface.
>>>>>
>>>>>
>>>> perhaps the DBUS interface can replace the command line monitor ?
>>>> We have just to move the command line interface to a client speaking to
>>>> qemu through the DBUS interface.
>>>>
>>>>
>>>>
>>> This is a valid option but the problem is that local user will have to
>>> use another tool (client) to
>>> send commands. Another option is to have a common backend with machine
>>> & user interfaces.
>>> For example, if we use dbus as the backend, monitor commands will just
>>> be translated into dbus.
>>> The opposite option is also valid.
>>>
>>> Anyway, the motivation behind a new interface is that the monitor
>>> interface is not good enough for automation:
>>> There are not return status for commands, no option for async
>>> notifications, no option for parallel actions in case
>>> a command takes long time to complete (like snapshot).
>>>
>> All of these are valid, and addressable. Return statuses can just be
>> added to the beginning of the output of each command (similar to how
>> POP3 works). Async notification can be made to work by add support to
>> the monitor for a "select" command. Semantically, select would block
>> the monitor and then output events. For this to work really well, you
>> would have to support multiple simultaneous monitor sessions. The
>> parallel options for long running commands is already address in KVM
>> with the migration command. We just have to rework the snapshotting to
>> be properly asynchronous.
>>
>
> Or have 2 monitor interaction modes. One mode uses the command line style
> suitable for people / scripting languages. The other umode ses a binary XDR
> protocol for serializing the args & returns values for formal control
> APIs to use in a easy manner. It ought to be reasonably straightforward to
> add a binary serialization format for all existing commands
>
I don't think binary is inherently easier to parse than text provided
that some thought is put into the format of the textual output.
I think we just want to levels of verbosity.
Regards,
Anthony Liguori
> Dan.
>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 14:51 ` Anthony Liguori
2007-12-11 15:00 ` Daniel P. Berrange
2007-12-11 15:02 ` Daniel P. Berrange
@ 2007-12-11 15:17 ` Jean-Christian de Rivaz
2007-12-11 15:24 ` Daniel P. Berrange
2 siblings, 1 reply; 37+ messages in thread
From: Jean-Christian de Rivaz @ 2007-12-11 15:17 UTC (permalink / raw)
To: qemu-devel, anthony
Anthony Liguori a écrit :
> The main objection I have to dbus is that it's very heavy weight. It
> implies a rather fat infrastructure and it not very suitable for
> embedding. QEMU has very few dependencies and that is a strength ATM.
> People interested in embedding QEMU still want a good management
> interface so enhancing the monitor seems more preferable to me than
> adding a dbus dependency.
I must object again that.
I use D-Bus on a very small processor (Analog Devices Blackfin BF-537)
and it work very well. The library is around 200k on the target: this is
very supportable for embedded device, especially when you take in
account all the simplifications it allow in the code of each
applications. The D-Bus library have very few and simple dependency.
D-Bus is a growing standard for the communication between applications.
I expect that sooner or later, QEMU will be a D-Bus service.
Best regards,
--
Jean-Christian de Rivaz
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:00 ` Daniel P. Berrange
@ 2007-12-11 15:21 ` Yuval Kashtan
2007-12-11 15:31 ` Daniel P. Berrange
2007-12-11 15:36 ` Anthony Liguori
0 siblings, 2 replies; 37+ messages in thread
From: Yuval Kashtan @ 2007-12-11 15:21 UTC (permalink / raw)
To: Daniel P. Berrange, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 5523 bytes --]
As I can see,
There is HUGH interest in management API for QEMU.
seemly, DBus is NOT the right solution for direct integration into QEMU as
it is not cross platform enough, pose extra dependency and (probably) not
suitable for embedded systems.
Keeping only the "old" monitor interface with no formal interface will make
QEMU harder to integrate with as it requires extra work
C API is not a complete solution as it does not define well enough how will
you integrate with QEMU without changing or adding to the source..
But combined with AVI's idea of some plug-in mechanism, which will use this
C API, it sounds like a complete and valid solution.
The monitor should be kept for backward compatibility, human interface and
be implemented on top of that API as well, so there will also be a reference
implementation of how to use the API and create a plug-in.
As of Daniel remarks regarding DBus:
- I actually have a newer version where commands are divided into different
DBus interfaces. So (hopefully) that solves the methods naming problem.
- I had to pass the server name at the CLI, since I was executing multiple
instances of QEMU.. Having an external server, raises again the question of
how will that server communicate with each instance of QEMU?
- It was easier for my project to configure QEMU after it started and not
through a file, that why there is a configuration method for each option. of
course there could also be a bulk method which receive them all or even read
them from a file (and actually with some extra work, many of them could be
made dynamics)
On Dec 11, 2007 5:00 PM, Daniel P. Berrange <berrange@redhat.com> wrote:
> On Tue, Dec 11, 2007 at 08:51:32AM -0600, Anthony Liguori wrote:
> > Dor Laor wrote:
> > >Laurent Vivier wrote:
> > >>Le mardi 11 décembre 2007 à 10:10 +0100, Fabrice Bellard a écrit :
> > >>
> > >>>Hi,
> > >>>
> > >>
> > >>Hi,
> > >>
> > >>
> > >>>At this point I am not interested in integrating it into QEMU as it
> is
> > >>>one more API level to maintain in addition to the command line
> monitor.
> > >>>However, I can change my mind if several projects insists to have a
> > >>>similar interface.
> > >>>
> > >>
> > >>perhaps the DBUS interface can replace the command line monitor ?
> > >>We have just to move the command line interface to a client speaking
> to
> > >>qemu through the DBUS interface.
> > >>
> > >>
> > >This is a valid option but the problem is that local user will have to
> > >use another tool (client) to
> > >send commands. Another option is to have a common backend with machine
> > >& user interfaces.
> > >For example, if we use dbus as the backend, monitor commands will just
> > >be translated into dbus.
> > >The opposite option is also valid.
> > >
> > >Anyway, the motivation behind a new interface is that the monitor
> > >interface is not good enough for automation:
> > >There are not return status for commands, no option for async
> > >notifications, no option for parallel actions in case
> > >a command takes long time to complete (like snapshot).
> >
> > All of these are valid, and addressable. Return statuses can just be
> > added to the beginning of the output of each command (similar to how
> > POP3 works). Async notification can be made to work by add support to
> > the monitor for a "select" command. Semantically, select would block
> > the monitor and then output events. For this to work really well, you
> > would have to support multiple simultaneous monitor sessions. The
> > parallel options for long running commands is already address in KVM
> > with the migration command. We just have to rework the snapshotting to
> > be properly asynchronous.
> >
> > >
> > >So we either a new interface is added or the existing one will be
> > >enhanced.
> > >Since Qemu/KVM will be used in production its highly important to have
> > >a reliable channel to connects with mgmt daemons.
> > >Dbus is a common practice for communication and used in Linux,
> > >libvirt, etc. The question is whether to add a dbus server to Qemu or
> > >a client is sufficient.
> >
> > The main objection I have to dbus is that it's very heavy weight. It
> > implies a rather fat infrastructure and it not very suitable for
> > embedding. QEMU has very few dependencies and that is a strength ATM.
> > People interested in embedding QEMU still want a good management
> > interface so enhancing the monitor seems more preferable to me than
> > adding a dbus dependency.
>
> It is also not so easily portable to other OS like Windows & Mac OS, who
> will still be lacking a decent control API. As I mentioned in my other
> thread, embedding a DBus in each individual QEMU process is not the right
> way to write DBus services either. If you want DBus (which is questionable
> in itself), then you want to have a single service which manages all a
> QEMU
> VMs. This mandates that the DBus service be outside the context of the
> QEMU
> process itself.
>
>
> Dan.
> --
> |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496
> -=|
> |=- Perl modules: http://search.cpan.org/~danberr/<http://search.cpan.org/%7Edanberr/> -=|
> |=- Projects: http://freshmeat.net/~danielpb/<http://freshmeat.net/%7Edanielpb/> -=|
> |=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505
> -=|
>
>
>
--
Sincerly,
Yuval Kashtan
[-- Attachment #2: Type: text/html, Size: 6582 bytes --]
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:17 ` Jean-Christian de Rivaz
@ 2007-12-11 15:24 ` Daniel P. Berrange
0 siblings, 0 replies; 37+ messages in thread
From: Daniel P. Berrange @ 2007-12-11 15:24 UTC (permalink / raw)
To: qemu-devel
On Tue, Dec 11, 2007 at 04:17:51PM +0100, Jean-Christian de Rivaz wrote:
> Anthony Liguori a écrit :
> > The main objection I have to dbus is that it's very heavy weight. It
> >implies a rather fat infrastructure and it not very suitable for
> >embedding. QEMU has very few dependencies and that is a strength ATM.
> >People interested in embedding QEMU still want a good management
> >interface so enhancing the monitor seems more preferable to me than
> >adding a dbus dependency.
>
> I must object again that.
>
> I use D-Bus on a very small processor (Analog Devices Blackfin BF-537)
> and it work very well. The library is around 200k on the target: this is
> very supportable for embedded device, especially when you take in
> account all the simplifications it allow in the code of each
> applications. The D-Bus library have very few and simple dependency.
>
> D-Bus is a growing standard for the communication between applications.
> I expect that sooner or later, QEMU will be a D-Bus service.
A DBus service for controlling QEMU, does not imply that QEMU needs to use
DBus. It is perfectly possible to write DBus services for managing QEMU
outside of the QEMU process. I've written 2 myself - the first exposed a
DBus service for managing a collection of VMs, and communicated with QEMU
via its monitor. The second, simply exposed the libvirt API over DBus
which allows managing of QEMU, Xen, KVM, etc via the same interface.
Embedding DBus within QEMU is flawed because it neccessarily restricts you
to only managing a single VM, and does not provide you any management
capabilities when QEMU is not running.
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:21 ` Yuval Kashtan
@ 2007-12-11 15:31 ` Daniel P. Berrange
2007-12-11 15:36 ` Anthony Liguori
1 sibling, 0 replies; 37+ messages in thread
From: Daniel P. Berrange @ 2007-12-11 15:31 UTC (permalink / raw)
To: Yuval Kashtan; +Cc: qemu-devel
On Tue, Dec 11, 2007 at 05:21:08PM +0200, Yuval Kashtan wrote:
> As I can see,
> There is HUGH interest in management API for QEMU.
> seemly, DBus is NOT the right solution for direct integration into QEMU as
> it is not cross platform enough, pose extra dependency and (probably) not
> suitable for embedded systems.
>
> Keeping only the "old" monitor interface with no formal interface will make
> QEMU harder to integrate with as it requires extra work
The monitor does have an initial barrier to entry, but that can be addressed
by providing a C API which sends & receives monitor commands. This does not
require any intrusive modification of QEMU, at most incremental enhancements
to make the monitor more complete.
> C API is not a complete solution as it does not define well enough how will
> you integrate with QEMU without changing or adding to the source..
> But combined with AVI's idea of some plug-in mechanism, which will use this
> C API, it sounds like a complete and valid solution.
You are now exposing the internals of QEMU as a stable ABI which has to be
maintained indefinittely to avoid breaking these out-of-tree plugins. THis
does not sound like a winning solution since it'll dramatically restrict
the scope of future development of QEMU code.
Regards,
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:21 ` Yuval Kashtan
2007-12-11 15:31 ` Daniel P. Berrange
@ 2007-12-11 15:36 ` Anthony Liguori
2007-12-11 15:59 ` Avi Kivity
1 sibling, 1 reply; 37+ messages in thread
From: Anthony Liguori @ 2007-12-11 15:36 UTC (permalink / raw)
To: qemu-devel
Yuval Kashtan wrote:
> As I can see,
> There is HUGH interest in management API for QEMU.
> seemly, DBus is NOT the right solution for direct integration into
> QEMU as it is not cross platform enough, pose extra dependency and
> (probably) not suitable for embedded systems.
>
> Keeping only the "old" monitor interface with no formal interface will
> make QEMU harder to integrate with as it requires extra work
Why can't we make the monitor interface a "formal" interface?
Regards,
Anthony Liguori
> C API is not a complete solution as it does not define well enough how
> will you integrate with QEMU without changing or adding to the source..
> But combined with AVI's idea of some plug-in mechanism, which will use
> this C API, it sounds like a complete and valid solution.
>
> The monitor should be kept for backward compatibility, human interface
> and be implemented on top of that API as well, so there will also be a
> reference implementation of how to use the API and create a plug-in.
>
>
>
>
> As of Daniel remarks regarding DBus:
> - I actually have a newer version where commands are divided into
> different DBus interfaces. So (hopefully) that solves the methods
> naming problem.
> - I had to pass the server name at the CLI, since I was executing
> multiple instances of QEMU.. Having an external server, raises again
> the question of how will that server communicate with each instance of
> QEMU?
> - It was easier for my project to configure QEMU after it started and
> not through a file, that why there is a configuration method for each
> option. of course there could also be a bulk method which receive them
> all or even read them from a file (and actually with some extra work,
> many of them could be made dynamics)
>
> On Dec 11, 2007 5:00 PM, Daniel P. Berrange <berrange@redhat.com
> <mailto:berrange@redhat.com>> wrote:
>
> On Tue, Dec 11, 2007 at 08:51:32AM -0600, Anthony Liguori wrote:
> > Dor Laor wrote:
> > >Laurent Vivier wrote:
> > >>Le mardi 11 décembre 2007 à 10:10 +0100, Fabrice Bellard a
> écrit :
> > >>
> > >>>Hi,
> > >>>
> > >>
> > >>Hi,
> > >>
> > >>
> > >>>At this point I am not interested in integrating it into QEMU
> as it is
> > >>>one more API level to maintain in addition to the command
> line monitor.
> > >>>However, I can change my mind if several projects insists to
> have a
> > >>>similar interface.
> > >>>
> > >>
> > >>perhaps the DBUS interface can replace the command line monitor ?
> > >>We have just to move the command line interface to a client
> speaking to
> > >>qemu through the DBUS interface.
> > >>
> > >>
> > >This is a valid option but the problem is that local user will
> have to
> > >use another tool (client) to
> > >send commands. Another option is to have a common backend with
> machine
> > >& user interfaces.
> > >For example, if we use dbus as the backend, monitor commands
> will just
> > >be translated into dbus.
> > >The opposite option is also valid.
> > >
> > >Anyway, the motivation behind a new interface is that the monitor
> > >interface is not good enough for automation:
> > >There are not return status for commands, no option for async
> > >notifications, no option for parallel actions in case
> > >a command takes long time to complete (like snapshot).
> >
> > All of these are valid, and addressable. Return statuses can
> just be
> > added to the beginning of the output of each command (similar to how
> > POP3 works). Async notification can be made to work by add
> support to
> > the monitor for a "select" command. Semantically, select would
> block
> > the monitor and then output events. For this to work really
> well, you
> > would have to support multiple simultaneous monitor sessions. The
> > parallel options for long running commands is already address in KVM
> > with the migration command. We just have to rework the
> snapshotting to
> > be properly asynchronous.
> >
> > >
> > >So we either a new interface is added or the existing one will be
> > >enhanced.
> > >Since Qemu/KVM will be used in production its highly important
> to have
> > >a reliable channel to connects with mgmt daemons.
> > >Dbus is a common practice for communication and used in Linux,
> > >libvirt, etc. The question is whether to add a dbus server to
> Qemu or
> > >a client is sufficient.
> >
> > The main objection I have to dbus is that it's very heavy
> weight. It
> > implies a rather fat infrastructure and it not very suitable for
> > embedding. QEMU has very few dependencies and that is a
> strength ATM.
> > People interested in embedding QEMU still want a good management
> > interface so enhancing the monitor seems more preferable to me than
> > adding a dbus dependency.
>
> It is also not so easily portable to other OS like Windows & Mac
> OS, who
> will still be lacking a decent control API. As I mentioned in my other
> thread, embedding a DBus in each individual QEMU process is not
> the right
> way to write DBus services either. If you want DBus (which is
> questionable
> in itself), then you want to have a single service which manages
> all a QEMU
> VMs. This mandates that the DBus service be outside the context of
> the QEMU
> process itself.
>
>
> Dan.
> --
> |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978
> 392 2496 -=|
> |=- Perl modules: http://search.cpan.org/~danberr/
> <http://search.cpan.org/%7Edanberr/> -=|
> |=- Projects: http://freshmeat.net/~danielpb/
> <http://freshmeat.net/%7Edanielpb/> -=|
> |=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742
> 7D3B 9505 -=|
>
>
>
>
>
> --
> Sincerly,
> Yuval Kashtan
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:15 ` Anthony Liguori
@ 2007-12-11 15:40 ` Richard W.M. Jones
2007-12-11 15:48 ` Anthony Liguori
0 siblings, 1 reply; 37+ messages in thread
From: Richard W.M. Jones @ 2007-12-11 15:40 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1921 bytes --]
Anthony Liguori wrote:
> Daniel P. Berrange wrote:
>> Or have 2 monitor interaction modes. One mode uses the command line style
>> suitable for people / scripting languages. The other umode ses a
>> binary XDR
>> protocol for serializing the args & returns values for formal control
>> APIs to use in a easy manner. It ought to be reasonably
>> straightforward to
>> add a binary serialization format for all existing commands
>>
>
> I don't think binary is inherently easier to parse than text provided
> that some thought is put into the format of the textual output.
XDR (aka RFC 1014 & RFC 4506) does let you generate complex interfaces
with relative ease. For example, here's the description of the remote
protocol used by libvirt:
http://git.et.redhat.com/?p=libvirt.git;a=blob;f=qemud/remote_protocol.x;h=d409c74387c2642651896136aba9bc1e2b62b621;hb=HEAD
"Parsing" is done for you by stubs that are generated from the above file.
On the downside it turns out that it's not very well supported under
Windows. For libvirt I had to basically port an XDR implementation by
hand to MinGW and add extra functions from glibc to it.
> I think we just want to levels of verbosity.
This would work too.
On the point of controlling multiple qemu instances on a machine from a
single place: Easiest way to do this would be to direct all the monitor
sockets into a single known directory. Something along the lines of:
qemu -monitor unix:/var/lib/qemu-monitors/`uuidgen`,nowait
A control process can then just keep an eye on entries under that
directory, and (unlike libvirtd) it's robust against the control process
restarting.
Rich.
--
Emerging Technologies, Red Hat - http://et.redhat.com/~rjones/
Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod
Street, Windsor, Berkshire, SL4 1TE, United Kingdom. Registered in
England and Wales under Company Registration No. 03798903
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/x-pkcs7-signature, Size: 3237 bytes --]
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 7:16 ` Yuval Kashtan
2007-12-11 9:10 ` Fabrice Bellard
@ 2007-12-11 15:44 ` Daniel P. Berrange
2007-12-11 16:10 ` Fabrice Bellard
1 sibling, 1 reply; 37+ messages in thread
From: Daniel P. Berrange @ 2007-12-11 15:44 UTC (permalink / raw)
To: qemu-devel
On Tue, Dec 11, 2007 at 09:16:43AM +0200, Yuval Kashtan wrote:
> - This is very useful when you want to manage and control QEMU, for instance
> developing a GUI to attach and detach usb devices or controlling more than
> one instance of QEMU from a single management point, receiving parameters
> externally and more.
This capability is already possible using the monitor API. I've implemented
it in libvirt, and in virt-manager and can easily hotplug/remove USB devices.
So DBus is not required to do this and does not really make it any easier
to use. DBus is very verbose to use from languages like C, so switching from
the monitor to DBus API would not really help simplify my existing code. On
the other hand, having a library providing a simple client side C API to
send & receive monitor commands, would be beneficial
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:40 ` Richard W.M. Jones
@ 2007-12-11 15:48 ` Anthony Liguori
2007-12-11 15:58 ` Daniel P. Berrange
2007-12-11 15:59 ` Dor Laor
0 siblings, 2 replies; 37+ messages in thread
From: Anthony Liguori @ 2007-12-11 15:48 UTC (permalink / raw)
To: qemu-devel
Richard W.M. Jones wrote:
> Anthony Liguori wrote:
>> Daniel P. Berrange wrote:
>>> Or have 2 monitor interaction modes. One mode uses the command line
>>> style
>>> suitable for people / scripting languages. The other umode ses a
>>> binary XDR
>>> protocol for serializing the args & returns values for formal control
>>> APIs to use in a easy manner. It ought to be reasonably
>>> straightforward to
>>> add a binary serialization format for all existing commands
>>>
>>
>> I don't think binary is inherently easier to parse than text provided
>> that some thought is put into the format of the textual output.
>
> XDR (aka RFC 1014 & RFC 4506) does let you generate complex interfaces
> with relative ease. For example, here's the description of the remote
> protocol used by libvirt:
>
> http://git.et.redhat.com/?p=libvirt.git;a=blob;f=qemud/remote_protocol.x;h=d409c74387c2642651896136aba9bc1e2b62b621;hb=HEAD
>
>
> "Parsing" is done for you by stubs that are generated from the above
> file.
>
> On the downside it turns out that it's not very well supported under
> Windows. For libvirt I had to basically port an XDR implementation by
> hand to MinGW and add extra functions from glibc to it.
>
>> I think we just want to levels of verbosity.
>
> This would work too.
>
> On the point of controlling multiple qemu instances on a machine from
> a single place: Easiest way to do this would be to direct all the
> monitor sockets into a single known directory. Something along the
> lines of:
>
> qemu -monitor unix:/var/lib/qemu-monitors/`uuidgen`,nowait
>
> A control process can then just keep an eye on entries under that
> directory, and (unlike libvirtd) it's robust against the control
> process restarting.
Actually, this was the original intention of the -name parameter. What
a management tool would want to do is:
1) if -name is specified by user, generate one with uuidgen
2) pass -name <name> and -pidfile /path/to/well/known/location/name.pid
This will ensure uniqueness of name without requiring the creation tool
to maintain any state (so no daemon is required). Right now, you would
also have to store a monitor socket in that well known path. However,
I'm working on a VNC tunnels patch right now that would allow the
monitor to be tunneled through a VNC session. The idea here is that a
management tool could just store a hint about the VNC location and then
you can get at the rest of the character devices through the VNC session.
Otherwise, you end up with a bunch of temporary sockets for things like
the monitor, serial devices, parallel devices, etc.
Regards,
Anthony Liguori
> Rich.
>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 14:56 ` Daniel P. Berrange
@ 2007-12-11 15:57 ` Avi Kivity
2007-12-11 16:07 ` Richard W.M. Jones
0 siblings, 1 reply; 37+ messages in thread
From: Avi Kivity @ 2007-12-11 15:57 UTC (permalink / raw)
To: Daniel P. Berrange, qemu-devel
Daniel P. Berrange wrote:
>>
>> I think that many projects now want to control qemu programatically.
>> The monitor is not a good interface since it is text-based, hard to
>> parse, and liable to change without notice when new features are added.
>> However, I agree that having many similar constructs is not a good
>> thing, and that we should retain the monitor for non-programmatic control.
>>
>> What do you say to implementing the qemu interface as a plugin API, and
>> implementing the monitor on top of this API? e.g.:
>>
>> qemu loads /usr/local/lib/qemu/libmonitor.so, which uses the API to
>> export the good old qemu monitor interface. If it finds
>> /usr/local/lib/qemu/libdbus.so, it loads an additional dbus interface.
>> If libvirt wants to drop a libvirtapi.so into that directory, it can
>> control qemu through that.
>>
>
> To be honest this is overkill. IMHO, there should simply be a client side
> 'libqemumonitor.so' which provides a formal C API for applications to use.
>
libqemumonitor.so is an excellent idea. perhaps the libvirt code can be
used as a base?
We should also provide bindings to the saner languages that management
apps are typically written in.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:48 ` Anthony Liguori
@ 2007-12-11 15:58 ` Daniel P. Berrange
2007-12-11 16:49 ` Anthony Liguori
2007-12-11 15:59 ` Dor Laor
1 sibling, 1 reply; 37+ messages in thread
From: Daniel P. Berrange @ 2007-12-11 15:58 UTC (permalink / raw)
To: qemu-devel
On Tue, Dec 11, 2007 at 09:48:22AM -0600, Anthony Liguori wrote:
> Richard W.M. Jones wrote:
>
> Actually, this was the original intention of the -name parameter. What
> a management tool would want to do is:
>
> 1) if -name is specified by user, generate one with uuidgen
> 2) pass -name <name> and -pidfile /path/to/well/known/location/name.pid
>
> This will ensure uniqueness of name without requiring the creation tool
> to maintain any state (so no daemon is required). Right now, you would
> also have to store a monitor socket in that well known path. However,
> I'm working on a VNC tunnels patch right now that would allow the
> monitor to be tunneled through a VNC session. The idea here is that a
> management tool could just store a hint about the VNC location and then
> you can get at the rest of the character devices through the VNC session.
>
> Otherwise, you end up with a bunch of temporary sockets for things like
> the monitor, serial devices, parallel devices, etc.
Tunnelling things like the serial devices / parallel devices over VNC
would be very useful, as using a pty/file isn't useful for remote
management. Tunnelling the monitor over VNC is questionable though because
it has very significant security implications - if you can connect to the
VNC server, you essentially own the entire user account that the VM is
running under since the monitor can be used to map arbitrary files into
the guest VM. Now this may be useful in some cases, but for libvirt we
really just want the monitor accessible locally via a well-known UNIX
socket. Also, VNC ports are typically auto-allocated at startup so not
neccessary a good predictable access method.
The reason libvirt use the PTY & direct PID ownership was because we stared
off with QEMU 0.8.0. We should really just mandate use of QEMU 0.9.0 with
libvirt now since its been around quite a while. Then we could just run
with -daemonize, -pidfile and -monitor unix:/well/known/path.
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:48 ` Anthony Liguori
2007-12-11 15:58 ` Daniel P. Berrange
@ 2007-12-11 15:59 ` Dor Laor
1 sibling, 0 replies; 37+ messages in thread
From: Dor Laor @ 2007-12-11 15:59 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 3339 bytes --]
Anthony Liguori wrote:
>
> Richard W.M. Jones wrote:
> > Anthony Liguori wrote:
> >> Daniel P. Berrange wrote:
> >>> Or have 2 monitor interaction modes. One mode uses the command line
> >>> style
> >>> suitable for people / scripting languages. The other umode ses a
> >>> binary XDR
> >>> protocol for serializing the args & returns values for formal control
> >>> APIs to use in a easy manner. It ought to be reasonably
> >>> straightforward to
> >>> add a binary serialization format for all existing commands
> >>>
> >>
> >> I don't think binary is inherently easier to parse than text provided
> >> that some thought is put into the format of the textual output.
> >
> > XDR (aka RFC 1014 & RFC 4506) does let you generate complex interfaces
> > with relative ease. For example, here's the description of the remote
> > protocol used by libvirt:
> >
> >
> http://git.et.redhat.com/?p=libvirt.git;a=blob;f=qemud/remote_protocol.x;h=d409c74387c2642651896136aba9bc1e2b62b621;hb=HEAD
> >
> >
> > "Parsing" is done for you by stubs that are generated from the above
> > file.
> >
> > On the downside it turns out that it's not very well supported under
> > Windows. For libvirt I had to basically port an XDR implementation by
> > hand to MinGW and add extra functions from glibc to it.
> >
> >> I think we just want to levels of verbosity.
> >
> > This would work too.
> >
> > On the point of controlling multiple qemu instances on a machine from
> > a single place: Easiest way to do this would be to direct all the
> > monitor sockets into a single known directory. Something along the
> > lines of:
> >
> > qemu -monitor unix:/var/lib/qemu-monitors/`uuidgen`,nowait
> >
> > A control process can then just keep an eye on entries under that
> > directory, and (unlike libvirtd) it's robust against the control
> > process restarting.
>
> Actually, this was the original intention of the -name parameter. What
> a management tool would want to do is:
>
> 1) if -name is specified by user, generate one with uuidgen
> 2) pass -name <name> and -pidfile /path/to/well/known/location/name.pid
>
> This will ensure uniqueness of name without requiring the creation tool
> to maintain any state (so no daemon is required). Right now, you would
> also have to store a monitor socket in that well known path. However,
> I'm working on a VNC tunnels patch right now that would allow the
> monitor to be tunneled through a VNC session. The idea here is that a
> management tool could just store a hint about the VNC location and then
> you can get at the rest of the character devices through the VNC session.
>
While this is good for home usage, it does not match product needs because
you don't always want to allow the user of the VM to control it. For
example,
the user might hack memory values from the monitor and comprise his
permission
within the guest.
>
> Otherwise, you end up with a bunch of temporary sockets for things like
> the monitor, serial devices, parallel devices, etc.
>
Actually this is what we do in Qumranet to run multiple VMs.
We just need to improve/replace the monitor. Maybe enhancing the current
implementation
as you suggested might be good enough, although library interface might
be cleaner (no ugly return code
for the user).
Thanks,
Dor.
> Regards,
>
> Anthony Liguori
>
> > Rich.
> >
>
>
>
[-- Attachment #2: Type: text/html, Size: 4760 bytes --]
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:36 ` Anthony Liguori
@ 2007-12-11 15:59 ` Avi Kivity
2007-12-11 16:18 ` Paul Brook
0 siblings, 1 reply; 37+ messages in thread
From: Avi Kivity @ 2007-12-11 15:59 UTC (permalink / raw)
To: qemu-devel
Anthony Liguori wrote:
> Yuval Kashtan wrote:
>> As I can see,
>> There is HUGH interest in management API for QEMU.
>> seemly, DBus is NOT the right solution for direct integration into
>> QEMU as it is not cross platform enough, pose extra dependency and
>> (probably) not suitable for embedded systems.
>>
>> Keeping only the "old" monitor interface with no formal interface
>> will make QEMU harder to integrate with as it requires extra work
>
> Why can't we make the monitor interface a "formal" interface?
>
Because then fixing a type or extending the interface becomes a pain.
It's also much more difficult to specify a text-base interface
completey, compared to a C api (where sometimes all you need is the
header and a few comments).
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:57 ` Avi Kivity
@ 2007-12-11 16:07 ` Richard W.M. Jones
0 siblings, 0 replies; 37+ messages in thread
From: Richard W.M. Jones @ 2007-12-11 16:07 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 626 bytes --]
Avi Kivity wrote:
> libqemumonitor.so is an excellent idea. perhaps the libvirt code can be
> used as a base?
>
> We should also provide bindings to the saner languages that management
> apps are typically written in.
Libvirt has most of the major languages covered now. The only language
I'm aware of that we are missing (and people request) is PHP.
Rich.
--
Emerging Technologies, Red Hat - http://et.redhat.com/~rjones/
Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod
Street, Windsor, Berkshire, SL4 1TE, United Kingdom. Registered in
England and Wales under Company Registration No. 03798903
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/x-pkcs7-signature, Size: 3237 bytes --]
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:44 ` Daniel P. Berrange
@ 2007-12-11 16:10 ` Fabrice Bellard
0 siblings, 0 replies; 37+ messages in thread
From: Fabrice Bellard @ 2007-12-11 16:10 UTC (permalink / raw)
To: Daniel P. Berrange, qemu-devel
Daniel P. Berrange wrote:
> On Tue, Dec 11, 2007 at 09:16:43AM +0200, Yuval Kashtan wrote:
>> - This is very useful when you want to manage and control QEMU, for instance
>> developing a GUI to attach and detach usb devices or controlling more than
>> one instance of QEMU from a single management point, receiving parameters
>> externally and more.
>
> This capability is already possible using the monitor API. I've implemented
> it in libvirt, and in virt-manager and can easily hotplug/remove USB devices.
> So DBus is not required to do this and does not really make it any easier
> to use. DBus is very verbose to use from languages like C, so switching from
> the monitor to DBus API would not really help simplify my existing code. On
> the other hand, having a library providing a simple client side C API to
> send & receive monitor commands, would be beneficial
For the short term I think it is better as you said to rely on libvirt
which already has some support for QEMU.
As it was suggested, improving the monitor seems the easiest, maybe with
an additionnal mode to provide a standardized way to get a return value
for each command. Providing an example client code to directly use the
monitor seems a good idea too.
Regarding the configuration, I can assure there will be soon a QEMU
configuration file. The question is whether it will be included before
the next release is out !
Regards,
Fabrice.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:59 ` Avi Kivity
@ 2007-12-11 16:18 ` Paul Brook
2007-12-11 16:40 ` Avi Kivity
0 siblings, 1 reply; 37+ messages in thread
From: Paul Brook @ 2007-12-11 16:18 UTC (permalink / raw)
To: qemu-devel
> > Why can't we make the monitor interface a "formal" interface?
>
> Because then fixing a type or extending the interface becomes a pain.
>
> It's also much more difficult to specify a text-base interface
> completey, compared to a C api (where sometimes all you need is the
> header and a few comments).
I disagree.
It's entirely possible to fully specify a text protocol, and it's just as easy
to extend it in a backwards compatible way. A C API is about the most fixed
interface you could possible use. A C API also requires that both sides of
the interface be part of the same process on the same machine. A text
protocol is trivial to implement over pretty much any transport you can think
of.
IMHO we have two options:
- Integrate a GUI into qemu. This will be the only supported GUI. As different
people want very different things this is unlikely to ever happen.
- Implement some sort of remote control protocol. Maybe based on the existing
monitor comands, but definitely using based on a simple serial data link.
This allows third party frontends to control qemu without having to integrate
them into qemu itself.
If you want to implement a C library to implement the text protocol, then you
can do so. If it's any good then maybe other people will also use it. However
I bet a C API isn't going to be particularly pleasant, and people are going
to want to talk to qemu from e.g. python and C++ without having to mess about
going via your C API.
Paul
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 16:18 ` Paul Brook
@ 2007-12-11 16:40 ` Avi Kivity
0 siblings, 0 replies; 37+ messages in thread
From: Avi Kivity @ 2007-12-11 16:40 UTC (permalink / raw)
To: Paul Brook; +Cc: qemu-devel
Paul Brook wrote:
>>> Why can't we make the monitor interface a "formal" interface?
>>>
>> Because then fixing a type or extending the interface becomes a pain.
>>
>> It's also much more difficult to specify a text-base interface
>> completey, compared to a C api (where sometimes all you need is the
>> header and a few comments).
>>
>
> I disagree.
>
> It's entirely possible to fully specify a text protocol,
Of course it's possible; it has been done many times. I've printed out
several pounds of http myself. It isn't easy, especially starting from
something intended for human consumption.
> and it's just as easy
> to extend it in a backwards compatible way.
It's hard to correct a typo in a backwards compatible way. I think it's
best to separate the human readable protocol from the machine readable
protocol.
> A C API is about the most fixed
> interface you could possible use.
But it's easy to add things without breaking it.
> A C API also requires that both sides of
> the interface be part of the same process on the same machine.
My plan was for the library to connect to the managing process using a
protocol of its choice. But I'm withdrawing it in favor of Dan
Berrange's idea of having a client library.
If you prefer a dedicated machine readable protocol, then I think that's
workable too. But it has to be decoupled from the human readable
monitor protocol.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 15:58 ` Daniel P. Berrange
@ 2007-12-11 16:49 ` Anthony Liguori
2007-12-11 17:04 ` Daniel P. Berrange
0 siblings, 1 reply; 37+ messages in thread
From: Anthony Liguori @ 2007-12-11 16:49 UTC (permalink / raw)
To: Daniel P. Berrange, qemu-devel
Daniel P. Berrange wrote:
> On Tue, Dec 11, 2007 at 09:48:22AM -0600, Anthony Liguori wrote:
>
>> Richard W.M. Jones wrote:
>>
>> Actually, this was the original intention of the -name parameter. What
>> a management tool would want to do is:
>>
>> 1) if -name is specified by user, generate one with uuidgen
>> 2) pass -name <name> and -pidfile /path/to/well/known/location/name.pid
>>
>> This will ensure uniqueness of name without requiring the creation tool
>> to maintain any state (so no daemon is required). Right now, you would
>> also have to store a monitor socket in that well known path. However,
>> I'm working on a VNC tunnels patch right now that would allow the
>> monitor to be tunneled through a VNC session. The idea here is that a
>> management tool could just store a hint about the VNC location and then
>> you can get at the rest of the character devices through the VNC session.
>>
>> Otherwise, you end up with a bunch of temporary sockets for things like
>> the monitor, serial devices, parallel devices, etc.
>>
>
> Tunnelling things like the serial devices / parallel devices over VNC
> would be very useful, as using a pty/file isn't useful for remote
> management. Tunnelling the monitor over VNC is questionable though because
> it has very significant security implications - if you can connect to the
> VNC server, you essentially own the entire user account that the VM is
> running under since the monitor can be used to map arbitrary files into
> the guest VM. Now this may be useful in some cases, but for libvirt we
> really just want the monitor accessible locally via a well-known UNIX
> socket. Also, VNC ports are typically auto-allocated at startup so not
> neccessary a good predictable access method.
>
The monitor is already tunneled through VNC ala a 'vc'. The tunnels
extension I'm developing would just expose 'vc's as plain-text instead
of rendered. If your management tools policy is to not make the monitor
exposed over a 'vc', then it wouldn't be exposed via VNC tunneling either.
> The reason libvirt use the PTY & direct PID ownership was because we stared
> off with QEMU 0.8.0. We should really just mandate use of QEMU 0.9.0 with
> libvirt now since its been around quite a while. Then we could just run
> with -daemonize, -pidfile and -monitor unix:/well/known/path.
>
Yeah, it would be very nice to eliminate the extra daemon.
Regards,
Anthony Liguori
> Dan.
>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API
2007-12-11 16:49 ` Anthony Liguori
@ 2007-12-11 17:04 ` Daniel P. Berrange
0 siblings, 0 replies; 37+ messages in thread
From: Daniel P. Berrange @ 2007-12-11 17:04 UTC (permalink / raw)
To: Anthony Liguori; +Cc: qemu-devel
On Tue, Dec 11, 2007 at 10:49:05AM -0600, Anthony Liguori wrote:
> Daniel P. Berrange wrote:
> >On Tue, Dec 11, 2007 at 09:48:22AM -0600, Anthony Liguori wrote:
> >
> >>Richard W.M. Jones wrote:
> >>
> >>Actually, this was the original intention of the -name parameter. What
> >>a management tool would want to do is:
> >>
> >>1) if -name is specified by user, generate one with uuidgen
> >>2) pass -name <name> and -pidfile /path/to/well/known/location/name.pid
> >>
> >>This will ensure uniqueness of name without requiring the creation tool
> >>to maintain any state (so no daemon is required). Right now, you would
> >>also have to store a monitor socket in that well known path. However,
> >>I'm working on a VNC tunnels patch right now that would allow the
> >>monitor to be tunneled through a VNC session. The idea here is that a
> >>management tool could just store a hint about the VNC location and then
> >>you can get at the rest of the character devices through the VNC session.
> >>
> >>Otherwise, you end up with a bunch of temporary sockets for things like
> >>the monitor, serial devices, parallel devices, etc.
> >>
> >
> >Tunnelling things like the serial devices / parallel devices over VNC
> >would be very useful, as using a pty/file isn't useful for remote
> >management. Tunnelling the monitor over VNC is questionable though because
> >it has very significant security implications - if you can connect to the
> >VNC server, you essentially own the entire user account that the VM is
> >running under since the monitor can be used to map arbitrary files into
> >the guest VM. Now this may be useful in some cases, but for libvirt we
> >really just want the monitor accessible locally via a well-known UNIX
> >socket. Also, VNC ports are typically auto-allocated at startup so not
> >neccessary a good predictable access method.
> >
>
> The monitor is already tunneled through VNC ala a 'vc'. The tunnels
> extension I'm developing would just expose 'vc's as plain-text instead
> of rendered. If your management tools policy is to not make the monitor
> exposed over a 'vc', then it wouldn't be exposed via VNC tunneling either.
Ah, ok that makes alot more sense now. We already disable 'vc' for the
monitor so that wouldn't be an issue.
> >The reason libvirt use the PTY & direct PID ownership was because we stared
> >off with QEMU 0.8.0. We should really just mandate use of QEMU 0.9.0 with
> >libvirt now since its been around quite a while. Then we could just run
> >with -daemonize, -pidfile and -monitor unix:/well/known/path.
>
> Yeah, it would be very nice to eliminate the extra daemon.
Of course libvirt daemon provides other things besides just managing the
QEMU process, but yes fixing the hard parent-child relationship between
the two would be good.
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
^ permalink raw reply [flat|nested] 37+ messages in thread
end of thread, other threads:[~2007-12-11 17:04 UTC | newest]
Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-10 8:28 [Qemu-devel] [RFC] QEMU Dbus support - a proposal management API Yuval Kashtan
2007-12-10 20:51 ` Blue Swirl
2007-12-11 7:16 ` Yuval Kashtan
2007-12-11 9:10 ` Fabrice Bellard
2007-12-11 9:23 ` Laurent Vivier
2007-12-11 10:06 ` Brad Campbell
2007-12-11 10:07 ` Dor Laor
2007-12-11 14:51 ` Anthony Liguori
2007-12-11 15:00 ` Daniel P. Berrange
2007-12-11 15:21 ` Yuval Kashtan
2007-12-11 15:31 ` Daniel P. Berrange
2007-12-11 15:36 ` Anthony Liguori
2007-12-11 15:59 ` Avi Kivity
2007-12-11 16:18 ` Paul Brook
2007-12-11 16:40 ` Avi Kivity
2007-12-11 15:02 ` Daniel P. Berrange
2007-12-11 15:15 ` Anthony Liguori
2007-12-11 15:40 ` Richard W.M. Jones
2007-12-11 15:48 ` Anthony Liguori
2007-12-11 15:58 ` Daniel P. Berrange
2007-12-11 16:49 ` Anthony Liguori
2007-12-11 17:04 ` Daniel P. Berrange
2007-12-11 15:59 ` Dor Laor
2007-12-11 15:17 ` Jean-Christian de Rivaz
2007-12-11 15:24 ` Daniel P. Berrange
2007-12-11 10:20 ` Andreas Färber
2007-12-11 10:29 ` Laurent Vivier
2007-12-11 10:50 ` Andreas Färber
2007-12-11 10:21 ` Heikki Lindholm
2007-12-11 11:05 ` Avi Kivity
2007-12-11 14:43 ` Anthony Liguori
2007-12-11 14:56 ` Daniel P. Berrange
2007-12-11 15:57 ` Avi Kivity
2007-12-11 16:07 ` Richard W.M. Jones
2007-12-11 15:44 ` Daniel P. Berrange
2007-12-11 16:10 ` Fabrice Bellard
2007-12-11 14:53 ` Daniel P. Berrange
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).