ia64/xen-unstable

changeset 14646:414735d45904

Added asynchronous event notification through the Xen-API. Added a new command,
xm event-monitor, a new test program for the C bindings, and new bindings
themselves.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Thu Mar 29 15:46:30 2007 +0100 (2007-03-29)
parents 121fb4046945
children dd844ac0c289
files .hgignore docs/xen-api/xenapi-datamodel.tex tools/libxen/Makefile tools/libxen/include/xen_event.h tools/libxen/include/xen_event_decl.h tools/libxen/include/xen_event_operation.h tools/libxen/include/xen_event_operation_internal.h tools/libxen/src/xen_event.c tools/libxen/src/xen_event_operation.c tools/libxen/test/test_event_handling.c tools/python/xen/xend/XendAPI.py tools/python/xen/xm/main.py
line diff
     1.1 --- a/.hgignore	Thu Mar 29 15:22:02 2007 +0100
     1.2 +++ b/.hgignore	Thu Mar 29 15:46:30 2007 +0100
     1.3 @@ -126,6 +126,7 @@
     1.4  ^tools/ioemu/qemu\.pod$
     1.5  ^tools/libxc/xen/.*$
     1.6  ^tools/libxen/test/test_bindings$
     1.7 +^tools/libxen/test/test_event_handling$
     1.8  ^tools/libaio/src/.*\.ol$
     1.9  ^tools/libaio/src/.*\.os$
    1.10  ^tools/misc/cpuperf/cpuperf-perfcntr$
     2.1 --- a/docs/xen-api/xenapi-datamodel.tex	Thu Mar 29 15:22:02 2007 +0100
     2.2 +++ b/docs/xen-api/xenapi-datamodel.tex	Thu Mar 29 15:46:30 2007 +0100
     2.3 @@ -24,6 +24,7 @@ Name & Description \\
     2.4  \hline
     2.5  {\tt session} & A session \\
     2.6  {\tt task} & A long-running asynchronous task \\
     2.7 +{\tt event} & Asynchronous event registration and handling \\
     2.8  {\tt VM} & A virtual machine (or 'guest') \\
     2.9  {\tt VM\_metrics} & The metrics associated with a VM \\
    2.10  {\tt VM\_guest\_metrics} & The metrics reported by the guest (as opposed to inferred from outside) \\
    2.11 @@ -112,6 +113,17 @@ The following enumeration types are used
    2.12  
    2.13  \begin{longtable}{|ll|}
    2.14  \hline
    2.15 +{\tt enum event\_operation} & \\
    2.16 +\hline
    2.17 +\hspace{0.5cm}{\tt add} & An object has been created \\
    2.18 +\hspace{0.5cm}{\tt del} & An object has been deleted \\
    2.19 +\hspace{0.5cm}{\tt mod} & An object has been modified \\
    2.20 +\hline
    2.21 +\end{longtable}
    2.22 +
    2.23 +\vspace{1cm}
    2.24 +\begin{longtable}{|ll|}
    2.25 +\hline
    2.26  {\tt enum console\_protocol} & \\
    2.27  \hline
    2.28  \hspace{0.5cm}{\tt vt100} & VT100 terminal \\
    2.29 @@ -1016,6 +1028,114 @@ references to objects with match names
    2.30  
    2.31  \vspace{1cm}
    2.32  \newpage
    2.33 +\section{Class: event}
    2.34 +\subsection{Fields for class: event}
    2.35 +\begin{longtable}{|lllp{0.38\textwidth}|}
    2.36 +\hline
    2.37 +\multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf event} \\
    2.38 +\multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em
    2.39 +Asynchronous event registration and handling.}} \\
    2.40 +\hline
    2.41 +Quals & Field & Type & Description \\
    2.42 +\hline
    2.43 +$\mathit{RO}_\mathit{ins}$ &  {\tt id} & int & An ID, monotonically increasing, and local to the current session \\
    2.44 +$\mathit{RO}_\mathit{ins}$ &  {\tt timestamp} & datetime & The time at which the event occurred \\
    2.45 +$\mathit{RO}_\mathit{ins}$ &  {\tt class} & string & The name of the class of the object that changed \\
    2.46 +$\mathit{RO}_\mathit{ins}$ &  {\tt operation} & event\_operation & The operation that was performed \\
    2.47 +$\mathit{RO}_\mathit{ins}$ &  {\tt ref} & string & A reference to the object that changed \\
    2.48 +$\mathit{RO}_\mathit{ins}$ &  {\tt obj\_uuid} & string & The uuid of the object that changed \\
    2.49 +\hline
    2.50 +\end{longtable}
    2.51 +\subsection{RPCs associated with class: event}
    2.52 +\subsubsection{RPC name:~register}
    2.53 +
    2.54 +{\bf Overview:} 
    2.55 +Registers this session with the event system.  Specifying the empty list
    2.56 +will register for all classes.
    2.57 +
    2.58 + \noindent {\bf Signature:} 
    2.59 +\begin{verbatim} void register (session_id s, string Set classes)\end{verbatim}
    2.60 +
    2.61 +
    2.62 +\noindent{\bf Arguments:}
    2.63 +
    2.64 + 
    2.65 +\vspace{0.3cm}
    2.66 +\begin{tabular}{|c|c|p{7cm}|}
    2.67 + \hline
    2.68 +{\bf type} & {\bf name} & {\bf description} \\ \hline
    2.69 +{\tt string Set } & classes & register for events for the indicated classes \\ \hline 
    2.70 +
    2.71 +\end{tabular}
    2.72 +
    2.73 +\vspace{0.3cm}
    2.74 +
    2.75 + \noindent {\bf Return Type:} 
    2.76 +{\tt 
    2.77 +void
    2.78 +}
    2.79 +
    2.80 +
    2.81 +
    2.82 +\vspace{0.3cm}
    2.83 +\vspace{0.3cm}
    2.84 +\vspace{0.3cm}
    2.85 +\subsubsection{RPC name:~unregister}
    2.86 +
    2.87 +{\bf Overview:} 
    2.88 +Unregisters this session with the event system.
    2.89 +
    2.90 + \noindent {\bf Signature:} 
    2.91 +\begin{verbatim} void unregister (session_id s, string Set classes)\end{verbatim}
    2.92 +
    2.93 +
    2.94 +\noindent{\bf Arguments:}
    2.95 +
    2.96 + 
    2.97 +\vspace{0.3cm}
    2.98 +\begin{tabular}{|c|c|p{7cm}|}
    2.99 + \hline
   2.100 +{\bf type} & {\bf name} & {\bf description} \\ \hline
   2.101 +{\tt string Set } & classes & remove this session's registration for the indicated classes \\ \hline 
   2.102 +
   2.103 +\end{tabular}
   2.104 +
   2.105 +\vspace{0.3cm}
   2.106 +
   2.107 + \noindent {\bf Return Type:} 
   2.108 +{\tt 
   2.109 +void
   2.110 +}
   2.111 +
   2.112 +
   2.113 +
   2.114 +\vspace{0.3cm}
   2.115 +\vspace{0.3cm}
   2.116 +\vspace{0.3cm}
   2.117 +\subsubsection{RPC name:~next}
   2.118 +
   2.119 +{\bf Overview:} 
   2.120 +Blocking call which returns a (possibly empty) batch of events.
   2.121 +
   2.122 + \noindent {\bf Signature:} 
   2.123 +\begin{verbatim} ((event record) Set) next (session_id s)\end{verbatim}
   2.124 +
   2.125 +
   2.126 +\vspace{0.3cm}
   2.127 +
   2.128 + \noindent {\bf Return Type:} 
   2.129 +{\tt 
   2.130 +(event record) Set
   2.131 +}
   2.132 +
   2.133 +
   2.134 +the batch of events
   2.135 +\vspace{0.3cm}
   2.136 +\vspace{0.3cm}
   2.137 +\vspace{0.3cm}
   2.138 +
   2.139 +\vspace{1cm}
   2.140 +\newpage
   2.141  \section{Class: VM}
   2.142  \subsection{Fields for class: VM}
   2.143  \begin{longtable}{|lllp{0.38\textwidth}|}
     3.1 --- a/tools/libxen/Makefile	Thu Mar 29 15:22:02 2007 +0100
     3.2 +++ b/tools/libxen/Makefile	Thu Mar 29 15:46:30 2007 +0100
     3.3 @@ -51,6 +51,9 @@ libxenapi.a: $(LIBXENAPI_OBJS)
     3.4  test/test_bindings: test/test_bindings.o libxenapi.so
     3.5  	$(CC) $(LDFLAGS) -o $@ $< -L . -lxenapi
     3.6  
     3.7 +test/test_event_handling: test/test_event_handling.o libxenapi.so
     3.8 +	$(CC) $(LDFLAGS) -o $@ $< -L . -lxenapi
     3.9 +
    3.10  test/test_hvm_bindings: test/test_hvm_bindings.o libxenapi.so
    3.11  	$(CC) $(LDFLAGS) -o $@ $< -L . -lxenapi
    3.12  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/libxen/include/xen_event.h	Thu Mar 29 15:46:30 2007 +0100
     4.3 @@ -0,0 +1,102 @@
     4.4 +/*
     4.5 + * Copyright (c) 2006-2007, XenSource Inc.
     4.6 + *
     4.7 + * This library is free software; you can redistribute it and/or
     4.8 + * modify it under the terms of the GNU Lesser General Public
     4.9 + * License as published by the Free Software Foundation; either
    4.10 + * version 2.1 of the License, or (at your option) any later version.
    4.11 + *
    4.12 + * This library is distributed in the hope that it will be useful,
    4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    4.15 + * Lesser General Public License for more details.
    4.16 + *
    4.17 + * You should have received a copy of the GNU Lesser General Public
    4.18 + * License along with this library; if not, write to the Free Software
    4.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
    4.20 + */
    4.21 +
    4.22 +#ifndef XEN_EVENT_H
    4.23 +#define XEN_EVENT_H
    4.24 +
    4.25 +#include "xen_common.h"
    4.26 +#include "xen_event_decl.h"
    4.27 +#include "xen_event_operation.h"
    4.28 +#include "xen_string_set.h"
    4.29 +
    4.30 +
    4.31 +/*
    4.32 + * The event class.
    4.33 + * 
    4.34 + * Asynchronous event registration and handling.
    4.35 + */
    4.36 +
    4.37 +
    4.38 +
    4.39 +typedef struct xen_event_record
    4.40 +{
    4.41 +    int64_t id;
    4.42 +    time_t timestamp;
    4.43 +    char *class;
    4.44 +    enum xen_event_operation operation;
    4.45 +    char *ref;
    4.46 +    char *obj_uuid;
    4.47 +} xen_event_record;
    4.48 +
    4.49 +/**
    4.50 + * Allocate a xen_event_record.
    4.51 + */
    4.52 +extern xen_event_record *
    4.53 +xen_event_record_alloc(void);
    4.54 +
    4.55 +/**
    4.56 + * Free the given xen_event_record, and all referenced values.  The
    4.57 + * given record must have been allocated by this library.
    4.58 + */
    4.59 +extern void
    4.60 +xen_event_record_free(xen_event_record *record);
    4.61 +
    4.62 +
    4.63 +typedef struct xen_event_record_set
    4.64 +{
    4.65 +    size_t size;
    4.66 +    xen_event_record *contents[];
    4.67 +} xen_event_record_set;
    4.68 +
    4.69 +/**
    4.70 + * Allocate a xen_event_record_set of the given size.
    4.71 + */
    4.72 +extern xen_event_record_set *
    4.73 +xen_event_record_set_alloc(size_t size);
    4.74 +
    4.75 +/**
    4.76 + * Free the given xen_event_record_set, and all referenced values.  The
    4.77 + * given set must have been allocated by this library.
    4.78 + */
    4.79 +extern void
    4.80 +xen_event_record_set_free(xen_event_record_set *set);
    4.81 +
    4.82 +
    4.83 +/**
    4.84 + * Registers this session with the event system.  Specifying the empty
    4.85 + * list will register for all classes.
    4.86 + */
    4.87 +extern bool
    4.88 +xen_event_register(xen_session *session, struct xen_string_set *classes);
    4.89 +
    4.90 +
    4.91 +/**
    4.92 + * Unregisters this session with the event system.
    4.93 + */
    4.94 +extern bool
    4.95 +xen_event_unregister(xen_session *session, struct xen_string_set *classes);
    4.96 +
    4.97 +
    4.98 +/**
    4.99 + * Blocking call which returns a (possibly empty) batch of events.
   4.100 + */
   4.101 +extern bool
   4.102 +xen_event_next(xen_session *session, struct xen_event_record_set **result);
   4.103 +
   4.104 +
   4.105 +#endif
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/libxen/include/xen_event_decl.h	Thu Mar 29 15:46:30 2007 +0100
     5.3 @@ -0,0 +1,25 @@
     5.4 +/*
     5.5 + * Copyright (c) 2006-2007, XenSource Inc.
     5.6 + *
     5.7 + * This library is free software; you can redistribute it and/or
     5.8 + * modify it under the terms of the GNU Lesser General Public
     5.9 + * License as published by the Free Software Foundation; either
    5.10 + * version 2.1 of the License, or (at your option) any later version.
    5.11 + *
    5.12 + * This library is distributed in the hope that it will be useful,
    5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    5.15 + * Lesser General Public License for more details.
    5.16 + *
    5.17 + * You should have received a copy of the GNU Lesser General Public
    5.18 + * License along with this library; if not, write to the Free Software
    5.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
    5.20 + */
    5.21 +
    5.22 +#ifndef XEN_EVENT_DECL_H
    5.23 +#define XEN_EVENT_DECL_H
    5.24 +
    5.25 +struct xen_event_record;
    5.26 +struct xen_event_record_set;
    5.27 +
    5.28 +#endif
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/libxen/include/xen_event_operation.h	Thu Mar 29 15:46:30 2007 +0100
     6.3 @@ -0,0 +1,82 @@
     6.4 +/*
     6.5 + * Copyright (c) 2006-2007, XenSource Inc.
     6.6 + *
     6.7 + * This library is free software; you can redistribute it and/or
     6.8 + * modify it under the terms of the GNU Lesser General Public
     6.9 + * License as published by the Free Software Foundation; either
    6.10 + * version 2.1 of the License, or (at your option) any later version.
    6.11 + *
    6.12 + * This library is distributed in the hope that it will be useful,
    6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    6.15 + * Lesser General Public License for more details.
    6.16 + *
    6.17 + * You should have received a copy of the GNU Lesser General Public
    6.18 + * License along with this library; if not, write to the Free Software
    6.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
    6.20 + */
    6.21 +
    6.22 +#ifndef XEN_EVENT_OPERATION_H
    6.23 +#define XEN_EVENT_OPERATION_H
    6.24 +
    6.25 +
    6.26 +#include "xen_common.h"
    6.27 +
    6.28 +
    6.29 +enum xen_event_operation
    6.30 +{
    6.31 +    /**
    6.32 +     * An object has been created
    6.33 +     */
    6.34 +    XEN_EVENT_OPERATION_ADD,
    6.35 +
    6.36 +    /**
    6.37 +     * An object has been deleted
    6.38 +     */
    6.39 +    XEN_EVENT_OPERATION_DEL,
    6.40 +
    6.41 +    /**
    6.42 +     * An object has been modified
    6.43 +     */
    6.44 +    XEN_EVENT_OPERATION_MOD
    6.45 +};
    6.46 +
    6.47 +
    6.48 +typedef struct xen_event_operation_set
    6.49 +{
    6.50 +    size_t size;
    6.51 +    enum xen_event_operation contents[];
    6.52 +} xen_event_operation_set;
    6.53 +
    6.54 +/**
    6.55 + * Allocate a xen_event_operation_set of the given size.
    6.56 + */
    6.57 +extern xen_event_operation_set *
    6.58 +xen_event_operation_set_alloc(size_t size);
    6.59 +
    6.60 +/**
    6.61 + * Free the given xen_event_operation_set.  The given set must have
    6.62 + * been allocated by this library.
    6.63 + */
    6.64 +extern void
    6.65 +xen_event_operation_set_free(xen_event_operation_set *set);
    6.66 +
    6.67 +
    6.68 +/**
    6.69 + * Return the name corresponding to the given code.  This string must
    6.70 + * not be modified or freed.
    6.71 + */
    6.72 +extern const char *
    6.73 +xen_event_operation_to_string(enum xen_event_operation val);
    6.74 +
    6.75 +
    6.76 +/**
    6.77 + * Return the correct code for the given string, or set the session
    6.78 + * object to failure and return an undefined value if the given string does
    6.79 + * not match a known code.
    6.80 + */
    6.81 +extern enum xen_event_operation
    6.82 +xen_event_operation_from_string(xen_session *session, const char *str);
    6.83 +
    6.84 +
    6.85 +#endif
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/libxen/include/xen_event_operation_internal.h	Thu Mar 29 15:46:30 2007 +0100
     7.3 @@ -0,0 +1,37 @@
     7.4 +/*
     7.5 + * Copyright (c) 2006-2007, XenSource Inc.
     7.6 + *
     7.7 + * This library is free software; you can redistribute it and/or
     7.8 + * modify it under the terms of the GNU Lesser General Public
     7.9 + * License as published by the Free Software Foundation; either
    7.10 + * version 2.1 of the License, or (at your option) any later version.
    7.11 + *
    7.12 + * This library is distributed in the hope that it will be useful,
    7.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    7.15 + * Lesser General Public License for more details.
    7.16 + *
    7.17 + * You should have received a copy of the GNU Lesser General Public
    7.18 + * License along with this library; if not, write to the Free Software
    7.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
    7.20 + */
    7.21 +
    7.22 +
    7.23 +/*
    7.24 + * Declarations of the abstract types used during demarshalling of enum
    7.25 + * xen_event_operation.  Internal to this library -- do not use from outside.
    7.26 + */
    7.27 +
    7.28 +
    7.29 +#ifndef XEN_EVENT_OPERATION_INTERNAL_H
    7.30 +#define XEN_EVENT_OPERATION_INTERNAL_H
    7.31 +
    7.32 +
    7.33 +#include "xen_internal.h"
    7.34 +
    7.35 +
    7.36 +extern const abstract_type xen_event_operation_abstract_type_;
    7.37 +extern const abstract_type xen_event_operation_set_abstract_type_;
    7.38 +
    7.39 +
    7.40 +#endif
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/libxen/src/xen_event.c	Thu Mar 29 15:46:30 2007 +0100
     8.3 @@ -0,0 +1,123 @@
     8.4 +/*
     8.5 + * Copyright (c) 2006-2007, XenSource Inc.
     8.6 + *
     8.7 + * This library is free software; you can redistribute it and/or
     8.8 + * modify it under the terms of the GNU Lesser General Public
     8.9 + * License as published by the Free Software Foundation; either
    8.10 + * version 2.1 of the License, or (at your option) any later version.
    8.11 + *
    8.12 + * This library is distributed in the hope that it will be useful,
    8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    8.15 + * Lesser General Public License for more details.
    8.16 + *
    8.17 + * You should have received a copy of the GNU Lesser General Public
    8.18 + * License along with this library; if not, write to the Free Software
    8.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
    8.20 + */
    8.21 +
    8.22 +
    8.23 +#include <stddef.h>
    8.24 +#include <stdlib.h>
    8.25 +
    8.26 +#include "xen_common.h"
    8.27 +#include "xen_event.h"
    8.28 +#include "xen_event_operation_internal.h"
    8.29 +#include "xen_internal.h"
    8.30 +
    8.31 +
    8.32 +XEN_ALLOC(xen_event_record)
    8.33 +XEN_SET_ALLOC_FREE(xen_event_record)
    8.34 +
    8.35 +
    8.36 +static const struct_member xen_event_record_struct_members[] =
    8.37 +    {
    8.38 +        { .key = "id",
    8.39 +          .type = &abstract_type_int,
    8.40 +          .offset = offsetof(xen_event_record, id) },
    8.41 +        { .key = "timestamp",
    8.42 +          .type = &abstract_type_datetime,
    8.43 +          .offset = offsetof(xen_event_record, timestamp) },
    8.44 +        { .key = "class",
    8.45 +          .type = &abstract_type_string,
    8.46 +          .offset = offsetof(xen_event_record, class) },
    8.47 +        { .key = "operation",
    8.48 +          .type = &xen_event_operation_abstract_type_,
    8.49 +          .offset = offsetof(xen_event_record, operation) },
    8.50 +        { .key = "ref",
    8.51 +          .type = &abstract_type_string,
    8.52 +          .offset = offsetof(xen_event_record, ref) },
    8.53 +        { .key = "obj_uuid",
    8.54 +          .type = &abstract_type_string,
    8.55 +          .offset = offsetof(xen_event_record, obj_uuid) }
    8.56 +    };
    8.57 +
    8.58 +const abstract_type xen_event_record_abstract_type_ =
    8.59 +    {
    8.60 +       .typename = STRUCT,
    8.61 +       .struct_size = sizeof(xen_event_record),
    8.62 +       .member_count =
    8.63 +           sizeof(xen_event_record_struct_members) / sizeof(struct_member),
    8.64 +       .members = xen_event_record_struct_members
    8.65 +    };
    8.66 +
    8.67 +
    8.68 +const abstract_type xen_event_record_set_abstract_type_ =
    8.69 +    {
    8.70 +       .typename = SET,
    8.71 +        .child = &xen_event_record_abstract_type_
    8.72 +    };
    8.73 +
    8.74 +
    8.75 +void
    8.76 +xen_event_record_free(xen_event_record *record)
    8.77 +{
    8.78 +    if (record == NULL)
    8.79 +    {
    8.80 +        return;
    8.81 +    }
    8.82 +    free(record->class);
    8.83 +    free(record->ref);
    8.84 +    free(record->obj_uuid);
    8.85 +    free(record);
    8.86 +}
    8.87 +
    8.88 +
    8.89 +bool
    8.90 +xen_event_register(xen_session *session, struct xen_string_set *classes)
    8.91 +{
    8.92 +    abstract_value param_values[] =
    8.93 +        {
    8.94 +            { .type = &abstract_type_string_set,
    8.95 +              .u.set_val = (arbitrary_set *)classes }
    8.96 +        };
    8.97 +
    8.98 +    xen_call_(session, "event.register", param_values, 1, NULL, NULL);
    8.99 +    return session->ok;
   8.100 +}
   8.101 +
   8.102 +
   8.103 +bool
   8.104 +xen_event_unregister(xen_session *session, struct xen_string_set *classes)
   8.105 +{
   8.106 +    abstract_value param_values[] =
   8.107 +        {
   8.108 +            { .type = &abstract_type_string_set,
   8.109 +              .u.set_val = (arbitrary_set *)classes }
   8.110 +        };
   8.111 +
   8.112 +    xen_call_(session, "event.unregister", param_values, 1, NULL, NULL);
   8.113 +    return session->ok;
   8.114 +}
   8.115 +
   8.116 +
   8.117 +bool
   8.118 +xen_event_next(xen_session *session, struct xen_event_record_set **result)
   8.119 +{
   8.120 +
   8.121 +    abstract_type result_type = xen_event_record_set_abstract_type_;
   8.122 +
   8.123 +    *result = NULL;
   8.124 +    xen_call_(session, "event.next", NULL, 0, &result_type, result);
   8.125 +    return session->ok;
   8.126 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/libxen/src/xen_event_operation.c	Thu Mar 29 15:46:30 2007 +0100
     9.3 @@ -0,0 +1,75 @@
     9.4 +/*
     9.5 + * Copyright (c) 2006-2007, XenSource Inc.
     9.6 + *
     9.7 + * This library is free software; you can redistribute it and/or
     9.8 + * modify it under the terms of the GNU Lesser General Public
     9.9 + * License as published by the Free Software Foundation; either
    9.10 + * version 2.1 of the License, or (at your option) any later version.
    9.11 + *
    9.12 + * This library is distributed in the hope that it will be useful,
    9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    9.15 + * Lesser General Public License for more details.
    9.16 + *
    9.17 + * You should have received a copy of the GNU Lesser General Public
    9.18 + * License along with this library; if not, write to the Free Software
    9.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
    9.20 + */
    9.21 +
    9.22 +#include <string.h>
    9.23 +
    9.24 +#include "xen_internal.h"
    9.25 +#include "xen_event_operation.h"
    9.26 +#include "xen_event_operation_internal.h"
    9.27 +
    9.28 +
    9.29 +/*
    9.30 + * Maintain this in the same order as the enum declaration!
    9.31 + */
    9.32 +static const char *lookup_table[] =
    9.33 +{
    9.34 +    "add",
    9.35 +    "del",
    9.36 +    "mod"
    9.37 +};
    9.38 +
    9.39 +
    9.40 +extern xen_event_operation_set *
    9.41 +xen_event_operation_set_alloc(size_t size)
    9.42 +{
    9.43 +    return calloc(1, sizeof(xen_event_operation_set) +
    9.44 +                  size * sizeof(enum xen_event_operation));
    9.45 +}
    9.46 +
    9.47 +
    9.48 +extern void
    9.49 +xen_event_operation_set_free(xen_event_operation_set *set)
    9.50 +{
    9.51 +    free(set);
    9.52 +}
    9.53 +
    9.54 +
    9.55 +const char *
    9.56 +xen_event_operation_to_string(enum xen_event_operation val)
    9.57 +{
    9.58 +    return lookup_table[val];
    9.59 +}
    9.60 +
    9.61 +
    9.62 +extern enum xen_event_operation
    9.63 +xen_event_operation_from_string(xen_session *session, const char *str)
    9.64 +{
    9.65 +    return ENUM_LOOKUP(session, str, lookup_table);
    9.66 +}
    9.67 +
    9.68 +
    9.69 +const abstract_type xen_event_operation_abstract_type_ =
    9.70 +    {
    9.71 +        .typename = ENUM,
    9.72 +        .enum_marshaller =
    9.73 +             (const char *(*)(int))&xen_event_operation_to_string,
    9.74 +        .enum_demarshaller =
    9.75 +             (int (*)(xen_session *, const char *))&xen_event_operation_from_string
    9.76 +    };
    9.77 +
    9.78 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/libxen/test/test_event_handling.c	Thu Mar 29 15:46:30 2007 +0100
    10.3 @@ -0,0 +1,211 @@
    10.4 +/*
    10.5 + * Copyright (c) 2006-2007 XenSource, Inc.
    10.6 + *
    10.7 + * This library is free software; you can redistribute it and/or
    10.8 + * modify it under the terms of the GNU Lesser General Public
    10.9 + * License as published by the Free Software Foundation; either
   10.10 + * version 2.1 of the License, or (at your option) any later version.
   10.11 + *
   10.12 + * This library is distributed in the hope that it will be useful,
   10.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   10.15 + * Lesser General Public License for more details.
   10.16 + *
   10.17 + * You should have received a copy of the GNU Lesser General Public
   10.18 + * License along with this library; if not, write to the Free Software
   10.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
   10.20 + */
   10.21 +
   10.22 +#define _GNU_SOURCE
   10.23 +#include <assert.h>
   10.24 +#include <inttypes.h>
   10.25 +#include <stdlib.h>
   10.26 +#include <stdio.h>
   10.27 +#include <string.h>
   10.28 +
   10.29 +#include <libxml/parser.h>
   10.30 +#include <curl/curl.h>
   10.31 +
   10.32 +#include "xen_event.h"
   10.33 +
   10.34 +//#define PRINT_XML
   10.35 +
   10.36 +static void usage()
   10.37 +{
   10.38 +    fprintf(stderr,
   10.39 +"Usage:\n"
   10.40 +"\n"
   10.41 +"    test_event_handling <server> <username> <password>\n"
   10.42 +"\n"
   10.43 +"where\n"
   10.44 +"        <server>   is the server's host and port, e.g. localhost:9363;\n"
   10.45 +"        <username> is the username to use at the server; and\n"
   10.46 +"        <password> is the password.\n");
   10.47 +
   10.48 +    exit(EXIT_FAILURE);
   10.49 +}
   10.50 +
   10.51 +
   10.52 +static char *url;
   10.53 +
   10.54 +
   10.55 +typedef struct
   10.56 +{
   10.57 +    xen_result_func func;
   10.58 +    void *handle;
   10.59 +} xen_comms;
   10.60 +
   10.61 +
   10.62 +static size_t
   10.63 +write_func(void *ptr, size_t size, size_t nmemb, xen_comms *comms)
   10.64 +{
   10.65 +    size_t n = size * nmemb;
   10.66 +#ifdef PRINT_XML
   10.67 +    printf("\n\n---Result from server -----------------------\n");
   10.68 +    printf("%s\n",((char*) ptr));
   10.69 +    fflush(stdout);
   10.70 +#endif
   10.71 +    return comms->func(ptr, n, comms->handle) ? n : 0;
   10.72 +}
   10.73 +
   10.74 +
   10.75 +static int
   10.76 +call_func(const void *data, size_t len, void *user_handle,
   10.77 +          void *result_handle, xen_result_func result_func)
   10.78 +{
   10.79 +    (void)user_handle;
   10.80 +
   10.81 +#ifdef PRINT_XML
   10.82 +    printf("\n\n---Data to server: -----------------------\n");
   10.83 +    printf("%s\n",((char*) data));
   10.84 +    fflush(stdout);
   10.85 +#endif
   10.86 +
   10.87 +    CURL *curl = curl_easy_init();
   10.88 +    if (!curl) {
   10.89 +        return -1;
   10.90 +    }
   10.91 +
   10.92 +    xen_comms comms = {
   10.93 +        .func = result_func,
   10.94 +        .handle = result_handle
   10.95 +    };
   10.96 +
   10.97 +    curl_easy_setopt(curl, CURLOPT_URL, url);
   10.98 +    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
   10.99 +    curl_easy_setopt(curl, CURLOPT_MUTE, 1);
  10.100 +    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_func);
  10.101 +    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &comms);
  10.102 +    curl_easy_setopt(curl, CURLOPT_POST, 1);
  10.103 +    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
  10.104 +    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
  10.105 +
  10.106 +    CURLcode result = curl_easy_perform(curl);
  10.107 +
  10.108 +    curl_easy_cleanup(curl);
  10.109 +
  10.110 +    return result;
  10.111 +}
  10.112 +
  10.113 +
  10.114 +static void print_error(xen_session *session)
  10.115 +{
  10.116 +    fprintf(stderr, "Error: %d", session->error_description_count);
  10.117 +    for (int i = 0; i < session->error_description_count; i++)
  10.118 +    {
  10.119 +        fprintf(stderr, "%s ", session->error_description[i]);
  10.120 +    }
  10.121 +    fprintf(stderr, "\n");
  10.122 +}
  10.123 +
  10.124 +
  10.125 +/**
  10.126 + * Workaround for whinging GCCs, as suggested by strftime(3).
  10.127 + */
  10.128 +static size_t my_strftime(char *s, size_t max, const char *fmt,
  10.129 +                          const struct tm *tm)
  10.130 +{
  10.131 +    return strftime(s, max, fmt, tm);
  10.132 +}
  10.133 +
  10.134 +
  10.135 +int main(int argc, char **argv)
  10.136 +{
  10.137 +    if (argc != 4)
  10.138 +    {
  10.139 +        usage();
  10.140 +    }
  10.141 +
  10.142 +    url = argv[1];
  10.143 +    char *username = argv[2];
  10.144 +    char *password = argv[3];
  10.145 +
  10.146 +    xmlInitParser();
  10.147 +    xen_init();
  10.148 +    curl_global_init(CURL_GLOBAL_ALL);
  10.149 +
  10.150 +#define CLEANUP                                 \
  10.151 +    do {                                        \
  10.152 +        xen_session_logout(session);            \
  10.153 +        curl_global_cleanup();                  \
  10.154 +        xen_fini();                             \
  10.155 +        xmlCleanupParser();                     \
  10.156 +    } while(0)                                  \
  10.157 +
  10.158 +    
  10.159 +    xen_session *session =
  10.160 +        xen_session_login_with_password(call_func, NULL, username, password);
  10.161 +
  10.162 +    struct xen_string_set *classes = xen_string_set_alloc(0);
  10.163 +    xen_event_register(session, classes);
  10.164 +    xen_string_set_free(classes);
  10.165 +
  10.166 +    if (!session->ok)
  10.167 +    {
  10.168 +        print_error(session);
  10.169 +        CLEANUP;
  10.170 +        return 1;
  10.171 +    }
  10.172 +
  10.173 +    while (true)
  10.174 +    {
  10.175 +        struct xen_event_record_set *events;
  10.176 +        if (!xen_event_next(session, &events))
  10.177 +        {
  10.178 +            print_error(session);
  10.179 +            CLEANUP;
  10.180 +            return 1;
  10.181 +        }
  10.182 +
  10.183 +        for (size_t i = 0; i < events->size; i++)
  10.184 +        {
  10.185 +            xen_event_record *ev = events->contents[i];
  10.186 +            char time[256];
  10.187 +            struct tm *tm = localtime(&ev->timestamp);
  10.188 +            my_strftime(time, 256, "%c, local time", tm);
  10.189 +            printf("Event received: ID = %"PRId64", %s.\n", ev->id, time);
  10.190 +            switch (ev->operation)
  10.191 +            {
  10.192 +            case XEN_EVENT_OPERATIONS_ADD:
  10.193 +                printf("%s created with UUID %s.\n", ev->class, ev->obj_uuid);
  10.194 +                break;
  10.195 +
  10.196 +            case XEN_EVENT_OPERATIONS_DEL:
  10.197 +                printf("%s with UUID %s deleted.\n", ev->class, ev->obj_uuid);
  10.198 +                break;
  10.199 +
  10.200 +            case XEN_EVENT_OPERATIONS_MOD:
  10.201 +                printf("%s with UUID %s modified.\n", ev->class, ev->obj_uuid);
  10.202 +                break;
  10.203 +            default:
  10.204 +                assert(false);
  10.205 +            }
  10.206 +        }
  10.207 +
  10.208 +        xen_event_record_set_free(events);
  10.209 +    }
  10.210 +
  10.211 +    CLEANUP;
  10.212 +
  10.213 +    return 0;
  10.214 +}
    11.1 --- a/tools/python/xen/xend/XendAPI.py	Thu Mar 29 15:22:02 2007 +0100
    11.2 +++ b/tools/python/xen/xend/XendAPI.py	Thu Mar 29 15:46:30 2007 +0100
    11.3 @@ -17,6 +17,8 @@
    11.4  
    11.5  import inspect
    11.6  import os
    11.7 +import Queue
    11.8 +import sets
    11.9  import string
   11.10  import sys
   11.11  import traceback
   11.12 @@ -87,6 +89,91 @@ def now():
   11.13  
   11.14  
   11.15  # ---------------------------------------------------
   11.16 +# Event dispatch
   11.17 +# ---------------------------------------------------
   11.18 +
   11.19 +EVENT_QUEUE_LENGTH = 50
   11.20 +event_registrations = {}
   11.21 +
   11.22 +def event_register(session, reg_classes):
   11.23 +    if session not in event_registrations:
   11.24 +        event_registrations[session] = {
   11.25 +            'classes' : sets.Set(),
   11.26 +            'queue'   : Queue.Queue(EVENT_QUEUE_LENGTH),
   11.27 +            'next-id' : 1
   11.28 +            }
   11.29 +    if not reg_classes:
   11.30 +        reg_classes = classes
   11.31 +    event_registrations[session]['classes'].union_update(reg_classes)
   11.32 +
   11.33 +
   11.34 +def event_unregister(session, unreg_classes):
   11.35 +    if session not in event_registrations:
   11.36 +        return
   11.37 +
   11.38 +    if unreg_classes:
   11.39 +        event_registrations[session]['classes'].intersection_update(
   11.40 +            unreg_classes)
   11.41 +        if len(event_registrations[session]['classes']) == 0:
   11.42 +            del event_registrations[session]
   11.43 +    else:
   11.44 +        del event_registrations[session]
   11.45 +
   11.46 +
   11.47 +def event_next(session):
   11.48 +    if session not in event_registrations:
   11.49 +        return xen_api_error(['SESSION_INVALID', session])
   11.50 +    queue = event_registrations[session]['queue']
   11.51 +    events = [queue.get()]
   11.52 +    try:
   11.53 +        while True:
   11.54 +            events.append(queue.get(False))
   11.55 +    except Queue.Empty:
   11.56 +        pass
   11.57 +
   11.58 +    return xen_api_success(events)
   11.59 +
   11.60 +
   11.61 +def _ctor_event_dispatch(xenapi, ctor, api_cls, session, args):
   11.62 +    result = ctor(xenapi, session, *args)
   11.63 +    if result['Status'] == 'Success':
   11.64 +        ref = result['Value']
   11.65 +        _event_dispatch('add', api_cls, ref, '')
   11.66 +    return result
   11.67 +
   11.68 +
   11.69 +def _dtor_event_dispatch(xenapi, dtor, api_cls, session, ref, args):
   11.70 +    result = dtor(xenapi, session, ref, *args)
   11.71 +    if result['Status'] == 'Success':
   11.72 +        _event_dispatch('del', api_cls, ref, '')
   11.73 +    return result
   11.74 +
   11.75 +
   11.76 +def _setter_event_dispatch(xenapi, setter, api_cls, attr_name, session, ref,
   11.77 +                           args):
   11.78 +    result = setter(xenapi, session, ref, *args)
   11.79 +    if result['Status'] == 'Success':
   11.80 +        _event_dispatch('mod', api_cls, ref, attr_name)
   11.81 +    return result
   11.82 +
   11.83 +
   11.84 +def _event_dispatch(operation, api_cls, ref, attr_name):
   11.85 +    event = {
   11.86 +        'timestamp' : now(),
   11.87 +        'class'     : api_cls,
   11.88 +        'operation' : operation,
   11.89 +        'ref'       : ref,
   11.90 +        'obj_uuid'  : ref,
   11.91 +        'field'     : attr_name,
   11.92 +        }
   11.93 +    for reg in event_registrations.values():
   11.94 +        if api_cls in reg['classes']:
   11.95 +            event['id'] = reg['next-id']
   11.96 +            reg['next-id'] += 1
   11.97 +            reg['queue'].put(event)
   11.98 +
   11.99 +
  11.100 +# ---------------------------------------------------
  11.101  # Python Method Decorators for input value validation
  11.102  # ---------------------------------------------------
  11.103  
  11.104 @@ -375,6 +462,36 @@ def do_vm_func(fn_name, vm_ref, *args, *
  11.105                                exn.actual])
  11.106  
  11.107  
  11.108 +classes = {
  11.109 +    'session'      : None,
  11.110 +    'event'        : None,
  11.111 +    'host'         : valid_host,
  11.112 +    'host_cpu'     : valid_host_cpu,
  11.113 +    'host_metrics' : valid_host_metrics,
  11.114 +    'network'      : valid_network,
  11.115 +    'VM'           : valid_vm,
  11.116 +    'VM_metrics'   : valid_vm_metrics,
  11.117 +    'VBD'          : valid_vbd,
  11.118 +    'VBD_metrics'  : valid_vbd_metrics,
  11.119 +    'VIF'          : valid_vif,
  11.120 +    'VIF_metrics'  : valid_vif_metrics,
  11.121 +    'VDI'          : valid_vdi,
  11.122 +    'VTPM'         : valid_vtpm,
  11.123 +    'console'      : valid_console,
  11.124 +    'SR'           : valid_sr,
  11.125 +    'PIF'          : valid_pif,
  11.126 +    'PIF_metrics'  : valid_pif_metrics,
  11.127 +    'task'         : valid_task,
  11.128 +    'debug'        : valid_debug,
  11.129 +}
  11.130 +
  11.131 +autoplug_classes = {
  11.132 +    'network'     : XendNetwork,
  11.133 +    'VM_metrics'  : XendVMMetrics,
  11.134 +    'PIF_metrics' : XendPIFMetrics,
  11.135 +}
  11.136 +
  11.137 +
  11.138  class XendAPI(object):
  11.139      """Implementation of the Xen-API in Xend. Expects to be
  11.140      used via XMLRPCServer.
  11.141 @@ -416,33 +533,7 @@ class XendAPI(object):
  11.142          server.
  11.143          """
  11.144          global_validators = [session_required, catch_typeerror]
  11.145 -        classes = {
  11.146 -            'session'      : None,
  11.147 -            'host'         : valid_host,
  11.148 -            'host_cpu'     : valid_host_cpu,
  11.149 -            'host_metrics' : valid_host_metrics,
  11.150 -            'network'      : valid_network,
  11.151 -            'VM'           : valid_vm,
  11.152 -            'VM_metrics'   : valid_vm_metrics,
  11.153 -            'VBD'          : valid_vbd,
  11.154 -            'VBD_metrics'  : valid_vbd_metrics,
  11.155 -            'VIF'          : valid_vif,
  11.156 -            'VIF_metrics'  : valid_vif_metrics,
  11.157 -            'VDI'          : valid_vdi,
  11.158 -            'VTPM'         : valid_vtpm,
  11.159 -            'console'      : valid_console,
  11.160 -            'SR'           : valid_sr,
  11.161 -            'PIF'          : valid_pif,
  11.162 -            'PIF_metrics'  : valid_pif_metrics,
  11.163 -            'task'         : valid_task,
  11.164 -            'debug'        : valid_debug,
  11.165 -        }
  11.166 -
  11.167 -        autoplug_classes = {
  11.168 -            'network'     : XendNetwork,
  11.169 -            'VM_metrics'  : XendVMMetrics,
  11.170 -            'PIF_metrics' : XendPIFMetrics,
  11.171 -        }
  11.172 +
  11.173  
  11.174          # Cheat methods
  11.175          # -------------
  11.176 @@ -499,6 +590,43 @@ class XendAPI(object):
  11.177                  doit('%s' % func_name)
  11.178  
  11.179  
  11.180 +        def wrap_method(name, new_f):
  11.181 +            try:
  11.182 +                f = getattr(cls, name)
  11.183 +                wrapped_f = (lambda *args: new_f(f, *args))
  11.184 +                wrapped_f.api = f.api
  11.185 +                wrapped_f.async = f.async
  11.186 +                setattr(cls, name, wrapped_f)
  11.187 +            except AttributeError:
  11.188 +                # Logged below (API call: %s not found)
  11.189 +                pass
  11.190 +
  11.191 +
  11.192 +        def setter_event_wrapper(api_cls, attr_name):
  11.193 +            setter_name = '%s_set_%s' % (api_cls, attr_name)
  11.194 +            wrap_method(
  11.195 +                setter_name,
  11.196 +                lambda setter, s, session, ref, *args:
  11.197 +                _setter_event_dispatch(s, setter, api_cls, attr_name,
  11.198 +                                       session, ref, args))
  11.199 +
  11.200 +
  11.201 +        def ctor_event_wrapper(api_cls):
  11.202 +            ctor_name = '%s_create' % api_cls
  11.203 +            wrap_method(
  11.204 +                ctor_name,
  11.205 +                lambda ctor, s, session, *args:
  11.206 +                _ctor_event_dispatch(s, ctor, api_cls, session, args))
  11.207 +
  11.208 +
  11.209 +        def dtor_event_wrapper(api_cls):
  11.210 +            dtor_name = '%s_destroy' % api_cls
  11.211 +            wrap_method(
  11.212 +                dtor_name,
  11.213 +                lambda dtor, s, session, ref, *args:
  11.214 +                _dtor_event_dispatch(s, dtor, api_cls, session, ref, args))
  11.215 +
  11.216 +
  11.217          # Wrapping validators around XMLRPC calls
  11.218          # ---------------------------------------
  11.219  
  11.220 @@ -541,6 +669,7 @@ class XendAPI(object):
  11.221              for attr_name in rw_attrs + cls.Base_attr_rw:
  11.222                  doit('%s.set_%s' % (api_cls, attr_name), True,
  11.223                       async_support = False)
  11.224 +                setter_event_wrapper(api_cls, attr_name)
  11.225  
  11.226              # wrap validators around methods
  11.227              for method_name, return_type in methods + cls.Base_methods:
  11.228 @@ -552,6 +681,10 @@ class XendAPI(object):
  11.229                  doit('%s.%s' % (api_cls, func_name), False, async_support = True,
  11.230                       return_type = return_type)
  11.231  
  11.232 +            ctor_event_wrapper(api_cls)
  11.233 +            dtor_event_wrapper(api_cls)
  11.234 +
  11.235 +
  11.236      _decorate = classmethod(_decorate)
  11.237  
  11.238      def __init__(self, auth):
  11.239 @@ -2388,6 +2521,26 @@ class XendAPI(object):
  11.240          return xen_api_success_void()
  11.241  
  11.242  
  11.243 +    # Xen API: Class event
  11.244 +    # ----------------------------------------------------------------
  11.245 +
  11.246 +    event_attr_ro = []
  11.247 +    event_attr_rw = []
  11.248 +    event_funcs = [('register', None),
  11.249 +                   ('unregister', None),
  11.250 +                   ('next', None)]
  11.251 +
  11.252 +    def event_register(self, session, reg_classes):
  11.253 +        event_register(session, reg_classes)
  11.254 +        return xen_api_success_void()
  11.255 +
  11.256 +    def event_unregister(self, session, unreg_classes):
  11.257 +        event_unregister(session, reg_classes)
  11.258 +        return xen_api_success_void()
  11.259 +
  11.260 +    def event_next(self, session):
  11.261 +        return event_next(session)
  11.262 +
  11.263      # Xen API: Class debug
  11.264      # ----------------------------------------------------------------
  11.265  
    12.1 --- a/tools/python/xen/xm/main.py	Thu Mar 29 15:22:02 2007 +0100
    12.2 +++ b/tools/python/xen/xm/main.py	Thu Mar 29 15:46:30 2007 +0100
    12.3 @@ -345,7 +345,8 @@ acm_commands = [
    12.4      ]
    12.5  
    12.6  all_commands = (domain_commands + host_commands + scheduler_commands +
    12.7 -                device_commands + vnet_commands + acm_commands + ['shell'])
    12.8 +                device_commands + vnet_commands + acm_commands +
    12.9 +                ['shell', 'event-monitor'])
   12.10  
   12.11  
   12.12  ##
   12.13 @@ -633,6 +634,17 @@ def xm_shell(args):
   12.14      Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
   12.15  
   12.16  
   12.17 +def xm_event_monitor(args):
   12.18 +    if serverType == SERVER_XEN_API:
   12.19 +        while True:
   12.20 +            server.xenapi.event.register(args)
   12.21 +            events = server.xenapi.event.next()
   12.22 +            for e in events:
   12.23 +                print e
   12.24 +    else:
   12.25 +        err("Event monitoring not supported unless using Xen-API.")
   12.26 +
   12.27 +
   12.28  #########################################################################
   12.29  #
   12.30  #  Main xm functions
   12.31 @@ -2169,6 +2181,7 @@ def xm_vnet_delete(args):
   12.32  
   12.33  commands = {
   12.34      "shell": xm_shell,
   12.35 +    "event-monitor": xm_event_monitor,
   12.36      # console commands
   12.37      "console": xm_console,
   12.38      # xenstat commands