anvil/devstack/libvirt.py
2012-02-26 19:22:21 -08:00

173 lines
5.7 KiB
Python

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (C) 2012 Yahoo! Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import time
from devstack import exceptions as excp
from devstack import log as logging
from devstack import settings
from devstack import shell as sh
from devstack import utils
LOG = logging.getLogger('devstack.libvirt')
#http://libvirt.org/uri.html
LIBVIRT_PROTOCOL_MAP = {
'qemu': "qemu:///system",
'kvm': "qemu:///system",
'xen': 'xen:///',
'uml': 'uml:///system',
'lxc': 'lxc:///',
}
VIRT_TYPE = 'libvirt'
VIRT_LIB = VIRT_TYPE
#distros name the libvirt service differently :-(
SV_NAME_MAP = {
settings.RHEL6: 'libvirtd',
settings.FEDORA16: 'libvirtd',
settings.UBUNTU11: 'libvirt-bin',
}
#how libvirt is restarted
LIBVIRT_RESTART_CMD = ['service', '%SERVICE%', 'restart']
#how we check its status
LIBVIRT_STATUS_CMD = ['service', '%SERVICE%', 'status']
#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!
_DEAD = 'DEAD'
_ALIVE = 'ALIVE'
#alive wait time, just a sleep we put into so that the service can start up
WAIT_ALIVE_TIME = settings.WAIT_ALIVE_SECS
def _get_virt_lib():
#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
return utils.import_module(VIRT_LIB)
def _status(distro):
cmds = list()
cmds.append({
'cmd': LIBVIRT_STATUS_CMD,
'run_as_root': True,
})
mp = dict()
mp['SERVICE'] = SV_NAME_MAP[distro]
result = utils.execute_template(*cmds,
check_exit_code=False,
params=mp)
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 _destroy_domain(libvirt, conn, dom_name):
try:
dom = conn.lookupByName(dom_name)
LOG.debug("Destroying domain (%s) (id=%s) running %s" % (dom_name, dom.ID(), dom.OSType()))
dom.destroy()
dom.undefine()
except libvirt.libvirtError, e:
LOG.warn("Could not clear out libvirt domain (%s) due to [%s]" % (dom_name, e.message))
def restart(distro):
if _status(distro) != _ALIVE:
cmds = list()
cmds.append({
'cmd': LIBVIRT_RESTART_CMD,
'run_as_root': True,
})
mp = dict()
mp['SERVICE'] = SV_NAME_MAP[distro]
utils.execute_template(*cmds, params=mp)
LOG.info("Restarting the libvirt service, please wait %s seconds until its started." % (WAIT_ALIVE_TIME))
time.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 on distro [%s] due to [%s]" % (distro, e.message))
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:
restart(distro)
except excp.ProcessExecutionError, e:
LOG.warn("Could not restart libvirt on distro [%s] due to [%s]" % (distro, e.message))
return
try:
conn = libvirt.open(virt_protocol)
except libvirt.libvirtError, e:
LOG.warn("Could not connect to libvirt using protocol [%s] due to [%s]" % (virt_protocol, e.message))
return
try:
defined_domains = conn.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):
_destroy_domain(libvirt, conn, domain)
except libvirt.libvirtError, e:
LOG.warn("Could not clear out libvirt domains due to [%s]" % (e.message))