initial commit after bringing over cleaned up code and testing some examples
This commit is contained in:
parent
c4858e6e0d
commit
00f4ebf5a9
93 changed files with 15189 additions and 13083 deletions
|
@ -1,11 +1,4 @@
|
|||
#
|
||||
# CORE
|
||||
# Copyright (c)2011-2012 the Boeing Company.
|
||||
# See the LICENSE file included in this distribution.
|
||||
#
|
||||
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||
#
|
||||
'''
|
||||
"""
|
||||
xenconfig.py: Implementation of the XenConfigManager class for managing
|
||||
configurable items for XenNodes.
|
||||
|
||||
|
@ -17,72 +10,93 @@ Node type config: XenConfigManager.configs[0] = (type='mytype', values)
|
|||
All nodes of this type have this config.
|
||||
Node-specific config: XenConfigManager.configs[nodenumber] = (type, values)
|
||||
The node having this specific number has this config.
|
||||
'''
|
||||
"""
|
||||
|
||||
import sys, os, threading, subprocess, time, string
|
||||
import ConfigParser
|
||||
from xml.dom.minidom import parseString, Document
|
||||
from core.constants import *
|
||||
import os
|
||||
import string
|
||||
|
||||
from core import constants
|
||||
from core.api import coreapi
|
||||
from core.conf import ConfigurableManager, Configurable
|
||||
from core.conf import Configurable
|
||||
from core.conf import ConfigurableManager
|
||||
from core.enumerations import ConfigDataTypes
|
||||
from core.enumerations import ConfigFlags
|
||||
from core.enumerations import ConfigTlvs
|
||||
from core.enumerations import RegisterTlvs
|
||||
from core.misc import log
|
||||
|
||||
logger = log.get_logger(__name__)
|
||||
|
||||
|
||||
class XenConfigManager(ConfigurableManager):
|
||||
''' Xen controller object. Lives in a Session instance and is used for
|
||||
building Xen profiles.
|
||||
'''
|
||||
_name = "xen"
|
||||
_type = coreapi.CORE_TLV_REG_EMULSRV
|
||||
|
||||
"""
|
||||
Xen controller object. Lives in a Session instance and is used for
|
||||
building Xen profiles.
|
||||
"""
|
||||
name = "xen"
|
||||
config_type = RegisterTlvs.EMULATION_SERVER.value
|
||||
|
||||
def __init__(self, session):
|
||||
ConfigurableManager.__init__(self, session)
|
||||
self.verbose = self.session.getcfgitembool('verbose', False)
|
||||
self.default_config = XenDefaultConfig(session, objid=None)
|
||||
"""
|
||||
Creates a XenConfigManager instance.
|
||||
|
||||
:param core.session.Session session: session this manager is tied to
|
||||
:return: nothing
|
||||
"""
|
||||
ConfigurableManager.__init__(self)
|
||||
self.default_config = XenDefaultConfig(session, object_id=None)
|
||||
self.loadconfigfile()
|
||||
|
||||
def setconfig(self, nodenum, conftype, values):
|
||||
''' add configuration values for a node to a dictionary; values are
|
||||
usually received from a Configuration Message, and may refer to a
|
||||
node for which no object exists yet
|
||||
'''
|
||||
if nodenum is None:
|
||||
nodenum = 0 # used for storing the global default config
|
||||
"""
|
||||
add configuration values for a node to a dictionary; values are
|
||||
usually received from a Configuration Message, and may refer to a
|
||||
node for which no object exists yet
|
||||
"""
|
||||
if nodenum is None:
|
||||
nodenum = 0 # used for storing the global default config
|
||||
return ConfigurableManager.setconfig(self, nodenum, conftype, values)
|
||||
|
||||
def getconfig(self, nodenum, conftype, defaultvalues):
|
||||
''' get configuration values for a node; if the values don't exist in
|
||||
our dictionary then return the default values supplied; if conftype
|
||||
is None then we return a match on any conftype.
|
||||
'''
|
||||
if nodenum is None:
|
||||
nodenum = 0 # used for storing the global default config
|
||||
return ConfigurableManager.getconfig(self, nodenum, conftype,
|
||||
defaultvalues)
|
||||
"""
|
||||
get configuration values for a node; if the values don't exist in
|
||||
our dictionary then return the default values supplied; if conftype
|
||||
is None then we return a match on any conftype.
|
||||
"""
|
||||
if nodenum is None:
|
||||
nodenum = 0 # used for storing the global default config
|
||||
return ConfigurableManager.getconfig(self, nodenum, conftype, defaultvalues)
|
||||
|
||||
def clearconfig(self, nodenum):
|
||||
''' remove configuration values for a node
|
||||
'''
|
||||
"""
|
||||
remove configuration values for a node
|
||||
"""
|
||||
ConfigurableManager.clearconfig(self, nodenum)
|
||||
if 0 in self.configs:
|
||||
self.configs.pop(0)
|
||||
|
||||
def configure(self, session, msg):
|
||||
''' Handle configuration messages for global Xen config.
|
||||
'''
|
||||
return self.default_config.configure(self, msg)
|
||||
def configure(self, session, config_data):
|
||||
"""
|
||||
Handle configuration messages for global Xen config.
|
||||
|
||||
:param core.conf.ConfigData config_data: configuration data for carrying out a configuration
|
||||
"""
|
||||
return self.default_config.configure(self, config_data)
|
||||
|
||||
def loadconfigfile(self, filename=None):
|
||||
''' Load defaults from the /etc/core/xen.conf file into dict object.
|
||||
'''
|
||||
"""
|
||||
Load defaults from the /etc/core/xen.conf file into dict object.
|
||||
"""
|
||||
if filename is None:
|
||||
filename = os.path.join(CORE_CONF_DIR, 'xen.conf')
|
||||
filename = os.path.join(constants.CORE_CONF_DIR, 'xen.conf')
|
||||
cfg = ConfigParser.SafeConfigParser()
|
||||
if filename not in cfg.read(filename):
|
||||
self.session.warn("unable to read Xen config file: %s" % filename)
|
||||
logger.warn("unable to read Xen config file: %s" % filename)
|
||||
return
|
||||
section = "xen"
|
||||
if not cfg.has_section(section):
|
||||
self.session.warn("%s is missing a xen section!" % filename)
|
||||
logger.warn("%s is missing a xen section!" % filename)
|
||||
return
|
||||
self.configfile = dict(cfg.items(section))
|
||||
# populate default config items from config file entries
|
||||
|
@ -92,13 +106,14 @@ class XenConfigManager(ConfigurableManager):
|
|||
if names[i] in self.configfile:
|
||||
vals[i] = self.configfile[names[i]]
|
||||
# this sets XenConfigManager.configs[0] = (type='xen', vals)
|
||||
self.setconfig(None, self.default_config._name, vals)
|
||||
self.setconfig(None, self.default_config.name, vals)
|
||||
|
||||
def getconfigitem(self, name, model=None, node=None, value=None):
|
||||
''' Get a config item of the given name, first looking for node-specific
|
||||
configuration, then model specific, and finally global defaults.
|
||||
If a value is supplied, it will override any stored config.
|
||||
'''
|
||||
"""
|
||||
Get a config item of the given name, first looking for node-specific
|
||||
configuration, then model specific, and finally global defaults.
|
||||
If a value is supplied, it will override any stored config.
|
||||
"""
|
||||
if value is not None:
|
||||
return value
|
||||
n = None
|
||||
|
@ -111,8 +126,8 @@ class XenConfigManager(ConfigurableManager):
|
|||
defaultvalues=None)
|
||||
if v is None:
|
||||
# get item from default config for the machine type
|
||||
(t, v) = self.getconfig(nodenum=None,
|
||||
conftype=self.default_config._name,
|
||||
(t, v) = self.getconfig(nodenum=None,
|
||||
conftype=self.default_config.name,
|
||||
defaultvalues=None)
|
||||
|
||||
confignames = self.default_config.getnames()
|
||||
|
@ -124,142 +139,136 @@ class XenConfigManager(ConfigurableManager):
|
|||
if name in self.configfile:
|
||||
return self.configfile[name]
|
||||
else:
|
||||
#self.warn("missing config item '%s'" % name)
|
||||
# logger.warn("missing config item '%s'" % name)
|
||||
return None
|
||||
|
||||
|
||||
class XenConfig(Configurable):
|
||||
''' Manage Xen configuration profiles.
|
||||
'''
|
||||
|
||||
@classmethod
|
||||
def configure(cls, xen, msg):
|
||||
''' Handle configuration messages for setting up a model.
|
||||
Similar to Configurable.configure(), but considers opaque data
|
||||
for indicating node types.
|
||||
'''
|
||||
reply = None
|
||||
nodenum = msg.gettlv(coreapi.CORE_TLV_CONF_NODE)
|
||||
objname = msg.gettlv(coreapi.CORE_TLV_CONF_OBJ)
|
||||
conftype = msg.gettlv(coreapi.CORE_TLV_CONF_TYPE)
|
||||
opaque = msg.gettlv(coreapi.CORE_TLV_CONF_OPAQUE)
|
||||
"""
|
||||
Manage Xen configuration profiles.
|
||||
"""
|
||||
|
||||
nodetype = objname
|
||||
@classmethod
|
||||
def configure(cls, xen, config_data):
|
||||
"""
|
||||
Handle configuration messages for setting up a model.
|
||||
Similar to Configurable.configure(), but considers opaque data
|
||||
for indicating node types.
|
||||
|
||||
:param xen: xen instance to configure
|
||||
:param core.conf.ConfigData config_data: configuration data for carrying out a configuration
|
||||
"""
|
||||
reply = None
|
||||
node_id = config_data.node
|
||||
object_name = config_data.object
|
||||
config_type = config_data.type
|
||||
opaque = config_data.opaque
|
||||
values_str = config_data.data_values
|
||||
|
||||
nodetype = object_name
|
||||
if opaque is not None:
|
||||
opaque_items = opaque.split(':')
|
||||
if len(opaque_items) != 2:
|
||||
xen.warn("xen config: invalid opaque data in conf message")
|
||||
logger.warn("xen config: invalid opaque data in conf message")
|
||||
return None
|
||||
nodetype = opaque_items[1]
|
||||
|
||||
if xen.verbose:
|
||||
xen.info("received configure message for %s" % nodetype)
|
||||
if conftype == coreapi.CONF_TYPE_FLAGS_REQUEST:
|
||||
if xen.verbose:
|
||||
xen.info("replying to configure request for %s " % nodetype)
|
||||
logger.info("received configure message for %s", nodetype)
|
||||
if config_type == ConfigFlags.REQUEST.value:
|
||||
logger.info("replying to configure request for %s " % nodetype)
|
||||
# when object name is "all", the reply to this request may be None
|
||||
# if this node has not been configured for this model; otherwise we
|
||||
# reply with the defaults for this model
|
||||
if objname == "all":
|
||||
typeflags = coreapi.CONF_TYPE_FLAGS_UPDATE
|
||||
if object_name == "all":
|
||||
typeflags = ConfigFlags.UPDATE.value
|
||||
else:
|
||||
typeflags = coreapi.CONF_TYPE_FLAGS_NONE
|
||||
values = xen.getconfig(nodenum, nodetype, defaultvalues=None)[1]
|
||||
typeflags = ConfigFlags.NONE.value
|
||||
values = xen.getconfig(node_id, nodetype, defaultvalues=None)[1]
|
||||
if values is None:
|
||||
# get defaults from default "xen" config which includes
|
||||
# settings from both cls._confdefaultvalues and xen.conf
|
||||
# settings from both cls._confdefaultvalues and xen.conf
|
||||
defaults = cls.getdefaultvalues()
|
||||
values = xen.getconfig(nodenum, cls._name, defaults)[1]
|
||||
values = xen.getconfig(node_id, cls.name, defaults)[1]
|
||||
if values is None:
|
||||
return None
|
||||
# reply with config options
|
||||
if nodenum is None:
|
||||
nodenum = 0
|
||||
reply = cls.toconfmsg(0, nodenum, typeflags, nodetype, values)
|
||||
elif conftype == coreapi.CONF_TYPE_FLAGS_RESET:
|
||||
if objname == "all":
|
||||
xen.clearconfig(nodenum)
|
||||
#elif conftype == coreapi.CONF_TYPE_FLAGS_UPDATE:
|
||||
if node_id is None:
|
||||
node_id = 0
|
||||
reply = cls.config_data(0, node_id, typeflags, nodetype, values)
|
||||
elif config_type == ConfigFlags.RESET.value:
|
||||
if object_name == "all":
|
||||
xen.clearconfig(node_id)
|
||||
# elif conftype == coreapi.CONF_TYPE_FLAGS_UPDATE:
|
||||
else:
|
||||
# store the configuration values for later use, when the XenNode
|
||||
# object has been created
|
||||
if objname is None:
|
||||
xen.info("no configuration object for node %s" % nodenum)
|
||||
if object_name is None:
|
||||
logger.info("no configuration object for node %s" % node_id)
|
||||
return None
|
||||
values_str = msg.gettlv(coreapi.CORE_TLV_CONF_VALUES)
|
||||
if values_str is None:
|
||||
# use default or preconfigured values
|
||||
defaults = cls.getdefaultvalues()
|
||||
values = xen.getconfig(nodenum, cls._name, defaults)[1]
|
||||
values = xen.getconfig(node_id, cls.name, defaults)[1]
|
||||
else:
|
||||
# use new values supplied from the conf message
|
||||
values = values_str.split('|')
|
||||
xen.setconfig(nodenum, nodetype, values)
|
||||
xen.setconfig(node_id, nodetype, values)
|
||||
|
||||
return reply
|
||||
|
||||
@classmethod
|
||||
def toconfmsg(cls, flags, nodenum, typeflags, nodetype, values):
|
||||
''' Convert this class to a Config API message. Some TLVs are defined
|
||||
by the class, but node number, conf type flags, and values must
|
||||
be passed in.
|
||||
'''
|
||||
def config_data(cls, flags, node_id, type_flags, nodetype, values):
|
||||
"""
|
||||
Convert this class to a Config API message. Some TLVs are defined
|
||||
by the class, but node number, conf type flags, and values must
|
||||
be passed in.
|
||||
"""
|
||||
values_str = string.join(values, '|')
|
||||
tlvdata = ""
|
||||
tlvdata += coreapi.CoreConfTlv.pack(coreapi.CORE_TLV_CONF_NODE, nodenum)
|
||||
tlvdata += coreapi.CoreConfTlv.pack(coreapi.CORE_TLV_CONF_OBJ,
|
||||
cls._name)
|
||||
tlvdata += coreapi.CoreConfTlv.pack(coreapi.CORE_TLV_CONF_TYPE,
|
||||
typeflags)
|
||||
datatypes = tuple( map(lambda x: x[1], cls._confmatrix) )
|
||||
tlvdata += coreapi.CoreConfTlv.pack(coreapi.CORE_TLV_CONF_DATA_TYPES,
|
||||
datatypes)
|
||||
tlvdata += coreapi.CoreConfTlv.pack(coreapi.CORE_TLV_CONF_VALUES,
|
||||
values_str)
|
||||
captions = reduce( lambda a,b: a + '|' + b, \
|
||||
map(lambda x: x[4], cls._confmatrix))
|
||||
tlvdata += coreapi.CoreConfTlv.pack(coreapi.CORE_TLV_CONF_CAPTIONS,
|
||||
captions)
|
||||
possiblevals = reduce( lambda a,b: a + '|' + b, \
|
||||
map(lambda x: x[3], cls._confmatrix))
|
||||
tlvdata += coreapi.CoreConfTlv.pack(
|
||||
coreapi.CORE_TLV_CONF_POSSIBLE_VALUES, possiblevals)
|
||||
if cls._bitmap is not None:
|
||||
tlvdata += coreapi.CoreConfTlv.pack(coreapi.CORE_TLV_CONF_BITMAP,
|
||||
cls._bitmap)
|
||||
if cls._confgroups is not None:
|
||||
tlvdata += coreapi.CoreConfTlv.pack(coreapi.CORE_TLV_CONF_GROUPS,
|
||||
cls._confgroups)
|
||||
opaque = "%s:%s" % (cls._name, nodetype)
|
||||
tlvdata += coreapi.CoreConfTlv.pack(coreapi.CORE_TLV_CONF_OPAQUE,
|
||||
opaque)
|
||||
tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.NODE.value, node_id)
|
||||
tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.OBJECT.value, cls.name)
|
||||
tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.TYPE.value, type_flags)
|
||||
datatypes = tuple(map(lambda x: x[1], cls.config_matrix))
|
||||
tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.DATA_TYPES.value, datatypes)
|
||||
tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.VALUES.value, values_str)
|
||||
captions = reduce(lambda a, b: a + '|' + b, map(lambda x: x[4], cls.config_matrix))
|
||||
tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.CAPTIONS, captions)
|
||||
possiblevals = reduce(lambda a, b: a + '|' + b, map(lambda x: x[3], cls.config_matrix))
|
||||
tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.POSSIBLE_VALUES.value, possiblevals)
|
||||
if cls.bitmap is not None:
|
||||
tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.BITMAP.value, cls.bitmap)
|
||||
if cls.config_groups is not None:
|
||||
tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.GROUPS.value, cls.config_groups)
|
||||
opaque = "%s:%s" % (cls.name, nodetype)
|
||||
tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.OPAQUE.value, opaque)
|
||||
msg = coreapi.CoreConfMessage.pack(flags, tlvdata)
|
||||
return msg
|
||||
|
||||
|
||||
class XenDefaultConfig(XenConfig):
|
||||
''' Global default Xen configuration options.
|
||||
'''
|
||||
_name = "xen"
|
||||
"""
|
||||
Global default Xen configuration options.
|
||||
"""
|
||||
name = "xen"
|
||||
# Configuration items:
|
||||
# ('name', 'type', 'default', 'possible-value-list', 'caption')
|
||||
_confmatrix = [
|
||||
('ram_size', coreapi.CONF_DATA_TYPE_STRING, '256', '',
|
||||
config_matrix = [
|
||||
('ram_size', ConfigDataTypes.STRING.value, '256', '',
|
||||
'ram size (MB)'),
|
||||
('disk_size', coreapi.CONF_DATA_TYPE_STRING, '256M', '',
|
||||
('disk_size', ConfigDataTypes.STRING.value, '256M', '',
|
||||
'disk size (use K/M/G suffix)'),
|
||||
('iso_file', coreapi.CONF_DATA_TYPE_STRING, '', '',
|
||||
('iso_file', ConfigDataTypes.STRING.value, '', '',
|
||||
'iso file'),
|
||||
('mount_path', coreapi.CONF_DATA_TYPE_STRING, '', '',
|
||||
('mount_path', ConfigDataTypes.STRING.value, '', '',
|
||||
'mount path'),
|
||||
('etc_path', coreapi.CONF_DATA_TYPE_STRING, '', '',
|
||||
('etc_path', ConfigDataTypes.STRING.value, '', '',
|
||||
'etc path'),
|
||||
('persist_tar_iso', coreapi.CONF_DATA_TYPE_STRING, '', '',
|
||||
('persist_tar_iso', ConfigDataTypes.STRING.value, '', '',
|
||||
'iso persist tar file'),
|
||||
('persist_tar', coreapi.CONF_DATA_TYPE_STRING, '', '',
|
||||
('persist_tar', ConfigDataTypes.STRING.value, '', '',
|
||||
'persist tar file'),
|
||||
('root_password', coreapi.CONF_DATA_TYPE_STRING, 'password', '',
|
||||
('root_password', ConfigDataTypes.STRING.value, 'password', '',
|
||||
'root password'),
|
||||
]
|
||||
|
||||
_confgroups = "domU properties:1-%d" % len(_confmatrix)
|
||||
]
|
||||
|
||||
config_groups = "domU properties:1-%d" % len(config_matrix)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue