Files
nova/plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py
T
Matt Riedemann 016e39734e Fix several flake8 issues in the plugins/xenserver code
Due to some issues in the gate, several flake8 errors got merged
recently. This patch fixes the most recent issues found.

For the H304 relative import errors, we have to skip those because they
are put into /etc/xensource/scripts which is the current working
directory when running the plugin.

For the H231 incompatible python 3 'except x,y' construct, we have to
skip those because this code is written to run on python 2.4 and 'except
x as y' does not work with python 2.4.

Note that in cleaning up some of the H304 failures for relative imports,
I also re-arranged the imports to follow the hacking guide of doing
standard library packages first, then third party packages, and finally
nova-specific packages.

Closes-Bug: #1229753

Change-Id: I1c2211fd6a10d43d7e65cdb4e18530397788cf2c
2013-09-24 09:04:21 -07:00

144 lines
4.7 KiB
Python

# Copyright (c) 2010 Citrix Systems, Inc.
#
# 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.
#
# Helper functions for the Nova xapi plugins. In time, this will merge
# with the pluginlib.py shipped with xapi, but for now, that file is not
# very stable, so it's easiest just to have a copy of all the functions
# that we need.
#
import gettext
import logging
import logging.handlers
import time
import XenAPI
translations = gettext.translation('nova', fallback=True)
_ = translations.ugettext
##### Logging setup
def configure_logging(name):
log = logging.getLogger()
log.setLevel(logging.DEBUG)
sysh = logging.handlers.SysLogHandler('/dev/log')
sysh.setLevel(logging.DEBUG)
formatter = logging.Formatter('%s: %%(levelname)-8s %%(message)s' % name)
sysh.setFormatter(formatter)
log.addHandler(sysh)
##### Exceptions
class PluginError(Exception):
"""Base Exception class for all plugin errors."""
def __init__(self, *args):
Exception.__init__(self, *args)
class ArgumentError(PluginError):
"""Raised when required arguments are missing, argument values are invalid,
or incompatible arguments are given.
"""
def __init__(self, *args):
PluginError.__init__(self, *args)
##### Argument validation
def exists(args, key):
"""Validates that a freeform string argument to a RPC method call is given.
Returns the string.
"""
if key in args:
return args[key]
else:
raise ArgumentError(_('Argument %s is required.') % key)
def optional(args, key):
"""If the given key is in args, return the corresponding value, otherwise
return None
"""
return key in args and args[key] or None
def _get_domain_0(session):
this_host_ref = session.xenapi.session.get_this_host(session.handle)
expr = 'field "is_control_domain" = "true" and field "resident_on" = "%s"'
expr = expr % this_host_ref
return session.xenapi.VM.get_all_records_where(expr).keys()[0]
def with_vdi_in_dom0(session, vdi, read_only, f):
dom0 = _get_domain_0(session)
vbd_rec = {}
vbd_rec['VM'] = dom0
vbd_rec['VDI'] = vdi
vbd_rec['userdevice'] = 'autodetect'
vbd_rec['bootable'] = False
vbd_rec['mode'] = read_only and 'RO' or 'RW'
vbd_rec['type'] = 'disk'
vbd_rec['unpluggable'] = True
vbd_rec['empty'] = False
vbd_rec['other_config'] = {}
vbd_rec['qos_algorithm_type'] = ''
vbd_rec['qos_algorithm_params'] = {}
vbd_rec['qos_supported_algorithms'] = []
logging.debug(_('Creating VBD for VDI %s ... '), vdi)
vbd = session.xenapi.VBD.create(vbd_rec)
logging.debug(_('Creating VBD for VDI %s done.'), vdi)
try:
logging.debug(_('Plugging VBD %s ... '), vbd)
session.xenapi.VBD.plug(vbd)
logging.debug(_('Plugging VBD %s done.'), vbd)
return f(session.xenapi.VBD.get_device(vbd))
finally:
logging.debug(_('Destroying VBD for VDI %s ... '), vdi)
_vbd_unplug_with_retry(session, vbd)
try:
session.xenapi.VBD.destroy(vbd)
except XenAPI.Failure, e: # noqa
logging.error(_('Ignoring XenAPI.Failure %s'), e)
logging.debug(_('Destroying VBD for VDI %s done.'), vdi)
def _vbd_unplug_with_retry(session, vbd):
"""Call VBD.unplug on the given VBD, with a retry if we get
DEVICE_DETACH_REJECTED. For reasons which I don't understand, we're
seeing the device still in use, even when all processes using the device
should be dead.
"""
while True:
try:
session.xenapi.VBD.unplug(vbd)
logging.debug(_('VBD.unplug successful first time.'))
return
except XenAPI.Failure, e: # noqa
if (len(e.details) > 0 and
e.details[0] == 'DEVICE_DETACH_REJECTED'):
logging.debug(_('VBD.unplug rejected: retrying...'))
time.sleep(1)
elif (len(e.details) > 0 and
e.details[0] == 'DEVICE_ALREADY_DETACHED'):
logging.debug(_('VBD.unplug successful eventually.'))
return
else:
logging.error(_('Ignoring XenAPI.Failure in VBD.unplug: %s'),
e)
return