aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEwan Mellor <ewan@xensource.com>2007-03-27 00:19:20 +0100
committerEwan Mellor <ewan@xensource.com>2007-03-27 00:19:20 +0100
commit99b271fd7d5999dc54a6073da59983fc41b51af8 (patch)
treedb3fd7a3d89771286a603c021adc2ddbdf2c7e98
parent6b8760eabada5dd7f76476a589e7425d64a80721 (diff)
downloadxen-99b271fd7d5999dc54a6073da59983fc41b51af8.tar.gz
xen-99b271fd7d5999dc54a6073da59983fc41b51af8.tar.bz2
xen-99b271fd7d5999dc54a6073da59983fc41b51af8.zip
Added network.other_config map. To make this easier, add a new automatic
plumbing facility from the XendNetwork class into XendAPI (credit to Tom Wilkie for the idea). Signed-off-by: Ewan Mellor <ewan@xensource.com>
-rw-r--r--docs/xen-api/xenapi-datamodel.tex140
-rw-r--r--tools/libxen/include/xen_network.h33
-rw-r--r--tools/libxen/src/xen_network.c74
-rw-r--r--tools/python/xen/xend/XendAPI.py83
-rw-r--r--tools/python/xen/xend/XendNetwork.py43
-rw-r--r--tools/python/xen/xend/XendNode.py14
-rw-r--r--tools/python/xen/xend/XendStateStore.py13
7 files changed, 350 insertions, 50 deletions
diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex
index 65c1acd2e1..827ccc4e57 100644
--- a/docs/xen-api/xenapi-datamodel.tex
+++ b/docs/xen-api/xenapi-datamodel.tex
@@ -6549,6 +6549,7 @@ $\mathit{RW}$ & {\tt name/label} & string & a human-readable name \\
$\mathit{RW}$ & {\tt name/description} & string & a notes field containg human-readable description \\
$\mathit{RO}_\mathit{run}$ & {\tt VIFs} & (VIF ref) Set & list of connected vifs \\
$\mathit{RO}_\mathit{run}$ & {\tt PIFs} & (PIF ref) Set & list of connected pifs \\
+$\mathit{RW}$ & {\tt other\_config} & (string $\rightarrow$ string) Map & additional configuration \\
\hline
\end{longtable}
\subsection{RPCs associated with class: network}
@@ -6801,6 +6802,145 @@ value of the field
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
+\subsubsection{RPC name:~get\_other\_config}
+
+{\bf Overview:}
+Get the other\_config field of the given network.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} ((string -> string) Map) get_other_config (session_id s, network ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt network ref } & self & reference to the object \\ \hline
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:}
+{\tt
+(string $\rightarrow$ string) Map
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_other\_config}
+
+{\bf Overview:}
+Set the other\_config field of the given network.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void set_other_config (session_id s, network ref self, (string -> string) Map value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt network ref } & self & reference to the object \\ \hline
+
+{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:}
+{\tt
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~add\_to\_other\_config}
+
+{\bf Overview:}
+Add the given key-value pair to the other\_config field of the given
+network.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void add_to_other_config (session_id s, network ref self, string key, string value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt network ref } & self & reference to the object \\ \hline
+
+{\tt string } & key & Key to add \\ \hline
+
+{\tt string } & value & Value to add \\ \hline
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:}
+{\tt
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~remove\_from\_other\_config}
+
+{\bf Overview:}
+Remove the given key and its corresponding value from the other\_config
+field of the given network. If the key is not in that Map, then do
+nothing.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void remove_from_other_config (session_id s, network ref self, string key)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt network ref } & self & reference to the object \\ \hline
+
+{\tt string } & key & Key to remove \\ \hline
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:}
+{\tt
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
\subsubsection{RPC name:~create}
{\bf Overview:}
diff --git a/tools/libxen/include/xen_network.h b/tools/libxen/include/xen_network.h
index f1bff0e229..988495f2f4 100644
--- a/tools/libxen/include/xen_network.h
+++ b/tools/libxen/include/xen_network.h
@@ -22,6 +22,7 @@
#include "xen_common.h"
#include "xen_network_decl.h"
#include "xen_pif_decl.h"
+#include "xen_string_string_map.h"
#include "xen_vif_decl.h"
@@ -68,6 +69,7 @@ typedef struct xen_network_record
char *name_description;
struct xen_vif_record_opt_set *vifs;
struct xen_pif_record_opt_set *pifs;
+ xen_string_string_map *other_config;
} xen_network_record;
/**
@@ -220,6 +222,13 @@ xen_network_get_pifs(xen_session *session, struct xen_pif_set **result, xen_netw
/**
+ * Get the other_config field of the given network.
+ */
+extern bool
+xen_network_get_other_config(xen_session *session, xen_string_string_map **result, xen_network network);
+
+
+/**
* Set the name/label field of the given network.
*/
extern bool
@@ -234,6 +243,30 @@ xen_network_set_name_description(xen_session *session, xen_network network, char
/**
+ * Set the other_config field of the given network.
+ */
+extern bool
+xen_network_set_other_config(xen_session *session, xen_network network, xen_string_string_map *other_config);
+
+
+/**
+ * Add the given key-value pair to the other_config field of the given
+ * network.
+ */
+extern bool
+xen_network_add_to_other_config(xen_session *session, xen_network network, char *key, char *value);
+
+
+/**
+ * Remove the given key and its corresponding value from the
+ * other_config field of the given network. If the key is not in that Map,
+ * then do nothing.
+ */
+extern bool
+xen_network_remove_from_other_config(xen_session *session, xen_network network, char *key);
+
+
+/**
* Return a list of all the networks known to the system.
*/
extern bool
diff --git a/tools/libxen/src/xen_network.c b/tools/libxen/src/xen_network.c
index 723616204c..01393f6773 100644
--- a/tools/libxen/src/xen_network.c
+++ b/tools/libxen/src/xen_network.c
@@ -24,6 +24,7 @@
#include "xen_internal.h"
#include "xen_network.h"
#include "xen_pif.h"
+#include "xen_string_string_map.h"
#include "xen_vif.h"
@@ -52,7 +53,10 @@ static const struct_member xen_network_record_struct_members[] =
.offset = offsetof(xen_network_record, vifs) },
{ .key = "PIFs",
.type = &abstract_type_ref_set,
- .offset = offsetof(xen_network_record, pifs) }
+ .offset = offsetof(xen_network_record, pifs) },
+ { .key = "other_config",
+ .type = &abstract_type_string_string_map,
+ .offset = offsetof(xen_network_record, other_config) }
};
const abstract_type xen_network_record_abstract_type_ =
@@ -78,6 +82,7 @@ xen_network_record_free(xen_network_record *record)
free(record->name_description);
xen_vif_record_opt_set_free(record->vifs);
xen_pif_record_opt_set_free(record->pifs);
+ xen_string_string_map_free(record->other_config);
free(record);
}
@@ -239,6 +244,23 @@ xen_network_get_pifs(xen_session *session, struct xen_pif_set **result, xen_netw
bool
+xen_network_get_other_config(xen_session *session, xen_string_string_map **result, xen_network network)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = network }
+ };
+
+ abstract_type result_type = abstract_type_string_string_map;
+
+ *result = NULL;
+ XEN_CALL_("network.get_other_config");
+ return session->ok;
+}
+
+
+bool
xen_network_set_name_label(xen_session *session, xen_network network, char *label)
{
abstract_value param_values[] =
@@ -271,6 +293,56 @@ xen_network_set_name_description(xen_session *session, xen_network network, char
bool
+xen_network_set_other_config(xen_session *session, xen_network network, xen_string_string_map *other_config)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = network },
+ { .type = &abstract_type_string_string_map,
+ .u.set_val = (arbitrary_set *)other_config }
+ };
+
+ xen_call_(session, "network.set_other_config", param_values, 2, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
+xen_network_add_to_other_config(xen_session *session, xen_network network, char *key, char *value)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = network },
+ { .type = &abstract_type_string,
+ .u.string_val = key },
+ { .type = &abstract_type_string,
+ .u.string_val = value }
+ };
+
+ xen_call_(session, "network.add_to_other_config", param_values, 3, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
+xen_network_remove_from_other_config(xen_session *session, xen_network network, char *key)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = network },
+ { .type = &abstract_type_string,
+ .u.string_val = key }
+ };
+
+ xen_call_(session, "network.remove_from_other_config", param_values, 2, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
xen_network_get_all(xen_session *session, struct xen_network_set **result)
{
diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py
index 63da4a6138..67f1a15f76 100644
--- a/tools/python/xen/xend/XendAPI.py
+++ b/tools/python/xen/xend/XendAPI.py
@@ -32,6 +32,7 @@ from xen.xend.XendAuthSessions import instance as auth_manager
from xen.xend.XendError import *
from xen.xend.XendClient import ERROR_INVALID_DOMAIN
from xen.xend.XendLogging import log
+from xen.xend.XendNetwork import XendNetwork
from xen.xend.XendTask import XendTask
from xen.xend.XendVMMetrics import XendVMMetrics
@@ -436,6 +437,10 @@ class XendAPI(object):
'debug' : valid_debug,
}
+ autoplug_classes = {
+ 'network' : XendNetwork
+ }
+
# Cheat methods
# -------------
# Methods that have a trivial implementation for all classes.
@@ -457,6 +462,41 @@ class XendAPI(object):
setattr(cls, get_by_uuid, _get_by_uuid)
setattr(cls, get_uuid, _get_uuid)
+
+ # Autoplugging classes
+ # --------------------
+ # These have all of their methods grabbed out from the implementation
+ # class, and wrapped up to be compatible with the Xen-API.
+
+ for api_cls, impl_cls in autoplug_classes.items():
+ getter = getattr(cls, '_%s_get' % api_cls)
+
+ def doit(n):
+ dot_n = '%s.%s' % (api_cls, n)
+ full_n = '%s_%s' % (api_cls, n)
+ if not hasattr(cls, full_n):
+ f = getattr(impl_cls, n)
+ argcounts[dot_n] = f.func_code.co_argcount + 1
+ setattr(cls, full_n,
+ lambda s, session, ref, *args: \
+ xen_api_success( \
+ f(getter(s, session, ref), *args)))
+
+ ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, [])
+ rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, [])
+ methods = getattr(cls, '%s_methods' % api_cls, [])
+ funcs = getattr(cls, '%s_funcs' % api_cls, [])
+
+ for attr_name in ro_attrs + rw_attrs:
+ doit('get_%s' % attr_name)
+ for attr_name in rw_attrs + cls.Base_attr_rw:
+ doit('set_%s' % attr_name)
+ for method_name, return_type in methods + cls.Base_methods:
+ doit('%s' % method_name)
+ for func_name, return_type in funcs + cls.Base_funcs:
+ doit('%s' % func_name)
+
+
# Wrapping validators around XMLRPC calls
# ---------------------------------------
@@ -466,7 +506,8 @@ class XendAPI(object):
n_ = n.replace('.', '_')
try:
f = getattr(cls, n_)
- argcounts[n] = f.func_code.co_argcount - 1
+ if n not in argcounts:
+ argcounts[n] = f.func_code.co_argcount - 1
validators = takes_instance and validator and \
[validator] or []
@@ -916,44 +957,24 @@ class XendAPI(object):
network_attr_ro = ['VIFs', 'PIFs']
network_attr_rw = ['name_label',
- 'name_description']
-
- network_funcs = [('create', 'network')]
+ 'name_description',
+ 'other_config']
+ network_methods = [('add_to_other_config', None),
+ ('remove_from_other_config', None)]
+ network_funcs = [('create', None)]
- def network_create(self, _, name_label, name_description):
- return xen_api_success(
- XendNode.instance().network_create(name_label, name_description))
-
- def network_destroy(self, _, ref):
- return xen_api_success(XendNode.instance().network_destroy(ref))
-
- def _get_network(self, ref):
+ def _network_get(self, _, ref):
return XendNode.instance().get_network(ref)
def network_get_all(self, _):
return xen_api_success(XendNode.instance().get_network_refs())
- def network_get_record(self, _, ref):
- return xen_api_success(
- XendNode.instance().get_network(ref).get_record())
-
- def network_get_name_label(self, _, ref):
- return xen_api_success(self._get_network(ref).name_label)
-
- def network_get_name_description(self, _, ref):
- return xen_api_success(self._get_network(ref).name_description)
-
- def network_get_VIFs(self, _, ref):
- return xen_api_success(self._get_network(ref).get_VIF_UUIDs())
+ def network_create(self, _, record):
+ return xen_api_success(XendNode.instance().network_create(record))
- def network_get_PIFs(self, session, ref):
- return xen_api_success(self._get_network(ref).get_PIF_UUIDs())
-
- def network_set_name_label(self, _, ref, val):
- return xen_api_success(self._get_network(ref).set_name_label(val))
+ def network_destroy(self, _, ref):
+ return xen_api_success(XendNode.instance().network_destroy(ref))
- def network_set_name_description(self, _, ref, val):
- return xen_api_success(self._get_network(ref).set_name_description(val))
# Xen API: Class PIF
# ----------------------------------------------------------------
diff --git a/tools/python/xen/xend/XendNetwork.py b/tools/python/xen/xend/XendNetwork.py
index b589545ca5..f01088d693 100644
--- a/tools/python/xen/xend/XendNetwork.py
+++ b/tools/python/xen/xend/XendNetwork.py
@@ -28,10 +28,17 @@ from XendLogging import log
IP_ROUTE_RE = r'^default via ([\d\.]+) dev (\w+)'
class XendNetwork:
- def __init__(self, uuid, name, description):
+ def __init__(self, uuid, record):
self.uuid = uuid
- self.name_label = name
- self.name_description = description
+ self.name_label = record.get('name_label', '')
+ self.name_description = record.get('name_description', '')
+ self.other_config = record.get('other_config', {})
+
+ def get_name_label(self):
+ return self.name_label
+
+ def get_name_description(self):
+ return self.name_description
def set_name_label(self, new_name):
self.name_label = new_name
@@ -41,7 +48,7 @@ class XendNetwork:
self.name_description = new_desc
XendNode.instance().save_networks()
- def get_VIF_UUIDs(self):
+ def get_VIFs(self):
result = []
vms = XendDomain.instance().get_all_vms()
for vm in vms:
@@ -52,17 +59,37 @@ class XendNetwork:
result.append(vif)
return result
- def get_PIF_UUIDs(self):
+ def get_PIFs(self):
return [x.uuid for x in XendNode.instance().pifs.values()
if x.network == self]
- def get_record(self, transient = True):
+ def get_other_config(self):
+ return self.other_config
+
+ def set_other_config(self, value):
+ self.other_config = value
+ XendNode.instance().save_networks()
+
+ def add_to_other_config(self, key, value):
+ self.other_config[key] = value
+ XendNode.instance().save_networks()
+
+ def remove_from_other_config(self, key):
+ if key in self.other_config:
+ del self.other_config[key]
+ XendNode.instance().save_networks()
+
+ def get_record(self):
+ return self.get_record_internal(True)
+
+ def get_record_internal(self, transient):
result = {
'uuid': self.uuid,
'name_label': self.name_label,
'name_description': self.name_description,
+ 'other_config' : self.other_config,
}
if transient:
- result['VIFs'] = self.get_VIF_UUIDs()
- result['PIFs'] = self.get_PIF_UUIDs()
+ result['VIFs'] = self.get_VIFs()
+ result['PIFs'] = self.get_PIFs()
return result
diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py
index b8b9800602..887b1f1b80 100644
--- a/tools/python/xen/xend/XendNode.py
+++ b/tools/python/xen/xend/XendNode.py
@@ -141,11 +141,9 @@ class XendNode:
saved_networks = self.state_store.load_state('network')
if saved_networks:
for net_uuid, network in saved_networks.items():
- self.network_create(network.get('name_label'),
- network.get('name_description', ''),
- False, net_uuid)
+ self.network_create(network, False, net_uuid)
else:
- self.network_create('net0', '', False)
+ self.network_create({'name_label' : 'net0' }, False)
# initialise PIFs
saved_pifs = self.state_store.load_state('pif')
@@ -199,12 +197,10 @@ class XendNode:
- def network_create(self, name_label, name_description, persist = True,
- net_uuid = None):
+ def network_create(self, record, persist = True, net_uuid = None):
if net_uuid is None:
net_uuid = uuid.createString()
- self.networks[net_uuid] = XendNetwork(net_uuid, name_label,
- name_description)
+ self.networks[net_uuid] = XendNetwork(net_uuid, record)
if persist:
self.save_networks()
return net_uuid
@@ -280,7 +276,7 @@ class XendNode:
self.state_store.save_state('pif', pif_records)
def save_networks(self):
- net_records = dict([(k, v.get_record(transient = False))
+ net_records = dict([(k, v.get_record_internal(False))
for k, v in self.networks.items()])
self.state_store.save_state('network', net_records)
diff --git a/tools/python/xen/xend/XendStateStore.py b/tools/python/xen/xend/XendStateStore.py
index 7776415ee3..8bea86ec95 100644
--- a/tools/python/xen/xend/XendStateStore.py
+++ b/tools/python/xen/xend/XendStateStore.py
@@ -126,6 +126,13 @@ class XendStateStore:
if val_name not in cls_dict:
cls_dict[val_name] = {}
cls_dict[val_name][val_uuid] = None
+ elif val_type == '':
+ # dictionary
+ k = val_elem.getAttribute('key').encode('utf8')
+ v = val_elem.getAttribute('value').encode('utf8')
+ if val_name not in cls_dict:
+ cls_dict[val_name] = {}
+ cls_dict[val_name][k] = v
elif val_type == 'string':
cls_dict[val_name] = val_text.encode('utf8')
elif val_type == 'float':
@@ -197,7 +204,11 @@ class XendStateStore:
if type(val) == dict:
for val_uuid in val.keys():
val_node = doc.createElement(key)
- val_node.setAttribute('uuid', val_uuid)
+ if key == 'other_config':
+ val_node.setAttribute('key', str(val_uuid))
+ val_node.setAttribute('value', str(val[val_uuid]))
+ else:
+ val_node.setAttribute('uuid', val_uuid)
node.appendChild(val_node)
elif type(val) in (list, tuple):
for val_uuid in val: