This file is indexed.

/usr/lib/python2.7/dist-packages/os_xenapi/dom0/etc/xapi.d/plugins/dom0_pluginlib.py is in python-os-xenapi 0.3.1-0ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# 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.

# NOTE: XenServer still only supports Python 2.4 in it's dom0 userspace
# which means the Nova xenapi plugins must use only Python 2.4 features

#
# 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 logging
import logging.handlers
import os
import time

import XenAPI

# global variable definition
MAX_VBD_UNPLUG_RETRIES = 30


# Logging setup

def configure_logging(name):
    log = logging.getLogger()
    log.setLevel(logging.DEBUG)
    if os.path.exists('/dev/log'):
        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 list(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.
    """
    retry_count = MAX_VBD_UNPLUG_RETRIES
    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'):
                retry_count -= 1
                if (retry_count <= 0):
                    raise PluginError('VBD.unplug failed after retry %s times.'
                                      % MAX_VBD_UNPLUG_RETRIES)
                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