# 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 DEFAULT_VIRT = 'qemu' #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 default(virt_type): if not virt_type: return DEFAULT_VIRT virt_type = virt_type.lower().strip() if not virt_type in LIBVIRT_PROTOCOL_MAP: return DEFAULT_VIRT else: return virt_type def virt_ok(virt_type, distro): virt_protocol = LIBVIRT_PROTOCOL_MAP.get(virt_type) if not virt_protocol: return False restart(distro) cmds = list() cmds.append({ 'cmd': VIRSH_SANITY_CMD, 'run_as_root': True, }) mp = dict() mp['VIRT_PROTOCOL'] = virt_protocol try: utils.execute_template(*cmds, params=mp) return True except excp.ProcessExecutionError: 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)) restart(distro) conn = None try: conn = libvirt.open(virt_protocol) except libvirt.libvirtError: LOG.warn("Could not connect to libvirt using protocol [%s]" % (virt_protocol)) if conn: 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))