mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
Merge with xen-unstable.hg.
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
This commit is contained in:
commit
001e8c5cd8
236 files changed
+5564
-3043
No files matched your search
@@ -39,14 +39,13 @@ vm_cfg = {
|
||||
local_vdi_cfg = {
|
||||
'name_label': 'gentoo.hvm',
|
||||
'name_description': '',
|
||||
'location': 'file:/root/gentoo.amd64.hvm.img',
|
||||
'virtual_size': 0,
|
||||
'sector_size': 0,
|
||||
'type': 'system',
|
||||
'parent': '',
|
||||
'SR_name': 'Local',
|
||||
'sharable': False,
|
||||
'read_only': False,
|
||||
'other_config': {'location': 'file:/root/gentoo.amd64.hvm.img'},
|
||||
}
|
||||
|
||||
local_vbd_cfg = {
|
||||
|
||||
@@ -39,8 +39,7 @@ vm_cfg = {
|
||||
vdi_cfg = {
|
||||
'name_label': 'API_VDI',
|
||||
'name_description': '',
|
||||
'virtual_size': 100 * 1024 * 1024,
|
||||
'sector_size': 1024,
|
||||
'virtual_size': 100 * 1024 * 1024 * 1024,
|
||||
'type': 'system',
|
||||
'parent': '',
|
||||
'SR_name': 'QCoW',
|
||||
@@ -60,14 +59,13 @@ vbd_cfg = {
|
||||
local_vdi_cfg = {
|
||||
'name_label': 'gentoo.amd64.img',
|
||||
'name_description': '',
|
||||
'location': 'file:/root/gentoo.amd64.img',
|
||||
'virtual_size': 0,
|
||||
'sector_size': 0,
|
||||
'type': 'system',
|
||||
'parent': '',
|
||||
'SR_name': 'Local',
|
||||
'sharable': False,
|
||||
'read_only': False,
|
||||
'other_config': {'location': 'file:/root/gentoo.amd64.img'},
|
||||
}
|
||||
|
||||
local_vbd_cfg = {
|
||||
|
||||
@@ -40,8 +40,7 @@ VM_LIST_FORMAT = '%(name_label)-18s %(memory_actual)-5s %(VCPUs_number)-5s'\
|
||||
' %(power_state)-10s %(uuid)-36s'
|
||||
SR_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(physical_size)-10s' \
|
||||
'%(type)-10s'
|
||||
VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s '\
|
||||
'%(sector_size)-8s'
|
||||
VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s'
|
||||
VBD_LIST_FORMAT = '%(device)-6s %(uuid)-36s %(VDI)-8s'
|
||||
TASK_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(status)-8s %(progress)-4s'
|
||||
VIF_LIST_FORMAT = '%(name)-8s %(device)-7s %(uuid)-36s %(MAC)-10s'
|
||||
@@ -96,12 +95,9 @@ OPTIONS = {
|
||||
|
||||
'vdi-create': [(('--name-label',), {'help': 'Name for VDI'}),
|
||||
(('--name-description',), {'help': 'Description for VDI'}),
|
||||
(('--sector-size',), {'type': 'int',
|
||||
'help': 'Sector size',
|
||||
'default': 0}),
|
||||
(('--virtual-size',), {'type': 'int',
|
||||
'default': 0,
|
||||
'help': 'Size of VDI in sectors'}),
|
||||
'help': 'Size of VDI in bytes'}),
|
||||
(('--type',), {'choices': ['system', 'user', 'ephemeral'],
|
||||
'default': 'system',
|
||||
'help': 'VDI type'}),
|
||||
@@ -569,8 +565,7 @@ def xapi_vdi_list(args, async = False):
|
||||
if not is_long:
|
||||
print VDI_LIST_FORMAT % {'name_label': 'VDI Label',
|
||||
'uuid' : 'UUID',
|
||||
'virtual_size': 'Bytes',
|
||||
'sector_size': 'Sector Size'}
|
||||
'virtual_size': 'Bytes'}
|
||||
|
||||
for vdi in vdis:
|
||||
vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
name_label = 'VDI 1'
|
||||
name_description = ''
|
||||
virtual_size = 10 * 1024 * 1024
|
||||
sector_size = 1024
|
||||
virtual_size = 10 * 1024 * 1024 * 1024
|
||||
type = 'system'
|
||||
sharable = False
|
||||
read_only = False
|
||||
@@ -47,20 +47,24 @@ static PyObject *dom_op(XcObject *self, PyObject *args,
|
||||
static PyObject *pyxc_error_to_exception(void)
|
||||
{
|
||||
PyObject *pyerr;
|
||||
const xc_error const *err = xc_get_last_error();
|
||||
const xc_error *err = xc_get_last_error();
|
||||
const char *desc = xc_error_code_to_desc(err->code);
|
||||
|
||||
if (err->code == XC_ERROR_NONE)
|
||||
if ( err->code == XC_ERROR_NONE )
|
||||
return PyErr_SetFromErrno(xc_error_obj);
|
||||
|
||||
if (err->message[0] != '\0')
|
||||
if ( err->message[0] != '\0' )
|
||||
pyerr = Py_BuildValue("(iss)", err->code, desc, err->message);
|
||||
else
|
||||
pyerr = Py_BuildValue("(is)", err->code, desc);
|
||||
|
||||
xc_clear_last_error();
|
||||
|
||||
PyErr_SetObject(xc_error_obj, pyerr);
|
||||
if ( pyerr != NULL )
|
||||
{
|
||||
PyErr_SetObject(xc_error_obj, pyerr);
|
||||
Py_DECREF(pyerr);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -70,13 +74,13 @@ static PyObject *pyxc_domain_dumpcore(XcObject *self, PyObject *args)
|
||||
uint32_t dom;
|
||||
char *corefile;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "is", &dom, &corefile))
|
||||
if ( !PyArg_ParseTuple(args, "is", &dom, &corefile) )
|
||||
return NULL;
|
||||
|
||||
if ( (corefile == NULL) || (corefile[0] == '\0') )
|
||||
return NULL;
|
||||
|
||||
if (xc_domain_dumpcore(self->xc_handle, dom, corefile) != 0)
|
||||
if ( xc_domain_dumpcore(self->xc_handle, dom, corefile) != 0 )
|
||||
return pyxc_error_to_exception();
|
||||
|
||||
Py_INCREF(zero);
|
||||
@@ -168,10 +172,10 @@ static PyObject *pyxc_domain_shutdown(XcObject *self, PyObject *args)
|
||||
{
|
||||
uint32_t dom, reason;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii", &dom, &reason))
|
||||
if ( !PyArg_ParseTuple(args, "ii", &dom, &reason) )
|
||||
return NULL;
|
||||
|
||||
if (xc_domain_shutdown(self->xc_handle, dom, reason) != 0)
|
||||
if ( xc_domain_shutdown(self->xc_handle, dom, reason) != 0 )
|
||||
return pyxc_error_to_exception();
|
||||
|
||||
Py_INCREF(zero);
|
||||
@@ -183,10 +187,10 @@ static PyObject *pyxc_domain_resume(XcObject *self, PyObject *args)
|
||||
uint32_t dom;
|
||||
int fast;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii", &dom, &fast))
|
||||
if ( !PyArg_ParseTuple(args, "ii", &dom, &fast) )
|
||||
return NULL;
|
||||
|
||||
if (xc_domain_resume(self->xc_handle, dom, fast) != 0)
|
||||
if ( xc_domain_resume(self->xc_handle, dom, fast) != 0 )
|
||||
return pyxc_error_to_exception();
|
||||
|
||||
Py_INCREF(zero);
|
||||
@@ -282,7 +286,7 @@ static PyObject *pyxc_domain_getinfo(XcObject *self,
|
||||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
PyObject *list, *info_dict;
|
||||
PyObject *list, *info_dict, *pyhandle;
|
||||
|
||||
uint32_t first_dom = 0;
|
||||
int max_doms = 1024, nr_doms, i, j;
|
||||
@@ -308,26 +312,34 @@ static PyObject *pyxc_domain_getinfo(XcObject *self,
|
||||
list = PyList_New(nr_doms);
|
||||
for ( i = 0 ; i < nr_doms; i++ )
|
||||
{
|
||||
PyObject *pyhandle = PyList_New(sizeof(xen_domain_handle_t));
|
||||
info_dict = Py_BuildValue(
|
||||
"{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
|
||||
",s:L,s:L,s:L,s:i,s:i}",
|
||||
"domid", (int)info[i].domid,
|
||||
"online_vcpus", info[i].nr_online_vcpus,
|
||||
"max_vcpu_id", info[i].max_vcpu_id,
|
||||
"hvm", info[i].hvm,
|
||||
"dying", info[i].dying,
|
||||
"crashed", info[i].crashed,
|
||||
"shutdown", info[i].shutdown,
|
||||
"paused", info[i].paused,
|
||||
"blocked", info[i].blocked,
|
||||
"running", info[i].running,
|
||||
"mem_kb", (long long)info[i].nr_pages*(XC_PAGE_SIZE/1024),
|
||||
"cpu_time", (long long)info[i].cpu_time,
|
||||
"maxmem_kb", (long long)info[i].max_memkb,
|
||||
"ssidref", (int)info[i].ssidref,
|
||||
"shutdown_reason", info[i].shutdown_reason);
|
||||
pyhandle = PyList_New(sizeof(xen_domain_handle_t));
|
||||
if ( (pyhandle == NULL) || (info_dict == NULL) )
|
||||
{
|
||||
Py_DECREF(list);
|
||||
if ( pyhandle != NULL ) { Py_DECREF(pyhandle); }
|
||||
if ( info_dict != NULL ) { Py_DECREF(info_dict); }
|
||||
return NULL;
|
||||
}
|
||||
for ( j = 0; j < sizeof(xen_domain_handle_t); j++ )
|
||||
PyList_SetItem(pyhandle, j, PyInt_FromLong(info[i].handle[j]));
|
||||
info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
|
||||
",s:l,s:L,s:l,s:i,s:i}",
|
||||
"domid", info[i].domid,
|
||||
"online_vcpus", info[i].nr_online_vcpus,
|
||||
"max_vcpu_id", info[i].max_vcpu_id,
|
||||
"hvm", info[i].hvm,
|
||||
"dying", info[i].dying,
|
||||
"crashed", info[i].crashed,
|
||||
"shutdown", info[i].shutdown,
|
||||
"paused", info[i].paused,
|
||||
"blocked", info[i].blocked,
|
||||
"running", info[i].running,
|
||||
"mem_kb", info[i].nr_pages*(XC_PAGE_SIZE/1024),
|
||||
"cpu_time", info[i].cpu_time,
|
||||
"maxmem_kb", info[i].max_memkb,
|
||||
"ssidref", info[i].ssidref,
|
||||
"shutdown_reason", info[i].shutdown_reason);
|
||||
PyDict_SetItemString(info_dict, "handle", pyhandle);
|
||||
Py_DECREF(pyhandle);
|
||||
PyList_SetItem(list, i, info_dict);
|
||||
@@ -1007,6 +1019,24 @@ static PyObject *pyxc_domain_send_trigger(XcObject *self,
|
||||
return zero;
|
||||
}
|
||||
|
||||
static PyObject *pyxc_send_debug_keys(XcObject *self,
|
||||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
char *keys;
|
||||
|
||||
static char *kwd_list[] = { "keys", NULL };
|
||||
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list, &keys) )
|
||||
return NULL;
|
||||
|
||||
if ( xc_send_debug_keys(self->xc_handle, keys) != 0 )
|
||||
return pyxc_error_to_exception();
|
||||
|
||||
Py_INCREF(zero);
|
||||
return zero;
|
||||
}
|
||||
|
||||
static PyObject *dom_op(XcObject *self, PyObject *args,
|
||||
int (*fn)(int, uint32_t))
|
||||
{
|
||||
@@ -1380,6 +1410,12 @@ static PyMethodDef pyxc_methods[] = {
|
||||
" vcpu [int]: VCPU to be sent trigger.\n"
|
||||
"Returns: [int] 0 on success; -1 on error.\n" },
|
||||
|
||||
{ "send_debug_keys",
|
||||
(PyCFunction)pyxc_send_debug_keys,
|
||||
METH_VARARGS | METH_KEYWORDS, "\n"
|
||||
"Inject debug keys into Xen.\n"
|
||||
" keys [str]: String of keys to inject.\n" },
|
||||
|
||||
#ifdef __powerpc__
|
||||
{ "arch_alloc_real_mode_area",
|
||||
(PyCFunction)pyxc_alloc_real_mode_area,
|
||||
|
||||
@@ -66,16 +66,23 @@ def blkdev_segment(name):
|
||||
'type' : 'Disk' }
|
||||
return val
|
||||
|
||||
def blkdev_uname_to_file(uname):
|
||||
"""Take a blkdev uname and return the corresponding filename."""
|
||||
fn = None
|
||||
def _parse_uname(uname):
|
||||
fn = taptype = None
|
||||
if uname.find(":") != -1:
|
||||
(typ, fn) = uname.split(":", 1)
|
||||
if typ == "phy" and not fn.startswith("/"):
|
||||
fn = "/dev/%s" %(fn,)
|
||||
if typ == "tap":
|
||||
(typ, fn) = fn.split(":", 1)
|
||||
return fn
|
||||
(taptype, fn) = fn.split(":", 1)
|
||||
return (fn, taptype)
|
||||
|
||||
def blkdev_uname_to_file(uname):
|
||||
"""Take a blkdev uname and return the corresponding filename."""
|
||||
return _parse_uname(uname)[0]
|
||||
|
||||
def blkdev_uname_to_taptype(uname):
|
||||
"""Take a blkdev uname and return the blktap type."""
|
||||
return _parse_uname(uname)[1]
|
||||
|
||||
def mount_mode(name):
|
||||
mode = None
|
||||
|
||||
@@ -200,6 +200,18 @@ class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer):
|
||||
else:
|
||||
response = self._dispatch(method, params)
|
||||
|
||||
if self.xenapi and \
|
||||
(response is None or
|
||||
not isinstance(response, dict) or
|
||||
'Status' not in response):
|
||||
log.exception('Internal error handling %s: Invalid result %s',
|
||||
method, response)
|
||||
response = { "Status": "Failure",
|
||||
"ErrorDescription":
|
||||
['INTERNAL_ERROR',
|
||||
'Invalid result %s handling %s' %
|
||||
(response, method)]}
|
||||
|
||||
# With either Unicode or normal strings, we can only transmit
|
||||
# \t, \n, \r, \u0020-\ud7ff, \ue000-\ufffd, and \u10000-\u10ffff
|
||||
# in an XML document. xmlrpclib does not escape these values
|
||||
@@ -215,24 +227,30 @@ class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer):
|
||||
response = xmlrpclib.dumps(response,
|
||||
methodresponse=1,
|
||||
allow_none=1)
|
||||
except xmlrpclib.Fault, fault:
|
||||
response = xmlrpclib.dumps(fault)
|
||||
except Exception, exn:
|
||||
if self.xenapi:
|
||||
if _is_not_supported(exn):
|
||||
errdesc = ['MESSAGE_METHOD_UNKNOWN', method]
|
||||
try:
|
||||
if self.xenapi:
|
||||
if _is_not_supported(exn):
|
||||
errdesc = ['MESSAGE_METHOD_UNKNOWN', method]
|
||||
else:
|
||||
log.exception('Internal error handling %s', method)
|
||||
errdesc = ['INTERNAL_ERROR', str(exn)]
|
||||
|
||||
response = xmlrpclib.dumps(
|
||||
({ "Status": "Failure",
|
||||
"ErrorDescription": errdesc },),
|
||||
methodresponse = 1)
|
||||
else:
|
||||
log.exception('Internal error handling %s', method)
|
||||
errdesc = ['INTERNAL_ERROR', str(exn)]
|
||||
response = xmlrpclib.dumps(
|
||||
({ "Status": "Failure",
|
||||
"ErrorDescription": errdesc },),
|
||||
methodresponse = 1)
|
||||
else:
|
||||
log.exception('Internal error handling %s', method)
|
||||
import xen.xend.XendClient
|
||||
response = xmlrpclib.dumps(
|
||||
xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn)))
|
||||
import xen.xend.XendClient
|
||||
if isinstance(exn, xmlrpclib.Fault):
|
||||
response = xmlrpclib.dumps(exn)
|
||||
else:
|
||||
log.exception('Internal error handling %s', method)
|
||||
response = xmlrpclib.dumps(
|
||||
xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn)))
|
||||
except:
|
||||
log.exception('Internal error handling error')
|
||||
|
||||
return response
|
||||
|
||||
|
||||
@@ -241,7 +259,7 @@ def _is_not_supported(exn):
|
||||
try:
|
||||
m = notSupportedRE.search(exn[0])
|
||||
return m is not None
|
||||
except TypeError, e:
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
|
||||
+275
-149
@@ -31,10 +31,14 @@ from xen.xend.XendError import *
|
||||
from xen.xend.XendClient import ERROR_INVALID_DOMAIN
|
||||
from xen.xend.XendLogging import log
|
||||
from xen.xend.XendTask import XendTask
|
||||
from xen.xend.XendVMMetrics import XendVMMetrics
|
||||
|
||||
from xen.xend.XendAPIConstants import *
|
||||
from xen.util.xmlrpclib2 import stringify
|
||||
|
||||
from xen.util.blkif import blkdev_name_to_number
|
||||
|
||||
|
||||
AUTH_NONE = 'none'
|
||||
AUTH_PAM = 'pam'
|
||||
|
||||
@@ -192,6 +196,16 @@ def valid_vm(func):
|
||||
_check_ref(XendDomain.instance().is_valid_vm,
|
||||
'VM', func, *args, **kwargs)
|
||||
|
||||
def valid_vm_metrics(func):
|
||||
"""Decorator to verify if vm_metrics_ref is valid before calling method.
|
||||
|
||||
@param func: function with params: (self, session, vm_metrics_ref, ...)
|
||||
@rtype: callable object
|
||||
"""
|
||||
return lambda *args, **kwargs: \
|
||||
_check_ref(XendVMMetrics.is_valid_vm_metrics,
|
||||
'VM_metrics', func, *args, **kwargs)
|
||||
|
||||
def valid_network(func):
|
||||
"""Decorator to verify if network_ref is valid before calling method.
|
||||
|
||||
@@ -400,6 +414,7 @@ class XendAPI(object):
|
||||
'host_metrics' : valid_host_metrics,
|
||||
'network' : valid_network,
|
||||
'VM' : valid_vm,
|
||||
'VM_metrics' : valid_vm_metrics,
|
||||
'VBD' : valid_vbd,
|
||||
'VBD_metrics' : valid_vbd_metrics,
|
||||
'VIF' : valid_vif,
|
||||
@@ -629,6 +644,7 @@ class XendAPI(object):
|
||||
host_attr_ro = ['software_version',
|
||||
'resident_VMs',
|
||||
'host_CPUs',
|
||||
'cpu_configuration',
|
||||
'metrics',
|
||||
'capabilities',
|
||||
'supported_bootloaders',
|
||||
@@ -638,6 +654,7 @@ class XendAPI(object):
|
||||
'API_version_vendor_implementation']
|
||||
|
||||
host_attr_rw = ['name_label',
|
||||
'sched_policy',
|
||||
'name_description',
|
||||
'other_config']
|
||||
|
||||
@@ -647,7 +664,9 @@ class XendAPI(object):
|
||||
('shutdown', None),
|
||||
('add_to_other_config', None),
|
||||
('remove_from_other_config', None),
|
||||
('dmesg', 'String')]
|
||||
('dmesg', 'String'),
|
||||
('get_log', 'String'),
|
||||
('send_debug_keys', None)]
|
||||
|
||||
host_funcs = [('get_by_name_label', 'Set(host)')]
|
||||
|
||||
@@ -676,8 +695,9 @@ class XendAPI(object):
|
||||
return xen_api_success_void()
|
||||
def host_remove_from_other_config(self, session, host_ref, key):
|
||||
node = XendNode.instance()
|
||||
del node.other_config[key]
|
||||
node.save()
|
||||
if key in node.other_config:
|
||||
del node.other_config[key]
|
||||
node.save()
|
||||
return xen_api_success_void()
|
||||
def host_get_API_version_major(self, _, ref):
|
||||
return xen_api_success(XEN_API_VERSION_MAJOR)
|
||||
@@ -699,7 +719,13 @@ class XendAPI(object):
|
||||
return xen_api_success(XendNode.instance().get_capabilities())
|
||||
def host_get_supported_bootloaders(self, session, host_ref):
|
||||
return xen_api_success(['pygrub'])
|
||||
|
||||
def host_get_sched_policy(self, _, host_ref):
|
||||
return xen_api_success(XendNode.instance().get_vcpus_policy())
|
||||
def host_set_sched_policy(self, _, host_ref, policy):
|
||||
return xen_api_todo()
|
||||
def host_get_cpu_configuration(self, _, host_ref):
|
||||
return xen_api_success(XendNode.instance().get_cpu_configuration())
|
||||
|
||||
# object methods
|
||||
def host_disable(self, session, host_ref):
|
||||
XendDomain.instance().set_allow_new_domains(False)
|
||||
@@ -716,8 +742,21 @@ class XendAPI(object):
|
||||
return xen_api_error(XEND_ERROR_HOST_RUNNING)
|
||||
return xen_api_error(XEND_ERROR_UNSUPPORTED)
|
||||
|
||||
def host_dmesg(self, session, host_ref):
|
||||
return xen_api_success(XendDmesg.instance().info())
|
||||
def host_dmesg(self, session, host_ref, clear):
|
||||
if clear:
|
||||
return xen_api_success(XendDmesg.instance().clear())
|
||||
else:
|
||||
return xen_api_success(XendDmesg.instance().info())
|
||||
|
||||
def host_get_log(self, session, host_ref):
|
||||
log_file = open(XendLogging.getLogFilename())
|
||||
log_buffer = log_file.read()
|
||||
return xen_api_success(log_buffer)
|
||||
|
||||
def host_send_debug_keys(self, _, host_ref, keys):
|
||||
node = XendNode.instance()
|
||||
node.send_debug_keys(keys)
|
||||
return xen_api_success_void()
|
||||
|
||||
def host_get_record(self, session, host_ref):
|
||||
node = XendNode.instance()
|
||||
@@ -734,9 +773,11 @@ class XendAPI(object):
|
||||
'other_config': node.other_config,
|
||||
'resident_VMs': dom.get_domain_refs(),
|
||||
'host_CPUs': node.get_host_cpu_refs(),
|
||||
'cpu_configuration': node.get_cpu_configuration(),
|
||||
'metrics': node.host_metrics_uuid,
|
||||
'capabilities': node.get_capabilities(),
|
||||
'supported_bootloaders': 'pygrub'}
|
||||
'supported_bootloaders': 'pygrub',
|
||||
'sched_policy': node.get_vcpus_policy()}
|
||||
return xen_api_success(record)
|
||||
|
||||
# class methods
|
||||
@@ -758,7 +799,8 @@ class XendAPI(object):
|
||||
'modelname',
|
||||
'stepping',
|
||||
'flags',
|
||||
'utilisation']
|
||||
'utilisation',
|
||||
'features']
|
||||
|
||||
# attributes
|
||||
def _host_cpu_get(self, ref, field):
|
||||
@@ -767,6 +809,8 @@ class XendAPI(object):
|
||||
|
||||
def host_cpu_get_host(self, _, ref):
|
||||
return xen_api_success(XendNode.instance().uuid)
|
||||
def host_cpu_get_features(self, _, ref):
|
||||
return self._host_cpu_get(ref, 'features')
|
||||
def host_cpu_get_number(self, _, ref):
|
||||
return self._host_cpu_get(ref, 'number')
|
||||
def host_cpu_get_vendor(self, _, ref):
|
||||
@@ -989,19 +1033,17 @@ class XendAPI(object):
|
||||
|
||||
VM_attr_ro = ['power_state',
|
||||
'resident_on',
|
||||
'memory_actual',
|
||||
'memory_static_max',
|
||||
'memory_static_min',
|
||||
'VCPUs_number',
|
||||
'VCPUs_utilisation',
|
||||
'consoles',
|
||||
'VIFs',
|
||||
'VBDs',
|
||||
'VTPMs',
|
||||
'PCI_bus',
|
||||
'tools_version',
|
||||
'domid',
|
||||
'is_control_domain',
|
||||
'metrics'
|
||||
]
|
||||
|
||||
VM_attr_rw = ['name_label',
|
||||
@@ -1011,7 +1053,6 @@ class XendAPI(object):
|
||||
'auto_power_on',
|
||||
'memory_dynamic_max',
|
||||
'memory_dynamic_min',
|
||||
'VCPUs_policy',
|
||||
'VCPUs_params',
|
||||
'actions_after_shutdown',
|
||||
'actions_after_reboot',
|
||||
@@ -1024,12 +1065,8 @@ class XendAPI(object):
|
||||
'PV_bootloader_args',
|
||||
'HVM_boot_policy',
|
||||
'HVM_boot_params',
|
||||
'platform_std_VGA',
|
||||
'platform_serial',
|
||||
'platform_localtime',
|
||||
'platform_clock_offset',
|
||||
'platform_enable_audio',
|
||||
'platform_keymap',
|
||||
'platform',
|
||||
'PCI_bus',
|
||||
'other_config']
|
||||
|
||||
VM_methods = [('clone', 'VM'),
|
||||
@@ -1042,8 +1079,16 @@ class XendAPI(object):
|
||||
('hard_reboot', None),
|
||||
('suspend', None),
|
||||
('resume', None),
|
||||
('send_sysrq', None),
|
||||
('add_to_HVM_boot_params', None),
|
||||
('remove_from_HVM_boot_params', None),
|
||||
('add_to_VCPUs_params', None),
|
||||
('remove_from_VCPUs_params', None),
|
||||
('add_to_platform', None),
|
||||
('remove_from_platform', None),
|
||||
('add_to_other_config', None),
|
||||
('remove_from_other_config', None)]
|
||||
('remove_from_other_config', None),
|
||||
('send_trigger', None)]
|
||||
|
||||
VM_funcs = [('create', 'VM'),
|
||||
('get_by_name_label', 'Set(VM)')]
|
||||
@@ -1058,7 +1103,6 @@ class XendAPI(object):
|
||||
'memory_dynamic_max',
|
||||
'memory_dynamic_min',
|
||||
'memory_static_min',
|
||||
'VCPUs_policy',
|
||||
'VCPUs_params',
|
||||
'actions_after_shutdown',
|
||||
'actions_after_reboot',
|
||||
@@ -1071,13 +1115,7 @@ class XendAPI(object):
|
||||
'PV_bootloader_args',
|
||||
'HVM_boot_policy',
|
||||
'HVM_boot_params',
|
||||
'platform_std_VGA',
|
||||
'platform_serial',
|
||||
'platform_localtime',
|
||||
'platform_clock_offset',
|
||||
'platform_enable_audio',
|
||||
'platform_keymap',
|
||||
'grub_cmdline',
|
||||
'platform',
|
||||
'PCI_bus',
|
||||
'other_config']
|
||||
|
||||
@@ -1089,7 +1127,10 @@ class XendAPI(object):
|
||||
xd = XendDomain.instance()
|
||||
dominfo = xd.get_vm_by_uuid(vm_ref)
|
||||
dominfo.info[name] = value
|
||||
xd.managed_config_save(dominfo)
|
||||
return self._VM_save(dominfo)
|
||||
|
||||
def _VM_save(self, dominfo):
|
||||
XendDomain.instance().managed_config_save(dominfo)
|
||||
return xen_api_success_void()
|
||||
|
||||
# attributes (ro)
|
||||
@@ -1099,11 +1140,7 @@ class XendAPI(object):
|
||||
|
||||
def VM_get_resident_on(self, session, vm_ref):
|
||||
return xen_api_success(XendNode.instance().uuid)
|
||||
|
||||
def VM_get_memory_actual(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_todo() # unsupported by xc
|
||||
|
||||
|
||||
def VM_get_memory_static_max(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.get_memory_static_max())
|
||||
@@ -1116,10 +1153,6 @@ class XendAPI(object):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.getVCpuCount())
|
||||
|
||||
def VM_get_VCPUs_utilisation(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.get_vcpus_util())
|
||||
|
||||
def VM_get_VIFs(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.get_vifs())
|
||||
@@ -1136,14 +1169,14 @@ class XendAPI(object):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.get_consoles())
|
||||
|
||||
def VM_get_PCI_bus(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return dom.get_pci_bus()
|
||||
|
||||
def VM_get_tools_version(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return dom.get_tools_version()
|
||||
|
||||
def VM_get_metrics(self, _, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.get_metrics())
|
||||
|
||||
# attributes (rw)
|
||||
def VM_get_name_label(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
@@ -1167,11 +1200,7 @@ class XendAPI(object):
|
||||
|
||||
def VM_get_memory_dynamic_min(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.get_memory_dynamic_min())
|
||||
|
||||
def VM_get_VCPUs_policy(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.get_vcpus_policy())
|
||||
return xen_api_success(dom.get_memory_dynamic_min())
|
||||
|
||||
def VM_get_VCPUs_params(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
@@ -1214,29 +1243,16 @@ class XendAPI(object):
|
||||
def VM_get_HVM_boot_params(self, session, vm_ref):
|
||||
return self.VM_get('HVM_boot_params', session, vm_ref)
|
||||
|
||||
def VM_get_platform_std_VGA(self, session, vm_ref):
|
||||
def VM_get_platform(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.get_platform_std_vga())
|
||||
return xen_api_success(dom.get_platform())
|
||||
|
||||
def VM_get_platform_serial(self, session, vm_ref):
|
||||
def VM_get_PCI_bus(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.get_platform_serial())
|
||||
return dom.get_pci_bus()
|
||||
|
||||
def VM_get_platform_localtime(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.get_platform_localtime())
|
||||
|
||||
def VM_get_platform_clock_offset(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.get_platform_clock_offset())
|
||||
|
||||
def VM_get_platform_enable_audio(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.get_platform_enable_audio())
|
||||
|
||||
def VM_get_platform_keymap(self, session, vm_ref):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_success(dom.get_platform_keymap())
|
||||
def VM_set_PCI_bus(self, session, vm_ref, val):
|
||||
return self.VM_set('PCI_bus', session, vm_ref, val)
|
||||
|
||||
def VM_get_other_config(self, session, vm_ref):
|
||||
return self.VM_get('other_config', session, vm_ref)
|
||||
@@ -1253,7 +1269,7 @@ class XendAPI(object):
|
||||
def VM_set_name_label(self, session, vm_ref, label):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
dom.setName(label)
|
||||
return xen_api_success_void()
|
||||
return self._VM_save(dom)
|
||||
|
||||
def VM_set_name_description(self, session, vm_ref, desc):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
@@ -1275,21 +1291,32 @@ class XendAPI(object):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_todo()
|
||||
|
||||
def VM_set_VCPUs_policy(self, session, vm_ref, policy):
|
||||
def VM_set_VCPUs_params(self, session, vm_ref, value):
|
||||
return self.VM_set('vcpus_params', session, vm_ref, value)
|
||||
|
||||
def VM_add_to_VCPUs_params(self, session, vm_ref, key, value):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_todo()
|
||||
|
||||
def VM_set_VCPUs_params(self, session, vm_ref, params):
|
||||
if 'vcpus_params' not in dom.info:
|
||||
dom.info['vcpus_params'] = {}
|
||||
dom.info['vcpus_params'][key] = value
|
||||
return self._VM_save(dom)
|
||||
|
||||
def VM_remove_from_VCPUs_params(self, session, vm_ref, key):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
return xen_api_todo()
|
||||
if 'vcpus_params' in dom.info \
|
||||
and key in dom.info['vcpus_params']:
|
||||
del dom.info['vcpus_params'][key]
|
||||
return self._VM_save(dom)
|
||||
else:
|
||||
return xen_api_success_void()
|
||||
|
||||
def VM_set_actions_after_shutdown(self, session, vm_ref, action):
|
||||
if action not in XEN_API_ON_NORMAL_EXIST:
|
||||
if action not in XEN_API_ON_NORMAL_EXIT:
|
||||
return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
|
||||
return self.VM_set('actions_after_shutdown', session, vm_ref, action)
|
||||
|
||||
def VM_set_actions_after_reboot(self, session, vm_ref, action):
|
||||
if action not in XEN_API_ON_NORMAL_EXIST:
|
||||
if action not in XEN_API_ON_NORMAL_EXIT:
|
||||
return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
|
||||
return self.VM_set('actions_after_reboot', session, vm_ref, action)
|
||||
|
||||
@@ -1319,14 +1346,16 @@ class XendAPI(object):
|
||||
if 'HVM_boot_params' not in dom.info:
|
||||
dom.info['HVM_boot_params'] = {}
|
||||
dom.info['HVM_boot_params'][key] = value
|
||||
return xen_api_success_void()
|
||||
return self._VM_save(dom)
|
||||
|
||||
def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
if 'HVM_boot_params' in dom.info \
|
||||
and key in dom.info['HVM_boot_params']:
|
||||
del dom.info['HVM_boot_params'][key]
|
||||
return xen_api_success_void()
|
||||
return self._VM_save(dom)
|
||||
else:
|
||||
return xen_api_success_void()
|
||||
|
||||
def VM_set_PV_bootloader(self, session, vm_ref, value):
|
||||
return self.VM_set('PV_bootloader', session, vm_ref, value)
|
||||
@@ -1343,40 +1372,42 @@ class XendAPI(object):
|
||||
def VM_set_PV_bootloader_args(self, session, vm_ref, value):
|
||||
return self.VM_set('PV_bootloader_args', session, vm_ref, value)
|
||||
|
||||
def VM_set_platform_std_VGA(self, session, vm_ref, value):
|
||||
return self.VM_set('platform_std_vga', session, vm_ref, value)
|
||||
def VM_set_platform(self, session, vm_ref, value):
|
||||
return self.VM_set('platform', session, vm_ref, value)
|
||||
|
||||
def VM_set_platform_serial(self, session, vm_ref, value):
|
||||
return self.VM_set('platform_serial', session, vm_ref, value)
|
||||
def VM_add_to_platform(self, session, vm_ref, key, value):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
plat = dom.get_platform()
|
||||
plat[key] = value
|
||||
return self.VM_set_platform(session, vm_ref, plat)
|
||||
|
||||
def VM_remove_from_platform(self, session, vm_ref, key):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
plat = dom.get_platform()
|
||||
if key in plat:
|
||||
del plat[key]
|
||||
return self.VM_set_platform(session, vm_ref, plat)
|
||||
else:
|
||||
return xen_api_success_void()
|
||||
|
||||
def VM_set_platform_keymap(self, session, vm_ref, value):
|
||||
return self.VM_set('platform_keymap', session, vm_ref, value)
|
||||
|
||||
def VM_set_platform_localtime(self, session, vm_ref, value):
|
||||
return self.VM_set('platform_localtime', session, vm_ref, value)
|
||||
|
||||
def VM_set_platform_clock_offset(self, session, vm_ref, value):
|
||||
return self.VM_set('platform_clock_offset', session, vm_ref, value)
|
||||
|
||||
def VM_set_platform_enable_audio(self, session, vm_ref, value):
|
||||
return self.VM_set('platform_enable_audio', session, vm_ref, value)
|
||||
|
||||
def VM_set_other_config(self, session, vm_ref, value):
|
||||
return self.VM_set('otherconfig', session, vm_ref, value)
|
||||
return self.VM_set('other_config', session, vm_ref, value)
|
||||
|
||||
def VM_add_to_other_config(self, session, vm_ref, key, value):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
if dom and 'otherconfig' in dom.info:
|
||||
dom.info['otherconfig'][key] = value
|
||||
return xen_api_success_void()
|
||||
if dom and 'other_config' in dom.info:
|
||||
dom.info['other_config'][key] = value
|
||||
return self._VM_save(dom)
|
||||
|
||||
def VM_remove_from_other_config(self, session, vm_ref, key):
|
||||
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
if dom and 'otherconfig' in dom.info \
|
||||
and key in dom.info['otherconfig']:
|
||||
del dom.info['otherconfig'][key]
|
||||
return xen_api_success_void()
|
||||
|
||||
if dom and 'other_config' in dom.info \
|
||||
and key in dom.info['other_config']:
|
||||
del dom.info['other_config'][key]
|
||||
return self._VM_save(dom)
|
||||
else:
|
||||
return xen_api_success_void()
|
||||
|
||||
# class methods
|
||||
def VM_get_all(self, session):
|
||||
refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
|
||||
@@ -1417,11 +1448,8 @@ class XendAPI(object):
|
||||
'memory_static_max': xeninfo.get_memory_static_max(),
|
||||
'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
|
||||
'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
|
||||
'memory_actual': xeninfo.get_memory_static_min(),
|
||||
'VCPUs_policy': xeninfo.get_vcpus_policy(),
|
||||
'VCPUs_params': xeninfo.get_vcpus_params(),
|
||||
'VCPUs_number': xeninfo.getVCpuCount(),
|
||||
'VCPUs_utilisation': xeninfo.get_vcpus_util(),
|
||||
'actions_after_shutdown': xeninfo.get_on_shutdown(),
|
||||
'actions_after_reboot': xeninfo.get_on_reboot(),
|
||||
'actions_after_suspend': xeninfo.get_on_suspend(),
|
||||
@@ -1437,12 +1465,7 @@ class XendAPI(object):
|
||||
'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
|
||||
'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
|
||||
'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
|
||||
'platform_std_VGA': xeninfo.get_platform_std_vga(),
|
||||
'platform_serial': xeninfo.get_platform_serial(),
|
||||
'platform_localtime': xeninfo.get_platform_localtime(),
|
||||
'platform_clock_offset': xeninfo.get_platform_clock_offset(),
|
||||
'platform_enable_audio': xeninfo.get_platform_enable_audio(),
|
||||
'platform_keymap': xeninfo.get_platform_keymap(),
|
||||
'platform': xeninfo.get_platform(),
|
||||
'PCI_bus': xeninfo.get_pci_bus(),
|
||||
'tools_version': xeninfo.get_tools_version(),
|
||||
'other_config': xeninfo.info.get('other_config', {}),
|
||||
@@ -1486,10 +1509,13 @@ class XendAPI(object):
|
||||
start_paused = start_paused)
|
||||
|
||||
def VM_start(self, session, vm_ref, start_paused):
|
||||
return XendTask.log_progress(0, 100, do_vm_func,
|
||||
"domain_start", vm_ref,
|
||||
start_paused = start_paused)
|
||||
|
||||
try:
|
||||
return XendTask.log_progress(0, 100, do_vm_func,
|
||||
"domain_start", vm_ref,
|
||||
start_paused = start_paused)
|
||||
except HVMRequired, exn:
|
||||
return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
|
||||
|
||||
def VM_suspend(self, session, vm_ref):
|
||||
return XendTask.log_progress(0, 100, do_vm_func,
|
||||
"domain_suspend", vm_ref)
|
||||
@@ -1498,10 +1524,56 @@ class XendAPI(object):
|
||||
return XendTask.log_progress(0, 100, do_vm_func,
|
||||
"domain_unpause", vm_ref)
|
||||
|
||||
def VM_send_sysrq(self, _, vm_ref, req):
|
||||
xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref)
|
||||
if xeninfo.state != XEN_API_VM_POWER_STATE_RUNNING:
|
||||
return xen_api_error(
|
||||
['VM_BAD_POWER_STATE', vm_ref,
|
||||
XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING],
|
||||
XendDomain.POWER_STATE_NAMES[xeninfo.state]])
|
||||
xeninfo.send_sysrq(req)
|
||||
return xen_api_success_void()
|
||||
|
||||
|
||||
def VM_send_trigger(self, _, vm_ref, trigger, vcpu):
|
||||
xendom = XendDomain.instance()
|
||||
xeninfo = xendom.get_vm_by_uuid(vm_ref)
|
||||
xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu)
|
||||
return xen_api_success_void()
|
||||
|
||||
|
||||
# Xen API: Class VM_metrics
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
VM_metrics_attr_ro = ['memory_actual',
|
||||
'vcpus_number',
|
||||
'vcpus_utilisation']
|
||||
VM_metrics_attr_rw = []
|
||||
VM_metrics_methods = []
|
||||
|
||||
def _VM_metrics_get(self, ref):
|
||||
return XendVMMetrics.get_by_uuid(ref)
|
||||
|
||||
def VM_metrics_get_all(self, _):
|
||||
return xen_api_success(XendVMMetrics.get_all())
|
||||
|
||||
def VM_metrics_get_record(self, _, ref):
|
||||
return xen_api_success(self._VM_metrics_get(ref).get_record())
|
||||
|
||||
def VM_metrics_get_memory_actual(self, _, ref):
|
||||
return xen_api_success(self._VM_metrics_get(ref).get_memory_actual())
|
||||
|
||||
def VM_metrics_get_vcpus_number(self, _, ref):
|
||||
return xen_api_success(self._VM_metrics_get(ref).get_vcpus_number())
|
||||
|
||||
def VM_metrics_get_vcpus_utilisation(self, _, ref):
|
||||
return xen_api_success(self._VM_metrics_get(ref).get_vcpus_utilisation())
|
||||
|
||||
# Xen API: Class VBD
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
VBD_attr_ro = ['metrics']
|
||||
VBD_attr_ro = ['metrics',
|
||||
'runtime_properties']
|
||||
VBD_attr_rw = ['VM',
|
||||
'VDI',
|
||||
'device',
|
||||
@@ -1542,23 +1614,28 @@ class XendAPI(object):
|
||||
# class methods
|
||||
def VBD_create(self, session, vbd_struct):
|
||||
xendom = XendDomain.instance()
|
||||
xennode = XendNode.instance()
|
||||
|
||||
if not xendom.is_valid_vm(vbd_struct['VM']):
|
||||
return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
|
||||
|
||||
dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
|
||||
vbd_ref = ''
|
||||
vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI'])
|
||||
if not vdi:
|
||||
return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
|
||||
|
||||
# new VBD via VDI/SR
|
||||
vdi_image = vdi.get_location()
|
||||
|
||||
try:
|
||||
# new VBD via VDI/SR
|
||||
vdi_ref = vbd_struct.get('VDI')
|
||||
vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
|
||||
if not vdi:
|
||||
return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
|
||||
vdi_image = vdi.get_location()
|
||||
vbd_ref = XendTask.log_progress(0, 100,
|
||||
dom.create_vbd,
|
||||
vbd_struct, vdi_image)
|
||||
except XendError:
|
||||
return xen_api_todo()
|
||||
except XendError, e:
|
||||
log.exception("Error in VBD_create")
|
||||
return xen_api_error(['INTERNAL_ERROR', str(e)])
|
||||
|
||||
vdi.addVBD(vbd_ref)
|
||||
|
||||
xendom.managed_config_save(dom)
|
||||
return xen_api_success(vbd_ref)
|
||||
@@ -1570,7 +1647,14 @@ class XendAPI(object):
|
||||
if not vm:
|
||||
return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
|
||||
|
||||
vdi_ref = XendDomain.instance()\
|
||||
.get_dev_property_by_uuid('vbd', vbd_ref, "VDI")
|
||||
vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
|
||||
|
||||
XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
|
||||
|
||||
vdi.removeVBD(vbd_ref)
|
||||
|
||||
return xen_api_success_void()
|
||||
|
||||
def _VBD_get(self, vbd_ref, prop):
|
||||
@@ -1582,6 +1666,24 @@ class XendAPI(object):
|
||||
def VBD_get_metrics(self, _, vbd_ref):
|
||||
return xen_api_success(vbd_ref)
|
||||
|
||||
def VBD_get_runtime_properties(self, _, vbd_ref):
|
||||
xendom = XendDomain.instance()
|
||||
dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
|
||||
device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref)
|
||||
|
||||
try:
|
||||
devid = int(device['id'])
|
||||
device_sxps = dominfo.getDeviceSxprs('vbd')
|
||||
device_dicts = [dict(device_sxp[1][1:]) for device_sxp in device_sxps]
|
||||
device_dict = [device_dict
|
||||
for device_dict in device_dicts
|
||||
if int(device_dict['virtual-device']) == devid][0]
|
||||
|
||||
return xen_api_success(device_dict)
|
||||
except Exception, exn:
|
||||
log.exception(exn)
|
||||
return xen_api_success({})
|
||||
|
||||
# attributes (rw)
|
||||
def VBD_get_VM(self, session, vbd_ref):
|
||||
return self._VBD_get(vbd_ref, 'VM')
|
||||
@@ -1642,7 +1744,8 @@ class XendAPI(object):
|
||||
# Xen API: Class VIF
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
VIF_attr_ro = ['metrics']
|
||||
VIF_attr_ro = ['metrics',
|
||||
'runtime_properties']
|
||||
VIF_attr_rw = ['device',
|
||||
'network',
|
||||
'VM',
|
||||
@@ -1679,18 +1782,17 @@ class XendAPI(object):
|
||||
# class methods
|
||||
def VIF_create(self, session, vif_struct):
|
||||
xendom = XendDomain.instance()
|
||||
if xendom.is_valid_vm(vif_struct['VM']):
|
||||
dom = xendom.get_vm_by_uuid(vif_struct['VM'])
|
||||
try:
|
||||
vif_ref = dom.create_vif(vif_struct)
|
||||
xendom.managed_config_save(dom)
|
||||
return xen_api_success(vif_ref)
|
||||
except XendError:
|
||||
return xen_api_error(XEND_ERROR_TODO)
|
||||
else:
|
||||
if not xendom.is_valid_vm(vif_struct['VM']):
|
||||
return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
|
||||
|
||||
|
||||
dom = xendom.get_vm_by_uuid(vif_struct['VM'])
|
||||
try:
|
||||
vif_ref = dom.create_vif(vif_struct)
|
||||
xendom.managed_config_save(dom)
|
||||
return xen_api_success(vif_ref)
|
||||
except XendError:
|
||||
return xen_api_error(XEND_ERROR_TODO)
|
||||
|
||||
def VIF_destroy(self, session, vif_ref):
|
||||
xendom = XendDomain.instance()
|
||||
vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
|
||||
@@ -1728,6 +1830,27 @@ class XendAPI(object):
|
||||
vifs = reduce(lambda x, y: x + y, vifs)
|
||||
return xen_api_success(vifs)
|
||||
|
||||
def VIF_get_runtime_properties(self, _, vif_ref):
|
||||
xendom = XendDomain.instance()
|
||||
dominfo = xendom.get_vm_with_dev_uuid('vif', vif_ref)
|
||||
device = dominfo.get_dev_config_by_uuid('vif', vif_ref)
|
||||
|
||||
try:
|
||||
devid = int(device['id'])
|
||||
|
||||
device_sxps = dominfo.getDeviceSxprs('vif')
|
||||
device_dicts = [dict(device_sxp[1][1:])
|
||||
for device_sxp in device_sxps]
|
||||
|
||||
device_dict = [device_dict
|
||||
for device_dict in device_dicts
|
||||
if int(device_dict['handle']) == devid][0]
|
||||
|
||||
return xen_api_success(device_dict)
|
||||
|
||||
except Exception, exn:
|
||||
log.exception(exn)
|
||||
return xen_api_success({})
|
||||
|
||||
# Xen API: Class VIF_metrics
|
||||
# ----------------------------------------------------------------
|
||||
@@ -1754,16 +1877,16 @@ class XendAPI(object):
|
||||
|
||||
# Xen API: Class VDI
|
||||
# ----------------------------------------------------------------
|
||||
VDI_attr_ro = ['VBDs',
|
||||
VDI_attr_ro = ['SR',
|
||||
'VBDs',
|
||||
'physical_utilisation',
|
||||
'sector_size',
|
||||
'type']
|
||||
VDI_attr_rw = ['name_label',
|
||||
'name_description',
|
||||
'SR',
|
||||
'virtual_size',
|
||||
'sharable',
|
||||
'read_only']
|
||||
'read_only',
|
||||
'other_config']
|
||||
VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
|
||||
|
||||
VDI_methods = [('snapshot', 'VDI')]
|
||||
@@ -1774,14 +1897,12 @@ class XendAPI(object):
|
||||
return XendNode.instance().get_vdi_by_uuid(ref)
|
||||
|
||||
def VDI_get_VBDs(self, session, vdi_ref):
|
||||
return xen_api_todo()
|
||||
vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
|
||||
return xen_api_success(vdi.getVBDs())
|
||||
|
||||
def VDI_get_physical_utilisation(self, session, vdi_ref):
|
||||
return xen_api_success(self._get_VDI(vdi_ref).
|
||||
get_physical_utilisation())
|
||||
|
||||
def VDI_get_sector_size(self, session, vdi_ref):
|
||||
return xen_api_success(self._get_VDI(vdi_ref).sector_size)
|
||||
get_physical_utilisation())
|
||||
|
||||
def VDI_get_type(self, session, vdi_ref):
|
||||
return xen_api_success(self._get_VDI(vdi_ref).type)
|
||||
@@ -1812,9 +1933,6 @@ class XendAPI(object):
|
||||
self._get_VDI(vdi_ref).name_description = value
|
||||
return xen_api_success_void()
|
||||
|
||||
def VDI_set_SR(self, session, vdi_ref, value):
|
||||
return xen_api_error(XEND_ERROR_UNSUPPORTED)
|
||||
|
||||
def VDI_set_virtual_size(self, session, vdi_ref, value):
|
||||
return xen_api_error(XEND_ERROR_UNSUPPORTED)
|
||||
|
||||
@@ -1826,6 +1944,14 @@ class XendAPI(object):
|
||||
self._get_VDI(vdi_ref).read_only = bool(value)
|
||||
return xen_api_success_void()
|
||||
|
||||
def VDI_get_other_config(self, session, vdi_ref):
|
||||
return xen_api_success(
|
||||
self._get_VDI(vdi_ref).other_config)
|
||||
|
||||
def VDI_set_other_config(self, session, vdi_ref, other_config):
|
||||
self._get_VDI(vdi_ref).other_config = other_config
|
||||
return xen_api_success_void()
|
||||
|
||||
# Object Methods
|
||||
def VDI_snapshot(self, session, vdi_ref):
|
||||
return xen_api_todo()
|
||||
@@ -1842,13 +1968,13 @@ class XendAPI(object):
|
||||
'name_label': image.name_label,
|
||||
'name_description': image.name_description,
|
||||
'SR': image.sr_uuid,
|
||||
'VBDs': [], # TODO
|
||||
'VBDs': image.getVBDs(),
|
||||
'virtual_size': image.virtual_size,
|
||||
'physical_utilisation': image.physical_utilisation,
|
||||
'sector_size': image.sector_size,
|
||||
'type': image.type,
|
||||
'sharable': image.sharable,
|
||||
'read_only': image.read_only,
|
||||
'other_config': image.other_config
|
||||
})
|
||||
|
||||
# Class Functions
|
||||
@@ -1929,7 +2055,7 @@ class XendAPI(object):
|
||||
XendDomain.POWER_STATE_NAMES[dom.state]])
|
||||
from xen.xend.server import tpmif
|
||||
tpmif.destroy_vtpmstate(dom.getName())
|
||||
return xen_api_success(True)
|
||||
return xen_api_success_void()
|
||||
else:
|
||||
return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import os
|
||||
import re
|
||||
import string
|
||||
import threading
|
||||
import fcntl
|
||||
from struct import pack, unpack, calcsize
|
||||
|
||||
from xen.util.xpopen import xPopen3
|
||||
@@ -73,10 +74,15 @@ def save(fd, dominfo, network, live, dst, checkpoint=False):
|
||||
write_exact(fd, config, "could not write guest state file: config")
|
||||
|
||||
image_cfg = dominfo.info.get('image', {})
|
||||
hvm = image_cfg.has_key('hvm')
|
||||
hvm = dominfo.info.is_hvm()
|
||||
stdvga = 0
|
||||
|
||||
if hvm:
|
||||
log.info("save hvm domain")
|
||||
if dominfo.info['platform'].has_key('stdvga'):
|
||||
if dominfo.info['platform']['stdvga'] == 1:
|
||||
stdvga = 1
|
||||
|
||||
# xc_save takes three customization parameters: maxit, max_f, and
|
||||
# flags the last controls whether or not save is 'live', while the
|
||||
# first two further customize behaviour when 'live' save is
|
||||
@@ -84,7 +90,8 @@ def save(fd, dominfo, network, live, dst, checkpoint=False):
|
||||
# libxenguest; see the comments and/or code in xc_linux_save() for
|
||||
# more information.
|
||||
cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
|
||||
str(dominfo.getDomid()), "0", "0", str(int(live) | (int(hvm) << 2)) ]
|
||||
str(dominfo.getDomid()), "0", "0",
|
||||
str(int(live) | (int(hvm) << 2) | (int(stdvga) << 3)) ]
|
||||
log.debug("[xc_save]: %s", string.join(cmd))
|
||||
|
||||
def saveInputHandler(line, tochild):
|
||||
@@ -183,11 +190,11 @@ def restore(xd, fd, dominfo = None, paused = False):
|
||||
|
||||
# if hvm, pass mem size to calculate the store_mfn
|
||||
image_cfg = dominfo.info.get('image', {})
|
||||
is_hvm = image_cfg.has_key('hvm')
|
||||
is_hvm = dominfo.info.is_hvm()
|
||||
if is_hvm:
|
||||
hvm = dominfo.info['memory_static_min']
|
||||
apic = dominfo.info['image']['hvm'].get('apic', 0)
|
||||
pae = dominfo.info['image']['hvm'].get('pae', 0)
|
||||
apic = int(dominfo.info['platform'].get('apic', 0))
|
||||
pae = int(dominfo.info['platform'].get('pae', 0))
|
||||
log.info("restore hvm domain %d, mem=%d, apic=%d, pae=%d",
|
||||
dominfo.domid, hvm, apic, pae)
|
||||
else:
|
||||
@@ -224,6 +231,15 @@ def restore(xd, fd, dominfo = None, paused = False):
|
||||
|
||||
forkHelper(cmd, fd, handler.handler, True)
|
||||
|
||||
# We don't want to pass this fd to any other children -- we
|
||||
# might need to recover ths disk space that backs it.
|
||||
try:
|
||||
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
|
||||
flags |= fcntl.FD_CLOEXEC
|
||||
fcntl.fcntl(fd, fcntl.F_SETFD, flags)
|
||||
except:
|
||||
pass
|
||||
|
||||
if handler.store_mfn is None:
|
||||
raise XendError('Could not read store MFN')
|
||||
|
||||
|
||||
+149
-227
@@ -12,7 +12,7 @@
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2006 XenSource Ltd
|
||||
# Copyright (C) 2006-2007 XenSource Ltd
|
||||
#============================================================================
|
||||
|
||||
import logging
|
||||
@@ -28,7 +28,7 @@ from xen.xend.PrettyPrint import prettyprintstring
|
||||
from xen.xend.XendConstants import DOM_STATE_HALTED
|
||||
|
||||
log = logging.getLogger("xend.XendConfig")
|
||||
log.setLevel(logging.DEBUG)
|
||||
log.setLevel(logging.WARN)
|
||||
|
||||
|
||||
"""
|
||||
@@ -105,28 +105,23 @@ XENAPI_CFG_TO_LEGACY_CFG = {
|
||||
'uuid': 'uuid',
|
||||
'vcpus_number': 'vcpus',
|
||||
'cpus': 'cpus',
|
||||
'memory_static_min': 'memory',
|
||||
'memory_static_max': 'maxmem',
|
||||
'name_label': 'name',
|
||||
'actions_after_shutdown': 'on_poweroff',
|
||||
'actions_after_reboot': 'on_reboot',
|
||||
'actions_after_crash': 'on_crash',
|
||||
'platform_localtime': 'localtime',
|
||||
'PV_bootloader': 'bootloader',
|
||||
'PV_bootloader_args': 'bootloader_args',
|
||||
}
|
||||
|
||||
LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(XENAPI_CFG_TO_LEGACY_CFG)
|
||||
|
||||
# Mapping from XendConfig configuration keys to the old
|
||||
# legacy configuration keys that are found in the 'image'
|
||||
# SXP object.
|
||||
XENAPI_HVM_CFG = {
|
||||
'platform_std_vga': 'stdvga',
|
||||
'platform_serial' : 'serial',
|
||||
'platform_localtime': 'localtime',
|
||||
'platform_keymap' : 'keymap'
|
||||
}
|
||||
# Platform configuration keys.
|
||||
XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'boot', 'device_model', 'display',
|
||||
'fda', 'fdb', 'keymap', 'isa', 'localtime',
|
||||
'nographic', 'pae', 'serial', 'sdl',
|
||||
'soundhw','stdvga', 'usb', 'usbdevice', 'vnc',
|
||||
'vncconsole', 'vncdisplay', 'vnclisten',
|
||||
'vncpasswd', 'vncunused', 'xauthority']
|
||||
|
||||
# List of XendConfig configuration keys that have no direct equivalent
|
||||
# in the old world.
|
||||
@@ -139,11 +134,10 @@ XENAPI_CFG_TYPES = {
|
||||
'user_version': str,
|
||||
'is_a_template': bool0,
|
||||
'resident_on': str,
|
||||
'memory_static_min': int,
|
||||
'memory_static_min': int, # note these are stored in bytes, not KB!
|
||||
'memory_static_max': int,
|
||||
'memory_dynamic_min': int,
|
||||
'memory_dynamic_max': int,
|
||||
'memory_actual': int,
|
||||
'cpus': list,
|
||||
'vcpus_policy': str,
|
||||
'vcpus_params': dict,
|
||||
@@ -151,7 +145,6 @@ XENAPI_CFG_TYPES = {
|
||||
'actions_after_shutdown': str,
|
||||
'actions_after_reboot': str,
|
||||
'actions_after_crash': str,
|
||||
'tpm_backend': int,
|
||||
'PV_bootloader': str,
|
||||
'PV_kernel': str,
|
||||
'PV_ramdisk': str,
|
||||
@@ -159,15 +152,10 @@ XENAPI_CFG_TYPES = {
|
||||
'PV_bootloader_args': str,
|
||||
'HVM_boot_policy': str,
|
||||
'HVM_boot_params': dict,
|
||||
'platform_std_vga': bool0,
|
||||
'platform_serial': str,
|
||||
'platform_localtime': bool0,
|
||||
'platform_clock_offset': bool0,
|
||||
'platform_enable_audio': bool0,
|
||||
'platform_keymap': str,
|
||||
'pci_bus': str,
|
||||
'PCI_bus': str,
|
||||
'platform': dict,
|
||||
'tools_version': dict,
|
||||
'otherconfig': dict,
|
||||
'other_config': dict,
|
||||
}
|
||||
|
||||
# List of legacy configuration keys that have no equivalent in the
|
||||
@@ -237,44 +225,7 @@ LEGACY_XENSTORE_VM_PARAMS = [
|
||||
'on_xend_stop',
|
||||
]
|
||||
|
||||
LEGACY_IMAGE_CFG = [
|
||||
('root', str),
|
||||
('ip', str),
|
||||
('nographic', int),
|
||||
('vnc', int),
|
||||
('sdl', int),
|
||||
('vncdisplay', int),
|
||||
('vncunused', int),
|
||||
('vncpasswd', str),
|
||||
('vnclisten', str),
|
||||
]
|
||||
|
||||
LEGACY_IMAGE_HVM_CFG = [
|
||||
('device_model', str),
|
||||
('display', str),
|
||||
('xauthority', str),
|
||||
('vncconsole', int),
|
||||
('pae', int),
|
||||
('apic', int),
|
||||
]
|
||||
|
||||
LEGACY_IMAGE_HVM_DEVICES_CFG = [
|
||||
('acpi', int),
|
||||
('boot', str),
|
||||
('fda', str),
|
||||
('fdb', str),
|
||||
('isa', int),
|
||||
('keymap', str),
|
||||
('localtime', int),
|
||||
('serial', str),
|
||||
('stdvga', int),
|
||||
('soundhw', str),
|
||||
('usb', int),
|
||||
('usbdevice', str),
|
||||
('vcpus', int),
|
||||
]
|
||||
|
||||
LEGACY_DM = '/usr/lib/xen/bin/qemu-dm'
|
||||
DEFAULT_DM = '/usr/lib/xen/bin/qemu-dm'
|
||||
|
||||
##
|
||||
## Config Choices
|
||||
@@ -316,7 +267,6 @@ class XendConfig(dict):
|
||||
self._sxp_to_xapi_unsupported(sxp_obj)
|
||||
elif xapi:
|
||||
self.update_with_xenapi_config(xapi)
|
||||
self._add_xapi_unsupported(xapi)
|
||||
elif dominfo:
|
||||
# output from xc.domain_getinfo
|
||||
self._dominfo_to_xapi(dominfo)
|
||||
@@ -361,9 +311,7 @@ class XendConfig(dict):
|
||||
'shadow_memory': 0,
|
||||
'memory_static_max': 0,
|
||||
'memory_dynamic_max': 0,
|
||||
'memory_actual': 0,
|
||||
'devices': {},
|
||||
'image': {},
|
||||
'security': None,
|
||||
'on_xend_start': 'ignore',
|
||||
'on_xend_stop': 'ignore',
|
||||
@@ -377,24 +325,44 @@ class XendConfig(dict):
|
||||
'vbd_refs': [],
|
||||
'vtpm_refs': [],
|
||||
'other_config': {},
|
||||
'platform': {}
|
||||
}
|
||||
|
||||
return defaults
|
||||
|
||||
#
|
||||
# Here we assume these values exist in the dict.
|
||||
# If they don't we have a bigger problem, lets not
|
||||
# try and 'fix it up' but acutually fix the cause ;-)
|
||||
#
|
||||
def _memory_sanity_check(self):
|
||||
if self['memory_static_min'] == 0:
|
||||
self['memory_static_min'] = self['memory_dynamic_min']
|
||||
|
||||
# If the static max is not set, let's set it to dynamic max.
|
||||
# If the static max is smaller than static min, then fix it!
|
||||
self['memory_static_max'] = max(self['memory_static_max'],
|
||||
self['memory_dynamic_max'],
|
||||
self['memory_static_min'])
|
||||
|
||||
for mem_type in ('memory_static_min', 'memory_static_max'):
|
||||
if self[mem_type] <= 0:
|
||||
raise XendConfigError('Memory value too low for %s: %d' %
|
||||
(mem_type, self[mem_type]))
|
||||
log.debug("_memory_sanity_check memory_static_min: %s, "
|
||||
"memory_static_max: %i, "
|
||||
"memory_dynamic_min: %i, "
|
||||
"memory_dynamic_max: %i",
|
||||
self["memory_static_min"],
|
||||
self["memory_static_max"],
|
||||
self["memory_dynamic_min"],
|
||||
self["memory_dynamic_max"])
|
||||
|
||||
if not self["memory_static_min"] <= self["memory_static_max"]:
|
||||
raise XendConfigError("memory_static_min must be less " \
|
||||
"than or equal to memory_static_max")
|
||||
if not self["memory_dynamic_min"] <= self["memory_dynamic_max"]:
|
||||
raise XendConfigError("memory_dynamic_min must be less " \
|
||||
"than or equal to memory_dynamic_max")
|
||||
if not self["memory_static_min"] <= self["memory_dynamic_min"]:
|
||||
raise XendConfigError("memory_static_min must be less " \
|
||||
"than or equal to memory_dynamic_min")
|
||||
if not self["memory_dynamic_max"] <= self["memory_static_max"]:
|
||||
raise XendConfigError("memory_dynamic_max must be less " \
|
||||
"than or equal to memory_static_max")
|
||||
if not self["memory_dynamic_max"] > 0:
|
||||
raise XendConfigError("memory_dynamic_max must be greater " \
|
||||
"than zero")
|
||||
if not self["memory_static_max"] > 0:
|
||||
raise XendConfigError("memory_static_max must be greater " \
|
||||
"than zero")
|
||||
|
||||
def _actions_sanity_check(self):
|
||||
for event in ['shutdown', 'reboot', 'crash']:
|
||||
@@ -417,19 +385,34 @@ class XendConfig(dict):
|
||||
if 'name_label' not in self:
|
||||
self['name_label'] = 'Domain-' + self['uuid']
|
||||
|
||||
def _platform_sanity_check(self):
|
||||
if self.is_hvm():
|
||||
if 'device_model' not in self['platform']:
|
||||
self['platform']['device_model'] = DEFAULT_DM
|
||||
|
||||
# Compatibility hack, can go away soon.
|
||||
if 'soundhw' not in self['platform'] and \
|
||||
self['platform'].get('enable_audio'):
|
||||
self['platform']['soundhw'] = 'sb16'
|
||||
|
||||
def validate(self):
|
||||
self._uuid_sanity_check()
|
||||
self._name_sanity_check()
|
||||
self._memory_sanity_check()
|
||||
self._actions_sanity_check()
|
||||
self._vcpus_sanity_check()
|
||||
self._platform_sanity_check()
|
||||
|
||||
def _dominfo_to_xapi(self, dominfo):
|
||||
self['domid'] = dominfo['domid']
|
||||
self['online_vcpus'] = dominfo['online_vcpus']
|
||||
self['vcpus_number'] = dominfo['max_vcpu_id'] + 1
|
||||
self['memory_dynamic_min'] = (dominfo['mem_kb'] + 1023)/1024
|
||||
self['memory_dynamic_max'] = (dominfo['maxmem_kb'] + 1023)/1024
|
||||
|
||||
self['memory_dynamic_min'] = dominfo['mem_kb'] * 1024
|
||||
self['memory_dynamic_max'] = dominfo['mem_kb'] * 1024
|
||||
self['memory_static_min'] = 0
|
||||
self['memory_static_max'] = dominfo['maxmem_kb'] * 1024
|
||||
|
||||
self['cpu_time'] = dominfo['cpu_time']/1e9
|
||||
# TODO: i don't know what the security stuff expects here
|
||||
if dominfo.get('ssidref'):
|
||||
@@ -483,6 +466,13 @@ class XendConfig(dict):
|
||||
log.warn('Ignoring unrecognised value for deprecated option:'
|
||||
'restart = \'%s\'', restart)
|
||||
|
||||
# Handle memory, passed in as MiB
|
||||
|
||||
if sxp.child_value(sxp_cfg, "memory") != None:
|
||||
cfg["memory"] = int(sxp.child_value(sxp_cfg, "memory"))
|
||||
if sxp.child_value(sxp_cfg, "maxmem") != None:
|
||||
cfg["maxmem"] = int(sxp.child_value(sxp_cfg, "maxmem"))
|
||||
|
||||
# Only extract options we know about.
|
||||
extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG
|
||||
extract_keys += XENAPI_CFG_TO_LEGACY_CFG.values()
|
||||
@@ -498,6 +488,18 @@ class XendConfig(dict):
|
||||
log.warn("Unable to parse key %s: %s: %s" %
|
||||
(key, str(val), e))
|
||||
|
||||
if 'platform' not in cfg:
|
||||
cfg['platform'] = {}
|
||||
localtime = sxp.child_value(sxp_cfg, 'localtime')
|
||||
if localtime is not None:
|
||||
cfg['platform']['localtime'] = localtime
|
||||
|
||||
# Compatibility hack -- can go soon.
|
||||
for key in XENAPI_PLATFORM_CFG:
|
||||
val = sxp.child_value(sxp_cfg, "platform_" + key, None)
|
||||
if val is not None:
|
||||
self['platform'][key] = val
|
||||
|
||||
# Compatibility hack -- can go soon.
|
||||
boot_order = sxp.child_value(sxp_cfg, 'HVM_boot')
|
||||
if boot_order:
|
||||
@@ -640,6 +642,21 @@ class XendConfig(dict):
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# Lets try and handle memory correctly
|
||||
|
||||
MiB = 1024 * 1024
|
||||
|
||||
if "memory" in cfg:
|
||||
self["memory_static_min"] = 0
|
||||
self["memory_static_max"] = int(cfg["memory"]) * MiB
|
||||
self["memory_dynamic_min"] = int(cfg["memory"]) * MiB
|
||||
self["memory_dynamic_max"] = int(cfg["memory"]) * MiB
|
||||
|
||||
if "maxmem" in cfg:
|
||||
self["memory_static_max"] = int(cfg["maxmem"]) * MiB
|
||||
|
||||
self._memory_sanity_check()
|
||||
|
||||
def update_with(n, o):
|
||||
if not self.get(n):
|
||||
self[n] = cfg.get(o, '')
|
||||
@@ -652,17 +669,9 @@ class XendConfig(dict):
|
||||
self.update_with_image_sxp(image_sxp)
|
||||
|
||||
# Convert Legacy HVM parameters to Xen API configuration
|
||||
self['platform_std_vga'] = bool0(cfg.get('stdvga', 0))
|
||||
self['platform_serial'] = str(cfg.get('serial', ''))
|
||||
self['platform_localtime'] = bool0(cfg.get('localtime', 0))
|
||||
self['platform_enable_audio'] = bool0(cfg.get('soundhw', 0))
|
||||
|
||||
# make sure a sane maximum is set
|
||||
if self['memory_static_max'] <= 0:
|
||||
self['memory_static_max'] = self['memory_static_min']
|
||||
|
||||
self['memory_dynamic_max'] = self['memory_static_max']
|
||||
self['memory_dynamic_min'] = self['memory_static_min']
|
||||
for key in XENAPI_PLATFORM_CFG:
|
||||
if key in cfg:
|
||||
self['platform'][key] = cfg[key]
|
||||
|
||||
# set device references in the configuration
|
||||
self['devices'] = cfg.get('devices', {})
|
||||
@@ -672,7 +681,7 @@ class XendConfig(dict):
|
||||
self['vtpm_refs'] = cfg.get('vtpm_refs', [])
|
||||
|
||||
# coalesce hvm vnc frame buffer with vfb config
|
||||
if self['image']['type'] == 'hvm' and self['image'].get('vnc', 0):
|
||||
if self.is_hvm() and self['platform'].get('vnc', 0):
|
||||
# add vfb device if it isn't there already
|
||||
has_rfb = False
|
||||
for console_uuid in self['console_refs']:
|
||||
@@ -685,11 +694,11 @@ class XendConfig(dict):
|
||||
|
||||
if not has_rfb:
|
||||
dev_config = ['vfb']
|
||||
# copy VNC related params from image config to vfb dev conf
|
||||
# copy VNC related params from platform config to vfb dev conf
|
||||
for key in ['vncpasswd', 'vncunused', 'vncdisplay',
|
||||
'vnclisten']:
|
||||
if key in self['image']:
|
||||
dev_config.append([key, self['image'][key]])
|
||||
if key in self['platform']:
|
||||
dev_config.append([key, self['platform'][key]])
|
||||
|
||||
self.device_add('vfb', cfg_sxp = dev_config)
|
||||
|
||||
@@ -706,39 +715,19 @@ class XendConfig(dict):
|
||||
# the image (as well as HVM images)
|
||||
image_sxp = sxp.child_value(sxp_cfg, 'image', [])
|
||||
if image_sxp:
|
||||
image = {}
|
||||
image['type'] = sxp.name(image_sxp)
|
||||
for arg, conv in LEGACY_IMAGE_CFG:
|
||||
val = sxp.child_value(image_sxp, arg, None)
|
||||
if val != None:
|
||||
image[arg] = conv(val)
|
||||
|
||||
image_hvm = {}
|
||||
for arg, conv in LEGACY_IMAGE_HVM_CFG:
|
||||
val = sxp.child_value(image_sxp, arg, None)
|
||||
if val != None:
|
||||
image_hvm[arg] = conv(val)
|
||||
|
||||
image_hvm_devices = {}
|
||||
for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
|
||||
val = sxp.child_value(image_sxp, arg, None)
|
||||
if val != None:
|
||||
image_hvm_devices[arg] = conv(val)
|
||||
|
||||
if image_hvm or image_hvm_devices:
|
||||
image['hvm'] = image_hvm
|
||||
image['hvm']['devices'] = image_hvm_devices
|
||||
|
||||
image_type = sxp.name(image_sxp)
|
||||
if image_type != 'hvm' and image_type != 'linux':
|
||||
self['platform']['image_type'] = image_type
|
||||
|
||||
for key in XENAPI_PLATFORM_CFG:
|
||||
val = sxp.child_value(image_sxp, key, None)
|
||||
if val is not None:
|
||||
self['platform'][key] = val
|
||||
|
||||
notes = sxp.children(image_sxp, 'notes')
|
||||
if notes:
|
||||
image['notes'] = self.notes_from_sxp(notes[0])
|
||||
self['notes'] = self.notes_from_sxp(notes[0])
|
||||
|
||||
self['image'] = image
|
||||
|
||||
for apikey, imgkey in XENAPI_HVM_CFG.items():
|
||||
val = sxp.child_value(image_sxp, imgkey, None)
|
||||
if val != None:
|
||||
self[apikey] = val
|
||||
self._hvm_boot_params_from_sxp(image_sxp)
|
||||
|
||||
# extract backend value
|
||||
@@ -774,33 +763,6 @@ class XendConfig(dict):
|
||||
_set_cfg_if_exists('up_time')
|
||||
_set_cfg_if_exists('status') # TODO, deprecated
|
||||
|
||||
def _add_xapi_unsupported(self, xapi_dict):
|
||||
"""Updates the configuration object with entries that are not
|
||||
officially supported by the Xen API but is required for
|
||||
the rest of Xend to function.
|
||||
"""
|
||||
|
||||
# populate image
|
||||
if 'image' in xapi_dict:
|
||||
self['image'].update(xapi_dict['image'])
|
||||
else:
|
||||
hvm = self['HVM_boot_policy'] != ''
|
||||
self['image']['type'] = hvm and 'hvm' or 'linux'
|
||||
if hvm:
|
||||
self['image']['hvm'] = {'devices': {}}
|
||||
for xapi, cfgapi in XENAPI_HVM_CFG.items():
|
||||
if xapi in self:
|
||||
self['image']['hvm']['devices'][cfgapi] = self[xapi]
|
||||
|
||||
# currently unsupported options
|
||||
self['image']['hvm']['device_model'] = LEGACY_DM
|
||||
self['image']['vnc'] = 0
|
||||
self['image']['hvm']['pae'] = 1
|
||||
|
||||
if self['platform_enable_audio']:
|
||||
self['image']['hvm']['devices']['soundhw'] = 'sb16'
|
||||
|
||||
|
||||
def _get_old_state_string(self):
|
||||
"""Returns the old xm state string.
|
||||
@rtype: string
|
||||
@@ -884,18 +846,29 @@ class XendConfig(dict):
|
||||
else:
|
||||
sxpr.append([legacy, self[xenapi]])
|
||||
|
||||
MiB = 1024*1024
|
||||
|
||||
sxpr.append(["maxmem", int(self["memory_static_max"])/MiB])
|
||||
sxpr.append(["memory", int(self["memory_dynamic_max"])/MiB])
|
||||
|
||||
if not legacy_only:
|
||||
sxpr.append(['memory_dynamic_min',
|
||||
int(self.get('memory_dynamic_min'))])
|
||||
sxpr.append(['memory_dynamic_max',
|
||||
int(self.get('memory_dynamic_max'))])
|
||||
sxpr.append(['memory_static_max',
|
||||
int(self.get('memory_static_max'))])
|
||||
sxpr.append(['memory_static_min',
|
||||
int(self.get('memory_static_min'))])
|
||||
|
||||
for legacy in LEGACY_UNSUPPORTED_BY_XENAPI_CFG:
|
||||
if legacy in ('domid', 'uuid'): # skip these
|
||||
continue
|
||||
if self.has_key(legacy) and self[legacy] not in (None, []):
|
||||
sxpr.append([legacy, self[legacy]])
|
||||
|
||||
if 'image' in self and self['image']:
|
||||
sxpr.append(['image', self.image_sxpr()])
|
||||
|
||||
sxpr.append(['image', self.image_sxpr()])
|
||||
sxpr.append(['status', domain.state])
|
||||
sxpr.append(['memory_dynamic_min', self.get('memory_dynamic_min')])
|
||||
sxpr.append(['memory_dynamic_max', self.get('memory_dynamic_max')])
|
||||
|
||||
if domain.getDomid() is not None:
|
||||
sxpr.append(['state', self._get_old_state_string()])
|
||||
@@ -1339,7 +1312,7 @@ class XendConfig(dict):
|
||||
def image_sxpr(self):
|
||||
"""Returns a backwards compatible image SXP expression that is
|
||||
used in xenstore's /vm/<uuid>/image value and xm list."""
|
||||
image = [self['image'].get('type', 'linux')]
|
||||
image = [self.image_type()]
|
||||
if self.has_key('PV_kernel'):
|
||||
image.append(['kernel', self['PV_kernel']])
|
||||
if self.has_key('PV_ramdisk') and self['PV_ramdisk']:
|
||||
@@ -1347,28 +1320,12 @@ class XendConfig(dict):
|
||||
if self.has_key('PV_args') and self['PV_args']:
|
||||
image.append(['args', self['PV_args']])
|
||||
|
||||
for arg, conv in LEGACY_IMAGE_CFG:
|
||||
if self['image'].has_key(arg):
|
||||
image.append([arg, self['image'][arg]])
|
||||
for key in XENAPI_PLATFORM_CFG:
|
||||
if key in self['platform']:
|
||||
image.append([key, self['platform'][key]])
|
||||
|
||||
if 'hvm' in self['image']:
|
||||
for arg, conv in LEGACY_IMAGE_HVM_CFG:
|
||||
if self['image']['hvm'].get(arg):
|
||||
image.append([arg, conv(self['image']['hvm'][arg])])
|
||||
|
||||
if 'hvm' in self['image'] and 'devices' in self['image']['hvm']:
|
||||
for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
|
||||
val = self['image']['hvm']['devices'].get(arg)
|
||||
if val != None:
|
||||
try:
|
||||
if conv: val = conv(val)
|
||||
except (ValueError, TypeError):
|
||||
if type(val) == bool: val = int(val)
|
||||
|
||||
image.append([arg, val])
|
||||
|
||||
if 'notes' in self['image']:
|
||||
image.append(self.notes_sxp(self['image']['notes']))
|
||||
if 'notes' in self:
|
||||
image.append(self.notes_sxp(self['notes']))
|
||||
|
||||
return image
|
||||
|
||||
@@ -1399,57 +1356,24 @@ class XendConfig(dict):
|
||||
self['PV_ramdisk'] = sxp.child_value(image_sxp, 'ramdisk','')
|
||||
self['PV_args'] = kernel_args
|
||||
|
||||
# Store image SXP in python dictionary format
|
||||
image = {}
|
||||
image['type'] = sxp.name(image_sxp)
|
||||
for arg, conv in LEGACY_IMAGE_CFG:
|
||||
val = sxp.child_value(image_sxp, arg, None)
|
||||
if val != None:
|
||||
image[arg] = conv(val)
|
||||
|
||||
image_hvm = {}
|
||||
for arg, conv in LEGACY_IMAGE_HVM_CFG:
|
||||
val = sxp.child_value(image_sxp, arg, None)
|
||||
if val != None:
|
||||
image_hvm[arg] = conv(val)
|
||||
|
||||
image_hvm_devices = {}
|
||||
for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
|
||||
val = sxp.child_value(image_sxp, arg, None)
|
||||
if val != None:
|
||||
try:
|
||||
image_hvm_devices[arg] = conv(val)
|
||||
except (ValueError, TypeError):
|
||||
image_hvm_devices[arg] = val
|
||||
|
||||
|
||||
if image_hvm or image_hvm_devices:
|
||||
image['hvm'] = image_hvm
|
||||
image['hvm']['devices'] = image_hvm_devices
|
||||
for key in XENAPI_PLATFORM_CFG:
|
||||
val = sxp.child_value(image_sxp, key, None)
|
||||
if val is not None:
|
||||
self['platform'][key] = val
|
||||
|
||||
notes = sxp.children(image_sxp, 'notes')
|
||||
if notes:
|
||||
image['notes'] = self.notes_from_sxp(notes[0])
|
||||
self['notes'] = self.notes_from_sxp(notes[0])
|
||||
|
||||
self['image'] = image
|
||||
|
||||
for apikey, imgkey in XENAPI_HVM_CFG.items():
|
||||
val = sxp.child_value(image_sxp, imgkey, None)
|
||||
if val != None:
|
||||
type_conv = XENAPI_CFG_TYPES[apikey]
|
||||
if callable(type_conv):
|
||||
self[apikey] = type_conv(val)
|
||||
else:
|
||||
self[apikey] = val
|
||||
self._hvm_boot_params_from_sxp(image_sxp)
|
||||
|
||||
def set_notes(self, notes):
|
||||
'Add parsed elfnotes to image'
|
||||
self['image']['notes'] = notes
|
||||
self['notes'] = notes
|
||||
|
||||
def get_notes(self):
|
||||
try:
|
||||
return self['image']['notes'] or {}
|
||||
return self['notes'] or {}
|
||||
except KeyError:
|
||||
return {}
|
||||
|
||||
@@ -1471,11 +1395,9 @@ class XendConfig(dict):
|
||||
self['HVM_boot_policy'] = 'BIOS order'
|
||||
self['HVM_boot_params'] = { 'order' : boot }
|
||||
|
||||
def is_hvm(self):
|
||||
return self['HVM_boot_policy'] != ''
|
||||
|
||||
#
|
||||
# debugging
|
||||
#
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
|
||||
def image_type(self):
|
||||
stored_type = self['platform'].get('image_type')
|
||||
return stored_type or (self.is_hvm() and 'hvm' or 'linux')
|
||||
@@ -495,7 +495,7 @@ class XendDomain:
|
||||
self._refresh(refresh_shutdown = False)
|
||||
dom = self.domain_lookup_nr(domid)
|
||||
if not dom:
|
||||
raise XendInvalidDomain("No domain named '%s'." % str(domid))
|
||||
raise XendInvalidDomain(str(domid))
|
||||
return dom
|
||||
finally:
|
||||
self.domains_lock.release()
|
||||
@@ -674,7 +674,7 @@ class XendDomain:
|
||||
else:
|
||||
return domid
|
||||
|
||||
raise XendInvalidDomain("Domain does not exist")
|
||||
raise XendInvalidDomain(vm_uuid)
|
||||
finally:
|
||||
self.domains_lock.release()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
|
||||
# Copyright (C) 2005, 2006 XenSource Ltd
|
||||
# Copyright (C) 2005-2007 XenSource Ltd
|
||||
#============================================================================
|
||||
|
||||
"""Representation of a single domain.
|
||||
@@ -34,7 +34,7 @@ from types import StringTypes
|
||||
|
||||
import xen.lowlevel.xc
|
||||
from xen.util import asserts
|
||||
from xen.util.blkif import blkdev_uname_to_file
|
||||
from xen.util.blkif import blkdev_uname_to_file, blkdev_uname_to_taptype
|
||||
from xen.util import security
|
||||
|
||||
from xen.xend import balloon, sxp, uuid, image, arch, osdep
|
||||
@@ -51,6 +51,8 @@ from xen.xend.xenstore.xswatch import xswatch
|
||||
from xen.xend.XendConstants import *
|
||||
from xen.xend.XendAPIConstants import *
|
||||
|
||||
from xen.xend.XendVMMetrics import XendVMMetrics
|
||||
|
||||
MIGRATE_TIMEOUT = 30.0
|
||||
BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp'
|
||||
|
||||
@@ -176,14 +178,8 @@ def recreate(info, priv):
|
||||
vm._storeVmDetails()
|
||||
vm._storeDomDetails()
|
||||
|
||||
if vm.info['image']: # Only dom0 should be without an image entry when
|
||||
# recreating, but we cope with missing ones
|
||||
# elsewhere just in case.
|
||||
vm.image = image.create(vm,
|
||||
vm.info,
|
||||
vm.info['image'],
|
||||
vm.info['devices'])
|
||||
vm.image.recreate()
|
||||
vm.image = image.create(vm, vm.info)
|
||||
vm.image.recreate()
|
||||
|
||||
vm._registerWatches()
|
||||
vm.refreshShutdown(xeninfo)
|
||||
@@ -375,6 +371,8 @@ class XendDomainInfo:
|
||||
self._augmentInfo(priv)
|
||||
|
||||
self._checkName(self.info['name_label'])
|
||||
|
||||
self.metrics = XendVMMetrics(uuid.createString(), self)
|
||||
|
||||
|
||||
#
|
||||
@@ -448,9 +446,7 @@ class XendDomainInfo:
|
||||
self.storeDom("control/shutdown", reason)
|
||||
|
||||
## shutdown hypercall for hvm domain desides xenstore write
|
||||
image_cfg = self.info.get('image', {})
|
||||
hvm = image_cfg.has_key('hvm')
|
||||
if hvm:
|
||||
if self.info.is_hvm():
|
||||
for code in DOMAIN_SHUTDOWN_REASONS.keys():
|
||||
if DOMAIN_SHUTDOWN_REASONS[code] == reason:
|
||||
break
|
||||
@@ -580,12 +576,14 @@ class XendDomainInfo:
|
||||
if target <= 0:
|
||||
raise XendError('Invalid memory size')
|
||||
|
||||
self.info['memory_static_min'] = target
|
||||
MiB = 1024 * 1024
|
||||
self.info['memory_dynamic_min'] = target * MiB
|
||||
self.info['memory_dynamic_max'] = target * MiB
|
||||
|
||||
if self.domid >= 0:
|
||||
self.storeVm("memory", target)
|
||||
self.storeDom("memory/target", target << 10)
|
||||
else:
|
||||
self.info['memory_dynamic_min'] = target
|
||||
xen.xend.XendDomain.instance().managed_config_save(self)
|
||||
|
||||
def setMemoryMaximum(self, limit):
|
||||
@@ -635,6 +633,10 @@ class XendDomainInfo:
|
||||
except RuntimeError, exn:
|
||||
raise XendError(str(exn))
|
||||
|
||||
|
||||
def getDomInfo(self):
|
||||
return dom_get(self.domid)
|
||||
|
||||
#
|
||||
# internal functions ... TODO: re-categorised
|
||||
#
|
||||
@@ -664,6 +666,10 @@ class XendDomainInfo:
|
||||
if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG:
|
||||
xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
|
||||
self.info[xapiarg] = val
|
||||
elif arg == "memory":
|
||||
self.info["static_memory_min"] = val
|
||||
elif arg == "maxmem":
|
||||
self.info["static_memory_max"] = val
|
||||
else:
|
||||
self.info[arg] = val
|
||||
|
||||
@@ -780,7 +786,7 @@ class XendDomainInfo:
|
||||
'vm': self.vmpath,
|
||||
'name': self.info['name_label'],
|
||||
'console/limit': str(xoptions.get_console_limit() * 1024),
|
||||
'memory/target': str(self.info['memory_static_min'] * 1024),
|
||||
'memory/target': str(self.info['memory_dynamic_max'] / 1024),
|
||||
}
|
||||
|
||||
def f(n, v):
|
||||
@@ -864,7 +870,15 @@ class XendDomainInfo:
|
||||
xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
|
||||
if val != None and val != self.info[xapiarg]:
|
||||
self.info[xapiarg] = val
|
||||
changed= True
|
||||
changed = True
|
||||
elif arg == "memory":
|
||||
if val != None and val != self.info["static_memory_min"]:
|
||||
self.info["static_memory_min"] = val
|
||||
changed = True
|
||||
elif arg == "maxmem":
|
||||
if val != None and val != self.info["static_memory_max"]:
|
||||
self.info["static_memory_max"] = val
|
||||
changed = True
|
||||
|
||||
# Check whether image definition has been updated
|
||||
image_sxp = self._readVm('image')
|
||||
@@ -969,11 +983,12 @@ class XendDomainInfo:
|
||||
|
||||
def getMemoryTarget(self):
|
||||
"""Get this domain's target memory size, in KB."""
|
||||
return self.info['memory_static_min'] * 1024
|
||||
return self.info['memory_dynamic_max'] / 1024
|
||||
|
||||
def getMemoryMaximum(self):
|
||||
"""Get this domain's maximum memory size, in KB."""
|
||||
return self.info['memory_static_max'] * 1024
|
||||
# remember, info now stores memory in bytes
|
||||
return self.info['memory_static_max'] / 1024
|
||||
|
||||
def getResume(self):
|
||||
return str(self._resume)
|
||||
@@ -1389,9 +1404,7 @@ class XendDomainInfo:
|
||||
|
||||
self.shutdownStartTime = None
|
||||
|
||||
image_cfg = self.info.get('image', {})
|
||||
hvm = image_cfg.has_key('hvm')
|
||||
|
||||
hvm = self.info.is_hvm()
|
||||
if hvm:
|
||||
info = xc.xeninfo()
|
||||
if 'hvm' not in info['xen_caps']:
|
||||
@@ -1438,14 +1451,8 @@ class XendDomainInfo:
|
||||
|
||||
self._configureBootloader()
|
||||
|
||||
if not self._infoIsSet('image'):
|
||||
raise VmError('Missing image in configuration')
|
||||
|
||||
try:
|
||||
self.image = image.create(self,
|
||||
self.info,
|
||||
self.info['image'],
|
||||
self.info['devices'])
|
||||
self.image = image.create(self, self.info)
|
||||
|
||||
localtime = self.info.get('platform_localtime', False)
|
||||
if localtime:
|
||||
@@ -1463,13 +1470,14 @@ class XendDomainInfo:
|
||||
# Use architecture- and image-specific calculations to determine
|
||||
# the various headrooms necessary, given the raw configured
|
||||
# values. maxmem, memory, and shadow are all in KiB.
|
||||
# but memory_static_max etc are all stored in bytes now.
|
||||
memory = self.image.getRequiredAvailableMemory(
|
||||
self.info['memory_static_min'] * 1024)
|
||||
self.info['memory_dynamic_max'] / 1024)
|
||||
maxmem = self.image.getRequiredAvailableMemory(
|
||||
self.info['memory_static_max'] * 1024)
|
||||
self.info['memory_static_max'] / 1024)
|
||||
shadow = self.image.getRequiredShadowMemory(
|
||||
self.info['shadow_memory'] * 1024,
|
||||
self.info['memory_static_max'] * 1024)
|
||||
self.info['shadow_memory'] / 1024,
|
||||
self.info['memory_static_max'] / 1024)
|
||||
|
||||
log.debug("_initDomain:shadow_memory=0x%x, memory_static_max=0x%x, memory_static_min=0x%x.", self.info['shadow_memory'], self.info['memory_static_max'], self.info['memory_static_min'],)
|
||||
# Round shadow up to a multiple of a MiB, as shadow_mem_control
|
||||
@@ -1505,9 +1513,15 @@ class XendDomainInfo:
|
||||
self.info['start_time'] = time.time()
|
||||
|
||||
self._stateSet(DOM_STATE_RUNNING)
|
||||
except (RuntimeError, VmError), exn:
|
||||
except VmError, exn:
|
||||
log.exception("XendDomainInfo.initDomain: exception occurred")
|
||||
self.image.cleanupBootloading()
|
||||
if self.image:
|
||||
self.image.cleanupBootloading()
|
||||
raise exn
|
||||
except RuntimeError, exn:
|
||||
log.exception("XendDomainInfo.initDomain: exception occurred")
|
||||
if self.image:
|
||||
self.image.cleanupBootloading()
|
||||
raise VmError(str(exn))
|
||||
|
||||
|
||||
@@ -1574,13 +1588,8 @@ class XendDomainInfo:
|
||||
self.console_mfn = console_mfn
|
||||
|
||||
self._introduceDomain()
|
||||
image_cfg = self.info.get('image', {})
|
||||
hvm = image_cfg.has_key('hvm')
|
||||
if hvm:
|
||||
self.image = image.create(self,
|
||||
self.info,
|
||||
self.info['image'],
|
||||
self.info['devices'])
|
||||
if self.info.is_hvm():
|
||||
self.image = image.create(self, self.info)
|
||||
if self.image:
|
||||
self.image.createDeviceModel(True)
|
||||
self.image.register_shutdown_watch()
|
||||
@@ -1657,7 +1666,18 @@ class XendDomainInfo:
|
||||
log.exception("XendDomainInfo.destroy: xc.domain_destroy failed.")
|
||||
|
||||
from xen.xend import XendDomain
|
||||
XendDomain.instance().remove_domain(self)
|
||||
|
||||
if "transient" in self.info["other_config"]\
|
||||
and bool(self.info["other_config"]["transient"]):
|
||||
xendDomainInstance = XendDomain.instance()
|
||||
|
||||
xendDomainInstance.domains_lock.acquire()
|
||||
xendDomainInstance._refresh(refresh_shutdown = False)
|
||||
xendDomainInstance.domains_lock.release()
|
||||
|
||||
xendDomainInstance.domain_delete(self.info["name_label"])
|
||||
else:
|
||||
XendDomain.instance().remove_domain(self)
|
||||
|
||||
self.cleanupDomain()
|
||||
self._cleanup_phantom_devs(paths)
|
||||
@@ -1742,11 +1762,7 @@ class XendDomainInfo:
|
||||
|
||||
if boot:
|
||||
# HVM booting.
|
||||
self.info['image']['type'] = 'hvm'
|
||||
if not 'devices' in self.info['image']:
|
||||
self.info['image']['devices'] = {}
|
||||
self.info['image']['devices']['boot'] = \
|
||||
self.info['HVM_boot_params'].get('order', 'dc')
|
||||
pass
|
||||
elif not blexec and kernel:
|
||||
# Boot from dom0. Nothing left to do -- the kernel and ramdisk
|
||||
# will be picked up by image.py.
|
||||
@@ -1770,7 +1786,8 @@ class XendDomainInfo:
|
||||
disk = devinfo[1]['uname']
|
||||
|
||||
fn = blkdev_uname_to_file(disk)
|
||||
mounted = devtype == 'tap' and not os.stat(fn).st_rdev
|
||||
taptype = blkdev_uname_to_taptype(disk)
|
||||
mounted = devtype == 'tap' and taptype != 'aio' and taptype != 'sync' and not os.stat(fn).st_rdev
|
||||
if mounted:
|
||||
# This is a file, not a device. pygrub can cope with a
|
||||
# file if it's raw, but if it's QCOW or other such formats
|
||||
@@ -1786,7 +1803,7 @@ class XendDomainInfo:
|
||||
|
||||
from xen.xend import XendDomain
|
||||
dom0 = XendDomain.instance().privilegedDomain()
|
||||
dom0._waitForDeviceUUID(dom0.create_vbd(vbd, fn))
|
||||
dom0._waitForDeviceUUID(dom0.create_vbd(vbd, disk))
|
||||
fn = BOOTLOADER_LOOPBACK_DEVICE
|
||||
|
||||
try:
|
||||
@@ -1844,7 +1861,7 @@ class XendDomainInfo:
|
||||
# 1MB per vcpu plus 4Kib/Mib of RAM. This is higher than
|
||||
# the minimum that Xen would allocate if no value were given.
|
||||
overhead_kb = self.info['vcpus_number'] * 1024 + \
|
||||
self.info['memory_static_max'] * 4
|
||||
(self.info['memory_static_max'] / 1024 / 1024) * 4
|
||||
overhead_kb = ((overhead_kb + 1023) / 1024) * 1024
|
||||
# The domain might already have some shadow memory
|
||||
overhead_kb -= xc.shadow_mem_control(self.domid) * 1024
|
||||
@@ -1910,10 +1927,14 @@ class XendDomainInfo:
|
||||
if self._infoIsSet(info_key):
|
||||
to_store[key] = str(self.info[info_key])
|
||||
|
||||
if self.info.get('image'):
|
||||
image_sxpr = self.info.image_sxpr()
|
||||
if image_sxpr:
|
||||
to_store['image'] = sxp.to_string(image_sxpr)
|
||||
if self._infoIsSet("static_memory_min"):
|
||||
to_store["memory"] = str(self.info["static_memory_min"])
|
||||
if self._infoIsSet("static_memory_max"):
|
||||
to_store["maxmem"] = str(self.info["static_memory_max"])
|
||||
|
||||
image_sxpr = self.info.image_sxpr()
|
||||
if image_sxpr:
|
||||
to_store['image'] = sxp.to_string(image_sxpr)
|
||||
|
||||
if self._infoIsSet('security'):
|
||||
secinfo = self.info['security']
|
||||
@@ -2000,7 +2021,11 @@ class XendDomainInfo:
|
||||
info = dom_get(self.domid)
|
||||
if not info:
|
||||
return
|
||||
|
||||
|
||||
if info["maxmem_kb"] < 0:
|
||||
info["maxmem_kb"] = XendNode.instance() \
|
||||
.physinfo_dict()['total_memory'] * 1024
|
||||
|
||||
#manually update ssidref / security fields
|
||||
if security.on() and info.has_key('ssidref'):
|
||||
if (info['ssidref'] != 0) and self.info.has_key('security'):
|
||||
@@ -2057,15 +2082,6 @@ class XendDomainInfo:
|
||||
return self.info.get('memory_dynamic_max', 0)
|
||||
def get_memory_dynamic_min(self):
|
||||
return self.info.get('memory_dynamic_min', 0)
|
||||
|
||||
def get_vcpus_policy(self):
|
||||
sched_id = xc.sched_id_get()
|
||||
if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
|
||||
return 'sedf'
|
||||
elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
|
||||
return 'credit'
|
||||
else:
|
||||
return 'unknown'
|
||||
def get_vcpus_params(self):
|
||||
if self.getDomid() is None:
|
||||
return self.info['vcpus_params']
|
||||
@@ -2074,22 +2090,14 @@ class XendDomainInfo:
|
||||
return retval
|
||||
def get_power_state(self):
|
||||
return XEN_API_VM_POWER_STATE[self.state]
|
||||
def get_platform_std_vga(self):
|
||||
return self.info.get('platform_std_vga', False)
|
||||
def get_platform_serial(self):
|
||||
return self.info.get('platform_serial', '')
|
||||
def get_platform_localtime(self):
|
||||
return self.info.get('platform_localtime', False)
|
||||
def get_platform_clock_offset(self):
|
||||
return self.info.get('platform_clock_offset', False)
|
||||
def get_platform_enable_audio(self):
|
||||
return self.info.get('platform_enable_audio', False)
|
||||
def get_platform_keymap(self):
|
||||
return self.info.get('platform_keymap', '')
|
||||
def get_platform(self):
|
||||
return self.info.get('platform', {})
|
||||
def get_pci_bus(self):
|
||||
return self.info.get('pci_bus', '')
|
||||
def get_tools_version(self):
|
||||
return self.info.get('tools_version', {})
|
||||
def get_metrics(self):
|
||||
return self.metrics.get_uuid();
|
||||
|
||||
def get_on_shutdown(self):
|
||||
after_shutdown = self.info.get('actions_after_shutdown')
|
||||
@@ -2278,8 +2286,6 @@ class XendDomainInfo:
|
||||
@return: uuid of the device
|
||||
"""
|
||||
xenapi_vbd['image'] = vdi_image_path
|
||||
log.debug('create_vbd: %s' % xenapi_vbd)
|
||||
dev_uuid = ''
|
||||
if vdi_image_path.startswith('tap'):
|
||||
dev_uuid = self.info.device_add('tap', cfg_xenapi = xenapi_vbd)
|
||||
else:
|
||||
@@ -2289,16 +2295,25 @@ class XendDomainInfo:
|
||||
raise XendError('Failed to create device')
|
||||
|
||||
if self.state == XEN_API_VM_POWER_STATE_RUNNING:
|
||||
|
||||
_, config = self.info['devices'][dev_uuid]
|
||||
dev_control = None
|
||||
|
||||
if vdi_image_path.startswith('tap'):
|
||||
dev_control = self.getDeviceController('tap')
|
||||
dev_control = self.getDeviceController('tap')
|
||||
else:
|
||||
dev_control = self.getDeviceController('vbd')
|
||||
|
||||
config['devid'] = dev_control.createDevice(config)
|
||||
|
||||
try:
|
||||
devid = dev_control.createDevice(config)
|
||||
dev_control.waitForDevice(devid)
|
||||
self.info.device_update(dev_uuid,
|
||||
cfg_xenapi = {'devid': devid})
|
||||
except Exception, exn:
|
||||
log.exception(exn)
|
||||
del self.info['devices'][dev_uuid]
|
||||
self.info['vbd_refs'].remove(dev_uuid)
|
||||
raise
|
||||
|
||||
return dev_uuid
|
||||
|
||||
def create_phantom_vbd_with_vdi(self, xenapi_vbd, vdi_image_path):
|
||||
@@ -2332,9 +2347,21 @@ class XendDomainInfo:
|
||||
raise XendError('Failed to create device')
|
||||
|
||||
if self.state == XEN_API_VM_POWER_STATE_RUNNING:
|
||||
_, config = self.info['devices'][dev_uuid]
|
||||
config['devid'] = self.getDeviceController('vif').createDevice(config)
|
||||
|
||||
_, config = self.info['devices'][dev_uuid]
|
||||
dev_control = self.getDeviceController('vif')
|
||||
|
||||
try:
|
||||
devid = dev_control.createDevice(config)
|
||||
dev_control.waitForDevice(devid)
|
||||
self.info.device_update(dev_uuid,
|
||||
cfg_xenapi = {'devid': devid})
|
||||
except Exception, exn:
|
||||
log.exception(exn)
|
||||
del self.info['devices'][dev_uuid]
|
||||
self.info['vif_refs'].remove(dev_uuid)
|
||||
raise
|
||||
|
||||
return dev_uuid
|
||||
|
||||
def create_vtpm(self, xenapi_vtpm):
|
||||
@@ -2401,7 +2428,7 @@ class XendDomainInfo:
|
||||
def __str__(self):
|
||||
return '<domain id=%s name=%s memory=%s state=%s>' % \
|
||||
(str(self.domid), self.info['name_label'],
|
||||
str(self.info['memory_static_min']), DOM_STATES[self.state])
|
||||
str(self.info['memory_dynamic_max']), DOM_STATES[self.state])
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
|
||||
# Copyright (c) 2006, 2007 XenSource Inc.
|
||||
#============================================================================
|
||||
|
||||
from xmlrpclib import Fault
|
||||
@@ -55,6 +56,12 @@ class VmError(XendError):
|
||||
"""Vm construction error."""
|
||||
pass
|
||||
|
||||
class HVMRequired(VmError):
|
||||
def __init__(self):
|
||||
XendError.__init__(self,
|
||||
'HVM guest support is unavailable: is VT/AMD-V '
|
||||
'supported by your CPU and enabled in your BIOS?')
|
||||
|
||||
|
||||
XEND_ERROR_AUTHENTICATION_FAILED = ('ELUSER', 'Authentication Failed')
|
||||
XEND_ERROR_SESSION_INVALID = ('EPERMDENIED', 'Session Invalid')
|
||||
|
||||
@@ -59,6 +59,18 @@ if 'TRACE' not in logging.__dict__:
|
||||
return filename, frame[2]
|
||||
logging.Logger.findCaller = findCaller
|
||||
|
||||
# Work around a bug in Python's inspect module: findsource is supposed to
|
||||
# raise IOError if it fails, with other functions in that module coping
|
||||
# with that, but some people are seeing IndexError raised from there.
|
||||
if hasattr(inspect, 'findsource'):
|
||||
real_findsource = getattr(inspect, 'findsource')
|
||||
def findsource(*args, **kwargs):
|
||||
try:
|
||||
return real_findsource(*args, **kwargs)
|
||||
except IndexError, exn:
|
||||
raise IOError(exn)
|
||||
inspect.findsource = findsource
|
||||
|
||||
|
||||
log = logging.getLogger("xend")
|
||||
|
||||
|
||||
@@ -75,6 +75,11 @@ class XendNode:
|
||||
self.other_config = {}
|
||||
self.cpus = {}
|
||||
self.host_metrics_uuid = uuid.createString()
|
||||
|
||||
# put some arbitrary params in other_config as this
|
||||
# is directly exposed via XenAPI
|
||||
self.other_config["xen_pagesize"] = self.xeninfo_dict()["xen_pagesize"]
|
||||
self.other_config["platform_params"] = self.xeninfo_dict()["platform_params"]
|
||||
|
||||
# load CPU UUIDs
|
||||
saved_cpus = self.state_store.load_state('cpu')
|
||||
@@ -95,15 +100,12 @@ class XendNode:
|
||||
self.cpus[u] = {'uuid': u, 'number': i }
|
||||
|
||||
for u in self.cpus.keys():
|
||||
log.error(self.cpus[u])
|
||||
number = self.cpus[u]['number']
|
||||
# We can run off the end of the cpuinfo list if domain0 does not
|
||||
# have #vcpus == #pcpus. In that case we just replicate one that's
|
||||
# in the hash table.
|
||||
if not cpuinfo.has_key(number):
|
||||
number = cpuinfo.keys()[0]
|
||||
log.error(number)
|
||||
log.error(cpuinfo)
|
||||
if arch.type == "x86":
|
||||
self.cpus[u].update(
|
||||
{ 'host' : self.uuid,
|
||||
@@ -356,14 +358,37 @@ class XendNode:
|
||||
|
||||
def xen_version(self):
|
||||
info = self.xc.xeninfo()
|
||||
|
||||
try:
|
||||
from xen import VERSION
|
||||
return {'Xen': '%(xen_major)d.%(xen_minor)d' % info,
|
||||
info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info,
|
||||
'Xend': VERSION}
|
||||
except (ImportError, AttributeError):
|
||||
return {'Xen': '%(xen_major)d.%(xen_minor)d' % info,
|
||||
info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info,
|
||||
'Xend': '3.0.3'}
|
||||
|
||||
# Add xend_config_format
|
||||
info.update(self.xendinfo_dict())
|
||||
|
||||
# Add version info about machine
|
||||
info.update(self.nodeinfo_dict())
|
||||
|
||||
# Add specific xen version info
|
||||
xeninfo_dict = self.xeninfo_dict()
|
||||
|
||||
info.update({
|
||||
"xen_major": xeninfo_dict["xen_major"],
|
||||
"xen_minor": xeninfo_dict["xen_minor"],
|
||||
"xen_extra": xeninfo_dict["xen_extra"],
|
||||
"cc_compiler": xeninfo_dict["cc_compiler"],
|
||||
"cc_compile_by": xeninfo_dict["cc_compile_by"],
|
||||
"cc_compile_domain": xeninfo_dict["cc_compile_domain"],
|
||||
"cc_compile_date": xeninfo_dict["cc_compile_date"],
|
||||
"xen_changeset": xeninfo_dict["xen_changeset"]
|
||||
})
|
||||
|
||||
return info
|
||||
|
||||
def get_name(self):
|
||||
return self.name
|
||||
|
||||
@@ -418,6 +443,27 @@ class XendNode:
|
||||
|
||||
return 0.0
|
||||
|
||||
def get_vcpus_policy(self):
|
||||
sched_id = self.xc.sched_id_get()
|
||||
if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
|
||||
return 'sedf'
|
||||
elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
|
||||
return 'credit'
|
||||
else:
|
||||
return 'unknown'
|
||||
|
||||
def get_cpu_configuration(self):
|
||||
phys_info = self.physinfo_dict()
|
||||
|
||||
cpu_info = {
|
||||
"nr_nodes": phys_info["nr_nodes"],
|
||||
"sockets_per_node": phys_info["sockets_per_node"],
|
||||
"cores_per_socket": phys_info["cores_per_socket"],
|
||||
"threads_per_core": phys_info["threads_per_core"]
|
||||
}
|
||||
|
||||
return cpu_info
|
||||
|
||||
#
|
||||
# Network Functions
|
||||
#
|
||||
@@ -453,6 +499,12 @@ class XendNode:
|
||||
return pif.network
|
||||
raise Exception('Bridge %s is not connected to a network' % bridge)
|
||||
|
||||
#
|
||||
# Debug keys.
|
||||
#
|
||||
|
||||
def send_debug_keys(self, keys):
|
||||
return self.xc.send_debug_keys(keys)
|
||||
|
||||
#
|
||||
# Getting host information.
|
||||
@@ -478,7 +530,8 @@ class XendNode:
|
||||
info['cores_per_socket'] *
|
||||
info['threads_per_core'])
|
||||
info['cpu_mhz'] = info['cpu_khz'] / 1000
|
||||
# physinfo is in KiB
|
||||
|
||||
# physinfo is in KiB, need it in MiB
|
||||
info['total_memory'] = info['total_memory'] / 1024
|
||||
info['free_memory'] = info['free_memory'] / 1024
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@ class XendVDI(AutoSaveObject):
|
||||
|
||||
SAVED_CFG = ['name_label',
|
||||
'name_description',
|
||||
'sector_size',
|
||||
'virtual_size',
|
||||
'physical_utilisation',
|
||||
'sharable',
|
||||
@@ -67,13 +66,22 @@ class XendVDI(AutoSaveObject):
|
||||
self.sr_uuid = sr_uuid
|
||||
self.name_label = ""
|
||||
self.name_description = ""
|
||||
self.sector_size = 1024
|
||||
self.virtual_size = 0
|
||||
self.physical_utilisation = 0
|
||||
self.sharable = False
|
||||
self.read_only = False
|
||||
self.type = "system"
|
||||
self.location = ''
|
||||
self.other_config = {}
|
||||
self.vbds = []
|
||||
|
||||
def addVBD(self, vbd_ref):
|
||||
self.vbds.append(vbd_ref)
|
||||
|
||||
def removeVBD(self, vbd_ref):
|
||||
self.vbds.remove(vbd_ref)
|
||||
|
||||
def getVBDs(self):
|
||||
return self.vbds
|
||||
|
||||
def load_config_dict(self, cfg):
|
||||
"""Loads configuration into the object from a dict.
|
||||
@@ -144,11 +152,10 @@ class XendVDI(AutoSaveObject):
|
||||
'name_description': self.name_description,
|
||||
'virtual_size': self.virtual_size,
|
||||
'physical_utilisation': self.physical_utilisation,
|
||||
'sector_size': self.sector_size,
|
||||
'sharable': False,
|
||||
'readonly': False,
|
||||
'SR': self.sr_uuid,
|
||||
'location': self.get_location(),
|
||||
'other_config': self.other_config,
|
||||
'VBDs': []}
|
||||
|
||||
def get_location(self):
|
||||
@@ -163,12 +170,11 @@ class XendQCoWVDI(XendVDI):
|
||||
self.cfg_path = cfg_path
|
||||
self.physical_utilisation = psize
|
||||
self.virtual_size = vsize
|
||||
self.sector_size = 512
|
||||
self.auto_save = True
|
||||
self.location = 'tap:qcow:%s' % self.qcow_path
|
||||
self.other_config['location'] = 'tap:qcow:%s' % self.qcow_path
|
||||
|
||||
def get_location(self):
|
||||
return self.location
|
||||
return self.other_config['location']
|
||||
|
||||
class XendLocalVDI(XendVDI):
|
||||
def __init__(self, vdi_struct):
|
||||
@@ -182,11 +188,10 @@ class XendLocalVDI(XendVDI):
|
||||
self.name_description = vdi_struct.get('name_description', '')
|
||||
self.physical_utilisation = 0
|
||||
self.virtual_size = 0
|
||||
self.sector_size = 0
|
||||
self.type = vdi_struct.get('type', '')
|
||||
self.sharable = vdi_struct.get('sharable', False)
|
||||
self.read_only = vdi_struct.get('read_only', False)
|
||||
self.location = vdi_struct.get('location', 'file:/dev/null')
|
||||
self.other_config = vdi_struct.get('other_config', {})
|
||||
|
||||
def get_location(self):
|
||||
return self.location
|
||||
return self.other_config['location']
|
||||
@@ -0,0 +1,70 @@
|
||||
#============================================================================
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (c) 2006-2007 Xensource Inc.
|
||||
#============================================================================
|
||||
|
||||
from xen.xend.XendLogging import log
|
||||
|
||||
instances = {}
|
||||
|
||||
class XendVMMetrics:
|
||||
"""VM Metrics."""
|
||||
|
||||
def get_by_uuid(_, uuid):
|
||||
return instances[uuid]
|
||||
|
||||
get_by_uuid = classmethod(get_by_uuid)
|
||||
|
||||
def is_valid_vm_metrics(_, uuid):
|
||||
return uuid in instances
|
||||
|
||||
is_valid_vm_metrics = classmethod(is_valid_vm_metrics)
|
||||
|
||||
def get_all(_):
|
||||
return instances.keys()
|
||||
|
||||
get_all = classmethod(get_all)
|
||||
|
||||
def __init__(self, uuid, xend_domain_instance):
|
||||
self.uuid = uuid
|
||||
self.xend_domain_instance = xend_domain_instance
|
||||
instances[uuid] = self
|
||||
|
||||
def get_uuid(self):
|
||||
return self.uuid
|
||||
|
||||
def get_memory_actual(self):
|
||||
return self.get_record()["memory_actual"]
|
||||
|
||||
def get_vcpus_number(self):
|
||||
return self.get_record()["vcpus_number"]
|
||||
|
||||
def get_vcpus_utilisation(self):
|
||||
return self.xend_domain_instance.get_vcpus_util()
|
||||
|
||||
def get_record(self):
|
||||
domInfo = self.xend_domain_instance.getDomInfo()
|
||||
if domInfo:
|
||||
return { 'uuid' : self.uuid,
|
||||
'memory_actual' : domInfo["mem_kb"] * 1024,
|
||||
'vcpus_number' : domInfo["online_vcpus"],
|
||||
'vcpus_utilisation' : self.get_vcpus_utilisation()
|
||||
}
|
||||
else:
|
||||
return { 'uuid' : self.uuid,
|
||||
'memory_actual' : 0,
|
||||
'vcpus_number' : 0,
|
||||
'vcpus_utilisation' : {}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2005 Mike Wray <mike.wray@hp.com>
|
||||
# Copyright (C) 2005 XenSource Ltd
|
||||
# Copyright (C) 2005-2007 XenSource Ltd
|
||||
#============================================================================
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import signal
|
||||
|
||||
import xen.lowlevel.xc
|
||||
from xen.xend.XendConstants import REVERSE_DOMAIN_SHUTDOWN_REASONS
|
||||
from xen.xend.XendError import VmError, XendError
|
||||
from xen.xend.XendError import VmError, XendError, HVMRequired
|
||||
from xen.xend.XendLogging import log
|
||||
from xen.xend.XendOptions import instance as xenopts
|
||||
from xen.xend.server.netif import randomMAC
|
||||
@@ -36,13 +36,12 @@ xc = xen.lowlevel.xc.xc()
|
||||
MAX_GUEST_CMDLINE = 1024
|
||||
|
||||
|
||||
def create(vm, vmConfig, imageConfig, deviceConfig):
|
||||
def create(vm, vmConfig):
|
||||
"""Create an image handler for a vm.
|
||||
|
||||
@return ImageHandler instance
|
||||
"""
|
||||
return findImageHandlerClass(imageConfig)(vm, vmConfig, imageConfig,
|
||||
deviceConfig)
|
||||
return findImageHandlerClass(vmConfig)(vm, vmConfig)
|
||||
|
||||
|
||||
class ImageHandler:
|
||||
@@ -65,7 +64,7 @@ class ImageHandler:
|
||||
ostype = None
|
||||
|
||||
|
||||
def __init__(self, vm, vmConfig, imageConfig, deviceConfig):
|
||||
def __init__(self, vm, vmConfig):
|
||||
self.vm = vm
|
||||
|
||||
self.bootloader = False
|
||||
@@ -73,9 +72,9 @@ class ImageHandler:
|
||||
self.ramdisk = None
|
||||
self.cmdline = None
|
||||
|
||||
self.configure(vmConfig, imageConfig, deviceConfig)
|
||||
self.configure(vmConfig)
|
||||
|
||||
def configure(self, vmConfig, imageConfig, _):
|
||||
def configure(self, vmConfig):
|
||||
"""Config actions common to all unix-like domains."""
|
||||
if '_temp_using_bootloader' in vmConfig:
|
||||
self.bootloader = True
|
||||
@@ -233,30 +232,29 @@ class HVMImageHandler(ImageHandler):
|
||||
|
||||
ostype = "hvm"
|
||||
|
||||
def __init__(self, vm, vmConfig, imageConfig, deviceConfig):
|
||||
ImageHandler.__init__(self, vm, vmConfig, imageConfig, deviceConfig)
|
||||
def __init__(self, vm, vmConfig):
|
||||
ImageHandler.__init__(self, vm, vmConfig)
|
||||
self.shutdownWatch = None
|
||||
self.rebootFeatureWatch = None
|
||||
|
||||
def configure(self, vmConfig, imageConfig, deviceConfig):
|
||||
ImageHandler.configure(self, vmConfig, imageConfig, deviceConfig)
|
||||
def configure(self, vmConfig):
|
||||
ImageHandler.configure(self, vmConfig)
|
||||
|
||||
if not self.kernel:
|
||||
self.kernel = '/usr/lib/xen/boot/hvmloader'
|
||||
|
||||
info = xc.xeninfo()
|
||||
if 'hvm' not in info['xen_caps']:
|
||||
raise VmError("HVM guest support is unavailable: is VT/AMD-V "
|
||||
"supported by your CPU and enabled in your BIOS?")
|
||||
raise HVMRequired()
|
||||
|
||||
self.dmargs = self.parseDeviceModelArgs(vmConfig)
|
||||
self.device_model = imageConfig['hvm'].get('device_model')
|
||||
self.device_model = vmConfig['platform'].get('device_model')
|
||||
if not self.device_model:
|
||||
raise VmError("hvm: missing device model")
|
||||
|
||||
self.display = imageConfig['hvm'].get('display')
|
||||
self.xauthority = imageConfig['hvm'].get('xauthority')
|
||||
self.vncconsole = imageConfig['hvm'].get('vncconsole')
|
||||
self.display = vmConfig['platform'].get('display')
|
||||
self.xauthority = vmConfig['platform'].get('xauthority')
|
||||
self.vncconsole = vmConfig['platform'].get('vncconsole')
|
||||
|
||||
self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
|
||||
("image/device-model", self.device_model),
|
||||
@@ -264,9 +262,9 @@ class HVMImageHandler(ImageHandler):
|
||||
|
||||
self.pid = None
|
||||
|
||||
self.pae = imageConfig['hvm'].get('pae', 0)
|
||||
self.apic = imageConfig['hvm'].get('apic', 0)
|
||||
self.acpi = imageConfig['hvm']['devices'].get('acpi', 0)
|
||||
self.pae = int(vmConfig['platform'].get('pae', 0))
|
||||
self.apic = int(vmConfig['platform'].get('apic', 0))
|
||||
self.acpi = int(vmConfig['platform'].get('acpi', 0))
|
||||
|
||||
|
||||
def buildDomain(self):
|
||||
@@ -302,11 +300,10 @@ class HVMImageHandler(ImageHandler):
|
||||
'localtime', 'serial', 'stdvga', 'isa',
|
||||
'acpi', 'usb', 'usbdevice', 'keymap' ]
|
||||
|
||||
hvmDeviceConfig = vmConfig['image']['hvm']['devices']
|
||||
ret = ['-vcpus', str(self.vm.getVCpuCount())]
|
||||
|
||||
for a in dmargs:
|
||||
v = hvmDeviceConfig.get(a)
|
||||
v = vmConfig['platform'].get(a)
|
||||
|
||||
# python doesn't allow '-' in variable names
|
||||
if a == 'stdvga': a = 'std-vga'
|
||||
@@ -366,14 +363,14 @@ class HVMImageHandler(ImageHandler):
|
||||
# Find RFB console device, and if it exists, make QEMU enable
|
||||
# the VNC console.
|
||||
#
|
||||
if vmConfig['image'].get('nographic'):
|
||||
if int(vmConfig['platform'].get('nographic', 0)) != 0:
|
||||
# skip vnc init if nographic is set
|
||||
ret.append('-nographic')
|
||||
return ret
|
||||
|
||||
vnc_config = {}
|
||||
has_vnc = int(vmConfig['image'].get('vnc', 0)) != 0
|
||||
has_sdl = int(vmConfig['image'].get('sdl', 0)) != 0
|
||||
has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
|
||||
has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
|
||||
for dev_uuid in vmConfig['console_refs']:
|
||||
dev_type, dev_info = vmConfig['devices'][dev_uuid]
|
||||
if dev_type == 'vfb':
|
||||
@@ -385,8 +382,8 @@ class HVMImageHandler(ImageHandler):
|
||||
if not vnc_config:
|
||||
for key in ('vncunused', 'vnclisten', 'vncdisplay',
|
||||
'vncpasswd'):
|
||||
if key in vmConfig['image']:
|
||||
vnc_config[key] = vmConfig['image'][key]
|
||||
if key in vmConfig['platform']:
|
||||
vnc_config[key] = vmConfig['platform'][key]
|
||||
|
||||
if not vnc_config.get('vncunused', 0) and \
|
||||
vnc_config.get('vncdisplay', 0):
|
||||
@@ -604,9 +601,7 @@ def findImageHandlerClass(image):
|
||||
@param image config
|
||||
@return ImageHandler subclass or None
|
||||
"""
|
||||
image_type = image['type']
|
||||
if image_type is None:
|
||||
raise VmError('missing image type')
|
||||
image_type = image.image_type()
|
||||
try:
|
||||
return _handlers[arch.type][image_type]
|
||||
except KeyError:
|
||||
|
||||
@@ -276,9 +276,12 @@ class Daemon:
|
||||
if not m:
|
||||
return None
|
||||
modulename = m.group(1)
|
||||
if re.search('sxp.py', modulename):
|
||||
return None
|
||||
if re.search('SrvServer.py', modulename):
|
||||
if modulename.endswith('.pyc'):
|
||||
modulename = modulename[:-1]
|
||||
if modulename == 'sxp.py' or \
|
||||
modulename == 'XendLogging.py' or \
|
||||
modulename == 'XendMonitor.py' or \
|
||||
modulename == 'server/SrvServer.py':
|
||||
return None
|
||||
self.traceindent += 1
|
||||
self.print_trace("> %s:%s\n"
|
||||
|
||||
@@ -157,7 +157,7 @@ class XMLRPCServer:
|
||||
self.server.register_function(fn, "xend.domain.%s" % name[7:])
|
||||
|
||||
# Functions in XendNode and XendDmesg
|
||||
for type, lst, n in [(XendNode, ['info'], 'node'),
|
||||
for type, lst, n in [(XendNode, ['info', 'send_debug_keys'], 'node'),
|
||||
(XendDmesg, ['info', 'clear'], 'node.dmesg')]:
|
||||
inst = type.instance()
|
||||
for name in lst:
|
||||
|
||||
@@ -46,7 +46,7 @@ class VfbifController(DevController):
|
||||
|
||||
def createDevice(self, config):
|
||||
DevController.createDevice(self, config)
|
||||
if self.vm.info.get('HVM_boot_policy'):
|
||||
if self.vm.info.is_hvm():
|
||||
# is HVM, so qemu-dm will handle the vfb.
|
||||
return
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ class Session(xen.util.xmlrpclib2.ServerProxy):
|
||||
|
||||
def _parse_result(result):
|
||||
if type(result) != dict or 'Status' not in result:
|
||||
raise xmlrpclib.Fault(500, 'Missing Status in response from server')
|
||||
raise xmlrpclib.Fault(500, 'Missing Status in response from server: ' + str(result))
|
||||
if result['Status'] == 'Success':
|
||||
if 'Value' in result:
|
||||
return result['Value']
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# Author: Bryan D. Payne <bdpayne@us.ibm.com>
|
||||
#============================================================================
|
||||
|
||||
"""Labeling a domain configuration file or a resoruce.
|
||||
"""Labeling a domain configuration file or a resource.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
<!ENTITY % HTMLlat1 PUBLIC
|
||||
"-//W3C//ENTITIES Latin 1 for XHTML//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
|
||||
%HTMLlat1;
|
||||
<!ENTITY % HTMLsymbol PUBLIC
|
||||
"-//W3C//ENTITIES Symbols for XHTML//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">
|
||||
%HTMLsymbol;
|
||||
<!ENTITY % HTMLspecial PUBLIC
|
||||
"-//W3C//ENTITIES Special for XHTML//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
|
||||
%HTMLspecial;
|
||||
<!-- a Uniform Resource Identifier, see [RFC2396] -->
|
||||
<!ENTITY % URI "CDATA">
|
||||
<!ENTITY % NAMEID "name ID #REQUIRED">
|
||||
<!ENTITY % CRASH_BEHAVIOUR "( destroy
|
||||
| coredump_and_destroy
|
||||
| restart
|
||||
| coredump_and_restart
|
||||
| preserve
|
||||
| rename_restart )">
|
||||
<!ENTITY % NORMAL_EXIT "( destroy | restart )">
|
||||
<!ENTITY % VDI_TYPE "( system
|
||||
| user
|
||||
| ephemeral
|
||||
| suspend
|
||||
| crashdump )">
|
||||
|
||||
<!ELEMENT xm (vm*,
|
||||
vdi*)>
|
||||
|
||||
<!ELEMENT version (#PCDATA)>
|
||||
|
||||
<!ELEMENT vm (name,
|
||||
version,
|
||||
(pv|hvm),
|
||||
memory,
|
||||
vbd*,
|
||||
vif*,
|
||||
vcpu_param*,
|
||||
other_config*)>
|
||||
<!ATTLIST vm is_a_template CDATA #REQUIRED
|
||||
auto_power_on CDATA #REQUIRED
|
||||
vcpus_max CDATA #REQUIRED
|
||||
vcpus_at_startup CDATA #REQUIRED
|
||||
actions_after_shutdown %NORMAL_EXIT; #REQUIRED
|
||||
actions_after_reboot %NORMAL_EXIT; #REQUIRED
|
||||
actions_after_crash %CRASH_BEHAVIOUR; #REQUIRED
|
||||
platform_std_VGA CDATA #REQUIRED
|
||||
platform_serial CDATA #REQUIRED
|
||||
platform_localtime CDATA #REQUIRED
|
||||
platform_clock_offet CDATA #REQUIRED
|
||||
platform_enable_audio CDATA #REQUIRED
|
||||
PCI_bus CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT memory EMPTY>
|
||||
<!ATTLIST memory static_min CDATA #REQUIRED
|
||||
static_max CDATA #REQUIRED
|
||||
dynamic_min CDATA #REQUIRED
|
||||
dynamic_max CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT vbd (qos_algorithm_param*)>
|
||||
<!ATTLIST vbd %NAMEID;
|
||||
mode (RO | RW) #REQUIRED
|
||||
vdi IDREF #REQUIRED
|
||||
device CDATA #REQUIRED
|
||||
bootable CDATA #REQUIRED
|
||||
type (CD | disk) #REQUIRED
|
||||
qos_algorithm_type CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT vif (qos_algorithm_param*)>
|
||||
<!ATTLIST vif %NAMEID;
|
||||
mac CDATA #REQUIRED
|
||||
mtu CDATA #REQUIRED
|
||||
device CDATA #REQUIRED
|
||||
qos_algorithm_type CDATA #REQUIRED
|
||||
bridge CDATA #IMPLIED
|
||||
network CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT pv EMPTY>
|
||||
<!ATTLIST pv kernel CDATA #REQUIRED
|
||||
bootloader CDATA #REQUIRED
|
||||
ramdisk CDATA #REQUIRED
|
||||
args CDATA #REQUIRED
|
||||
bootloader_args CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT hvm (boot_param*)>
|
||||
<!ATTLIST hvm boot_policy CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT boot_param EMPTY>
|
||||
<!ATTLIST boot_param key CDATA #REQUIRED
|
||||
value CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT vdi (name)>
|
||||
<!ATTLIST vdi %NAMEID;
|
||||
src %URI; #REQUIRED
|
||||
type %VDI_TYPE; #REQUIRED
|
||||
size CDATA #REQUIRED
|
||||
shareable CDATA #REQUIRED
|
||||
read_only CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT name (label,
|
||||
description)>
|
||||
|
||||
<!ELEMENT label (#PCDATA)>
|
||||
<!ELEMENT description (#PCDATA)>
|
||||
|
||||
<!ELEMENT vcpu_param EMPTY>
|
||||
<!ATTLIST vcpu_param key CDATA #REQUIRED
|
||||
value CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT other_config EMPTY>
|
||||
<!ATTLIST other_config key CDATA #REQUIRED
|
||||
value CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT qos_algorithm_param EMPTY>
|
||||
<!ATTLIST qos_algorithm_param key CDATA #REQUIRED
|
||||
value CDATA #REQUIRED>
|
||||
@@ -28,12 +28,13 @@ import time
|
||||
import xmlrpclib
|
||||
|
||||
from xen.xend import sxp
|
||||
from xen.xend import PrettyPrint
|
||||
from xen.xend import PrettyPrint as SXPPrettyPrint
|
||||
from xen.xend import osdep
|
||||
import xen.xend.XendClient
|
||||
from xen.xend.XendBootloader import bootloader
|
||||
from xen.util import blkif
|
||||
from xen.util import security
|
||||
from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm
|
||||
|
||||
from xen.xm.opts import *
|
||||
|
||||
@@ -98,6 +99,11 @@ gopts.opt('dryrun', short='n',
|
||||
use="Dry run - prints the resulting configuration in SXP but "
|
||||
"does not create the domain.")
|
||||
|
||||
gopts.opt('xmldryrun', short='x',
|
||||
fn=set_true, default=0,
|
||||
use="XML dry run - prints the resulting configuration in XML but "
|
||||
"does not create the domain.")
|
||||
|
||||
gopts.opt('paused', short='p',
|
||||
fn=set_true, default=0,
|
||||
use='Leave the domain paused after it is created.')
|
||||
@@ -1241,34 +1247,59 @@ def main(argv):
|
||||
except IOError, exn:
|
||||
raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
from xen.xm.xenapi_create import sxp2xml
|
||||
sxp2xml_inst = sxp2xml()
|
||||
doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True)
|
||||
|
||||
if opts.vals.dryrun:
|
||||
PrettyPrint.prettyprint(config)
|
||||
SXPPrettyPrint.prettyprint(config)
|
||||
|
||||
if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
|
||||
from xml.dom.ext import PrettyPrint as XMLPrettyPrint
|
||||
XMLPrettyPrint(doc)
|
||||
|
||||
if opts.vals.dryrun or opts.vals.xmldryrun:
|
||||
return
|
||||
|
||||
if opts.vals.console_autoconnect:
|
||||
do_console(sxp.child_value(config, 'name', -1))
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
from xen.xm.xenapi_create import xenapi_create
|
||||
xenapi_create_inst = xenapi_create()
|
||||
vm_refs = xenapi_create_inst.create(document = doc)
|
||||
|
||||
map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
|
||||
else:
|
||||
if not create_security_check(config):
|
||||
raise security.ACMError('Security Configuration prevents domain from starting')
|
||||
else:
|
||||
if opts.vals.console_autoconnect:
|
||||
cpid = os.fork()
|
||||
if cpid != 0:
|
||||
for i in range(10):
|
||||
# Catch failure of the create process
|
||||
time.sleep(1)
|
||||
(p, rv) = os.waitpid(cpid, os.WNOHANG)
|
||||
if os.WIFEXITED(rv):
|
||||
if os.WEXITSTATUS(rv) != 0:
|
||||
sys.exit(os.WEXITSTATUS(rv))
|
||||
try:
|
||||
# Acquire the console of the created dom
|
||||
name = sxp.child_value(config, 'name', -1)
|
||||
dom = server.xend.domain(name)
|
||||
domid = int(sxp.child_value(dom, 'domid', '-1'))
|
||||
console.execConsole(domid)
|
||||
except:
|
||||
pass
|
||||
print("Could not start console\n");
|
||||
sys.exit(0)
|
||||
dom = make_domain(opts, config)
|
||||
|
||||
raise security.ACMError(
|
||||
'Security Configuration prevents domain from starting')
|
||||
dom = make_domain(opts, config)
|
||||
|
||||
def do_console(domain_name):
|
||||
cpid = os.fork()
|
||||
if cpid != 0:
|
||||
for i in range(10):
|
||||
# Catch failure of the create process
|
||||
time.sleep(1)
|
||||
(p, rv) = os.waitpid(cpid, os.WNOHANG)
|
||||
if os.WIFEXITED(rv):
|
||||
if os.WEXITSTATUS(rv) != 0:
|
||||
sys.exit(os.WEXITSTATUS(rv))
|
||||
try:
|
||||
# Acquire the console of the created dom
|
||||
if serverType == SERVER_XEN_API:
|
||||
domid = server.xenapi.VM.get_domid(
|
||||
get_single_vm(domain_name))
|
||||
else:
|
||||
dom = server.xend.domain(domain_name)
|
||||
domid = int(sxp.child_value(dom, 'domid', '-1'))
|
||||
console.execConsole(domid)
|
||||
except:
|
||||
pass
|
||||
print("Could not start console\n");
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
||||
+437
-102
@@ -25,6 +25,7 @@ import atexit
|
||||
import cmd
|
||||
import os
|
||||
import pprint
|
||||
import readline
|
||||
import shlex
|
||||
import sys
|
||||
import re
|
||||
@@ -32,11 +33,11 @@ import getopt
|
||||
import socket
|
||||
import traceback
|
||||
import xmlrpclib
|
||||
import traceback
|
||||
import time
|
||||
import datetime
|
||||
from select import select
|
||||
import xml.dom.minidom
|
||||
from xen.util.blkif import blkdev_name_to_number
|
||||
|
||||
import warnings
|
||||
warnings.filterwarnings('ignore', category=FutureWarning)
|
||||
@@ -48,18 +49,19 @@ from xen.xend.XendConstants import *
|
||||
|
||||
from xen.xm.opts import OptionError, Opts, wrap, set_true
|
||||
from xen.xm import console
|
||||
from xen.util import security
|
||||
from xen.util.xmlrpclib2 import ServerProxy
|
||||
|
||||
import XenAPI
|
||||
|
||||
|
||||
# getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
|
||||
# getopt.getopt if gnu_getopt is not available. This will mean that options
|
||||
# may only be specified before positional arguments.
|
||||
if not hasattr(getopt, 'gnu_getopt'):
|
||||
getopt.gnu_getopt = getopt.getopt
|
||||
|
||||
XM_CONFIG_FILE = '/etc/xen/xm-config.xml'
|
||||
XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
|
||||
XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml'
|
||||
|
||||
# Supported types of server
|
||||
SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
|
||||
@@ -133,11 +135,12 @@ SUBCOMMAND_HELP = {
|
||||
'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
|
||||
'Get/set credit scheduler parameters.'),
|
||||
'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
|
||||
'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
|
||||
'trigger' : ('<Domain> <nmi|reset|init> [<VCPU>]',
|
||||
'Send a trigger to a domain.'),
|
||||
'vcpu-list' : ('[<Domain>]',
|
||||
'List the VCPUs for a domain or all domains.'),
|
||||
'vcpu-pin' : ('<Domain> <VCPU> <CPUs>',
|
||||
'vcpu-pin' : ('<Domain> <VCPU> <CPUs|all>',
|
||||
'Set which CPUs a VCPU can use.'),
|
||||
'vcpu-set' : ('<Domain> <vCPUs>',
|
||||
'Set the number of active VCPUs for allowed for the'
|
||||
@@ -260,7 +263,6 @@ common_commands = [
|
||||
"shutdown",
|
||||
"start",
|
||||
"suspend",
|
||||
"trigger",
|
||||
"top",
|
||||
"unpause",
|
||||
"uptime",
|
||||
@@ -300,6 +302,7 @@ domain_commands = [
|
||||
]
|
||||
|
||||
host_commands = [
|
||||
"debug-keys",
|
||||
"dmesg",
|
||||
"info",
|
||||
"log",
|
||||
@@ -349,13 +352,14 @@ all_commands = (domain_commands + host_commands + scheduler_commands +
|
||||
# Configuration File Parsing
|
||||
##
|
||||
|
||||
xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
|
||||
config = None
|
||||
if os.path.isfile(XM_CONFIG_FILE):
|
||||
if os.path.isfile(xmConfigFile):
|
||||
try:
|
||||
config = xml.dom.minidom.parse(XM_CONFIG_FILE)
|
||||
config = xml.dom.minidom.parse(xmConfigFile)
|
||||
except:
|
||||
print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
|
||||
XM_CONFIG_FILE)
|
||||
xmConfigFile)
|
||||
|
||||
def parseServer():
|
||||
if config:
|
||||
@@ -489,6 +493,18 @@ def usage(cmd = None):
|
||||
#
|
||||
####################################################################
|
||||
|
||||
def get_default_SR():
|
||||
return [sr_ref
|
||||
for sr_ref in server.xenapi.SR.get_all()
|
||||
if server.xenapi.SR.get_type(sr_ref) == "local"][0]
|
||||
|
||||
def get_default_Network():
|
||||
return [network_ref
|
||||
for network_ref in server.xenapi.network.get_all()][0]
|
||||
|
||||
def map2sxp(m):
|
||||
return [[k, m[k]] for k in m.keys()]
|
||||
|
||||
def arg_check(args, name, lo, hi = -1):
|
||||
n = len([i for i in args if i != '--'])
|
||||
|
||||
@@ -555,7 +571,11 @@ class Shell(cmd.Cmd):
|
||||
if serverType == SERVER_XEN_API:
|
||||
res = server.xenapi._UNSUPPORTED_list_all_methods()
|
||||
for f in res:
|
||||
setattr(Shell, 'do_' + f, self.default)
|
||||
setattr(Shell, 'do_' + f + ' ', self.default)
|
||||
|
||||
def preloop(self):
|
||||
cmd.Cmd.preloop(self)
|
||||
readline.set_completer_delims(' ')
|
||||
|
||||
def default(self, line):
|
||||
words = shlex.split(line)
|
||||
@@ -576,9 +596,9 @@ class Shell(cmd.Cmd):
|
||||
return False
|
||||
|
||||
def completedefault(self, text, line, begidx, endidx):
|
||||
cmd = line.split(' ')[0]
|
||||
clas, func = cmd.split('.')
|
||||
if begidx != len(cmd) + 1 or \
|
||||
words = shlex.split(line[:begidx])
|
||||
clas, func = words[0].split('.')
|
||||
if len(words) > 1 or \
|
||||
func.startswith('get_by_') or \
|
||||
func == 'get_all':
|
||||
return []
|
||||
@@ -667,10 +687,41 @@ def xm_restore(args):
|
||||
|
||||
|
||||
def getDomains(domain_names, state, full = 0):
|
||||
if domain_names:
|
||||
return [server.xend.domain(dom, full) for dom in domain_names]
|
||||
if serverType == SERVER_XEN_API:
|
||||
doms_sxp = []
|
||||
doms_dict = []
|
||||
dom_refs = server.xenapi.VM.get_all()
|
||||
for dom_ref in dom_refs:
|
||||
dom_rec = server.xenapi.VM.get_record(dom_ref)
|
||||
dom_metrics_ref = server.xenapi.VM.get_metrics(dom_ref)
|
||||
dom_metrics = server.xenapi.VM_metrics.get_record(dom_metrics_ref)
|
||||
dom_rec.update({'name': dom_rec['name_label'],
|
||||
'memory_actual': int(dom_metrics['memory_actual'])/1024,
|
||||
'vcpus': dom_metrics['vcpus_number'],
|
||||
'state': '-----',
|
||||
'cpu_time': dom_metrics['vcpus_utilisation']})
|
||||
|
||||
doms_sxp.append(['domain'] + map2sxp(dom_rec))
|
||||
doms_dict.append(dom_rec)
|
||||
|
||||
if domain_names:
|
||||
doms = [['domain'] + map2sxp(dom) for dom in doms_dict
|
||||
if dom["name"] in domain_names]
|
||||
|
||||
if len(doms) > 0:
|
||||
return doms
|
||||
else:
|
||||
print "Error: no domain%s named %s" % \
|
||||
(len(domain_names) > 1 and 's' or '',
|
||||
', '.join(domain_names))
|
||||
sys.exit(-1)
|
||||
else:
|
||||
return doms_sxp
|
||||
else:
|
||||
return server.xend.domains_with_state(True, state, full)
|
||||
if domain_names:
|
||||
return [server.xend.domain(dom, full) for dom in domain_names]
|
||||
else:
|
||||
return server.xend.domains_with_state(True, state, full)
|
||||
|
||||
|
||||
def xm_list(args):
|
||||
@@ -729,26 +780,48 @@ def parse_doms_info(info):
|
||||
else:
|
||||
up_time = time.time() - start_time
|
||||
|
||||
return {
|
||||
parsed_info = {
|
||||
'domid' : get_info('domid', str, ''),
|
||||
'name' : get_info('name', str, '??'),
|
||||
'mem' : get_info('memory_dynamic_min', int, 0),
|
||||
'state' : get_info('state', str, ''),
|
||||
'cpu_time' : get_info('cpu_time', float, 0.0),
|
||||
|
||||
# VCPUs is the number online when the VM is up, or the number
|
||||
# configured otherwise.
|
||||
'vcpus' : get_info('online_vcpus', int,
|
||||
get_info('vcpus', int, 0)),
|
||||
'up_time' : up_time,
|
||||
'seclabel' : security.get_security_printlabel(info),
|
||||
'up_time' : up_time
|
||||
}
|
||||
|
||||
# We're not supporting security stuff just yet via XenAPI
|
||||
|
||||
if serverType != SERVER_XEN_API:
|
||||
from xen.util import security
|
||||
parsed_info['seclabel'] = security.get_security_printlabel(info)
|
||||
else:
|
||||
parsed_info['seclabel'] = ""
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
|
||||
cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
|
||||
if sum(cpu_times.values()) > 0:
|
||||
parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
|
||||
else:
|
||||
parsed_info['cpu_time'] = 0
|
||||
else:
|
||||
parsed_info['mem'] = get_info('memory', int,0)
|
||||
parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
|
||||
|
||||
return parsed_info
|
||||
|
||||
def check_sched_type(sched):
|
||||
current = 'unknown'
|
||||
for x in server.xend.node.info()[1:]:
|
||||
if len(x) > 1 and x[0] == 'xen_scheduler':
|
||||
current = x[1]
|
||||
break
|
||||
if serverType == SERVER_XEN_API:
|
||||
current = server.xenapi.host.get_sched_policy(server.xenapi.session.get_this_host())
|
||||
else:
|
||||
current = 'unknown'
|
||||
for x in server.xend.node.info()[1:]:
|
||||
if len(x) > 1 and x[0] == 'xen_scheduler':
|
||||
current = x[1]
|
||||
break
|
||||
if sched != current:
|
||||
err("Xen is running with the %s scheduler" % current)
|
||||
sys.exit(1)
|
||||
@@ -788,17 +861,22 @@ def xm_label_list(doms):
|
||||
output = []
|
||||
format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
|
||||
'%(cpu_time)8.1f %(seclabel)9s'
|
||||
|
||||
for dom in doms:
|
||||
d = parse_doms_info(dom)
|
||||
if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
|
||||
if not d['seclabel']:
|
||||
d['seclabel'] = 'ERROR'
|
||||
elif security.active_policy in ['DEFAULT']:
|
||||
d['seclabel'] = 'DEFAULT'
|
||||
else:
|
||||
d['seclabel'] = 'INACTIVE'
|
||||
output.append((format % d, d['seclabel']))
|
||||
|
||||
if serverType != SERVER_XEN_API:
|
||||
from xen.util import security
|
||||
|
||||
for dom in doms:
|
||||
d = parse_doms_info(dom)
|
||||
|
||||
if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
|
||||
if not d['seclabel']:
|
||||
d['seclabel'] = 'ERROR'
|
||||
elif security.active_policy in ['DEFAULT']:
|
||||
d['seclabel'] = 'DEFAULT'
|
||||
else:
|
||||
d['seclabel'] = 'INACTIVE'
|
||||
|
||||
output.append((format % d, d['seclabel']))
|
||||
|
||||
#sort by labels
|
||||
output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
|
||||
@@ -807,7 +885,6 @@ def xm_label_list(doms):
|
||||
|
||||
|
||||
def xm_vcpu_list(args):
|
||||
|
||||
if args:
|
||||
dominfo = map(server.xend.domain.getVCPUInfo, args)
|
||||
else:
|
||||
@@ -1078,7 +1155,10 @@ def xm_vcpu_pin(args):
|
||||
|
||||
dom = args[0]
|
||||
vcpu = args[1]
|
||||
cpumap = cpu_make_map(args[2])
|
||||
if args[2] == 'all':
|
||||
cpumap = cpu_make_map('0-63')
|
||||
else:
|
||||
cpumap = cpu_make_map(args[2])
|
||||
|
||||
server.xend.domain.pincpu(dom, vcpu, cpumap)
|
||||
|
||||
@@ -1086,49 +1166,69 @@ def xm_mem_max(args):
|
||||
arg_check(args, "mem-max", 2)
|
||||
|
||||
dom = args[0]
|
||||
mem = int_unit(args[1], 'm')
|
||||
|
||||
server.xend.domain.maxmem_set(dom, mem)
|
||||
if serverType == SERVER_XEN_API:
|
||||
mem = int_unit(args[1], 'k') * 1024
|
||||
server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
|
||||
else:
|
||||
mem = int_unit(args[1], 'm')
|
||||
server.xend.domain.maxmem_set(dom, mem)
|
||||
|
||||
def xm_mem_set(args):
|
||||
arg_check(args, "mem-set", 2)
|
||||
|
||||
dom = args[0]
|
||||
mem_target = int_unit(args[1], 'm')
|
||||
|
||||
server.xend.domain.setMemoryTarget(dom, mem_target)
|
||||
if serverType == SERVER_XEN_API:
|
||||
mem_target = int_unit(args[1], 'm') * 1024 * 1024
|
||||
server.xenapi.VM.set_memory_dynamic_max(get_single_vm(dom), mem_target)
|
||||
server.xenapi.VM.set_memory_dynamic_min(get_single_vm(dom), mem_target)
|
||||
else:
|
||||
mem_target = int_unit(args[1], 'm')
|
||||
server.xend.domain.setMemoryTarget(dom, mem_target)
|
||||
|
||||
def xm_vcpu_set(args):
|
||||
arg_check(args, "vcpu-set", 2)
|
||||
|
||||
server.xend.domain.setVCpuCount(args[0], int(args[1]))
|
||||
|
||||
dom = args[0]
|
||||
vcpus = int(args[1])
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
server.xenapi.VM.set_vcpus_live(get_single_vm(dom), vcpus)
|
||||
else:
|
||||
server.xend.domain.setVCpuCount(dom, vcpus)
|
||||
|
||||
def xm_destroy(args):
|
||||
arg_check(args, "destroy", 1)
|
||||
|
||||
dom = args[0]
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
server.xenapi.VM.hard_shutdown(get_single_vm(dom))
|
||||
else:
|
||||
server.xend.domain.destroy(dom)
|
||||
|
||||
|
||||
def xm_domid(args):
|
||||
arg_check(args, "domid", 1)
|
||||
|
||||
name = args[0]
|
||||
|
||||
dom = server.xend.domain(name)
|
||||
print sxp.child_value(dom, 'domid')
|
||||
if serverType == SERVER_XEN_API:
|
||||
print server.xenapi.VM.get_domid(get_single_vm(name))
|
||||
else:
|
||||
dom = server.xend.domain(name)
|
||||
print sxp.child_value(dom, 'domid')
|
||||
|
||||
def xm_domname(args):
|
||||
arg_check(args, "domname", 1)
|
||||
|
||||
name = args[0]
|
||||
|
||||
dom = server.xend.domain(name)
|
||||
print sxp.child_value(dom, 'name')
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
print server.xenapi.VM.get_name_label(get_single_vm(name))
|
||||
else:
|
||||
dom = server.xend.domain(name)
|
||||
print sxp.child_value(dom, 'name')
|
||||
|
||||
def xm_sched_sedf(args):
|
||||
def ns_to_ms(val):
|
||||
@@ -1276,13 +1376,59 @@ def xm_sched_credit(args):
|
||||
def xm_info(args):
|
||||
arg_check(args, "info", 0)
|
||||
|
||||
info = server.xend.node.info()
|
||||
|
||||
for x in info[1:]:
|
||||
if len(x) < 2:
|
||||
print "%-23s: (none)" % x[0]
|
||||
else:
|
||||
print "%-23s:" % x[0], x[1]
|
||||
if serverType == SERVER_XEN_API:
|
||||
|
||||
# Need to fake out old style xm info as people rely on parsing it
|
||||
|
||||
host_record = server.xenapi.host.get_record(
|
||||
server.xenapi.session.get_this_host())
|
||||
|
||||
host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
|
||||
|
||||
host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
|
||||
|
||||
info = {
|
||||
"host": host_record["name_label"],
|
||||
"release": host_record["software_version"]["release"],
|
||||
"version": host_record["software_version"]["version"],
|
||||
"machine": host_record["software_version"]["machine"],
|
||||
"nr_cpus": len(host_record["host_CPUs"]),
|
||||
"nr_nodes": host_record["cpu_configuration"]["nr_nodes"],
|
||||
"sockets_per_node": host_record["cpu_configuration"]["sockets_per_node"],
|
||||
"cores_per_socket": host_record["cpu_configuration"]["cores_per_socket"],
|
||||
"threads_per_core": host_record["cpu_configuration"]["threads_per_core"],
|
||||
"cpu_mhz": sum([int(host_cpu_record["speed"]) for host_cpu_record in host_cpu_records])
|
||||
/ len(host_cpu_records),
|
||||
"hw_caps": host_cpu_records[0]["features"],
|
||||
"total_memory": int(host_metrics_record["memory_total"])/1024/1024,
|
||||
"free_memory": int(host_metrics_record["memory_free"])/1024/1024,
|
||||
"xen_major": host_record["software_version"]["xen_major"],
|
||||
"xen_minor": host_record["software_version"]["xen_minor"],
|
||||
"xen_extra": host_record["software_version"]["xen_extra"],
|
||||
"xen_caps": " ".join(host_record["capabilities"]),
|
||||
"xen_scheduler": host_record["sched_policy"],
|
||||
"xen_pagesize": host_record["other_config"]["xen_pagesize"],
|
||||
"platform_params": host_record["other_config"]["platform_params"],
|
||||
"xen_changeset": host_record["software_version"]["xen_changeset"],
|
||||
"cc_compiler": host_record["software_version"]["cc_compiler"],
|
||||
"cc_compile_by": host_record["software_version"]["cc_compile_by"],
|
||||
"cc_compile_domain": host_record["software_version"]["cc_compile_domain"],
|
||||
"cc_compile_date": host_record["software_version"]["cc_compile_date"],
|
||||
"xend_config_format":host_record["software_version"]["xend_config_format"]
|
||||
}
|
||||
|
||||
sorted = info.items()
|
||||
sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
|
||||
|
||||
for (k, v) in sorted:
|
||||
print "%-23s:" % k, v
|
||||
else:
|
||||
info = server.xend.node.info()
|
||||
for x in info[1:]:
|
||||
if len(x) < 2:
|
||||
print "%-23s: (none)" % x[0]
|
||||
else:
|
||||
print "%-23s:" % x[0], x[1]
|
||||
|
||||
def xm_console(args):
|
||||
arg_check(args, "console", 1, 2)
|
||||
@@ -1308,13 +1454,17 @@ def xm_console(args):
|
||||
dom = params[0]
|
||||
|
||||
try:
|
||||
info = server.xend.domain(dom)
|
||||
if serverType == SERVER_XEN_API:
|
||||
domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
|
||||
else:
|
||||
info = server.xend.domain(dom)
|
||||
domid = int(sxp.child_value(info, 'domid', '-1'))
|
||||
except:
|
||||
if quiet:
|
||||
sys.exit(1)
|
||||
else:
|
||||
raise
|
||||
domid = int(sxp.child_value(info, 'domid', '-1'))
|
||||
|
||||
if domid == -1:
|
||||
if quiet:
|
||||
sys.exit(1)
|
||||
@@ -1382,7 +1532,10 @@ def xm_sysrq(args):
|
||||
arg_check(args, "sysrq", 2)
|
||||
dom = args[0]
|
||||
req = args[1]
|
||||
server.xend.domain.send_sysrq(dom, req)
|
||||
if serverType == SERVER_XEN_API:
|
||||
server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
|
||||
else:
|
||||
server.xend.domain.send_sysrq(dom, req)
|
||||
|
||||
def xm_trigger(args):
|
||||
vcpu = 0
|
||||
@@ -1392,8 +1545,23 @@ def xm_trigger(args):
|
||||
trigger = args[1]
|
||||
if len(args) == 3:
|
||||
vcpu = int(args[2])
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
|
||||
else:
|
||||
server.xend.domain.send_trigger(dom, trigger, vcpu)
|
||||
|
||||
def xm_debug_keys(args):
|
||||
arg_check(args, "debug-keys", 1)
|
||||
|
||||
keys = str(args[0])
|
||||
|
||||
server.xend.domain.send_trigger(dom, trigger, vcpu)
|
||||
if serverType == SERVER_XEN_API:
|
||||
server.xenapi.host.send_debug_keys(
|
||||
server.xenapi.session.get_this_host(),
|
||||
keys)
|
||||
else:
|
||||
server.xend.node.send_debug_keys(keys)
|
||||
|
||||
def xm_top(args):
|
||||
arg_check(args, "top", 0)
|
||||
@@ -1418,17 +1586,33 @@ def xm_dmesg(args):
|
||||
err("No parameter required")
|
||||
usage('dmesg')
|
||||
|
||||
if not use_clear:
|
||||
print server.xend.node.dmesg.info()
|
||||
if serverType == SERVER_XEN_API:
|
||||
if not use_clear:
|
||||
print server.xenapi.host.dmesg(
|
||||
server.xenapi.session.get_this_host(),0)
|
||||
else:
|
||||
server.xenapi.host.dmesg(
|
||||
server.xenapi.session.get_this_host(),1)
|
||||
else:
|
||||
server.xend.node.dmesg.clear()
|
||||
if not use_clear:
|
||||
print server.xend.node.dmesg.info()
|
||||
else:
|
||||
server.xend.node.dmesg.clear()
|
||||
|
||||
def xm_log(args):
|
||||
arg_check(args, "log", 0)
|
||||
|
||||
print server.xend.node.log()
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
print server.xenapi.host.get_log(
|
||||
server.xenapi.session.get_this_host())
|
||||
else:
|
||||
print server.xend.node.log()
|
||||
|
||||
def xm_serve(args):
|
||||
if serverType == SERVER_XEN_API:
|
||||
print "Not supported with XenAPI"
|
||||
sys.exit(-1)
|
||||
|
||||
arg_check(args, "serve", 0)
|
||||
|
||||
from fcntl import fcntl, F_SETFL
|
||||
@@ -1503,12 +1687,21 @@ def xm_network_list(args):
|
||||
(use_long, params) = arg_check_for_resource_list(args, "network-list")
|
||||
|
||||
dom = params[0]
|
||||
if use_long:
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
|
||||
vif_properties = \
|
||||
map(server.xenapi.VIF.get_runtime_properties, vif_refs)
|
||||
devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
|
||||
zip(range(len(vif_properties)), vif_properties))
|
||||
else:
|
||||
devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
|
||||
|
||||
if use_long:
|
||||
map(PrettyPrint.prettyprint, devs)
|
||||
else:
|
||||
hdr = 0
|
||||
for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
|
||||
for x in devs:
|
||||
if hdr == 0:
|
||||
print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
|
||||
hdr = 1
|
||||
@@ -1528,12 +1721,25 @@ def xm_block_list(args):
|
||||
(use_long, params) = arg_check_for_resource_list(args, "block-list")
|
||||
|
||||
dom = params[0]
|
||||
if use_long:
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
|
||||
vbd_properties = \
|
||||
map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
|
||||
vbd_devs = \
|
||||
map(server.xenapi.VBD.get_device, vbd_refs)
|
||||
vbd_devids = \
|
||||
map(blkdev_name_to_number, vbd_devs)
|
||||
devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
|
||||
zip(vbd_devids, vbd_properties))
|
||||
else:
|
||||
devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
|
||||
|
||||
if use_long:
|
||||
map(PrettyPrint.prettyprint, devs)
|
||||
else:
|
||||
hdr = 0
|
||||
for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
|
||||
for x in devs:
|
||||
if hdr == 0:
|
||||
print 'Vdev BE handle state evt-ch ring-ref BE-path'
|
||||
hdr = 1
|
||||
@@ -1588,13 +1794,17 @@ def parse_block_configuration(args):
|
||||
if len(args) == 5:
|
||||
vbd.append(['backend', args[4]])
|
||||
|
||||
# verify that policy permits attaching this resource
|
||||
if security.on():
|
||||
dominfo = server.xend.domain(dom)
|
||||
label = security.get_security_printlabel(dominfo)
|
||||
else:
|
||||
label = None
|
||||
security.res_security_check(args[1], label)
|
||||
if serverType != SERVER_XEN_API:
|
||||
# verify that policy permits attaching this resource
|
||||
from xen.util import security
|
||||
|
||||
if security.on():
|
||||
dominfo = server.xend.domain(dom)
|
||||
label = security.get_security_printlabel(dominfo)
|
||||
else:
|
||||
label = None
|
||||
|
||||
security.res_security_check(args[1], label)
|
||||
|
||||
return (dom, vbd)
|
||||
|
||||
@@ -1602,8 +1812,45 @@ def parse_block_configuration(args):
|
||||
def xm_block_attach(args):
|
||||
arg_check(args, 'block-attach', 4, 5)
|
||||
|
||||
(dom, vbd) = parse_block_configuration(args)
|
||||
server.xend.domain.device_create(dom, vbd)
|
||||
if serverType == SERVER_XEN_API:
|
||||
dom = args[0]
|
||||
uname = args[1]
|
||||
dev = args[2]
|
||||
mode = args[3]
|
||||
|
||||
# First create new VDI
|
||||
vdi_record = {
|
||||
"name_label": "vdi" + str(uname.__hash__()),
|
||||
"name_description": "",
|
||||
"SR": get_default_SR(),
|
||||
"virtual_size": 0,
|
||||
"sector_size": 512,
|
||||
"type": "system",
|
||||
"sharable": False,
|
||||
"read_only": mode!="w",
|
||||
"other_config": {"location": uname}
|
||||
}
|
||||
|
||||
vdi_ref = server.xenapi.VDI.create(vdi_record)
|
||||
|
||||
# Now create new VBD
|
||||
|
||||
vbd_record = {
|
||||
"VM": get_single_vm(dom),
|
||||
"VDI": vdi_ref,
|
||||
"device": dev,
|
||||
"bootable": True,
|
||||
"mode": mode=="w" and "RW" or "RO",
|
||||
"type": "Disk",
|
||||
"qos_algorithm_type": "",
|
||||
"qos_algorithm_params": {}
|
||||
}
|
||||
|
||||
server.xenapi.VBD.create(vbd_record)
|
||||
|
||||
else:
|
||||
(dom, vbd) = parse_block_configuration(args)
|
||||
server.xend.domain.device_create(dom, vbd)
|
||||
|
||||
|
||||
def xm_block_configure(args):
|
||||
@@ -1621,15 +1868,65 @@ def xm_network_attach(args):
|
||||
vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
|
||||
'backend', 'vifname', 'rate', 'model']
|
||||
|
||||
for a in args[1:]:
|
||||
vif_param = a.split("=")
|
||||
if len(vif_param) != 2 or vif_param[1] == '' or \
|
||||
vif_param[0] not in vif_params:
|
||||
err("Invalid argument: %s" % a)
|
||||
usage('network-attach')
|
||||
vif.append(vif_param)
|
||||
if serverType == SERVER_XEN_API:
|
||||
vif_record = {
|
||||
"device": "eth0",
|
||||
"network": get_default_Network(),
|
||||
"VM": get_single_vm(dom),
|
||||
"MAC": "",
|
||||
"MTU": "",
|
||||
"qos_algorithm_type": "",
|
||||
"qos_algorithm_params": {},
|
||||
"other_config": {}
|
||||
}
|
||||
|
||||
server.xend.domain.device_create(dom, vif)
|
||||
def set(keys, val):
|
||||
record = vif_record
|
||||
for key in keys[:-1]:
|
||||
record = record[key]
|
||||
record[keys[-1]] = val
|
||||
|
||||
vif_conv = {
|
||||
'type':
|
||||
lambda x: None,
|
||||
'mac':
|
||||
lambda x: set(['MAC'], x),
|
||||
'bridge':
|
||||
lambda x: set(['network'], get_net_from_bridge(x)),
|
||||
'ip':
|
||||
lambda x: set(['other_config', 'ip'], x),
|
||||
'script':
|
||||
lambda x: set(['other_config', 'script'], x),
|
||||
'backend':
|
||||
lambda x: set(['other_config', 'backend'], x),
|
||||
'vifname':
|
||||
lambda x: set(['device'], x),
|
||||
'rate':
|
||||
lambda x: set(['qos_algorithm_params', 'rate'], x),
|
||||
'model':
|
||||
lambda x: None
|
||||
}
|
||||
|
||||
for a in args[1:]:
|
||||
vif_param = a.split("=")
|
||||
if len(vif_param) != 2 or vif_param[1] == '' or \
|
||||
vif_param[0] not in vif_params:
|
||||
err("Invalid argument: %s" % a)
|
||||
usage('network-attach')
|
||||
else:
|
||||
vif_conv[vif_param[0]](vif_param[1])
|
||||
|
||||
print str(vif_record)
|
||||
server.xenapi.VIF.create(vif_record)
|
||||
else:
|
||||
for a in args[1:]:
|
||||
vif_param = a.split("=")
|
||||
if len(vif_param) != 2 or vif_param[1] == '' or \
|
||||
vif_param[0] not in vif_params:
|
||||
err("Invalid argument: %s" % a)
|
||||
usage('network-attach')
|
||||
vif.append(vif_param)
|
||||
server.xend.domain.device_create(dom, vif)
|
||||
|
||||
|
||||
def detach(args, command, deviceClass):
|
||||
@@ -1649,16 +1946,49 @@ def detach(args, command, deviceClass):
|
||||
|
||||
|
||||
def xm_block_detach(args):
|
||||
try:
|
||||
detach(args, 'block-detach', 'vbd')
|
||||
return
|
||||
except:
|
||||
pass
|
||||
detach(args, 'block-detach', 'tap')
|
||||
if serverType == SERVER_XEN_API:
|
||||
arg_check(args, "xm_block_detach", 2, 3)
|
||||
dom = args[0]
|
||||
dev = args[1]
|
||||
vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
|
||||
vbd_refs = [vbd_ref for vbd_ref in vbd_refs
|
||||
if server.xenapi.VBD.get_device(vbd_ref) == dev]
|
||||
if len(vbd_refs) > 0:
|
||||
vbd_ref = vbd_refs[0]
|
||||
vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
|
||||
|
||||
server.xenapi.VBD.destroy(vbd_ref)
|
||||
|
||||
if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
|
||||
server.xenapi.VDI.destroy(vdi_ref)
|
||||
else:
|
||||
raise OptionError("Cannot find device '%s' in domain '%s'"
|
||||
% (dev,dom))
|
||||
else:
|
||||
try:
|
||||
detach(args, 'block-detach', 'vbd')
|
||||
return
|
||||
except:
|
||||
pass
|
||||
detach(args, 'block-detach', 'tap')
|
||||
|
||||
def xm_network_detach(args):
|
||||
detach(args, 'network-detach', 'vif')
|
||||
if serverType == SERVER_XEN_API:
|
||||
arg_check(args, "xm_block_detach", 2, 3)
|
||||
dom = args[0]
|
||||
devid = args[1]
|
||||
vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
|
||||
vif_refs = [vif_ref for vif_ref in vif_refs
|
||||
if server.xenapi.VIF.\
|
||||
get_runtime_properties(vif_ref)["handle"] == devid]
|
||||
if len(vif_refs) > 0:
|
||||
vif_ref = vif_refs[0]
|
||||
|
||||
server.xenapi.VIF.destroy(vif_ref)
|
||||
else:
|
||||
print "Cannot find device '%s' in domain '%s'" % (devid,dom)
|
||||
else:
|
||||
detach(args, 'network-detach', 'vif')
|
||||
|
||||
|
||||
def xm_vnet_list(args):
|
||||
@@ -1738,6 +2068,7 @@ commands = {
|
||||
"pause": xm_pause,
|
||||
"unpause": xm_unpause,
|
||||
# host commands
|
||||
"debug-keys": xm_debug_keys,
|
||||
"dmesg": xm_dmesg,
|
||||
"info": xm_info,
|
||||
"log": xm_log,
|
||||
@@ -1881,7 +2212,7 @@ def _run_cmd(cmd, cmd_name, args):
|
||||
err("Domain '%s' does not exist." % ex.faultString)
|
||||
else:
|
||||
err(ex.faultString)
|
||||
_usage(cmd_name)
|
||||
_usage(cmd_name)
|
||||
except xmlrpclib.ProtocolError, ex:
|
||||
if ex.errcode == -1:
|
||||
print >>sys.stderr, (
|
||||
@@ -1898,13 +2229,17 @@ def _run_cmd(cmd, cmd_name, args):
|
||||
err(str(e))
|
||||
_usage(cmd_name)
|
||||
print e.usage
|
||||
except security.ACMError, e:
|
||||
err(str(e))
|
||||
except:
|
||||
print "Unexpected error:", sys.exc_info()[0]
|
||||
print
|
||||
print "Please report to xen-devel@lists.xensource.com"
|
||||
raise
|
||||
except Exception, e:
|
||||
if serverType != SERVER_XEN_API:
|
||||
from xen.util import security
|
||||
if isinstance(e, security.ACMError):
|
||||
err(str(e))
|
||||
return False, 1
|
||||
else:
|
||||
print "Unexpected error:", sys.exc_info()[0]
|
||||
print
|
||||
print "Please report to xen-devel@lists.xensource.com"
|
||||
raise
|
||||
|
||||
return False, 1
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Xen-xm 3.0\n"
|
||||
"PO-Revision-Date: 2007-02-20 15:22+0000\n"
|
||||
"PO-Revision-Date: 2007-03-10 23:17+0000\n"
|
||||
"Last-Translator: Ewan Mellor <ewan@xensource.com>\n"
|
||||
"Language-Team: xen-devel <xen-devel@lists.xensource.com>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -61,3 +61,6 @@ msgstr "The VLAN tag you gave (%(1)s) is invalid -- it must be between 0 and 409
|
||||
|
||||
msgid "VM_BAD_POWER_STATE"
|
||||
msgstr "The VM must be %(2)s to perform the requested operation (it is currently %(3)s)."
|
||||
|
||||
msgid "VM_HVM_REQUIRED"
|
||||
msgstr "HVM guest support is unavailable: is VT/AMD-V supported by your CPU and enabled in your BIOS?"
|
||||
@@ -22,6 +22,9 @@ from xen.xend import PrettyPrint
|
||||
from xen.xend import sxp
|
||||
from xen.xend import XendClient
|
||||
|
||||
from xen.xm.main import serverType, SERVER_XEN_API
|
||||
from xen.xm.xenapi_create import *
|
||||
|
||||
from opts import *
|
||||
from create import *
|
||||
|
||||
@@ -65,7 +68,15 @@ def main(argv):
|
||||
|
||||
if opts.vals.dryrun:
|
||||
PrettyPrint.prettyprint(config)
|
||||
else:
|
||||
return
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
sxp2xml_inst = sxp2xml()
|
||||
doc = sxp2xml_inst.convert_sxp_to_xml(config)
|
||||
|
||||
xenapi_create_inst = xenapi_create()
|
||||
vm_refs = xenapi_create_inst.create(document = doc)
|
||||
else:
|
||||
make_unstarted_domain(opts, config)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -21,7 +21,8 @@ import time
|
||||
|
||||
from xen.xend import sxp
|
||||
from opts import *
|
||||
from main import server
|
||||
from main import server, serverType, SERVER_XEN_API, get_single_vm
|
||||
from xen.xend.XendAPIConstants import *
|
||||
|
||||
gopts = Opts(use="""[options] [DOM]
|
||||
|
||||
@@ -49,6 +50,9 @@ gopts.opt('reboot', short='R',
|
||||
use='Shutdown and reboot.')
|
||||
|
||||
def wait_reboot(opts, doms, rcs):
|
||||
if serverType == SERVER_XEN_API:
|
||||
opts.err("Cannot wait for reboot w/ XenAPI (yet)")
|
||||
|
||||
while doms:
|
||||
alive = server.xend.domains(0)
|
||||
reboot = []
|
||||
@@ -68,7 +72,12 @@ def wait_reboot(opts, doms, rcs):
|
||||
|
||||
def wait_shutdown(opts, doms):
|
||||
while doms:
|
||||
alive = server.xend.domains(0)
|
||||
if serverType == SERVER_XEN_API:
|
||||
alive = [dom for dom in server.xenapi.VM.get_all()
|
||||
if server.xenapi.VM.get_power_state(dom) ==
|
||||
XEN_API_VM_POWER_STATE[XEN_API_VM_POWER_STATE_RUNNING]]
|
||||
else:
|
||||
alive = server.xend.domains(0)
|
||||
dead = []
|
||||
for d in doms:
|
||||
if d in alive: continue
|
||||
@@ -82,8 +91,16 @@ def wait_shutdown(opts, doms):
|
||||
def shutdown(opts, doms, mode, wait):
|
||||
rcs = {}
|
||||
for d in doms:
|
||||
rcs[d] = server.xend.domain.getRestartCount(d)
|
||||
server.xend.domain.shutdown(d, mode)
|
||||
if serverType == SERVER_XEN_API:
|
||||
if mode == 'halt':
|
||||
server.xenapi.VM.clean_shutdown(d)
|
||||
if mode == 'reboot':
|
||||
server.xenapi.VM.clean_reboot(d)
|
||||
if mode == 'poweroff':
|
||||
server.xenapi.VM.clean_shutdown(d)
|
||||
else:
|
||||
rcs[d] = server.xend.domain.getRestartCount(d)
|
||||
server.xend.domain.shutdown(d, mode)
|
||||
|
||||
if wait:
|
||||
if mode == 'reboot':
|
||||
@@ -103,9 +120,13 @@ def shutdown_mode(opts):
|
||||
return 'poweroff'
|
||||
|
||||
def main_all(opts, args):
|
||||
doms = server.xend.domains(0)
|
||||
dom0_name = sxp.child_value(server.xend.domain(0), 'name')
|
||||
doms.remove(dom0_name)
|
||||
if serverType == SERVER_XEN_API:
|
||||
doms = [dom for dom in server.xenapi.VM.get_all()
|
||||
if not server.xenapi.VM.get_is_control_domain(dom)]
|
||||
else:
|
||||
doms = server.xend.domains(0)
|
||||
dom0_name = sxp.child_value(server.xend.domain(0), 'name')
|
||||
doms.remove(dom0_name)
|
||||
mode = shutdown_mode(opts)
|
||||
shutdown(opts, doms, mode, opts.vals.wait)
|
||||
|
||||
@@ -113,6 +134,8 @@ def main_dom(opts, args):
|
||||
if len(args) == 0: opts.err('No domain parameter given')
|
||||
if len(args) > 1: opts.err('No multiple domain parameters allowed')
|
||||
dom = args[0]
|
||||
if serverType == SERVER_XEN_API:
|
||||
dom = get_single_vm(dom)
|
||||
mode = shutdown_mode(opts)
|
||||
shutdown(opts, [ dom ], mode, opts.vals.wait)
|
||||
|
||||
|
||||
@@ -0,0 +1,636 @@
|
||||
#!/usr/bin/python
|
||||
#============================================================================
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2007 Tom Wilkie <tom.wilkie@gmail.com>
|
||||
#============================================================================
|
||||
"""Domain creation using new XenAPI
|
||||
"""
|
||||
|
||||
from xen.xm.main import server, get_default_SR
|
||||
from xml.dom.minidom import parse, getDOMImplementation
|
||||
from xml.dom.ext import PrettyPrint
|
||||
from xml.parsers.xmlproc import xmlproc, xmlval, xmldtd
|
||||
from xen.xend import sxp
|
||||
from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \
|
||||
XEN_API_ON_CRASH_BEHAVIOUR
|
||||
|
||||
|
||||
import sys
|
||||
import os
|
||||
import traceback
|
||||
|
||||
def log(_, msg):
|
||||
#print "> " + msg
|
||||
pass
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
def get_name_label(node):
|
||||
name_node = node.getElementsByTagName("name")[0]
|
||||
label_node = name_node.getElementsByTagName("label")[0]
|
||||
return " ".join([child.nodeValue for child in label_node.childNodes])
|
||||
|
||||
def get_name_description(node):
|
||||
name_node = node.getElementsByTagName("name")[0]
|
||||
description_node = name_node.getElementsByTagName("description")[0]
|
||||
return " ".join([child.nodeValue for child in description_node.childNodes])
|
||||
|
||||
def get_text_in_child_node(node, child):
|
||||
tag_node = node.getElementsByTagName(child)[0]
|
||||
return tag_node.nodeValue
|
||||
|
||||
def get_child_node_attribute(node, child, attribute):
|
||||
tag_node = node.getElementsByTagName(child)[0]
|
||||
return tag_node.attributes[attribute].value
|
||||
|
||||
def get_child_nodes_as_dict(node, child_name,
|
||||
key_attribute_name,
|
||||
value_attribute_name):
|
||||
return dict([(child.attributes[key_attribute_name].value,
|
||||
child.attributes[value_attribute_name].value)
|
||||
for child in node.getElementsByTagName(child_name)])
|
||||
|
||||
def try_quietly(fn, *args):
|
||||
try:
|
||||
return fn(*args)
|
||||
except:
|
||||
return None
|
||||
|
||||
class xenapi_create:
|
||||
|
||||
def __init__(self):
|
||||
self.DEFAULT_STORAGE_REPOSITORY = get_default_SR()
|
||||
|
||||
self.dtd = "/usr/lib/python/xen/xm/create.dtd"
|
||||
|
||||
def create(self, filename=None, document=None):
|
||||
"""
|
||||
Create a domain from an XML file or DOM tree
|
||||
"""
|
||||
if filename is not None:
|
||||
self.check_dtd(file)
|
||||
document = parse(file)
|
||||
elif document is not None:
|
||||
self.check_dom_against_dtd(document)
|
||||
|
||||
self.check_doc(document)
|
||||
|
||||
vdis = document.getElementsByTagName("vdi")
|
||||
vdi_refs_dict = self.create_vdis(vdis)
|
||||
|
||||
try:
|
||||
vms = document.getElementsByTagName("vm")
|
||||
return self.create_vms(vms, vdi_refs_dict)
|
||||
except Exception, exn:
|
||||
try_quietly(self.cleanup_vdis(vdi_refs_dict))
|
||||
raise exn
|
||||
|
||||
# Methods to check xml file
|
||||
# try to use dtd to check where possible
|
||||
def check_dtd(self, file):
|
||||
"""
|
||||
Check file against DTD.
|
||||
Use this if possible as it gives nice
|
||||
error messages
|
||||
"""
|
||||
dtd = xmldtd.load_dtd(self.dtd)
|
||||
parser = xmlproc.XMLProcessor()
|
||||
parser.set_application(xmlval.ValidatingApp(dtd, parser))
|
||||
parser.dtd = dtd
|
||||
parser.ent = dtd
|
||||
parser.parse_resource(file)
|
||||
|
||||
def check_dom_against_dtd(self, dom):
|
||||
"""
|
||||
Check DOM again DTD.
|
||||
Doesn't give as nice error messages.
|
||||
(no location info)
|
||||
"""
|
||||
dtd = xmldtd.load_dtd(self.dtd)
|
||||
app = xmlval.ValidatingApp(dtd, self)
|
||||
app.set_locator(self)
|
||||
self.dom2sax(dom, app)
|
||||
|
||||
# Get errors back from ValidatingApp
|
||||
def report_error(self, number, args=None):
|
||||
self.errors = xmlproc.errors.english
|
||||
try:
|
||||
msg = self.errors[number]
|
||||
if args != None:
|
||||
msg = msg % args
|
||||
except KeyError:
|
||||
msg = self.errors[4002] % number # Unknown err msg :-)
|
||||
print msg
|
||||
sys.exit(-1)
|
||||
|
||||
# Here for compatibility with ValidatingApp
|
||||
def get_line(self):
|
||||
return -1
|
||||
|
||||
def get_column(self):
|
||||
return -1
|
||||
|
||||
def dom2sax(self, dom, app):
|
||||
"""
|
||||
Take a dom tree and tarverse it,
|
||||
issuing SAX calls to app.
|
||||
"""
|
||||
for child in dom.childNodes:
|
||||
if child.nodeType == child.TEXT_NODE:
|
||||
data = child.nodeValue
|
||||
app.handle_data(data, 0, len(data))
|
||||
else:
|
||||
app.handle_start_tag(
|
||||
child.nodeName,
|
||||
self.attrs_to_dict(child.attributes))
|
||||
self.dom2sax(child, app)
|
||||
app.handle_end_tag(child.nodeName)
|
||||
|
||||
def attrs_to_dict(self, attrs):
|
||||
return dict(attrs.items())
|
||||
|
||||
#
|
||||
# Checks which cannot be done with dtd
|
||||
#
|
||||
def check_doc(self, doc):
|
||||
vms = doc.getElementsByTagName("vm")
|
||||
self.check_vms(vms)
|
||||
|
||||
def check_vms(self, vms):
|
||||
map(self.check_vm, vms)
|
||||
|
||||
def check_vm(self, vm):
|
||||
vifs = vm.getElementsByTagName("vif")
|
||||
self.check_vifs(vifs)
|
||||
|
||||
def check_vifs(self, vifs):
|
||||
map(self.check_vif, vifs)
|
||||
|
||||
def check_vif(self, vif):
|
||||
"""
|
||||
Check that the vif has
|
||||
either a bridge or network
|
||||
name but not both
|
||||
"""
|
||||
if "bridge" in vif.attributes.keys() \
|
||||
and "network" in vif.attributes.keys():
|
||||
raise "You cannot specify both a bridge and\
|
||||
a network name."
|
||||
|
||||
# Cleanup methods here
|
||||
def cleanup_vdis(self, vdi_refs_dict):
|
||||
map(self.cleanup_vdi, vdi_refs_dict.values())
|
||||
|
||||
def cleanup_vdi(self, vdi_ref):
|
||||
server.xenapi.VDI.destroy(vdi_ref)
|
||||
|
||||
def cleanup_vms(self, vm_refs):
|
||||
map(self.cleanup_vm, vm_refs)
|
||||
|
||||
def cleanup_vm(self, vm_ref):
|
||||
server.xenapi.VM.destroy(vm_ref)
|
||||
|
||||
# Create methods here
|
||||
def create_vdis(self, vdis):
|
||||
log(DEBUG, "create_vdis")
|
||||
return dict(map(self.create_vdi, vdis))
|
||||
|
||||
def create_vdi(self, vdi):
|
||||
log(DEBUG, "create_vdi")
|
||||
|
||||
vdi_record = {
|
||||
"name_label": get_name_label(vdi),
|
||||
"name_description": get_name_description(vdi),
|
||||
"SR": self.DEFAULT_STORAGE_REPOSITORY,
|
||||
"virtual_size": vdi.attributes["size"].value,
|
||||
"type": vdi.attributes["type"].value,
|
||||
"shareable": vdi.attributes["shareable"].value,
|
||||
"read_only": vdi.attributes["read_only"].value,
|
||||
"other_config": {"location":
|
||||
vdi.attributes["src"].value}
|
||||
}
|
||||
|
||||
key = vdi.attributes["name"].value
|
||||
value = server.xenapi.VDI.create(vdi_record)
|
||||
|
||||
return (key, value)
|
||||
|
||||
def create_vms(self, vms, vdis):
|
||||
log(DEBUG, "create_vms")
|
||||
return map(lambda vm: self.create_vm(vm, vdis), vms)
|
||||
|
||||
def create_vm(self, vm, vdis):
|
||||
log(DEBUG, "create_vm")
|
||||
|
||||
vm_record = {
|
||||
"name_label":
|
||||
get_name_label(vm),
|
||||
"name_description":
|
||||
get_name_description(vm),
|
||||
"user_version":
|
||||
get_text_in_child_node(vm, "version"),
|
||||
"is_a_template":
|
||||
vm.attributes["is_a_template"].value,
|
||||
"auto_power_on":
|
||||
vm.attributes["auto_power_on"].value,
|
||||
"memory_static_max":
|
||||
get_child_node_attribute(vm, "memory", "static_max"),
|
||||
"memory_static_min":
|
||||
get_child_node_attribute(vm, "memory", "static_min"),
|
||||
"memory_dynamic_max":
|
||||
get_child_node_attribute(vm, "memory", "dynamic_max"),
|
||||
"memory_dynamic_min":
|
||||
get_child_node_attribute(vm, "memory", "dynamic_min"),
|
||||
"vcpus_params":
|
||||
get_child_nodes_as_dict(vm, "vcpu_param", "key", "value"),
|
||||
"vcpus_max":
|
||||
vm.attributes["vcpus_max"].value,
|
||||
"vcpus_at_startup":
|
||||
vm.attributes["vcpus_at_startup"].value,
|
||||
"actions_after_shutdown":
|
||||
vm.attributes["actions_after_shutdown"].value,
|
||||
"actions_after_reboot":
|
||||
vm.attributes["actions_after_reboot"].value,
|
||||
"actions_after_crash":
|
||||
vm.attributes["actions_after_crash"].value,
|
||||
"platform_std_VGA":
|
||||
vm.attributes["platform_std_VGA"].value,
|
||||
"platform_serial":
|
||||
vm.attributes["platform_serial"].value,
|
||||
"platform_localtime":
|
||||
vm.attributes["platform_localtime"].value,
|
||||
"platform_clock_offet":
|
||||
vm.attributes["platform_clock_offet"].value,
|
||||
"platform_enable_audio":
|
||||
vm.attributes["platform_enable_audio"].value,
|
||||
"PCI_bus":
|
||||
vm.attributes["platform_enable_audio"].value,
|
||||
"other_config":
|
||||
get_child_nodes_as_dict(vm, "other_config", "key", "value")
|
||||
}
|
||||
|
||||
if len(vm.getElementsByTagName("pv")) > 0:
|
||||
vm_record.update({
|
||||
"PV_bootloader":
|
||||
get_child_node_attribute(vm, "pv", "bootloader"),
|
||||
"PV_kernel":
|
||||
get_child_node_attribute(vm, "pv", "kernel"),
|
||||
"PV_ramdisk":
|
||||
get_child_node_attribute(vm, "pv", "ramdisk"),
|
||||
"PV_args":
|
||||
get_child_node_attribute(vm, "pv", "args"),
|
||||
"PV_bootloader_args":
|
||||
get_child_node_attribute(vm, "pv", "bootloader_args")
|
||||
})
|
||||
else:
|
||||
hvm = vm.getElementsByTagName("hvm")[0]
|
||||
vm_record.update({
|
||||
"HVM_boot_policy":
|
||||
get_child_node_attribute(vm, "hvm", "boot_policy"),
|
||||
"HVM_boot_params":
|
||||
get_child_nodes_as_dict(hvm, "boot_params", "key", "value")
|
||||
})
|
||||
try:
|
||||
vm_ref = server.xenapi.VM.create(vm_record)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
sys.exit(-1)
|
||||
|
||||
# Now create vbds
|
||||
|
||||
vbds = vm.getElementsByTagName("vbd")
|
||||
|
||||
self.create_vbds(vm_ref, vbds, vdis)
|
||||
|
||||
# Now create vifs
|
||||
|
||||
vifs = vm.getElementsByTagName("vif")
|
||||
|
||||
self.create_vifs(vm_ref, vifs)
|
||||
|
||||
return vm_ref
|
||||
|
||||
def create_vbds(self, vm_ref, vbds, vdis):
|
||||
log(DEBUG, "create_vbds")
|
||||
return map(lambda vbd: self.create_vbd(vm_ref, vbd, vdis), vbds)
|
||||
|
||||
def create_vbd(self, vm_ref, vbd, vdis):
|
||||
log(DEBUG, "create_vbd")
|
||||
|
||||
vbd_record = {
|
||||
"VM":
|
||||
vm_ref,
|
||||
"VDI":
|
||||
vdis[vbd.attributes["vdi"].value],
|
||||
"device":
|
||||
vbd.attributes["device"].value,
|
||||
"bootable":
|
||||
vbd.attributes["bootable"].value,
|
||||
"mode":
|
||||
vbd.attributes["mode"].value,
|
||||
"type":
|
||||
vbd.attributes["type"].value,
|
||||
"qos_algorithm_type":
|
||||
vbd.attributes["qos_algorithm_type"].value,
|
||||
"qos_algorithm_params":
|
||||
get_child_nodes_as_dict(vbd,
|
||||
"qos_algorithm_param", "key", "value")
|
||||
}
|
||||
|
||||
return server.xenapi.VBD.create(vbd_record)
|
||||
|
||||
def create_vifs(self, vm_ref, vifs):
|
||||
log(DEBUG, "create_vifs")
|
||||
return map(lambda vif: self.create_vif(vm_ref, vif), vifs)
|
||||
|
||||
def create_vif(self, vm_ref, vif):
|
||||
log(DEBUG, "create_vif")
|
||||
|
||||
if "bridge" in vif.attributes.keys():
|
||||
raise "Not allowed to add by bridge just yet"
|
||||
elif "network" in vif.attributes.keys():
|
||||
network = [network_ref
|
||||
for network_ref in server.xenapi.network.get_all()
|
||||
if server.xenapi.network.get_name_label(network_ref)
|
||||
== vif.attributes["network"].value][0]
|
||||
else:
|
||||
network = self._get_network_ref()
|
||||
|
||||
vif_record = {
|
||||
"device":
|
||||
vif.attributes["device"].value,
|
||||
"network":
|
||||
network,
|
||||
"VM":
|
||||
vm_ref,
|
||||
"MAC":
|
||||
vif.attributes["mac"].value,
|
||||
"MTU":
|
||||
vif.attributes["mtu"].value,
|
||||
"qos_algorithm_type":
|
||||
vif.attributes["qos_algorithm_type"].value,
|
||||
"qos_algorithm_params":
|
||||
get_child_nodes_as_dict(vif,
|
||||
"qos_algorithm_param", "key", "value")
|
||||
}
|
||||
|
||||
return server.xenapi.VIF.create(vif_record)
|
||||
|
||||
_network_refs = []
|
||||
|
||||
def _get_network_ref(self):
|
||||
try:
|
||||
return self._network_refs.pop(0)
|
||||
except IndexError:
|
||||
self._network_refs = server.xenapi.network.get_all()
|
||||
return self._network_refs.pop(0)
|
||||
|
||||
def get_child_by_name(exp, childname, default = None):
|
||||
try:
|
||||
return [child for child in sxp.children(exp)
|
||||
if child[0] == childname][0][1]
|
||||
except:
|
||||
return default
|
||||
|
||||
# Convert old sxp into new xml
|
||||
|
||||
class sxp2xml:
|
||||
|
||||
def convert_sxp_to_xml(self, config, transient=False):
|
||||
|
||||
devices = [child for child in sxp.children(config)
|
||||
if len(child) > 0 and child[0] == "device"]
|
||||
|
||||
vbds_sxp = map(lambda x: x[1], [device for device in devices
|
||||
if device[1][0] == "vbd"])
|
||||
|
||||
vifs_sxp = map(lambda x: x[1], [device for device in devices
|
||||
if device[1][0] == "vif"])
|
||||
# Create XML Document
|
||||
|
||||
impl = getDOMImplementation()
|
||||
|
||||
document = impl.createDocument(None, "xm", None)
|
||||
|
||||
# Lets make the VM tag..
|
||||
|
||||
vm = document.createElement("vm")
|
||||
|
||||
# Some string compatibility
|
||||
|
||||
actions_after_shutdown \
|
||||
= get_child_by_name(config, "on_poweroff", "destroy")
|
||||
actions_after_reboot \
|
||||
= get_child_by_name(config, "on_reboot", "restart")
|
||||
actions_after_crash \
|
||||
= get_child_by_name(config, "on_crash", "restart")
|
||||
|
||||
def conv_chk(val, vals):
|
||||
val.replace("-", "_")
|
||||
if val not in vals:
|
||||
raise "Invalid value: " + val
|
||||
else:
|
||||
return val
|
||||
|
||||
actions_after_shutdown = conv_chk(actions_after_shutdown,\
|
||||
XEN_API_ON_NORMAL_EXIT)
|
||||
actions_after_reboot = conv_chk(actions_after_reboot, \
|
||||
XEN_API_ON_NORMAL_EXIT)
|
||||
actions_after_crash = conv_chk(actions_after_crash, \
|
||||
XEN_API_ON_CRASH_BEHAVIOUR)
|
||||
# Flesh out tag attributes
|
||||
|
||||
vm.attributes["is_a_template"] = "false"
|
||||
vm.attributes["auto_power_on"] = "false"
|
||||
vm.attributes["actions_after_shutdown"] \
|
||||
= actions_after_shutdown
|
||||
vm.attributes["actions_after_reboot"] \
|
||||
= actions_after_reboot
|
||||
vm.attributes["actions_after_crash"] \
|
||||
= actions_after_crash
|
||||
vm.attributes["platform_std_VGA"] = "false"
|
||||
vm.attributes["platform_serial"] = ""
|
||||
vm.attributes["platform_localtime"] = ""
|
||||
vm.attributes["platform_clock_offet"] = ""
|
||||
vm.attributes["platform_enable_audio"] = ""
|
||||
vm.attributes["PCI_bus"] = ""
|
||||
|
||||
vm.attributes["vcpus_max"] \
|
||||
= str(get_child_by_name(config, "vcpus", 1))
|
||||
vm.attributes["vcpus_at_startup"] \
|
||||
= str(get_child_by_name(config, "vcpus", 1))
|
||||
|
||||
# Make the name tag
|
||||
|
||||
vm.appendChild(self.make_name_tag(
|
||||
get_child_by_name(config, "name"), document))
|
||||
|
||||
# Make version tag
|
||||
|
||||
version = document.createElement("version")
|
||||
version.appendChild(document.createTextNode("1.0"))
|
||||
vm.appendChild(version)
|
||||
|
||||
# Make pv or hvm tag
|
||||
|
||||
image = get_child_by_name(config, "image")
|
||||
|
||||
if image[0] == "linux":
|
||||
pv = document.createElement("pv")
|
||||
pv.attributes["kernel"] \
|
||||
= get_child_by_name(image, "kernel", "")
|
||||
pv.attributes["bootloader"] = ""
|
||||
pv.attributes["ramdisk"] \
|
||||
= get_child_by_name(image, "ramdisk", "")
|
||||
pv.attributes["args"] \
|
||||
= "root=" + get_child_by_name(image, "root", "") \
|
||||
+ " " + get_child_by_name(image, "args", "")
|
||||
pv.attributes["bootloader_args"] = ""
|
||||
|
||||
vm.appendChild(pv)
|
||||
elif image[0] == "hvm":
|
||||
hvm = document.createElement("hvm")
|
||||
hvm.attributes["boot_policy"] = ""
|
||||
|
||||
vm.appendChild(hvm)
|
||||
|
||||
# Make memory tag
|
||||
|
||||
memory = document.createElement("memory")
|
||||
|
||||
memory_str = str(int(
|
||||
get_child_by_name(config, "memory"))*1024*1024)
|
||||
|
||||
memory.attributes["static_min"] = str(0)
|
||||
memory.attributes["static_max"] = memory_str
|
||||
memory.attributes["dynamic_min"] = memory_str
|
||||
memory.attributes["dynamic_max"] = memory_str
|
||||
|
||||
if get_child_by_name(config, "maxmem"):
|
||||
memory.attributes["static_max"] = \
|
||||
str(int(get_child_by_name(config, "maxmem")*1024*1024))
|
||||
|
||||
vm.appendChild(memory)
|
||||
|
||||
# And now the vbds
|
||||
|
||||
vbds = map(lambda vbd: self.extract_vbd(vbd, document), vbds_sxp)
|
||||
|
||||
map(vm.appendChild, vbds)
|
||||
|
||||
# And now the vifs
|
||||
|
||||
vifs = map(lambda vif: self.extract_vif(vif, document), vifs_sxp)
|
||||
|
||||
map(vm.appendChild, vifs)
|
||||
|
||||
# transient?
|
||||
|
||||
if transient:
|
||||
other_config = document.createElement("other_config")
|
||||
other_config.attributes["key"] = "transient"
|
||||
other_config.attributes["value"] = "True"
|
||||
vm.appendChild(other_config)
|
||||
|
||||
# Add it to doc_root
|
||||
|
||||
document.documentElement.appendChild(vm)
|
||||
|
||||
# We want to pull out vdis
|
||||
|
||||
vdis = map(lambda vdb: self.extract_vdi(vdb, document), vbds_sxp)
|
||||
|
||||
map(document.documentElement.appendChild, vdis)
|
||||
|
||||
return document
|
||||
|
||||
def make_name_tag(self, label_text, document):
|
||||
name = document.createElement("name")
|
||||
|
||||
label = document.createElement("label")
|
||||
label.appendChild(document.createTextNode(str(label_text)))
|
||||
name.appendChild(label)
|
||||
|
||||
description = document.createElement("description")
|
||||
description.appendChild(document.createTextNode(" "))
|
||||
name.appendChild(description)
|
||||
|
||||
return name
|
||||
|
||||
def extract_vbd(self, vbd_sxp, document):
|
||||
src = get_child_by_name(vbd_sxp, "uname")
|
||||
name = str(src.__hash__())
|
||||
|
||||
vbd = document.createElement("vbd")
|
||||
|
||||
vbd.attributes["name"] = "vdb" + name
|
||||
vbd.attributes["vdi"] = "vdi" + name
|
||||
vbd.attributes["mode"] \
|
||||
= get_child_by_name(vbd_sxp, "mode") != "w" \
|
||||
and "RO" or "RW"
|
||||
vbd.attributes["device"] \
|
||||
= get_child_by_name(vbd_sxp, "dev")
|
||||
vbd.attributes["bootable"] = "1"
|
||||
vbd.attributes["type"] = "disk"
|
||||
vbd.attributes["qos_algorithm_type"] = ""
|
||||
|
||||
return vbd
|
||||
|
||||
def extract_vdi(self, vbd_sxp, document):
|
||||
src = get_child_by_name(vbd_sxp, "uname")
|
||||
name = "vdi" + str(src.__hash__())
|
||||
path = src[src.find(":")+1:]
|
||||
|
||||
vdi = document.createElement("vdi")
|
||||
|
||||
vdi.attributes["src"] = src
|
||||
vdi.attributes["read_only"] \
|
||||
= (get_child_by_name(vbd_sxp, "mode") != "w") \
|
||||
and "true" or "false"
|
||||
vdi.attributes["size"] \
|
||||
= str(os.path.getsize(path))
|
||||
vdi.attributes["type"] = "system"
|
||||
vdi.attributes["shareable"] = "false"
|
||||
vdi.attributes["name"] = name
|
||||
|
||||
vdi.appendChild(self.make_name_tag(name, document))
|
||||
|
||||
return vdi
|
||||
|
||||
def extract_vif(self, vif_sxp, document):
|
||||
|
||||
vif = document.createElement("vif")
|
||||
|
||||
dev = get_child_by_name(vif_sxp, "vifname", "eth0")
|
||||
|
||||
vif.attributes["name"] \
|
||||
= "vif" + str(dev.__hash__())
|
||||
vif.attributes["mac"] \
|
||||
= get_child_by_name(vif_sxp, "mac", "")
|
||||
vif.attributes["mtu"] \
|
||||
= get_child_by_name(vif_sxp, "mtu", "")
|
||||
vif.attributes["device"] = dev
|
||||
vif.attributes["qos_algorithm_type"] = ""
|
||||
|
||||
if get_child_by_name(vif_sxp, "bridge") is not None:
|
||||
vif.attributes["bridge"] \
|
||||
= get_child_by_name(vif_sxp, "bridge")
|
||||
|
||||
return vif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||