[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] Use SMF for xend configuration



# HG changeset patch
# User john.levon@xxxxxxx
# Date 1168012582 28800
# Node ID f13eb28a48af6959452a546574a4cb520e0eab5f
# Parent  1ca5153952db953ca99fa28c2a09aa24d31e439a
Allow xend configuration via Solaris SMF as well as the config file.

Signed-off-by: John Levon <john.levon@xxxxxxx>

diff --git a/tools/python/setup.py b/tools/python/setup.py
--- a/tools/python/setup.py
+++ b/tools/python/setup.py
@@ -30,12 +30,23 @@ xs = Extension("xs",
                libraries          = libraries,
                sources            = [ "xen/lowlevel/xs/xs.c" ])
 
+scf = Extension("scf",
+               extra_compile_args = extra_compile_args,
+               include_dirs       = include_dirs + [ "xen/lowlevel/scf" ],
+               library_dirs       = library_dirs,
+               libraries          = libraries,
+               sources            = [ "xen/lowlevel/scf/scf.c" ])
+             
 acm = Extension("acm",
                extra_compile_args = extra_compile_args,
                include_dirs       = include_dirs + [ "xen/lowlevel/acm" ],
                library_dirs       = library_dirs,
                libraries          = libraries,
                sources            = [ "xen/lowlevel/acm/acm.c" ])
+
+modules = [ xc, xs, acm ]
+if os.uname()[0] == 'SunOS':
+    modules.append(scf)
 
 setup(name            = 'xen',
       version         = '3.0',
@@ -56,7 +67,7 @@ setup(name            = 'xen',
                          'xen.xm.tests'
                          ],
       ext_package = "xen.lowlevel",
-      ext_modules = [ xc, xs, acm ]
+      ext_modules = modules
       )
 
 os.chdir('logging')
diff --git a/tools/python/xen/lowlevel/scf/scf.c 
b/tools/python/xen/lowlevel/scf/scf.c
new file mode 100644
--- /dev/null
+++ b/tools/python/xen/lowlevel/scf/scf.c
@@ -0,0 +1,156 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <Python.h>
+
+#include <libscf.h>
+#include <stdio.h>
+
+#define        XEND_FMRI "svc:/system/xen/xend:default"
+#define        XEND_PG "config"
+
+static PyObject *scf_exc;
+
+static void *
+scf_exception(const char *err, const char *value)
+{
+       int scferr = scf_error();
+       const char *scfstrerr = scf_strerror(scferr);
+       PyObject *obj = Py_BuildValue("(isss)", scferr, err, scfstrerr, value);
+       PyErr_SetObject(scf_exc, obj);
+       return (NULL);
+}
+
+static PyObject *
+pyscf_get_bool(PyObject *o, PyObject *args, PyObject *kwargs)
+{
+       static char *kwlist[] = { "name", NULL };
+       scf_simple_prop_t *prop;
+       uint8_t *val;
+       char *name;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
+               return (NULL);
+
+       prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
+
+       if (prop == NULL)
+               return (scf_exception("scf_simple_prop_get() failed", name));
+
+       if ((val = scf_simple_prop_next_boolean(prop)) == NULL)
+               return (scf_exception("scf_simple_prop_next_boolean() failed",
+                   name));
+
+       if (*val) {
+               scf_simple_prop_free(prop);
+               Py_INCREF(Py_True);
+               return (Py_True);
+       }
+
+       scf_simple_prop_free(prop);
+       Py_INCREF(Py_False);
+       return (Py_False);
+}
+
+static PyObject *
+pyscf_get_int(PyObject *o, PyObject *args, PyObject *kwargs)
+{
+       static char *kwlist[] = { "name", NULL };
+       scf_simple_prop_t *prop;
+       PyObject *obj;
+       int64_t *val;
+       char *name;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
+               return (NULL);
+
+       prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
+
+       if (prop == NULL)
+               return (scf_exception("scf_simple_prop_get() failed", name));
+
+       if ((val = scf_simple_prop_next_integer(prop)) == NULL)
+               return (scf_exception("scf_simple_prop_next_integer() failed",
+                   name));
+
+       obj = PyInt_FromLong((long)*val);
+       scf_simple_prop_free(prop);
+       return (obj);
+}
+
+static PyObject *
+pyscf_get_string(PyObject *o, PyObject *args, PyObject *kwargs)
+{
+       static char *kwlist[] = { "name", NULL };
+       scf_simple_prop_t *prop;
+       PyObject *obj;
+       char *name;
+       char *str;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
+               return (NULL);
+
+       prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
+
+       if (prop == NULL)
+               return (scf_exception("scf_simple_prop_get() failed", name));
+
+       if ((str = scf_simple_prop_next_astring(prop)) == NULL) {
+               scf_simple_prop_free(prop);
+               return (scf_exception("scf_simple_prop_next_astring() failed",
+                   name));
+       }
+
+       obj = PyString_FromString(str);
+       scf_simple_prop_free(prop);
+       return (obj);
+}
+
+PyDoc_STRVAR(pyscf_get_bool__doc__,
+   "get_bool(name) - get the value of the named boolean property");
+PyDoc_STRVAR(pyscf_get_int__doc__,
+   "get_int(name) - get the value of the named integer property");
+PyDoc_STRVAR(pyscf_get_string__doc__,
+   "get_string(name) - get the value of the named string property");
+
+static struct PyMethodDef pyscf_module_methods[] = {
+       { "get_bool", (PyCFunction) pyscf_get_bool,
+         METH_VARARGS|METH_KEYWORDS, pyscf_get_bool__doc__ },
+       { "get_int", (PyCFunction) pyscf_get_int,
+         METH_VARARGS|METH_KEYWORDS, pyscf_get_int__doc__ },
+       { "get_string", (PyCFunction) pyscf_get_string,
+         METH_VARARGS|METH_KEYWORDS, pyscf_get_string__doc__ },
+       { NULL, NULL, 0, NULL } 
+};
+
+PyMODINIT_FUNC
+initscf(void)
+{
+       PyObject *m;
+       m = Py_InitModule("scf", pyscf_module_methods);
+
+       scf_exc = PyErr_NewException("scf.error", NULL, NULL);
+       Py_INCREF(scf_exc);
+       PyModule_AddObject(m, "error", scf_exc);
+       PyModule_AddIntConstant(m, "SCF_ERROR_NOT_FOUND", SCF_ERROR_NOT_FOUND);
+}
diff --git a/tools/python/xen/xend/XendOptions.py 
b/tools/python/xen/xend/XendOptions.py
--- a/tools/python/xen/xend/XendOptions.py
+++ b/tools/python/xen/xend/XendOptions.py
@@ -33,14 +33,11 @@ from xen.xend import sxp, osdep, XendLog
 from xen.xend import sxp, osdep, XendLogging
 from xen.xend.XendError import XendError
 
+if os.uname()[0] == 'SunOS':
+    from xen.lowlevel import scf
+
 class XendOptions:
     """Configuration options."""
-
-    """Default path to the config file."""
-    config_default = "/etc/xen/xend-config.sxp"
-
-    """Environment variable used to override config_default."""
-    config_var     = "XEND_CONFIG"
 
     """Where network control scripts live."""
     network_script_dir = osdep.scripts_dir
@@ -75,10 +72,10 @@ class XendOptions:
     xend_relocation_address_default = ''
 
     """Default port xend serves HTTP at. """
-    xend_port_default         = '8000'
+    xend_port_default         = 8000
 
     """Default port xend serves relocation at. """
-    xend_relocation_port_default = '8002'
+    xend_relocation_port_default = 8002
 
     xend_relocation_hosts_allow_default = ''
 
@@ -92,9 +89,9 @@ class XendOptions:
     """Default path the unix-domain server listens at."""
     xend_unix_path_default = '/var/lib/xend/xend-socket'
 
-    dom0_min_mem_default = '0'
-
-    dom0_vcpus_default = '0'
+    dom0_min_mem_default = 0
+
+    dom0_vcpus_default = 0
 
     vncpasswd_default = None
 
@@ -107,13 +104,8 @@ class XendOptions:
     """Default xend management state storage."""
     xend_state_path_default = '/var/lib/xend/state'
 
-    components = {}
-
     def __init__(self):
-        self.config_path = None
-        self.config = None
         self.configure()
-
 
     def _logError(self, fmt, *args):
         """Logging function to log to stderr. We use this for XendOptions log
@@ -125,11 +117,142 @@ class XendOptions:
 
     def configure(self):
         self.set_config()
-        XendLogging.init(self.get_config_value("logfile",
+        XendLogging.init(self.get_config_string("logfile",
                                                self.logfile_default),
-                         self.get_config_value("loglevel",
+                         self.get_config_string("loglevel",
                                                self.loglevel_default))
 
+    def set_config(self):
+        raise NotImplementedError()
+
+    def get_config_bool(self, name, val=None):
+        raise NotImplementedError()
+         
+    def get_config_int(self, name, val=None):
+        raise NotImplementedError()
+
+    def get_config_string(self, name, val=None):
+        raise NotImplementedError()
+
+    def get_xen_api_server(self):
+        raise NotImplementedError()
+
+    def get_xend_http_server(self):
+        """Get the flag indicating whether xend should run an http server.
+        """
+        return self.get_config_bool("xend-http-server", 
self.xend_http_server_default)
+
+    def get_xend_tcp_xmlrpc_server(self):
+        return self.get_config_bool("xend-tcp-xmlrpc-server",
+                                    self.xend_tcp_xmlrpc_server_default)
+
+    def get_xend_unix_xmlrpc_server(self):
+        return self.get_config_bool("xend-unix-xmlrpc-server",
+                                    self.xend_unix_xmlrpc_server_default)
+
+    def get_xend_relocation_server(self):
+        """Get the flag indicating whether xend should run a relocation server.
+        """
+        return self.get_config_bool("xend-relocation-server",
+                                    self.xend_relocation_server_default)
+
+    def get_xend_port(self):
+        """Get the port xend listens at for its HTTP interface.
+        """
+        return self.get_config_int('xend-port', self.xend_port_default)
+
+    def get_xend_relocation_port(self):
+        """Get the port xend listens at for connection to its relocation 
server.
+        """
+        return self.get_config_int('xend-relocation-port',
+                                   self.xend_relocation_port_default)
+
+    def get_xend_relocation_hosts_allow(self):
+        return self.get_config_string("xend-relocation-hosts-allow",
+                                     self.xend_relocation_hosts_allow_default)
+
+    def get_xend_address(self):
+        """Get the address xend listens at for its HTTP port.
+        This defaults to the empty string which allows all hosts to connect.
+        If this is set to 'localhost' only the localhost will be able to 
connect
+        to the HTTP port.
+        """
+        return self.get_config_string('xend-address', 
self.xend_address_default)
+
+    def get_xend_relocation_address(self):
+        """Get the address xend listens at for its relocation server port.
+        This defaults to the empty string which allows all hosts to connect.
+        If this is set to 'localhost' only the localhost will be able to 
connect
+        to the relocation port.
+        """
+        return self.get_config_string('xend-relocation-address', 
self.xend_relocation_address_default)
+
+    def get_xend_unix_server(self):
+        """Get the flag indicating whether xend should run a unix-domain 
server.
+        """
+        return self.get_config_bool("xend-unix-server", 
self.xend_unix_server_default)
+
+    def get_xend_unix_path(self):
+        """Get the path the xend unix-domain server listens at.
+        """
+        return self.get_config_string("xend-unix-path", 
self.xend_unix_path_default)
+
+    def get_xend_domains_path(self):
+        """ Get the path for persistent domain configuration storage
+        """
+        return self.get_config_string("xend-domains-path", 
self.xend_domains_path_default)
+
+    def get_xend_state_path(self):
+        """ Get the path for persistent domain configuration storage
+        """
+        return self.get_config_string("xend-state-path", 
self.xend_state_path_default)    
+
+    def get_network_script(self):
+        """@return the script used to alter the network configuration when
+        Xend starts and stops, or None if no such script is specified."""
+        
+        s = self.get_config_string('network-script')
+
+        if s:
+            result = s.split(" ")
+            result[0] = os.path.join(self.network_script_dir, result[0])
+            return result
+        else:
+            return None
+
+    def get_external_migration_tool(self):
+        """@return the name of the tool to handle virtual TPM migration."""
+        return self.get_config_string('external-migration-tool', 
self.external_migration_tool_default)
+
+    def get_enable_dump(self):
+        return self.get_config_bool('enable-dump', 'no')
+
+    def get_vif_script(self):
+        return self.get_config_string('vif-script', 'vif-bridge')
+
+    def get_dom0_min_mem(self):
+        return self.get_config_int('dom0-min-mem', self.dom0_min_mem_default)
+
+    def get_dom0_vcpus(self):
+        return self.get_config_int('dom0-cpus', self.dom0_vcpus_default)
+
+    def get_console_limit(self):
+        return self.get_config_int('console-limit', 1024)
+
+    def get_vnclisten_address(self):
+        return self.get_config_string('vnc-listen', 
self.xend_vnc_listen_default)
+
+    def get_vncpasswd_default(self):
+        return self.get_config_string('vncpasswd',
+                                     self.vncpasswd_default)
+
+class XendOptionsFile(XendOptions):
+
+    """Default path to the config file."""
+    config_default = "/etc/xen/xend-config.sxp"
+
+    """Environment variable used to override config_default."""
+    config_var     = "XEND_CONFIG"
 
     def set_config(self):
         """If the config file exists, read it. If not, ignore it.
@@ -158,19 +281,6 @@ class XendOptions:
                            self.config_path)
             self.config = ['xend-config']
 
-    def get_config(self, name=None):
-        """Get the configuration element with the given name, or
-        the whole configuration if no name is given.
-
-        @param name: element name (optional)
-        @return: config or none
-        """
-        if name is None:
-            val = self.config
-        else:
-            val = sxp.child(self.config, name)
-        return val
-
     def get_config_value(self, name, val=None):
         """Get the value of an atomic configuration element.
 
@@ -195,120 +305,52 @@ class XendOptions:
         except Exception:
             raise XendError("invalid xend config %s: expected int: %s" % 
(name, v))
 
+    def get_config_string(self, name, val=None):
+        return get_config_value(self, name, val)
+
     def get_xen_api_server(self):
         """Get the Xen-API server configuration.
         """
         return self.get_config_value('xen-api-server',
                                      self.xen_api_server_default)
 
-    def get_xend_http_server(self):
-        """Get the flag indicating whether xend should run an http server.
-        """
-        return self.get_config_bool("xend-http-server", 
self.xend_http_server_default)
-
-    def get_xend_tcp_xmlrpc_server(self):
-        return self.get_config_bool("xend-tcp-xmlrpc-server",
-                                    self.xend_tcp_xmlrpc_server_default)
-
-    def get_xend_unix_xmlrpc_server(self):
-        return self.get_config_bool("xend-unix-xmlrpc-server",
-                                    self.xend_unix_xmlrpc_server_default)
-
-    def get_xend_relocation_server(self):
-        """Get the flag indicating whether xend should run a relocation server.
-        """
-        return self.get_config_bool("xend-relocation-server",
-                                    self.xend_relocation_server_default)
-
-    def get_xend_port(self):
-        """Get the port xend listens at for its HTTP interface.
-        """
-        return self.get_config_int('xend-port', self.xend_port_default)
-
-    def get_xend_relocation_port(self):
-        """Get the port xend listens at for connection to its relocation 
server.
-        """
-        return self.get_config_int('xend-relocation-port',
-                                   self.xend_relocation_port_default)
-
-    def get_xend_relocation_hosts_allow(self):
-        return self.get_config_value("xend-relocation-hosts-allow",
-                                     self.xend_relocation_hosts_allow_default)
-
-    def get_xend_address(self):
-        """Get the address xend listens at for its HTTP port.
-        This defaults to the empty string which allows all hosts to connect.
-        If this is set to 'localhost' only the localhost will be able to 
connect
-        to the HTTP port.
-        """
-        return self.get_config_value('xend-address', self.xend_address_default)
-
-    def get_xend_relocation_address(self):
-        """Get the address xend listens at for its relocation server port.
-        This defaults to the empty string which allows all hosts to connect.
-        If this is set to 'localhost' only the localhost will be able to 
connect
-        to the relocation port.
-        """
-        return self.get_config_value('xend-relocation-address', 
self.xend_relocation_address_default)
-
-    def get_xend_unix_server(self):
-        """Get the flag indicating whether xend should run a unix-domain 
server.
-        """
-        return self.get_config_bool("xend-unix-server", 
self.xend_unix_server_default)
-
-    def get_xend_unix_path(self):
-        """Get the path the xend unix-domain server listens at.
-        """
-        return self.get_config_value("xend-unix-path", 
self.xend_unix_path_default)
-
-    def get_xend_domains_path(self):
-        """ Get the path for persistent domain configuration storage
-        """
-        return self.get_config_value("xend-domains-path", 
self.xend_domains_path_default)
-
-    def get_xend_state_path(self):
-        """ Get the path for persistent domain configuration storage
-        """
-        return self.get_config_value("xend-state-path", 
self.xend_state_path_default)    
-
-    def get_network_script(self):
-        """@return the script used to alter the network configuration when
-        Xend starts and stops, or None if no such script is specified."""
-        
-        s = self.get_config_value('network-script')
-
-        if s:
-            result = s.split(" ")
-            result[0] = os.path.join(self.network_script_dir, result[0])
-            return result
-        else:
-            return None
-
-    def get_external_migration_tool(self):
-        """@return the name of the tool to handle virtual TPM migration."""
-        return self.get_config_value('external-migration-tool', 
self.external_migration_tool_default)
-
-    def get_enable_dump(self):
-        return self.get_config_bool('enable-dump', 'no')
-
-    def get_vif_script(self):
-        return self.get_config_value('vif-script', 'vif-bridge')
-
-    def get_dom0_min_mem(self):
-        return self.get_config_int('dom0-min-mem', self.dom0_min_mem_default)
-
-    def get_dom0_vcpus(self):
-        return self.get_config_int('dom0-cpus', self.dom0_vcpus_default)
-
-    def get_console_limit(self):
-        return self.get_config_int('console-limit', 1024)
-
-    def get_vnclisten_address(self):
-        return self.get_config_value('vnc-listen', 
self.xend_vnc_listen_default)
-
-    def get_vncpasswd_default(self):
-        return self.get_config_value('vncpasswd',
-                                     self.vncpasswd_default)
+if os.uname()[0] == 'SunOS':
+    class XendOptionsSMF(XendOptions):
+
+        def set_config(self):
+            pass
+
+        def get_config_bool(self, name, val=None):
+            try:
+                return scf.get_bool(name)
+            except scf.error, e:
+                if e[0] == scf.SCF_ERROR_NOT_FOUND:
+                    return val
+                else:
+                    raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
+
+        def get_config_int(self, name, val=None):
+            try:
+                return scf.get_int(name)
+            except scf.error, e:
+                if e[0] == scf.SCF_ERROR_NOT_FOUND:
+                    return val
+                else:
+                    raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
+
+        def get_config_string(self, name, val=None):
+            try:
+                return scf.get_string(name)
+            except scf.error, e:
+                if e[0] == scf.SCF_ERROR_NOT_FOUND:
+                    return val
+                else:
+                    raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
+
+        def get_xen_api_server(self):
+            # When the new server is a supported configuration, we should
+            # expand this.
+            return [["unix"]]
 
 def instance():
     """Get an instance of XendOptions.
@@ -318,5 +360,8 @@ def instance():
     try:
         inst
     except:
-        inst = XendOptions()
+        if os.uname()[0] == 'SunOS':
+            inst = XendOptionsSMF()
+        else:
+            inst = XendOptionsFile()
     return inst

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.