Class'ify' libvirt util

This commit is contained in:
Joshua Harlow 2012-03-21 23:33:36 -07:00
parent fc81122b7a
commit 3903e1aa82
6 changed files with 119 additions and 126 deletions

View File

@ -17,6 +17,8 @@ commands:
libvirt: libvirt:
restart: service libvirtd restart restart: service libvirtd restart
status: service libvirtd status status: service libvirtd status
# This is just used to check that libvirt will work with a given protocol
verify: virsh -c %VIRT_PROTOCOL% uri
mysql: mysql:
create_db: mysql --user=%USER% --password=%PASSWORD% -e "CREATE DATABASE %DB%;" create_db: mysql --user=%USER% --password=%PASSWORD% -e "CREATE DATABASE %DB%;"
drop_db: mysql --user=%USER% --password=%PASSWORD% -e "DROP DATABASE IF EXISTS drop_db: mysql --user=%USER% --password=%PASSWORD% -e "DROP DATABASE IF EXISTS

View File

@ -23,6 +23,8 @@ commands:
libvirt: libvirt:
restart: service libvirt-bin restart restart: service libvirt-bin restart
status: service libvirt-bin status status: service libvirt-bin status
# This is just used to check that libvirt will work with a given protocol
verify: virsh -c %VIRT_PROTOCOL% uri
mysql: mysql:
# NOTE: we aren't stopping any sql injection... # NOTE: we aren't stopping any sql injection...
create_db: mysql --user=%USER% --password=%PASSWORD% -e "CREATE DATABASE %DB%;" create_db: mysql --user=%USER% --password=%PASSWORD% -e "CREATE DATABASE %DB%;"

View File

@ -19,7 +19,7 @@ from urlparse import urlunparse
from devstack import component as comp from devstack import component as comp
from devstack import date from devstack import date
from devstack import exceptions from devstack import exceptions
from devstack import libvirt as virsh from devstack import libvirt as lv
from devstack import log as logging from devstack import log as logging
from devstack import shell as sh from devstack import shell as sh
from devstack import utils from devstack import utils
@ -145,7 +145,6 @@ DEF_VOL_TEMPL = DEF_VOL_PREFIX + '%08x'
# Default virt types # Default virt types
DEF_VIRT_DRIVER = 'libvirt' DEF_VIRT_DRIVER = 'libvirt'
DEF_VIRT_TYPE = 'qemu'
# Virt drivers map -> to there connection name # Virt drivers map -> to there connection name
VIRT_DRIVER_CON_MAP = { VIRT_DRIVER_CON_MAP = {
@ -198,21 +197,12 @@ def canon_virt_driver(virt_driver):
return virt_driver return virt_driver
def canon_libvirt_type(virt_type):
if not virt_type:
return DEF_VIRT_TYPE
virt_type = virt_type.lower().strip()
if not (virt_type in virsh.LIBVIRT_PROTOCOL_MAP):
return DEF_VIRT_TYPE
else:
return virt_type
class NovaUninstaller(comp.PythonUninstallComponent): class NovaUninstaller(comp.PythonUninstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
comp.PythonUninstallComponent.__init__(self, *args, **kargs) comp.PythonUninstallComponent.__init__(self, *args, **kargs)
self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR) self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR)
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR) self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
self.virsh = lv.Virsh(self.cfg, self.distro)
def known_subsystems(self): def known_subsystems(self):
return SUBSYSTEMS return SUBSYSTEMS
@ -238,8 +228,8 @@ class NovaUninstaller(comp.PythonUninstallComponent):
virt_driver = canon_virt_driver(self.cfg.get('nova', 'virt_driver')) virt_driver = canon_virt_driver(self.cfg.get('nova', 'virt_driver'))
if virt_driver == 'libvirt': if virt_driver == 'libvirt':
inst_prefix = self.cfg.getdefaulted('nova', 'instance_name_prefix', DEF_INSTANCE_PREFIX) inst_prefix = self.cfg.getdefaulted('nova', 'instance_name_prefix', DEF_INSTANCE_PREFIX)
libvirt_type = canon_libvirt_type(self.cfg.get('nova', 'libvirt_type')) libvirt_type = lv.canon_libvirt_type(self.cfg.get('nova', 'libvirt_type'))
virsh.clear_libvirt_domains(self.distro, libvirt_type, inst_prefix) self.virsh.clear_domains(libvirt_type, inst_prefix)
class NovaInstaller(comp.PythonInstallComponent): class NovaInstaller(comp.PythonInstallComponent):
@ -376,6 +366,7 @@ class NovaRuntime(comp.PythonRuntime):
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR) self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR) self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR)
self.wait_time = max(self.cfg.getint('default', 'service_wait_seconds'), 1) self.wait_time = max(self.cfg.getint('default', 'service_wait_seconds'), 1)
self.virsh = lv.Virsh(self.cfg, self.distro)
def _setup_network_init(self): def _setup_network_init(self):
tgt_fn = sh.joinpths(self.bin_dir, NET_INIT_CONF) tgt_fn = sh.joinpths(self.bin_dir, NET_INIT_CONF)
@ -420,13 +411,13 @@ class NovaRuntime(comp.PythonRuntime):
if virt_driver == 'libvirt': if virt_driver == 'libvirt':
# FIXME: The configuration for the virtualization-type # FIXME: The configuration for the virtualization-type
# should come from the persona. # should come from the persona.
virt_type = canon_libvirt_type(self.cfg.get('nova', 'libvirt_type')) virt_type = lv.canon_libvirt_type(self.cfg.get('nova', 'libvirt_type'))
LOG.info("Checking that your selected libvirt virtualization type [%s] is working and running." % (virt_type)) LOG.info("Checking that your selected libvirt virtualization type %r is working and running." % (virt_type))
if not virsh.virt_ok(virt_type, self.distro): if not self.virsh.check_virt(virt_type):
msg = ("Libvirt type %s does not seem to be active or configured correctly, " msg = ("Libvirt type %r does not seem to be active or configured correctly, "
"perhaps you should be using %s instead." % (virt_type, DEF_VIRT_TYPE)) "perhaps you should be using %r instead." % (virt_type, lv.DEF_VIRT_TYPE))
raise exceptions.StartException(msg) raise exceptions.StartException(msg)
virsh.restart(self.distro) self.virsh.restart_service()
def _get_param_map(self, app_name): def _get_param_map(self, app_name):
params = comp.PythonRuntime._get_param_map(self, app_name) params = comp.PythonRuntime._get_param_map(self, app_name)
@ -584,7 +575,7 @@ class NovaConfConfigurator(object):
# Configure anything libvirt related? # Configure anything libvirt related?
virt_driver = canon_virt_driver(self._getstr('virt_driver')) virt_driver = canon_virt_driver(self._getstr('virt_driver'))
if virt_driver == 'libvirt': if virt_driver == 'libvirt':
libvirt_type = canon_libvirt_type(self._getstr('libvirt_type')) libvirt_type = lv.canon_libvirt_type(self._getstr('libvirt_type'))
self._configure_libvirt(libvirt_type, nova_conf) self._configure_libvirt(libvirt_type, nova_conf)
# How instances will be presented # How instances will be presented

View File

@ -14,6 +14,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import contextlib
from devstack import exceptions as excp from devstack import exceptions as excp
from devstack import log as logging from devstack import log as logging
from devstack import shell as sh from devstack import shell as sh
@ -29,114 +31,111 @@ LIBVIRT_PROTOCOL_MAP = {
'uml': 'uml:///system', 'uml': 'uml:///system',
'lxc': 'lxc:///', 'lxc': 'lxc:///',
} }
VIRT_LIB = 'libvirt'
# This is just used to check that libvirt will work with
# a given protocol, may not be ideal but does seem to crap
# out if it won't work, so thats good...
VIRSH_SANITY_CMD = ['virsh', '-c', '%VIRT_PROTOCOL%', 'uri']
# Status is either dead or alive! # Status is either dead or alive!
_DEAD = 'DEAD' _DEAD = 'DEAD'
_ALIVE = 'ALIVE' _ALIVE = 'ALIVE'
# Alive wait time, just a sleep we put into so that the service can start up # Type that should always work
# FIXME: take from config... DEF_VIRT_TYPE = 'qemu'
WAIT_ALIVE_TIME = 5
def canon_libvirt_type(virt_type):
if not virt_type:
return DEF_VIRT_TYPE
virt_type = virt_type.lower().strip()
if not (virt_type in LIBVIRT_PROTOCOL_MAP):
return DEF_VIRT_TYPE
else:
return virt_type
def _get_virt_lib(): def _get_virt_lib():
# Late import so that we don't always need this library to be active # Late import so that we don't always need this library to be active
# ie if u aren't using libvirt in the first place... # ie if u aren't using libvirt in the first place...
return utils.import_module(VIRT_LIB) return utils.import_module('libvirt')
def _status(distro): class Virsh(object):
cmds = [{'cmd': distro.get_command('libvirt', 'status'),
'run_as_root': True, def __init__(self, config, distro):
}] self.cfg = config
result = utils.execute_template(*cmds, self.distro = distro
check_exit_code=False, self.wait_time = max(self.cfg.getint('default', 'service_wait_seconds'), 1)
params={})
if not result or not result[0]: def _service_status(self):
return _DEAD cmd = self.distro.get_command('libvirt', 'status')
(sysout, stderr) = result[0] (stdout, stderr) = sh.execute(*cmd, run_as_root=True, check_exit_code=False)
combined = str(sysout) + str(stderr) combined = (stdout + stderr).lower()
combined = combined.lower()
if combined.find("running") != -1 or combined.find('start') != -1: if combined.find("running") != -1 or combined.find('start') != -1:
return _ALIVE return _ALIVE
else: else:
return _DEAD return _DEAD
def _destroy_domain(self, conn, dom_name):
def _destroy_domain(libvirt, conn, dom_name): libvirt = _get_virt_lib()
try: try:
dom = conn.lookupByName(dom_name) dom = conn.lookupByName(dom_name)
LOG.debug("Destroying domain (%s) (id=%s) running %s" % (dom_name, dom.ID(), dom.OSType())) LOG.debug("Destroying domain (%r) (id=%s) running %r" % (dom_name, dom.ID(), dom.OSType()))
dom.destroy() dom.destroy()
dom.undefine() dom.undefine()
except libvirt.libvirtError, e: except libvirt.libvirtError as e:
LOG.warn("Could not clear out libvirt domain (%s) due to [%s]" % (dom_name, e.message)) LOG.warn("Could not clear out libvirt domain %r due to: %s" % (dom_name, e))
def restart_service(self):
if self._service_status() != _ALIVE:
cmd = self.distro.get_command('libvirt', 'restart')
sh.execute(*cmd, run_as_root=True)
LOG.info("Restarting the libvirt service, please wait %s seconds until its started." % (self.wait_time))
sh.sleep(self.wait_time)
def restart(distro): def check_virt(self, virt_type):
if _status(distro) != _ALIVE:
cmds = [{
'cmd': distro.get_command('libvirt', 'restart'),
'run_as_root': True,
}]
utils.execute_template(*cmds, params={})
LOG.info("Restarting the libvirt service, please wait %s seconds until its started." % (WAIT_ALIVE_TIME))
sh.sleep(WAIT_ALIVE_TIME)
def virt_ok(virt_type, distro):
virt_protocol = LIBVIRT_PROTOCOL_MAP.get(virt_type) virt_protocol = LIBVIRT_PROTOCOL_MAP.get(virt_type)
if not virt_protocol: if not virt_protocol:
return False return False
try: try:
restart(distro) self.restart_service()
except excp.ProcessExecutionError, e: except excp.ProcessExecutionError, e:
LOG.warn("Could not restart libvirt due to [%s]" % (e)) LOG.warn("Could not restart libvirt due to: %s" % (e))
return False return False
try: try:
cmds = list() cmds = list()
cmds.append({ cmds.append({
'cmd': VIRSH_SANITY_CMD, 'cmd': self.distro.get_command('libvirt', 'verify'),
'run_as_root': True, 'run_as_root': True,
}) })
mp = dict() mp = dict()
mp['VIRT_PROTOCOL'] = virt_protocol mp['VIRT_PROTOCOL'] = virt_protocol
utils.execute_template(*cmds, params=mp) utils.execute_template(*cmds, params=mp)
return True return True
except excp.ProcessExecutionError, e: except excp.ProcessExecutionError as e:
LOG.warn("Could check if libvirt was ok for protocol [%s] due to [%s]" % (virt_protocol, e.message)) LOG.warn("Could check if libvirt was ok for protocol %r due to: %s" % (virt_protocol, e))
return False return False
def clear_domains(self, virt_type, inst_prefix):
def clear_libvirt_domains(distro, virt_type, inst_prefix):
libvirt = _get_virt_lib() libvirt = _get_virt_lib()
if not libvirt: if not libvirt:
LOG.warn("Could not clear out libvirt domains, libvirt not available for python.") LOG.warn("Could not clear out libvirt domains, libvirt not available for python.")
return return
virt_protocol = LIBVIRT_PROTOCOL_MAP.get(virt_type) virt_protocol = LIBVIRT_PROTOCOL_MAP.get(virt_type)
if not virt_protocol: if not virt_protocol:
LOG.warn("Could not clear out libvirt domains, no known protocol for virt type %s" % (virt_type)) LOG.warn("Could not clear out libvirt domains, no known protocol for virt type %r" % (virt_type))
return return
with sh.Rooted(True): with sh.Rooted(True):
LOG.info("Attempting to clear out leftover libvirt domains using protocol %s" % (virt_protocol)) LOG.info("Attempting to clear out leftover libvirt domains using protocol %r" % (virt_protocol))
try: try:
restart(distro) self.restart_service()
except excp.ProcessExecutionError, e: except excp.ProcessExecutionError as e:
LOG.warn("Could not restart libvirt due to [%s]" % (e)) LOG.warn("Could not restart libvirt due to: %s" % (e))
return return
try: try:
conn = libvirt.open(virt_protocol) conn = libvirt.open(virt_protocol)
except libvirt.libvirtError, e: except libvirt.libvirtError as e:
LOG.warn("Could not connect to libvirt using protocol [%s] due to [%s]" % (virt_protocol, e.message)) LOG.warn("Could not connect to libvirt using protocol %r due to: %s" % (virt_protocol, e))
return return
with contextlib.closing(conn) as ch:
try: try:
defined_domains = conn.listDefinedDomains() defined_domains = ch.listDefinedDomains()
kill_domains = list() kill_domains = list()
for domain in defined_domains: for domain in defined_domains:
if domain.startswith(inst_prefix): if domain.startswith(inst_prefix):
@ -144,6 +143,6 @@ def clear_libvirt_domains(distro, virt_type, inst_prefix):
if kill_domains: if kill_domains:
LOG.info("Found %s old domains to destroy (%s)" % (len(kill_domains), ", ".join(sorted(kill_domains)))) LOG.info("Found %s old domains to destroy (%s)" % (len(kill_domains), ", ".join(sorted(kill_domains))))
for domain in sorted(kill_domains): for domain in sorted(kill_domains):
_destroy_domain(libvirt, conn, domain) self._destroy_domain(ch, domain)
except libvirt.libvirtError, e: except libvirt.libvirtError, e:
LOG.warn("Could not clear out libvirt domains due to [%s]" % (e.message)) LOG.warn("Could not clear out libvirt domains due to %s" % (e))

View File

@ -19,7 +19,6 @@ from optparse import OptionParser, OptionGroup
from devstack.progs import actions from devstack.progs import actions
from devstack import log as logging from devstack import log as logging
from devstack import settings
from devstack import version from devstack import version
HELP_WIDTH = 80 HELP_WIDTH = 80

View File

@ -29,6 +29,7 @@ class ActionRunner(object):
__meta__ = abc.ABCMeta __meta__ = abc.ABCMeta
PREREQ = None PREREQ = None
NAME = None
def __init__(self, def __init__(self,
distro, distro,
@ -69,13 +70,13 @@ class ActionRunner(object):
"""Create component objects for each component in the persona. """Create component objects for each component in the persona.
""" """
components = persona.wanted_components components = persona.wanted_components
desired_subsystems = persona.wanted_subsystems or dict() desired_subsystems = persona.wanted_subsystems or {}
component_opts = persona.component_options or dict() component_opts = persona.component_options or {}
instances = dict() instances = {}
for c in components: for c in components:
(cls, my_info) = self.distro.extract_component(c, self.NAME) (cls, my_info) = self.distro.extract_component(c, self.NAME)
LOG.debug("Constructing class %s" % (cls)) LOG.debug("Constructing class %s" % (cls))
cls_kvs = dict() cls_kvs = {}
cls_kvs['runner'] = self cls_kvs['runner'] = self
cls_kvs['component_dir'] = sh.joinpths(root_dir, c) cls_kvs['component_dir'] = sh.joinpths(root_dir, c)
cls_kvs['subsystem_info'] = my_info.get('subsystems', {}) cls_kvs['subsystem_info'] = my_info.get('subsystems', {})
@ -312,7 +313,6 @@ class UninstallRunner(ActionRunner):
) )
_NAMES_TO_RUNNER = { _NAMES_TO_RUNNER = {
'install': InstallRunner, 'install': InstallRunner,
'uninstall': UninstallRunner, 'uninstall': UninstallRunner,