direct-io.hg

changeset 13407:074170d7284c

Allow xend configuration via Solaris SMF as well as the config file.

Signed-off-by: John Levon <john.levon@sun.com>
author Ewan Mellor <ewan@xensource.com>
date Thu Jan 18 15:07:51 2007 +0000 (2007-01-18)
parents a18ae238eb53
children 9447d715956b
files tools/python/setup.py tools/python/xen/lowlevel/scf/scf.c tools/python/xen/xend/XendOptions.py
line diff
     1.1 --- a/tools/python/setup.py	Thu Jan 18 15:03:06 2007 +0000
     1.2 +++ b/tools/python/setup.py	Thu Jan 18 15:07:51 2007 +0000
     1.3 @@ -30,6 +30,13 @@ xs = Extension("xs",
     1.4                 libraries          = libraries,
     1.5                 sources            = [ "xen/lowlevel/xs/xs.c" ])
     1.6  
     1.7 +scf = Extension("scf",
     1.8 +               extra_compile_args = extra_compile_args,
     1.9 +               include_dirs       = include_dirs + [ "xen/lowlevel/scf" ],
    1.10 +               library_dirs       = library_dirs,
    1.11 +               libraries          = libraries,
    1.12 +               sources            = [ "xen/lowlevel/scf/scf.c" ])
    1.13 +             
    1.14  acm = Extension("acm",
    1.15                 extra_compile_args = extra_compile_args,
    1.16                 include_dirs       = include_dirs + [ "xen/lowlevel/acm" ],
    1.17 @@ -37,6 +44,10 @@ acm = Extension("acm",
    1.18                 libraries          = libraries,
    1.19                 sources            = [ "xen/lowlevel/acm/acm.c" ])
    1.20  
    1.21 +modules = [ xc, xs, acm ]
    1.22 +if os.uname()[0] == 'SunOS':
    1.23 +    modules.append(scf)
    1.24 +
    1.25  setup(name            = 'xen',
    1.26        version         = '3.0',
    1.27        description     = 'Xen',
    1.28 @@ -56,7 +67,7 @@ setup(name            = 'xen',
    1.29                           'xen.xm.tests'
    1.30                           ],
    1.31        ext_package = "xen.lowlevel",
    1.32 -      ext_modules = [ xc, xs, acm ]
    1.33 +      ext_modules = modules
    1.34        )
    1.35  
    1.36  os.chdir('logging')
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/python/xen/lowlevel/scf/scf.c	Thu Jan 18 15:07:51 2007 +0000
     2.3 @@ -0,0 +1,156 @@
     2.4 +/*
     2.5 + * Permission is hereby granted, free of charge, to any person obtaining a copy
     2.6 + * of this software and associated documentation files (the "Software"), to
     2.7 + * deal in the Software without restriction, including without limitation the
     2.8 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     2.9 + * sell copies of the Software, and to permit persons to whom the Software is
    2.10 + * furnished to do so, subject to the following conditions:
    2.11 + *
    2.12 + * The above copyright notice and this permission notice shall be included in
    2.13 + * all copies or substantial portions of the Software.
    2.14 + *
    2.15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    2.16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    2.17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    2.18 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    2.19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    2.20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    2.21 + * DEALINGS IN THE SOFTWARE.
    2.22 + *
    2.23 + * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
    2.24 + * Use is subject to license terms.
    2.25 + */
    2.26 +
    2.27 +#include <Python.h>
    2.28 +
    2.29 +#include <libscf.h>
    2.30 +#include <stdio.h>
    2.31 +
    2.32 +#define	XEND_FMRI "svc:/system/xen/xend:default"
    2.33 +#define	XEND_PG "config"
    2.34 +
    2.35 +static PyObject *scf_exc;
    2.36 +
    2.37 +static void *
    2.38 +scf_exception(const char *err, const char *value)
    2.39 +{
    2.40 +	int scferr = scf_error();
    2.41 +	const char *scfstrerr = scf_strerror(scferr);
    2.42 +	PyObject *obj = Py_BuildValue("(isss)", scferr, err, scfstrerr, value);
    2.43 +	PyErr_SetObject(scf_exc, obj);
    2.44 +	return (NULL);
    2.45 +}
    2.46 +
    2.47 +static PyObject *
    2.48 +pyscf_get_bool(PyObject *o, PyObject *args, PyObject *kwargs)
    2.49 +{
    2.50 +	static char *kwlist[] = { "name", NULL };
    2.51 +	scf_simple_prop_t *prop;
    2.52 +	uint8_t *val;
    2.53 +	char *name;
    2.54 +
    2.55 +	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
    2.56 +		return (NULL);
    2.57 +
    2.58 +	prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
    2.59 +
    2.60 +	if (prop == NULL)
    2.61 +		return (scf_exception("scf_simple_prop_get() failed", name));
    2.62 +
    2.63 +	if ((val = scf_simple_prop_next_boolean(prop)) == NULL)
    2.64 +		return (scf_exception("scf_simple_prop_next_boolean() failed",
    2.65 +		    name));
    2.66 +
    2.67 +	if (*val) {
    2.68 +		scf_simple_prop_free(prop);
    2.69 +		Py_INCREF(Py_True);
    2.70 +		return (Py_True);
    2.71 +	}
    2.72 +
    2.73 +	scf_simple_prop_free(prop);
    2.74 +	Py_INCREF(Py_False);
    2.75 +	return (Py_False);
    2.76 +}
    2.77 +
    2.78 +static PyObject *
    2.79 +pyscf_get_int(PyObject *o, PyObject *args, PyObject *kwargs)
    2.80 +{
    2.81 +	static char *kwlist[] = { "name", NULL };
    2.82 +	scf_simple_prop_t *prop;
    2.83 +	PyObject *obj;
    2.84 +	int64_t *val;
    2.85 +	char *name;
    2.86 +
    2.87 +	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
    2.88 +		return (NULL);
    2.89 +
    2.90 +	prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
    2.91 +
    2.92 +	if (prop == NULL)
    2.93 +		return (scf_exception("scf_simple_prop_get() failed", name));
    2.94 +
    2.95 +	if ((val = scf_simple_prop_next_integer(prop)) == NULL)
    2.96 +		return (scf_exception("scf_simple_prop_next_integer() failed",
    2.97 +		    name));
    2.98 +
    2.99 +	obj = PyInt_FromLong((long)*val);
   2.100 +	scf_simple_prop_free(prop);
   2.101 +	return (obj);
   2.102 +}
   2.103 +
   2.104 +static PyObject *
   2.105 +pyscf_get_string(PyObject *o, PyObject *args, PyObject *kwargs)
   2.106 +{
   2.107 +	static char *kwlist[] = { "name", NULL };
   2.108 +	scf_simple_prop_t *prop;
   2.109 +	PyObject *obj;
   2.110 +	char *name;
   2.111 +	char *str;
   2.112 +
   2.113 +	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
   2.114 +		return (NULL);
   2.115 +
   2.116 +	prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
   2.117 +
   2.118 +	if (prop == NULL)
   2.119 +		return (scf_exception("scf_simple_prop_get() failed", name));
   2.120 +
   2.121 +	if ((str = scf_simple_prop_next_astring(prop)) == NULL) {
   2.122 +		scf_simple_prop_free(prop);
   2.123 +		return (scf_exception("scf_simple_prop_next_astring() failed",
   2.124 +		    name));
   2.125 +	}
   2.126 +
   2.127 +	obj = PyString_FromString(str);
   2.128 +	scf_simple_prop_free(prop);
   2.129 +	return (obj);
   2.130 +}
   2.131 +
   2.132 +PyDoc_STRVAR(pyscf_get_bool__doc__,
   2.133 +   "get_bool(name) - get the value of the named boolean property");
   2.134 +PyDoc_STRVAR(pyscf_get_int__doc__,
   2.135 +   "get_int(name) - get the value of the named integer property");
   2.136 +PyDoc_STRVAR(pyscf_get_string__doc__,
   2.137 +   "get_string(name) - get the value of the named string property");
   2.138 +
   2.139 +static struct PyMethodDef pyscf_module_methods[] = {
   2.140 +	{ "get_bool", (PyCFunction) pyscf_get_bool,
   2.141 +	  METH_VARARGS|METH_KEYWORDS, pyscf_get_bool__doc__ },
   2.142 +	{ "get_int", (PyCFunction) pyscf_get_int,
   2.143 +	  METH_VARARGS|METH_KEYWORDS, pyscf_get_int__doc__ },
   2.144 +	{ "get_string", (PyCFunction) pyscf_get_string,
   2.145 +	  METH_VARARGS|METH_KEYWORDS, pyscf_get_string__doc__ },
   2.146 +	{ NULL, NULL, 0, NULL }	
   2.147 +};
   2.148 +
   2.149 +PyMODINIT_FUNC
   2.150 +initscf(void)
   2.151 +{
   2.152 +	PyObject *m;
   2.153 +	m = Py_InitModule("scf", pyscf_module_methods);
   2.154 +
   2.155 +	scf_exc = PyErr_NewException("scf.error", NULL, NULL);
   2.156 +	Py_INCREF(scf_exc);
   2.157 +	PyModule_AddObject(m, "error", scf_exc);
   2.158 +	PyModule_AddIntConstant(m, "SCF_ERROR_NOT_FOUND", SCF_ERROR_NOT_FOUND);
   2.159 +}
     3.1 --- a/tools/python/xen/xend/XendOptions.py	Thu Jan 18 15:03:06 2007 +0000
     3.2 +++ b/tools/python/xen/xend/XendOptions.py	Thu Jan 18 15:07:51 2007 +0000
     3.3 @@ -20,7 +20,7 @@
     3.4  Creates the servers and handles configuration.
     3.5  
     3.6  Other classes get config variables by importing this module,
     3.7 -using instance() to get a XendRoot instance, and then
     3.8 +using instance() to get a XendOptions instance, and then
     3.9  the config functions (e.g. get_xend_port()) to get
    3.10  configured values.
    3.11  """
    3.12 @@ -33,14 +33,11 @@ import sys
    3.13  from xen.xend import sxp, osdep, XendLogging
    3.14  from xen.xend.XendError import XendError
    3.15  
    3.16 -class XendRoot:
    3.17 -    """Root of the management classes."""
    3.18 +if os.uname()[0] == 'SunOS':
    3.19 +    from xen.lowlevel import scf
    3.20  
    3.21 -    """Default path to the config file."""
    3.22 -    config_default = "/etc/xen/xend-config.sxp"
    3.23 -
    3.24 -    """Environment variable used to override config_default."""
    3.25 -    config_var     = "XEND_CONFIG"
    3.26 +class XendOptions:
    3.27 +    """Configuration options."""
    3.28  
    3.29      """Where network control scripts live."""
    3.30      network_script_dir = osdep.scripts_dir
    3.31 @@ -75,10 +72,10 @@ class XendRoot:
    3.32      xend_relocation_address_default = ''
    3.33  
    3.34      """Default port xend serves HTTP at. """
    3.35 -    xend_port_default         = '8000'
    3.36 +    xend_port_default         = 8000
    3.37  
    3.38      """Default port xend serves relocation at. """
    3.39 -    xend_relocation_port_default = '8002'
    3.40 +    xend_relocation_port_default = 8002
    3.41  
    3.42      xend_relocation_hosts_allow_default = ''
    3.43  
    3.44 @@ -92,9 +89,9 @@ class XendRoot:
    3.45      """Default path the unix-domain server listens at."""
    3.46      xend_unix_path_default = '/var/lib/xend/xend-socket'
    3.47  
    3.48 -    dom0_min_mem_default = '0'
    3.49 +    dom0_min_mem_default = 0
    3.50  
    3.51 -    dom0_vcpus_default = '0'
    3.52 +    dom0_vcpus_default = 0
    3.53  
    3.54      vncpasswd_default = None
    3.55  
    3.56 @@ -107,16 +104,11 @@ class XendRoot:
    3.57      """Default xend management state storage."""
    3.58      xend_state_path_default = '/var/lib/xend/state'
    3.59  
    3.60 -    components = {}
    3.61 -
    3.62      def __init__(self):
    3.63 -        self.config_path = None
    3.64 -        self.config = None
    3.65          self.configure()
    3.66  
    3.67 -
    3.68      def _logError(self, fmt, *args):
    3.69 -        """Logging function to log to stderr. We use this for XendRoot log
    3.70 +        """Logging function to log to stderr. We use this for XendOptions log
    3.71          messages because they may be logged before the logger has been
    3.72          configured.  Other components can safely use the logger.
    3.73          """
    3.74 @@ -125,81 +117,25 @@ class XendRoot:
    3.75  
    3.76      def configure(self):
    3.77          self.set_config()
    3.78 -        XendLogging.init(self.get_config_value("logfile",
    3.79 +        XendLogging.init(self.get_config_string("logfile",
    3.80                                                 self.logfile_default),
    3.81 -                         self.get_config_value("loglevel",
    3.82 +                         self.get_config_string("loglevel",
    3.83                                                 self.loglevel_default))
    3.84  
    3.85 -
    3.86      def set_config(self):
    3.87 -        """If the config file exists, read it. If not, ignore it.
    3.88 -
    3.89 -        The config file is a sequence of sxp forms.
    3.90 -        """
    3.91 -        self.config_path = os.getenv(self.config_var, self.config_default)
    3.92 -        if os.path.exists(self.config_path):
    3.93 -            try:
    3.94 -                fin = file(self.config_path, 'rb')
    3.95 -                try:
    3.96 -                    config = sxp.parse(fin)
    3.97 -                finally:
    3.98 -                    fin.close()
    3.99 -                if config is None:
   3.100 -                    config = ['xend-config']
   3.101 -                else:
   3.102 -                    config.insert(0, 'xend-config')
   3.103 -                self.config = config
   3.104 -            except Exception, ex:
   3.105 -                self._logError('Reading config file %s: %s',
   3.106 -                               self.config_path, str(ex))
   3.107 -                raise
   3.108 -        else:
   3.109 -            self._logError('Config file does not exist: %s',
   3.110 -                           self.config_path)
   3.111 -            self.config = ['xend-config']
   3.112 -
   3.113 -    def get_config(self, name=None):
   3.114 -        """Get the configuration element with the given name, or
   3.115 -        the whole configuration if no name is given.
   3.116 -
   3.117 -        @param name: element name (optional)
   3.118 -        @return: config or none
   3.119 -        """
   3.120 -        if name is None:
   3.121 -            val = self.config
   3.122 -        else:
   3.123 -            val = sxp.child(self.config, name)
   3.124 -        return val
   3.125 -
   3.126 -    def get_config_value(self, name, val=None):
   3.127 -        """Get the value of an atomic configuration element.
   3.128 -
   3.129 -        @param name: element name
   3.130 -        @param val:  default value (optional, defaults to None)
   3.131 -        @return: value
   3.132 -        """
   3.133 -        return sxp.child_value(self.config, name, val=val)
   3.134 +        raise NotImplementedError()
   3.135  
   3.136      def get_config_bool(self, name, val=None):
   3.137 -        v = string.lower(str(self.get_config_value(name, val)))
   3.138 -        if v in ['yes', 'y', '1', 'on',  'true',  't']:
   3.139 -            return True
   3.140 -        if v in ['no',  'n', '0', 'off', 'false', 'f']:
   3.141 -            return False
   3.142 -        raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
   3.143 +        raise NotImplementedError()
   3.144 +         
   3.145 +    def get_config_int(self, name, val=None):
   3.146 +        raise NotImplementedError()
   3.147  
   3.148 -    def get_config_int(self, name, val=None):
   3.149 -        v = self.get_config_value(name, val)
   3.150 -        try:
   3.151 -            return int(v)
   3.152 -        except Exception:
   3.153 -            raise XendError("invalid xend config %s: expected int: %s" % (name, v))
   3.154 +    def get_config_string(self, name, val=None):
   3.155 +        raise NotImplementedError()
   3.156  
   3.157      def get_xen_api_server(self):
   3.158 -        """Get the Xen-API server configuration.
   3.159 -        """
   3.160 -        return self.get_config_value('xen-api-server',
   3.161 -                                     self.xen_api_server_default)
   3.162 +        raise NotImplementedError()
   3.163  
   3.164      def get_xend_http_server(self):
   3.165          """Get the flag indicating whether xend should run an http server.
   3.166 @@ -232,7 +168,7 @@ class XendRoot:
   3.167                                     self.xend_relocation_port_default)
   3.168  
   3.169      def get_xend_relocation_hosts_allow(self):
   3.170 -        return self.get_config_value("xend-relocation-hosts-allow",
   3.171 +        return self.get_config_string("xend-relocation-hosts-allow",
   3.172                                       self.xend_relocation_hosts_allow_default)
   3.173  
   3.174      def get_xend_address(self):
   3.175 @@ -241,7 +177,7 @@ class XendRoot:
   3.176          If this is set to 'localhost' only the localhost will be able to connect
   3.177          to the HTTP port.
   3.178          """
   3.179 -        return self.get_config_value('xend-address', self.xend_address_default)
   3.180 +        return self.get_config_string('xend-address', self.xend_address_default)
   3.181  
   3.182      def get_xend_relocation_address(self):
   3.183          """Get the address xend listens at for its relocation server port.
   3.184 @@ -249,7 +185,7 @@ class XendRoot:
   3.185          If this is set to 'localhost' only the localhost will be able to connect
   3.186          to the relocation port.
   3.187          """
   3.188 -        return self.get_config_value('xend-relocation-address', self.xend_relocation_address_default)
   3.189 +        return self.get_config_string('xend-relocation-address', self.xend_relocation_address_default)
   3.190  
   3.191      def get_xend_unix_server(self):
   3.192          """Get the flag indicating whether xend should run a unix-domain server.
   3.193 @@ -259,23 +195,23 @@ class XendRoot:
   3.194      def get_xend_unix_path(self):
   3.195          """Get the path the xend unix-domain server listens at.
   3.196          """
   3.197 -        return self.get_config_value("xend-unix-path", self.xend_unix_path_default)
   3.198 +        return self.get_config_string("xend-unix-path", self.xend_unix_path_default)
   3.199  
   3.200      def get_xend_domains_path(self):
   3.201          """ Get the path for persistent domain configuration storage
   3.202          """
   3.203 -        return self.get_config_value("xend-domains-path", self.xend_domains_path_default)
   3.204 +        return self.get_config_string("xend-domains-path", self.xend_domains_path_default)
   3.205  
   3.206      def get_xend_state_path(self):
   3.207          """ Get the path for persistent domain configuration storage
   3.208          """
   3.209 -        return self.get_config_value("xend-state-path", self.xend_state_path_default)    
   3.210 +        return self.get_config_string("xend-state-path", self.xend_state_path_default)    
   3.211  
   3.212      def get_network_script(self):
   3.213          """@return the script used to alter the network configuration when
   3.214          Xend starts and stops, or None if no such script is specified."""
   3.215          
   3.216 -        s = self.get_config_value('network-script')
   3.217 +        s = self.get_config_string('network-script')
   3.218  
   3.219          if s:
   3.220              result = s.split(" ")
   3.221 @@ -286,13 +222,13 @@ class XendRoot:
   3.222  
   3.223      def get_external_migration_tool(self):
   3.224          """@return the name of the tool to handle virtual TPM migration."""
   3.225 -        return self.get_config_value('external-migration-tool', self.external_migration_tool_default)
   3.226 +        return self.get_config_string('external-migration-tool', self.external_migration_tool_default)
   3.227  
   3.228      def get_enable_dump(self):
   3.229          return self.get_config_bool('enable-dump', 'no')
   3.230  
   3.231      def get_vif_script(self):
   3.232 -        return self.get_config_value('vif-script', 'vif-bridge')
   3.233 +        return self.get_config_string('vif-script', 'vif-bridge')
   3.234  
   3.235      def get_dom0_min_mem(self):
   3.236          return self.get_config_int('dom0-min-mem', self.dom0_min_mem_default)
   3.237 @@ -304,19 +240,128 @@ class XendRoot:
   3.238          return self.get_config_int('console-limit', 1024)
   3.239  
   3.240      def get_vnclisten_address(self):
   3.241 -        return self.get_config_value('vnc-listen', self.xend_vnc_listen_default)
   3.242 +        return self.get_config_string('vnc-listen', self.xend_vnc_listen_default)
   3.243  
   3.244      def get_vncpasswd_default(self):
   3.245 -        return self.get_config_value('vncpasswd',
   3.246 +        return self.get_config_string('vncpasswd',
   3.247                                       self.vncpasswd_default)
   3.248  
   3.249 +class XendOptionsFile(XendOptions):
   3.250 +
   3.251 +    """Default path to the config file."""
   3.252 +    config_default = "/etc/xen/xend-config.sxp"
   3.253 +
   3.254 +    """Environment variable used to override config_default."""
   3.255 +    config_var     = "XEND_CONFIG"
   3.256 +
   3.257 +    def set_config(self):
   3.258 +        """If the config file exists, read it. If not, ignore it.
   3.259 +
   3.260 +        The config file is a sequence of sxp forms.
   3.261 +        """
   3.262 +        self.config_path = os.getenv(self.config_var, self.config_default)
   3.263 +        if os.path.exists(self.config_path):
   3.264 +            try:
   3.265 +                fin = file(self.config_path, 'rb')
   3.266 +                try:
   3.267 +                    config = sxp.parse(fin)
   3.268 +                finally:
   3.269 +                    fin.close()
   3.270 +                if config is None:
   3.271 +                    config = ['xend-config']
   3.272 +                else:
   3.273 +                    config.insert(0, 'xend-config')
   3.274 +                self.config = config
   3.275 +            except Exception, ex:
   3.276 +                self._logError('Reading config file %s: %s',
   3.277 +                               self.config_path, str(ex))
   3.278 +                raise
   3.279 +        else:
   3.280 +            self._logError('Config file does not exist: %s',
   3.281 +                           self.config_path)
   3.282 +            self.config = ['xend-config']
   3.283 +
   3.284 +    def get_config_value(self, name, val=None):
   3.285 +        """Get the value of an atomic configuration element.
   3.286 +
   3.287 +        @param name: element name
   3.288 +        @param val:  default value (optional, defaults to None)
   3.289 +        @return: value
   3.290 +        """
   3.291 +        return sxp.child_value(self.config, name, val=val)
   3.292 +
   3.293 +    def get_config_bool(self, name, val=None):
   3.294 +        v = string.lower(str(self.get_config_value(name, val)))
   3.295 +        if v in ['yes', 'y', '1', 'on',  'true',  't']:
   3.296 +            return True
   3.297 +        if v in ['no',  'n', '0', 'off', 'false', 'f']:
   3.298 +            return False
   3.299 +        raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
   3.300 +
   3.301 +    def get_config_int(self, name, val=None):
   3.302 +        v = self.get_config_value(name, val)
   3.303 +        try:
   3.304 +            return int(v)
   3.305 +        except Exception:
   3.306 +            raise XendError("invalid xend config %s: expected int: %s" % (name, v))
   3.307 +
   3.308 +    def get_config_string(self, name, val=None):
   3.309 +        return get_config_value(self, name, val)
   3.310 +
   3.311 +    def get_xen_api_server(self):
   3.312 +        """Get the Xen-API server configuration.
   3.313 +        """
   3.314 +        return self.get_config_value('xen-api-server',
   3.315 +                                     self.xen_api_server_default)
   3.316 +
   3.317 +if os.uname()[0] == 'SunOS':
   3.318 +    class XendOptionsSMF(XendOptions):
   3.319 +
   3.320 +        def set_config(self):
   3.321 +            pass
   3.322 +
   3.323 +        def get_config_bool(self, name, val=None):
   3.324 +            try:
   3.325 +                return scf.get_bool(name)
   3.326 +            except scf.error, e:
   3.327 +                if e[0] == scf.SCF_ERROR_NOT_FOUND:
   3.328 +                    return val
   3.329 +                else:
   3.330 +                    raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
   3.331 +
   3.332 +        def get_config_int(self, name, val=None):
   3.333 +            try:
   3.334 +                return scf.get_int(name)
   3.335 +            except scf.error, e:
   3.336 +                if e[0] == scf.SCF_ERROR_NOT_FOUND:
   3.337 +                    return val
   3.338 +                else:
   3.339 +                    raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
   3.340 +
   3.341 +        def get_config_string(self, name, val=None):
   3.342 +            try:
   3.343 +                return scf.get_string(name)
   3.344 +            except scf.error, e:
   3.345 +                if e[0] == scf.SCF_ERROR_NOT_FOUND:
   3.346 +                    return val
   3.347 +                else:
   3.348 +                    raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
   3.349 +
   3.350 +        def get_xen_api_server(self):
   3.351 +            # When the new server is a supported configuration, we should
   3.352 +            # expand this.
   3.353 +            return [["unix"]]
   3.354 +
   3.355  def instance():
   3.356 -    """Get an instance of XendRoot.
   3.357 +    """Get an instance of XendOptions.
   3.358      Use this instead of the constructor.
   3.359      """
   3.360      global inst
   3.361      try:
   3.362          inst
   3.363      except:
   3.364 -        inst = XendRoot()
   3.365 +        if os.uname()[0] == 'SunOS':
   3.366 +            inst = XendOptionsSMF()
   3.367 +        else:
   3.368 +            inst = XendOptionsFile()
   3.369      return inst