direct-io.hg
changeset 14562:03d0dda70a8f
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>
plumbing facility from the XendNetwork class into XendAPI (credit to Tom
Wilkie for the idea).
Signed-off-by: Ewan Mellor <ewan@xensource.com>
author | Ewan Mellor <ewan@xensource.com> |
---|---|
date | Tue Mar 27 00:19:20 2007 +0100 (2007-03-27) |
parents | 616611521a1d |
children | 75c797744eb4 |
files | docs/xen-api/xenapi-datamodel.tex tools/libxen/include/xen_network.h tools/libxen/src/xen_network.c tools/python/xen/xend/XendAPI.py tools/python/xen/xend/XendNetwork.py tools/python/xen/xend/XendNode.py tools/python/xen/xend/XendStateStore.py |
line diff
1.1 --- a/docs/xen-api/xenapi-datamodel.tex Tue Mar 27 00:15:07 2007 +0100 1.2 +++ b/docs/xen-api/xenapi-datamodel.tex Tue Mar 27 00:19:20 2007 +0100 1.3 @@ -6549,6 +6549,7 @@ Quals & Field & Type & Description \\ 1.4 $\mathit{RW}$ & {\tt name/description} & string & a notes field containg human-readable description \\ 1.5 $\mathit{RO}_\mathit{run}$ & {\tt VIFs} & (VIF ref) Set & list of connected vifs \\ 1.6 $\mathit{RO}_\mathit{run}$ & {\tt PIFs} & (PIF ref) Set & list of connected pifs \\ 1.7 +$\mathit{RW}$ & {\tt other\_config} & (string $\rightarrow$ string) Map & additional configuration \\ 1.8 \hline 1.9 \end{longtable} 1.10 \subsection{RPCs associated with class: network} 1.11 @@ -6801,6 +6802,145 @@ value of the field 1.12 \vspace{0.3cm} 1.13 \vspace{0.3cm} 1.14 \vspace{0.3cm} 1.15 +\subsubsection{RPC name:~get\_other\_config} 1.16 + 1.17 +{\bf Overview:} 1.18 +Get the other\_config field of the given network. 1.19 + 1.20 + \noindent {\bf Signature:} 1.21 +\begin{verbatim} ((string -> string) Map) get_other_config (session_id s, network ref self)\end{verbatim} 1.22 + 1.23 + 1.24 +\noindent{\bf Arguments:} 1.25 + 1.26 + 1.27 +\vspace{0.3cm} 1.28 +\begin{tabular}{|c|c|p{7cm}|} 1.29 + \hline 1.30 +{\bf type} & {\bf name} & {\bf description} \\ \hline 1.31 +{\tt network ref } & self & reference to the object \\ \hline 1.32 + 1.33 +\end{tabular} 1.34 + 1.35 +\vspace{0.3cm} 1.36 + 1.37 + \noindent {\bf Return Type:} 1.38 +{\tt 1.39 +(string $\rightarrow$ string) Map 1.40 +} 1.41 + 1.42 + 1.43 +value of the field 1.44 +\vspace{0.3cm} 1.45 +\vspace{0.3cm} 1.46 +\vspace{0.3cm} 1.47 +\subsubsection{RPC name:~set\_other\_config} 1.48 + 1.49 +{\bf Overview:} 1.50 +Set the other\_config field of the given network. 1.51 + 1.52 + \noindent {\bf Signature:} 1.53 +\begin{verbatim} void set_other_config (session_id s, network ref self, (string -> string) Map value)\end{verbatim} 1.54 + 1.55 + 1.56 +\noindent{\bf Arguments:} 1.57 + 1.58 + 1.59 +\vspace{0.3cm} 1.60 +\begin{tabular}{|c|c|p{7cm}|} 1.61 + \hline 1.62 +{\bf type} & {\bf name} & {\bf description} \\ \hline 1.63 +{\tt network ref } & self & reference to the object \\ \hline 1.64 + 1.65 +{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline 1.66 + 1.67 +\end{tabular} 1.68 + 1.69 +\vspace{0.3cm} 1.70 + 1.71 + \noindent {\bf Return Type:} 1.72 +{\tt 1.73 +void 1.74 +} 1.75 + 1.76 + 1.77 + 1.78 +\vspace{0.3cm} 1.79 +\vspace{0.3cm} 1.80 +\vspace{0.3cm} 1.81 +\subsubsection{RPC name:~add\_to\_other\_config} 1.82 + 1.83 +{\bf Overview:} 1.84 +Add the given key-value pair to the other\_config field of the given 1.85 +network. 1.86 + 1.87 + \noindent {\bf Signature:} 1.88 +\begin{verbatim} void add_to_other_config (session_id s, network ref self, string key, string value)\end{verbatim} 1.89 + 1.90 + 1.91 +\noindent{\bf Arguments:} 1.92 + 1.93 + 1.94 +\vspace{0.3cm} 1.95 +\begin{tabular}{|c|c|p{7cm}|} 1.96 + \hline 1.97 +{\bf type} & {\bf name} & {\bf description} \\ \hline 1.98 +{\tt network ref } & self & reference to the object \\ \hline 1.99 + 1.100 +{\tt string } & key & Key to add \\ \hline 1.101 + 1.102 +{\tt string } & value & Value to add \\ \hline 1.103 + 1.104 +\end{tabular} 1.105 + 1.106 +\vspace{0.3cm} 1.107 + 1.108 + \noindent {\bf Return Type:} 1.109 +{\tt 1.110 +void 1.111 +} 1.112 + 1.113 + 1.114 + 1.115 +\vspace{0.3cm} 1.116 +\vspace{0.3cm} 1.117 +\vspace{0.3cm} 1.118 +\subsubsection{RPC name:~remove\_from\_other\_config} 1.119 + 1.120 +{\bf Overview:} 1.121 +Remove the given key and its corresponding value from the other\_config 1.122 +field of the given network. If the key is not in that Map, then do 1.123 +nothing. 1.124 + 1.125 + \noindent {\bf Signature:} 1.126 +\begin{verbatim} void remove_from_other_config (session_id s, network ref self, string key)\end{verbatim} 1.127 + 1.128 + 1.129 +\noindent{\bf Arguments:} 1.130 + 1.131 + 1.132 +\vspace{0.3cm} 1.133 +\begin{tabular}{|c|c|p{7cm}|} 1.134 + \hline 1.135 +{\bf type} & {\bf name} & {\bf description} \\ \hline 1.136 +{\tt network ref } & self & reference to the object \\ \hline 1.137 + 1.138 +{\tt string } & key & Key to remove \\ \hline 1.139 + 1.140 +\end{tabular} 1.141 + 1.142 +\vspace{0.3cm} 1.143 + 1.144 + \noindent {\bf Return Type:} 1.145 +{\tt 1.146 +void 1.147 +} 1.148 + 1.149 + 1.150 + 1.151 +\vspace{0.3cm} 1.152 +\vspace{0.3cm} 1.153 +\vspace{0.3cm} 1.154 \subsubsection{RPC name:~create} 1.155 1.156 {\bf Overview:}
2.1 --- a/tools/libxen/include/xen_network.h Tue Mar 27 00:15:07 2007 +0100 2.2 +++ b/tools/libxen/include/xen_network.h Tue Mar 27 00:19:20 2007 +0100 2.3 @@ -22,6 +22,7 @@ 2.4 #include "xen_common.h" 2.5 #include "xen_network_decl.h" 2.6 #include "xen_pif_decl.h" 2.7 +#include "xen_string_string_map.h" 2.8 #include "xen_vif_decl.h" 2.9 2.10 2.11 @@ -68,6 +69,7 @@ typedef struct xen_network_record 2.12 char *name_description; 2.13 struct xen_vif_record_opt_set *vifs; 2.14 struct xen_pif_record_opt_set *pifs; 2.15 + xen_string_string_map *other_config; 2.16 } xen_network_record; 2.17 2.18 /** 2.19 @@ -220,6 +222,13 @@ xen_network_get_pifs(xen_session *sessio 2.20 2.21 2.22 /** 2.23 + * Get the other_config field of the given network. 2.24 + */ 2.25 +extern bool 2.26 +xen_network_get_other_config(xen_session *session, xen_string_string_map **result, xen_network network); 2.27 + 2.28 + 2.29 +/** 2.30 * Set the name/label field of the given network. 2.31 */ 2.32 extern bool 2.33 @@ -234,6 +243,30 @@ xen_network_set_name_description(xen_ses 2.34 2.35 2.36 /** 2.37 + * Set the other_config field of the given network. 2.38 + */ 2.39 +extern bool 2.40 +xen_network_set_other_config(xen_session *session, xen_network network, xen_string_string_map *other_config); 2.41 + 2.42 + 2.43 +/** 2.44 + * Add the given key-value pair to the other_config field of the given 2.45 + * network. 2.46 + */ 2.47 +extern bool 2.48 +xen_network_add_to_other_config(xen_session *session, xen_network network, char *key, char *value); 2.49 + 2.50 + 2.51 +/** 2.52 + * Remove the given key and its corresponding value from the 2.53 + * other_config field of the given network. If the key is not in that Map, 2.54 + * then do nothing. 2.55 + */ 2.56 +extern bool 2.57 +xen_network_remove_from_other_config(xen_session *session, xen_network network, char *key); 2.58 + 2.59 + 2.60 +/** 2.61 * Return a list of all the networks known to the system. 2.62 */ 2.63 extern bool
3.1 --- a/tools/libxen/src/xen_network.c Tue Mar 27 00:15:07 2007 +0100 3.2 +++ b/tools/libxen/src/xen_network.c Tue Mar 27 00:19:20 2007 +0100 3.3 @@ -24,6 +24,7 @@ 3.4 #include "xen_internal.h" 3.5 #include "xen_network.h" 3.6 #include "xen_pif.h" 3.7 +#include "xen_string_string_map.h" 3.8 #include "xen_vif.h" 3.9 3.10 3.11 @@ -52,7 +53,10 @@ static const struct_member xen_network_r 3.12 .offset = offsetof(xen_network_record, vifs) }, 3.13 { .key = "PIFs", 3.14 .type = &abstract_type_ref_set, 3.15 - .offset = offsetof(xen_network_record, pifs) } 3.16 + .offset = offsetof(xen_network_record, pifs) }, 3.17 + { .key = "other_config", 3.18 + .type = &abstract_type_string_string_map, 3.19 + .offset = offsetof(xen_network_record, other_config) } 3.20 }; 3.21 3.22 const abstract_type xen_network_record_abstract_type_ = 3.23 @@ -78,6 +82,7 @@ xen_network_record_free(xen_network_reco 3.24 free(record->name_description); 3.25 xen_vif_record_opt_set_free(record->vifs); 3.26 xen_pif_record_opt_set_free(record->pifs); 3.27 + xen_string_string_map_free(record->other_config); 3.28 free(record); 3.29 } 3.30 3.31 @@ -239,6 +244,23 @@ xen_network_get_pifs(xen_session *sessio 3.32 3.33 3.34 bool 3.35 +xen_network_get_other_config(xen_session *session, xen_string_string_map **result, xen_network network) 3.36 +{ 3.37 + abstract_value param_values[] = 3.38 + { 3.39 + { .type = &abstract_type_string, 3.40 + .u.string_val = network } 3.41 + }; 3.42 + 3.43 + abstract_type result_type = abstract_type_string_string_map; 3.44 + 3.45 + *result = NULL; 3.46 + XEN_CALL_("network.get_other_config"); 3.47 + return session->ok; 3.48 +} 3.49 + 3.50 + 3.51 +bool 3.52 xen_network_set_name_label(xen_session *session, xen_network network, char *label) 3.53 { 3.54 abstract_value param_values[] = 3.55 @@ -271,6 +293,56 @@ xen_network_set_name_description(xen_ses 3.56 3.57 3.58 bool 3.59 +xen_network_set_other_config(xen_session *session, xen_network network, xen_string_string_map *other_config) 3.60 +{ 3.61 + abstract_value param_values[] = 3.62 + { 3.63 + { .type = &abstract_type_string, 3.64 + .u.string_val = network }, 3.65 + { .type = &abstract_type_string_string_map, 3.66 + .u.set_val = (arbitrary_set *)other_config } 3.67 + }; 3.68 + 3.69 + xen_call_(session, "network.set_other_config", param_values, 2, NULL, NULL); 3.70 + return session->ok; 3.71 +} 3.72 + 3.73 + 3.74 +bool 3.75 +xen_network_add_to_other_config(xen_session *session, xen_network network, char *key, char *value) 3.76 +{ 3.77 + abstract_value param_values[] = 3.78 + { 3.79 + { .type = &abstract_type_string, 3.80 + .u.string_val = network }, 3.81 + { .type = &abstract_type_string, 3.82 + .u.string_val = key }, 3.83 + { .type = &abstract_type_string, 3.84 + .u.string_val = value } 3.85 + }; 3.86 + 3.87 + xen_call_(session, "network.add_to_other_config", param_values, 3, NULL, NULL); 3.88 + return session->ok; 3.89 +} 3.90 + 3.91 + 3.92 +bool 3.93 +xen_network_remove_from_other_config(xen_session *session, xen_network network, char *key) 3.94 +{ 3.95 + abstract_value param_values[] = 3.96 + { 3.97 + { .type = &abstract_type_string, 3.98 + .u.string_val = network }, 3.99 + { .type = &abstract_type_string, 3.100 + .u.string_val = key } 3.101 + }; 3.102 + 3.103 + xen_call_(session, "network.remove_from_other_config", param_values, 2, NULL, NULL); 3.104 + return session->ok; 3.105 +} 3.106 + 3.107 + 3.108 +bool 3.109 xen_network_get_all(xen_session *session, struct xen_network_set **result) 3.110 { 3.111
4.1 --- a/tools/python/xen/xend/XendAPI.py Tue Mar 27 00:15:07 2007 +0100 4.2 +++ b/tools/python/xen/xend/XendAPI.py Tue Mar 27 00:19:20 2007 +0100 4.3 @@ -32,6 +32,7 @@ from xen.xend.XendAuthSessions import in 4.4 from xen.xend.XendError import * 4.5 from xen.xend.XendClient import ERROR_INVALID_DOMAIN 4.6 from xen.xend.XendLogging import log 4.7 +from xen.xend.XendNetwork import XendNetwork 4.8 from xen.xend.XendTask import XendTask 4.9 from xen.xend.XendVMMetrics import XendVMMetrics 4.10 4.11 @@ -436,6 +437,10 @@ class XendAPI(object): 4.12 'debug' : valid_debug, 4.13 } 4.14 4.15 + autoplug_classes = { 4.16 + 'network' : XendNetwork 4.17 + } 4.18 + 4.19 # Cheat methods 4.20 # ------------- 4.21 # Methods that have a trivial implementation for all classes. 4.22 @@ -457,6 +462,41 @@ class XendAPI(object): 4.23 setattr(cls, get_by_uuid, _get_by_uuid) 4.24 setattr(cls, get_uuid, _get_uuid) 4.25 4.26 + 4.27 + # Autoplugging classes 4.28 + # -------------------- 4.29 + # These have all of their methods grabbed out from the implementation 4.30 + # class, and wrapped up to be compatible with the Xen-API. 4.31 + 4.32 + for api_cls, impl_cls in autoplug_classes.items(): 4.33 + getter = getattr(cls, '_%s_get' % api_cls) 4.34 + 4.35 + def doit(n): 4.36 + dot_n = '%s.%s' % (api_cls, n) 4.37 + full_n = '%s_%s' % (api_cls, n) 4.38 + if not hasattr(cls, full_n): 4.39 + f = getattr(impl_cls, n) 4.40 + argcounts[dot_n] = f.func_code.co_argcount + 1 4.41 + setattr(cls, full_n, 4.42 + lambda s, session, ref, *args: \ 4.43 + xen_api_success( \ 4.44 + f(getter(s, session, ref), *args))) 4.45 + 4.46 + ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, []) 4.47 + rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, []) 4.48 + methods = getattr(cls, '%s_methods' % api_cls, []) 4.49 + funcs = getattr(cls, '%s_funcs' % api_cls, []) 4.50 + 4.51 + for attr_name in ro_attrs + rw_attrs: 4.52 + doit('get_%s' % attr_name) 4.53 + for attr_name in rw_attrs + cls.Base_attr_rw: 4.54 + doit('set_%s' % attr_name) 4.55 + for method_name, return_type in methods + cls.Base_methods: 4.56 + doit('%s' % method_name) 4.57 + for func_name, return_type in funcs + cls.Base_funcs: 4.58 + doit('%s' % func_name) 4.59 + 4.60 + 4.61 # Wrapping validators around XMLRPC calls 4.62 # --------------------------------------- 4.63 4.64 @@ -466,7 +506,8 @@ class XendAPI(object): 4.65 n_ = n.replace('.', '_') 4.66 try: 4.67 f = getattr(cls, n_) 4.68 - argcounts[n] = f.func_code.co_argcount - 1 4.69 + if n not in argcounts: 4.70 + argcounts[n] = f.func_code.co_argcount - 1 4.71 4.72 validators = takes_instance and validator and \ 4.73 [validator] or [] 4.74 @@ -916,44 +957,24 @@ class XendAPI(object): 4.75 4.76 network_attr_ro = ['VIFs', 'PIFs'] 4.77 network_attr_rw = ['name_label', 4.78 - 'name_description'] 4.79 - 4.80 - network_funcs = [('create', 'network')] 4.81 + 'name_description', 4.82 + 'other_config'] 4.83 + network_methods = [('add_to_other_config', None), 4.84 + ('remove_from_other_config', None)] 4.85 + network_funcs = [('create', None)] 4.86 4.87 - def network_create(self, _, name_label, name_description): 4.88 - return xen_api_success( 4.89 - XendNode.instance().network_create(name_label, name_description)) 4.90 - 4.91 - def network_destroy(self, _, ref): 4.92 - return xen_api_success(XendNode.instance().network_destroy(ref)) 4.93 - 4.94 - def _get_network(self, ref): 4.95 + def _network_get(self, _, ref): 4.96 return XendNode.instance().get_network(ref) 4.97 4.98 def network_get_all(self, _): 4.99 return xen_api_success(XendNode.instance().get_network_refs()) 4.100 4.101 - def network_get_record(self, _, ref): 4.102 - return xen_api_success( 4.103 - XendNode.instance().get_network(ref).get_record()) 4.104 - 4.105 - def network_get_name_label(self, _, ref): 4.106 - return xen_api_success(self._get_network(ref).name_label) 4.107 - 4.108 - def network_get_name_description(self, _, ref): 4.109 - return xen_api_success(self._get_network(ref).name_description) 4.110 + def network_create(self, _, record): 4.111 + return xen_api_success(XendNode.instance().network_create(record)) 4.112 4.113 - def network_get_VIFs(self, _, ref): 4.114 - return xen_api_success(self._get_network(ref).get_VIF_UUIDs()) 4.115 - 4.116 - def network_get_PIFs(self, session, ref): 4.117 - return xen_api_success(self._get_network(ref).get_PIF_UUIDs()) 4.118 + def network_destroy(self, _, ref): 4.119 + return xen_api_success(XendNode.instance().network_destroy(ref)) 4.120 4.121 - def network_set_name_label(self, _, ref, val): 4.122 - return xen_api_success(self._get_network(ref).set_name_label(val)) 4.123 - 4.124 - def network_set_name_description(self, _, ref, val): 4.125 - return xen_api_success(self._get_network(ref).set_name_description(val)) 4.126 4.127 # Xen API: Class PIF 4.128 # ----------------------------------------------------------------
5.1 --- a/tools/python/xen/xend/XendNetwork.py Tue Mar 27 00:15:07 2007 +0100 5.2 +++ b/tools/python/xen/xend/XendNetwork.py Tue Mar 27 00:19:20 2007 +0100 5.3 @@ -28,10 +28,17 @@ from XendLogging import log 5.4 IP_ROUTE_RE = r'^default via ([\d\.]+) dev (\w+)' 5.5 5.6 class XendNetwork: 5.7 - def __init__(self, uuid, name, description): 5.8 + def __init__(self, uuid, record): 5.9 self.uuid = uuid 5.10 - self.name_label = name 5.11 - self.name_description = description 5.12 + self.name_label = record.get('name_label', '') 5.13 + self.name_description = record.get('name_description', '') 5.14 + self.other_config = record.get('other_config', {}) 5.15 + 5.16 + def get_name_label(self): 5.17 + return self.name_label 5.18 + 5.19 + def get_name_description(self): 5.20 + return self.name_description 5.21 5.22 def set_name_label(self, new_name): 5.23 self.name_label = new_name 5.24 @@ -41,7 +48,7 @@ class XendNetwork: 5.25 self.name_description = new_desc 5.26 XendNode.instance().save_networks() 5.27 5.28 - def get_VIF_UUIDs(self): 5.29 + def get_VIFs(self): 5.30 result = [] 5.31 vms = XendDomain.instance().get_all_vms() 5.32 for vm in vms: 5.33 @@ -52,17 +59,37 @@ class XendNetwork: 5.34 result.append(vif) 5.35 return result 5.36 5.37 - def get_PIF_UUIDs(self): 5.38 + def get_PIFs(self): 5.39 return [x.uuid for x in XendNode.instance().pifs.values() 5.40 if x.network == self] 5.41 5.42 - def get_record(self, transient = True): 5.43 + def get_other_config(self): 5.44 + return self.other_config 5.45 + 5.46 + def set_other_config(self, value): 5.47 + self.other_config = value 5.48 + XendNode.instance().save_networks() 5.49 + 5.50 + def add_to_other_config(self, key, value): 5.51 + self.other_config[key] = value 5.52 + XendNode.instance().save_networks() 5.53 + 5.54 + def remove_from_other_config(self, key): 5.55 + if key in self.other_config: 5.56 + del self.other_config[key] 5.57 + XendNode.instance().save_networks() 5.58 + 5.59 + def get_record(self): 5.60 + return self.get_record_internal(True) 5.61 + 5.62 + def get_record_internal(self, transient): 5.63 result = { 5.64 'uuid': self.uuid, 5.65 'name_label': self.name_label, 5.66 'name_description': self.name_description, 5.67 + 'other_config' : self.other_config, 5.68 } 5.69 if transient: 5.70 - result['VIFs'] = self.get_VIF_UUIDs() 5.71 - result['PIFs'] = self.get_PIF_UUIDs() 5.72 + result['VIFs'] = self.get_VIFs() 5.73 + result['PIFs'] = self.get_PIFs() 5.74 return result
6.1 --- a/tools/python/xen/xend/XendNode.py Tue Mar 27 00:15:07 2007 +0100 6.2 +++ b/tools/python/xen/xend/XendNode.py Tue Mar 27 00:19:20 2007 +0100 6.3 @@ -141,11 +141,9 @@ class XendNode: 6.4 saved_networks = self.state_store.load_state('network') 6.5 if saved_networks: 6.6 for net_uuid, network in saved_networks.items(): 6.7 - self.network_create(network.get('name_label'), 6.8 - network.get('name_description', ''), 6.9 - False, net_uuid) 6.10 + self.network_create(network, False, net_uuid) 6.11 else: 6.12 - self.network_create('net0', '', False) 6.13 + self.network_create({'name_label' : 'net0' }, False) 6.14 6.15 # initialise PIFs 6.16 saved_pifs = self.state_store.load_state('pif') 6.17 @@ -199,12 +197,10 @@ class XendNode: 6.18 6.19 6.20 6.21 - def network_create(self, name_label, name_description, persist = True, 6.22 - net_uuid = None): 6.23 + def network_create(self, record, persist = True, net_uuid = None): 6.24 if net_uuid is None: 6.25 net_uuid = uuid.createString() 6.26 - self.networks[net_uuid] = XendNetwork(net_uuid, name_label, 6.27 - name_description) 6.28 + self.networks[net_uuid] = XendNetwork(net_uuid, record) 6.29 if persist: 6.30 self.save_networks() 6.31 return net_uuid 6.32 @@ -280,7 +276,7 @@ class XendNode: 6.33 self.state_store.save_state('pif', pif_records) 6.34 6.35 def save_networks(self): 6.36 - net_records = dict([(k, v.get_record(transient = False)) 6.37 + net_records = dict([(k, v.get_record_internal(False)) 6.38 for k, v in self.networks.items()]) 6.39 self.state_store.save_state('network', net_records) 6.40
7.1 --- a/tools/python/xen/xend/XendStateStore.py Tue Mar 27 00:15:07 2007 +0100 7.2 +++ b/tools/python/xen/xend/XendStateStore.py Tue Mar 27 00:19:20 2007 +0100 7.3 @@ -126,6 +126,13 @@ class XendStateStore: 7.4 if val_name not in cls_dict: 7.5 cls_dict[val_name] = {} 7.6 cls_dict[val_name][val_uuid] = None 7.7 + elif val_type == '': 7.8 + # dictionary 7.9 + k = val_elem.getAttribute('key').encode('utf8') 7.10 + v = val_elem.getAttribute('value').encode('utf8') 7.11 + if val_name not in cls_dict: 7.12 + cls_dict[val_name] = {} 7.13 + cls_dict[val_name][k] = v 7.14 elif val_type == 'string': 7.15 cls_dict[val_name] = val_text.encode('utf8') 7.16 elif val_type == 'float': 7.17 @@ -197,7 +204,11 @@ class XendStateStore: 7.18 if type(val) == dict: 7.19 for val_uuid in val.keys(): 7.20 val_node = doc.createElement(key) 7.21 - val_node.setAttribute('uuid', val_uuid) 7.22 + if key == 'other_config': 7.23 + val_node.setAttribute('key', str(val_uuid)) 7.24 + val_node.setAttribute('value', str(val[val_uuid])) 7.25 + else: 7.26 + val_node.setAttribute('uuid', val_uuid) 7.27 node.appendChild(val_node) 7.28 elif type(val) in (list, tuple): 7.29 for val_uuid in val: