¡@

Home 

OpenStack Study: linuxscsi.py

OpenStack Index

**** CubicPower OpenStack Study ****

# (c) Copyright 2013 Hewlett-Packard Development Company, L.P.

#

# 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.

"""Generic linux scsi subsystem and Multipath utilities.

Note, this is not iSCSI.

"""

import os

from cinder.brick import executor

from cinder.openstack.common.gettextutils import _

from cinder.openstack.common import log as logging

from cinder.openstack.common import processutils as putils

LOG = logging.getLogger(__name__)

**** CubicPower OpenStack Study ****

class LinuxSCSI(executor.Executor):

**** CubicPower OpenStack Study ****

    def __init__(self, root_helper, execute=putils.execute,

                 *args, **kwargs):

        super(LinuxSCSI, self).__init__(root_helper, execute,

                                        *args, **kwargs)

**** CubicPower OpenStack Study ****

    def echo_scsi_command(self, path, content):

        """Used to echo strings to scsi subsystem."""

        args = ["-a", path]

        kwargs = dict(process_input=content,

                      run_as_root=True,

                      root_helper=self._root_helper)

        self._execute('tee', *args, **kwargs)

**** CubicPower OpenStack Study ****

    def get_name_from_path(self, path):

        """Translates /dev/disk/by-path/ entry to /dev/sdX."""

        name = os.path.realpath(path)

        if name.startswith("/dev/"):

            return name

        else:

            return None

**** CubicPower OpenStack Study ****

    def remove_scsi_device(self, device):

        """Removes a scsi device based upon /dev/sdX name."""

        path = "/sys/block/%s/device/delete" % device.replace("/dev/", "")

        if os.path.exists(path):

            LOG.debug("Remove SCSI device(%s) with %s" % (device, path))

            self.echo_scsi_command(path, "1")

**** CubicPower OpenStack Study ****

    def get_device_info(self, device):

        (out, err) = self._execute('sg_scan', device, run_as_root=True,

                                   root_helper=self._root_helper)

        dev_info = {'device': device, 'host': None,

                    'channel': None, 'id': None, 'lun': None}

        if out:

            line = out.strip()

            line = line.replace(device + ": ", "")

            info = line.split(" ")

            for item in info:

                if '=' in item:

                    pair = item.split('=')

                    dev_info[pair[0]] = pair[1]

                elif 'scsi' in item:

                    dev_info['host'] = item.replace('scsi', '')

        return dev_info

**** CubicPower OpenStack Study ****

    def remove_multipath_device(self, multipath_name):

        """This removes LUNs associated with a multipath device

        and the multipath device itself.

        """

        LOG.debug("remove multipath device %s" % multipath_name)

        mpath_dev = self.find_multipath_device(multipath_name)

        if mpath_dev:

            devices = mpath_dev['devices']

            LOG.debug("multipath LUNs to remove %s" % devices)

            for device in devices:

                self.remove_scsi_device(device['device'])

            self.flush_multipath_device(mpath_dev['id'])

**** CubicPower OpenStack Study ****

    def flush_multipath_device(self, device):

        try:

            self._execute('multipath', '-f', device, run_as_root=True,

                          root_helper=self._root_helper)

        except putils.ProcessExecutionError as exc:

            LOG.warn(_("multipath call failed exit (%(code)s)")

                     % {'code': exc.exit_code})

**** CubicPower OpenStack Study ****

    def flush_multipath_devices(self):

        try:

            self._execute('multipath', '-F', run_as_root=True,

                          root_helper=self._root_helper)

        except putils.ProcessExecutionError as exc:

            LOG.warn(_("multipath call failed exit (%(code)s)")

                     % {'code': exc.exit_code})

**** CubicPower OpenStack Study ****

    def find_multipath_device(self, device):

        """Find a multipath device associated with a LUN device name.

        device can be either a /dev/sdX entry or a multipath id.

        """

        mdev = None

        devices = []

        out = None

        try:

            (out, err) = self._execute('multipath', '-l', device,

                                       run_as_root=True,

                                       root_helper=self._root_helper)

        except putils.ProcessExecutionError as exc:

            LOG.warn(_("multipath call failed exit (%(code)s)")

                     % {'code': exc.exit_code})

            return None

        if out:

            lines = out.strip()

            lines = lines.split("\n")

            if lines:

                line = lines[0]

                info = line.split(" ")

                # device line output is different depending

                # on /etc/multipath.conf settings.

                if info[1][:2] == "dm":

                    mdev = "/dev/%s" % info[1]

                    mdev_id = info[0]

                elif info[2][:2] == "dm":

                    mdev = "/dev/%s" % info[2]

                    mdev_id = info[1].replace('(', '')

                    mdev_id = mdev_id.replace(')', '')

                if mdev is None:

                    LOG.warn(_("Couldn't find multipath device %(line)s")

                             % {'line': line})

                    return None

                LOG.debug(_("Found multipath device = %(mdev)s")

                          % {'mdev': mdev})

                device_lines = lines[3:]

                for dev_line in device_lines:

                    if dev_line.find("policy") != -1:

                        continue

                    dev_line = dev_line.lstrip(' |-`')

                    dev_info = dev_line.split()

                    address = dev_info[0].split(":")

                    dev = {'device': '/dev/%s' % dev_info[1],

                           'host': address[0], 'channel': address[1],

                           'id': address[2], 'lun': address[3]

                           }

                    devices.append(dev)

        if mdev is not None:

            info = {"device": mdev,

                    "id": mdev_id,

                    "devices": devices}

            return info

        return None