mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 02:30:03 +01:00
Allow xend configuration via Solaris SMF as well as the config file.
Signed-off-by: John Levon <john.levon@sun.com>
This commit is contained in:
1 parent
2dd9828c75
commit
674fb7f63e
3 files changed
+310
-98
No files matched your search
+12
-1
@@ -30,6 +30,13 @@ 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" ],
|
||||
@@ -37,6 +44,10 @@ acm = Extension("acm",
|
||||
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',
|
||||
description = 'Xen',
|
||||
@@ -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')
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
Creates the servers and handles configuration.
|
||||
|
||||
Other classes get config variables by importing this module,
|
||||
using instance() to get a XendRoot instance, and then
|
||||
using instance() to get a XendOptions instance, and then
|
||||
the config functions (e.g. get_xend_port()) to get
|
||||
configured values.
|
||||
"""
|
||||
@@ -33,14 +33,11 @@ import sys
|
||||
from xen.xend import sxp, osdep, XendLogging
|
||||
from xen.xend.XendError import XendError
|
||||
|
||||
class XendRoot:
|
||||
"""Root of the management classes."""
|
||||
if os.uname()[0] == 'SunOS':
|
||||
from xen.lowlevel import scf
|
||||
|
||||
"""Default path to the config file."""
|
||||
config_default = "/etc/xen/xend-config.sxp"
|
||||
|
||||
"""Environment variable used to override config_default."""
|
||||
config_var = "XEND_CONFIG"
|
||||
class XendOptions:
|
||||
"""Configuration options."""
|
||||
|
||||
"""Where network control scripts live."""
|
||||
network_script_dir = osdep.scripts_dir
|
||||
@@ -75,10 +72,10 @@ class XendRoot:
|
||||
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 XendRoot:
|
||||
"""Default path the unix-domain server listens at."""
|
||||
xend_unix_path_default = '/var/lib/xend/xend-socket'
|
||||
|
||||
dom0_min_mem_default = '0'
|
||||
dom0_min_mem_default = 0
|
||||
|
||||
dom0_vcpus_default = '0'
|
||||
dom0_vcpus_default = 0
|
||||
|
||||
vncpasswd_default = None
|
||||
|
||||
@@ -107,16 +104,11 @@ class XendRoot:
|
||||
"""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 XendRoot log
|
||||
"""Logging function to log to stderr. We use this for XendOptions log
|
||||
messages because they may be logged before the logger has been
|
||||
configured. Other components can safely use the logger.
|
||||
"""
|
||||
@@ -125,81 +117,25 @@ class XendRoot:
|
||||
|
||||
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):
|
||||
"""If the config file exists, read it. If not, ignore it.
|
||||
|
||||
The config file is a sequence of sxp forms.
|
||||
"""
|
||||
self.config_path = os.getenv(self.config_var, self.config_default)
|
||||
if os.path.exists(self.config_path):
|
||||
try:
|
||||
fin = file(self.config_path, 'rb')
|
||||
try:
|
||||
config = sxp.parse(fin)
|
||||
finally:
|
||||
fin.close()
|
||||
if config is None:
|
||||
config = ['xend-config']
|
||||
else:
|
||||
config.insert(0, 'xend-config')
|
||||
self.config = config
|
||||
except Exception, ex:
|
||||
self._logError('Reading config file %s: %s',
|
||||
self.config_path, str(ex))
|
||||
raise
|
||||
else:
|
||||
self._logError('Config file does not exist: %s',
|
||||
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.
|
||||
|
||||
@param name: element name
|
||||
@param val: default value (optional, defaults to None)
|
||||
@return: value
|
||||
"""
|
||||
return sxp.child_value(self.config, name, val=val)
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_config_bool(self, name, val=None):
|
||||
v = string.lower(str(self.get_config_value(name, val)))
|
||||
if v in ['yes', 'y', '1', 'on', 'true', 't']:
|
||||
return True
|
||||
if v in ['no', 'n', '0', 'off', 'false', 'f']:
|
||||
return False
|
||||
raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_config_int(self, name, val=None):
|
||||
v = self.get_config_value(name, val)
|
||||
try:
|
||||
return int(v)
|
||||
except Exception:
|
||||
raise XendError("invalid xend config %s: expected int: %s" % (name, v))
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_config_string(self, name, val=None):
|
||||
raise NotImplementedError()
|
||||
|
||||
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)
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_xend_http_server(self):
|
||||
"""Get the flag indicating whether xend should run an http server.
|
||||
@@ -232,7 +168,7 @@ class XendRoot:
|
||||
self.xend_relocation_port_default)
|
||||
|
||||
def get_xend_relocation_hosts_allow(self):
|
||||
return self.get_config_value("xend-relocation-hosts-allow",
|
||||
return self.get_config_string("xend-relocation-hosts-allow",
|
||||
self.xend_relocation_hosts_allow_default)
|
||||
|
||||
def get_xend_address(self):
|
||||
@@ -241,7 +177,7 @@ class XendRoot:
|
||||
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)
|
||||
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.
|
||||
@@ -249,7 +185,7 @@ class XendRoot:
|
||||
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)
|
||||
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.
|
||||
@@ -259,23 +195,23 @@ class XendRoot:
|
||||
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)
|
||||
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_value("xend-domains-path", self.xend_domains_path_default)
|
||||
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_value("xend-state-path", self.xend_state_path_default)
|
||||
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_value('network-script')
|
||||
s = self.get_config_string('network-script')
|
||||
|
||||
if s:
|
||||
result = s.split(" ")
|
||||
@@ -286,13 +222,13 @@ class XendRoot:
|
||||
|
||||
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)
|
||||
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_value('vif-script', 'vif-bridge')
|
||||
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)
|
||||
@@ -304,19 +240,128 @@ class XendRoot:
|
||||
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)
|
||||
return self.get_config_string('vnc-listen', self.xend_vnc_listen_default)
|
||||
|
||||
def get_vncpasswd_default(self):
|
||||
return self.get_config_value('vncpasswd',
|
||||
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.
|
||||
|
||||
The config file is a sequence of sxp forms.
|
||||
"""
|
||||
self.config_path = os.getenv(self.config_var, self.config_default)
|
||||
if os.path.exists(self.config_path):
|
||||
try:
|
||||
fin = file(self.config_path, 'rb')
|
||||
try:
|
||||
config = sxp.parse(fin)
|
||||
finally:
|
||||
fin.close()
|
||||
if config is None:
|
||||
config = ['xend-config']
|
||||
else:
|
||||
config.insert(0, 'xend-config')
|
||||
self.config = config
|
||||
except Exception, ex:
|
||||
self._logError('Reading config file %s: %s',
|
||||
self.config_path, str(ex))
|
||||
raise
|
||||
else:
|
||||
self._logError('Config file does not exist: %s',
|
||||
self.config_path)
|
||||
self.config = ['xend-config']
|
||||
|
||||
def get_config_value(self, name, val=None):
|
||||
"""Get the value of an atomic configuration element.
|
||||
|
||||
@param name: element name
|
||||
@param val: default value (optional, defaults to None)
|
||||
@return: value
|
||||
"""
|
||||
return sxp.child_value(self.config, name, val=val)
|
||||
|
||||
def get_config_bool(self, name, val=None):
|
||||
v = string.lower(str(self.get_config_value(name, val)))
|
||||
if v in ['yes', 'y', '1', 'on', 'true', 't']:
|
||||
return True
|
||||
if v in ['no', 'n', '0', 'off', 'false', 'f']:
|
||||
return False
|
||||
raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
|
||||
|
||||
def get_config_int(self, name, val=None):
|
||||
v = self.get_config_value(name, val)
|
||||
try:
|
||||
return int(v)
|
||||
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)
|
||||
|
||||
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 XendRoot.
|
||||
"""Get an instance of XendOptions.
|
||||
Use this instead of the constructor.
|
||||
"""
|
||||
global inst
|
||||
try:
|
||||
inst
|
||||
except:
|
||||
inst = XendRoot()
|
||||
if os.uname()[0] == 'SunOS':
|
||||
inst = XendOptionsSMF()
|
||||
else:
|
||||
inst = XendOptionsFile()
|
||||
return inst
|
||||