Class'ify' libvirt util
This commit is contained in:
parent
fc81122b7a
commit
3903e1aa82
@ -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
|
||||||
|
@ -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%;"
|
||||||
|
@ -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
|
||||||
|
@ -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,121 +31,118 @@ 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,
|
|
||||||
}]
|
|
||||||
result = utils.execute_template(*cmds,
|
|
||||||
check_exit_code=False,
|
|
||||||
params={})
|
|
||||||
if not result or not result[0]:
|
|
||||||
return _DEAD
|
|
||||||
(sysout, stderr) = result[0]
|
|
||||||
combined = str(sysout) + str(stderr)
|
|
||||||
combined = combined.lower()
|
|
||||||
if combined.find("running") != -1 or combined.find('start') != -1:
|
|
||||||
return _ALIVE
|
|
||||||
else:
|
|
||||||
return _DEAD
|
|
||||||
|
|
||||||
|
def __init__(self, config, distro):
|
||||||
|
self.cfg = config
|
||||||
|
self.distro = distro
|
||||||
|
self.wait_time = max(self.cfg.getint('default', 'service_wait_seconds'), 1)
|
||||||
|
|
||||||
def _destroy_domain(libvirt, conn, dom_name):
|
def _service_status(self):
|
||||||
try:
|
cmd = self.distro.get_command('libvirt', 'status')
|
||||||
dom = conn.lookupByName(dom_name)
|
(stdout, stderr) = sh.execute(*cmd, run_as_root=True, check_exit_code=False)
|
||||||
LOG.debug("Destroying domain (%s) (id=%s) running %s" % (dom_name, dom.ID(), dom.OSType()))
|
combined = (stdout + stderr).lower()
|
||||||
dom.destroy()
|
if combined.find("running") != -1 or combined.find('start') != -1:
|
||||||
dom.undefine()
|
return _ALIVE
|
||||||
except libvirt.libvirtError, e:
|
else:
|
||||||
LOG.warn("Could not clear out libvirt domain (%s) due to [%s]" % (dom_name, e.message))
|
return _DEAD
|
||||||
|
|
||||||
|
def _destroy_domain(self, conn, dom_name):
|
||||||
def restart(distro):
|
libvirt = _get_virt_lib()
|
||||||
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)
|
|
||||||
if not virt_protocol:
|
|
||||||
return False
|
|
||||||
try:
|
|
||||||
restart(distro)
|
|
||||||
except excp.ProcessExecutionError, e:
|
|
||||||
LOG.warn("Could not restart libvirt due to [%s]" % (e))
|
|
||||||
return False
|
|
||||||
try:
|
|
||||||
cmds = list()
|
|
||||||
cmds.append({
|
|
||||||
'cmd': VIRSH_SANITY_CMD,
|
|
||||||
'run_as_root': True,
|
|
||||||
})
|
|
||||||
mp = dict()
|
|
||||||
mp['VIRT_PROTOCOL'] = virt_protocol
|
|
||||||
utils.execute_template(*cmds, params=mp)
|
|
||||||
return True
|
|
||||||
except excp.ProcessExecutionError, e:
|
|
||||||
LOG.warn("Could check if libvirt was ok for protocol [%s] due to [%s]" % (virt_protocol, e.message))
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def clear_libvirt_domains(distro, virt_type, inst_prefix):
|
|
||||||
libvirt = _get_virt_lib()
|
|
||||||
if not libvirt:
|
|
||||||
LOG.warn("Could not clear out libvirt domains, libvirt not available for python.")
|
|
||||||
return
|
|
||||||
virt_protocol = LIBVIRT_PROTOCOL_MAP.get(virt_type)
|
|
||||||
if not virt_protocol:
|
|
||||||
LOG.warn("Could not clear out libvirt domains, no known protocol for virt type %s" % (virt_type))
|
|
||||||
return
|
|
||||||
with sh.Rooted(True):
|
|
||||||
LOG.info("Attempting to clear out leftover libvirt domains using protocol %s" % (virt_protocol))
|
|
||||||
try:
|
try:
|
||||||
restart(distro)
|
dom = conn.lookupByName(dom_name)
|
||||||
|
LOG.debug("Destroying domain (%r) (id=%s) running %r" % (dom_name, dom.ID(), dom.OSType()))
|
||||||
|
dom.destroy()
|
||||||
|
dom.undefine()
|
||||||
|
except libvirt.libvirtError as e:
|
||||||
|
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 check_virt(self, virt_type):
|
||||||
|
virt_protocol = LIBVIRT_PROTOCOL_MAP.get(virt_type)
|
||||||
|
if not virt_protocol:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
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
|
return False
|
||||||
try:
|
try:
|
||||||
conn = libvirt.open(virt_protocol)
|
cmds = list()
|
||||||
except libvirt.libvirtError, e:
|
cmds.append({
|
||||||
LOG.warn("Could not connect to libvirt using protocol [%s] due to [%s]" % (virt_protocol, e.message))
|
'cmd': self.distro.get_command('libvirt', 'verify'),
|
||||||
|
'run_as_root': True,
|
||||||
|
})
|
||||||
|
mp = dict()
|
||||||
|
mp['VIRT_PROTOCOL'] = virt_protocol
|
||||||
|
utils.execute_template(*cmds, params=mp)
|
||||||
|
return True
|
||||||
|
except excp.ProcessExecutionError as e:
|
||||||
|
LOG.warn("Could check if libvirt was ok for protocol %r due to: %s" % (virt_protocol, e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
def clear_domains(self, virt_type, inst_prefix):
|
||||||
|
libvirt = _get_virt_lib()
|
||||||
|
if not libvirt:
|
||||||
|
LOG.warn("Could not clear out libvirt domains, libvirt not available for python.")
|
||||||
return
|
return
|
||||||
try:
|
virt_protocol = LIBVIRT_PROTOCOL_MAP.get(virt_type)
|
||||||
defined_domains = conn.listDefinedDomains()
|
if not virt_protocol:
|
||||||
kill_domains = list()
|
LOG.warn("Could not clear out libvirt domains, no known protocol for virt type %r" % (virt_type))
|
||||||
for domain in defined_domains:
|
return
|
||||||
if domain.startswith(inst_prefix):
|
with sh.Rooted(True):
|
||||||
kill_domains.append(domain)
|
LOG.info("Attempting to clear out leftover libvirt domains using protocol %r" % (virt_protocol))
|
||||||
if kill_domains:
|
try:
|
||||||
LOG.info("Found %s old domains to destroy (%s)" % (len(kill_domains), ", ".join(sorted(kill_domains))))
|
self.restart_service()
|
||||||
for domain in sorted(kill_domains):
|
except excp.ProcessExecutionError as e:
|
||||||
_destroy_domain(libvirt, conn, domain)
|
LOG.warn("Could not restart libvirt due to: %s" % (e))
|
||||||
except libvirt.libvirtError, e:
|
return
|
||||||
LOG.warn("Could not clear out libvirt domains due to [%s]" % (e.message))
|
try:
|
||||||
|
conn = libvirt.open(virt_protocol)
|
||||||
|
except libvirt.libvirtError as e:
|
||||||
|
LOG.warn("Could not connect to libvirt using protocol %r due to: %s" % (virt_protocol, e))
|
||||||
|
return
|
||||||
|
with contextlib.closing(conn) as ch:
|
||||||
|
try:
|
||||||
|
defined_domains = ch.listDefinedDomains()
|
||||||
|
kill_domains = list()
|
||||||
|
for domain in defined_domains:
|
||||||
|
if domain.startswith(inst_prefix):
|
||||||
|
kill_domains.append(domain)
|
||||||
|
if kill_domains:
|
||||||
|
LOG.info("Found %s old domains to destroy (%s)" % (len(kill_domains), ", ".join(sorted(kill_domains))))
|
||||||
|
for domain in sorted(kill_domains):
|
||||||
|
self._destroy_domain(ch, domain)
|
||||||
|
except libvirt.libvirtError, e:
|
||||||
|
LOG.warn("Could not clear out libvirt domains due to %s" % (e))
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user