**** CubicPower OpenStack Study ****
# Copyright (c) 2012 - 2014 EMC Corporation, 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.
"""
VNX CLI on iSCSI.
"""
import os
import time
from oslo.config import cfg
from cinder import exception
from cinder.openstack.common import log as logging
from cinder.openstack.common import loopingcall
from cinder.openstack.common import processutils
from cinder import utils
from cinder.volume.drivers.san import san
from cinder.volume import volume_types
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
VERSION = '02.00.00'
loc_opts = [
cfg.StrOpt('naviseccli_path',
default='',
help='Naviseccli Path'),
cfg.StrOpt('storage_vnx_pool_name',
default=None,
help='ISCSI pool name'),
cfg.IntOpt('default_timeout',
default=20,
help='Default Time Out For CLI operations in minutes'),
cfg.IntOpt('max_luns_per_storage_group',
default=256,
help='Default max number of LUNs in a storage group'), ]
CONF.register_opts(loc_opts)
**** CubicPower OpenStack Study ****
class EMCVnxCli(object):
"""This class
**** CubicPower OpenStack Study ****
def __init__(self, prtcl, configuration=None):
self.protocol = prtcl
self.configuration = configuration
self.configuration.append_config_values(loc_opts)
self.configuration.append_config_values(san.san_opts)
self.storage_ip = self.configuration.san_ip
self.storage_username = self.configuration.san_login
self.storage_password = self.configuration.san_password
self.pool_name = self.configuration.storage_vnx_pool_name
if not self.pool_name:
msg = (_('Pool name is not specified.'))
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
self.timeout = self.configuration.default_timeout
self.max_luns = self.configuration.max_luns_per_storage_group
self.hlu_set = set(xrange(1, self.max_luns + 1))
self.navisecclipath = self.configuration.naviseccli_path
self.cli_prefix = (self.navisecclipath, '-address', self.storage_ip)
self.cli_credentials = ()
self.wait_interval = 3
# if there is a username/password provided, use those in the cmd line
if self.storage_username is not None and \
self.storage_password is not None:
self.cli_credentials += ('-user', self.storage_username,
'-password', self.storage_password,
'-scope', '0')
# Checking for existence of naviseccli tool
if not os.path.exists(self.navisecclipath):
msg = (_('Could not find NAVISECCLI tool.'))
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
# Testing the naviseccli setup
query_list = ("storagepool", "-list",
"-name", self.pool_name, "-state")
out, rc = self._cli_execute(*query_list)
if rc != 0:
LOG.error(_("Failed to find pool %s"), self.pool_name)
raise exception.VolumeBackendAPIException(data=out)
**** CubicPower OpenStack Study ****
def _cli_execute(self, *cmd, **kwargv):
if "check_exit_code" not in kwargv:
kwargv["check_exit_code"] = True
rc = 0
try:
out, _err = utils.execute(*(self.cli_prefix +
self.cli_credentials + cmd), **kwargv)
except processutils.ProcessExecutionError as pe:
rc = pe.exit_code
out = pe.stdout + pe.stderr
return out, rc
**** CubicPower OpenStack Study ****
def create_volume(self, volume):
"""Creates a EMC volume."""
LOG.debug(_('Entering create_volume.'))
volumesize = volume['size']
volumename = volume['name']
LOG.info(_('Create Volume: %(volume)s Size: %(size)s')
% {'volume': volumename,
'size': volumesize})
# defining CLI command
thinness = self._get_provisioning_by_volume(volume)
# executing CLI command to create volume
LOG.debug(_('Create Volume: %(volumename)s')
% {'volumename': volumename})
lun_create = ('lun', '-create',
'-type', thinness,
'-capacity', volumesize,
'-sq', 'gb',
'-poolName', self.pool_name,
'-name', volumename)
out, rc = self._cli_execute(*lun_create)
LOG.debug(_('Create Volume: %(volumename)s Return code: %(rc)s')
% {'volumename': volumename,
'rc': rc})
if rc == 4:
LOG.warn(_('Volume %s already exists'), volumename)
elif rc != 0:
msg = (_('Failed to create %(volumename)s: %(out)s') %
{'volumename': volumename, 'out': out})
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
# wait for up to a minute to verify that the LUN has progressed
# to Ready state
def _wait_for_lun_ready(volumename, start_time):
# executing cli command to check volume
command_to_verify = ('lun', '-list', '-name', volumename)
out, rc = self._cli_execute(*command_to_verify)
if rc == 0 and out.find("Ready") > -1:
raise loopingcall.LoopingCallDone()
if int(time.time()) - start_time > self.timeout * 60:
msg = (_('LUN %s failed to become Ready'), volumename)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
timer = loopingcall.FixedIntervalLoopingCall(
_wait_for_lun_ready, volumename, int(time.time()))
timer.start(interval=self.wait_interval).wait()
**** CubicPower OpenStack Study ****
def _wait_for_lun_ready(volumename, start_time):
# executing cli command to check volume
command_to_verify = ('lun', '-list', '-name', volumename)
out, rc = self._cli_execute(*command_to_verify)
if rc == 0 and out.find("Ready") > -1:
raise loopingcall.LoopingCallDone()
if int(time.time()) - start_time > self.timeout * 60:
msg = (_('LUN %s failed to become Ready'), volumename)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
timer = loopingcall.FixedIntervalLoopingCall(
_wait_for_lun_ready, volumename, int(time.time()))
timer.start(interval=self.wait_interval).wait()
**** CubicPower OpenStack Study ****
def delete_volume(self, volume):
"""Deletes an EMC volume."""
LOG.debug(_('Entering delete_volume.'))
volumename = volume['name']
# defining CLI command
lun_destroy = ('lun', '-destroy',
'-name', volumename,
'-forceDetach', '-o')
# executing CLI command to delete volume
out, rc = self._cli_execute(*lun_destroy)
LOG.debug(_('Delete Volume: %(volumename)s Output: %(out)s')
% {'volumename': volumename, 'out': out})
if rc not in (0, 9):
msg = (_('Failed to destroy %s'), volumename)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
**** CubicPower OpenStack Study ****
def extend_volume(self, volume, new_size):
"""Extends an EMC volume."""
LOG.debug(_('Entering extend_volume.'))
volumename = volume['name']
# defining CLI command
lun_expand = ('lun', '-expand',
'-name', volumename,
'-capacity', new_size,
'-sq', 'gb',
'-o', '-ignoreThresholds')
# executing CLI command to extend volume
out, rc = self._cli_execute(*lun_expand)
LOG.debug(_('Extend Volume: %(volumename)s Output: %(out)s')
% {'volumename': volumename,
'out': out})
if rc == 97:
msg = (_('The LUN cannot be expanded or shrunk because '
'it has snapshots. Command to extend the specified '
'volume failed.'))
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
if rc != 0:
msg = (_('Failed to expand %s'), volumename)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
**** CubicPower OpenStack Study ****
def update_volume_status(self):
"""Retrieve status info."""
LOG.debug(_("Updating volume status"))
poolname = self.pool_name
pool_list = ('storagepool', '-list',
'-name', poolname,
'-userCap', '-availableCap')
out, rc = self._cli_execute(*pool_list)
if rc == 0:
pool_details = out.split('\n')
self.stats['total_capacity_gb'] = float(
pool_details[3].split(':')[1].strip())
self.stats['free_capacity_gb'] = float(
pool_details[5].split(':')[1].strip())
else:
msg = (_('Failed to list %s'), poolname)
LOG.error(msg)
return self.stats
**** CubicPower OpenStack Study ****
def create_export(self, context, volume):
"""Driver entry point to get the export info for a new volume."""
volumename = volume['name']
device_id = self._find_lun_id(volumename)
LOG.debug(_('create_export: Volume: %(volume)s Device ID: '
'%(device_id)s')
% {'volume': volumename,
'device_id': device_id})
return {'provider_location': device_id}
**** CubicPower OpenStack Study ****
def _find_lun_id(self, volumename):
"""Returns the LUN of a volume."""
lun_list = ('lun', '-list', '-name', volumename)
out, rc = self._cli_execute(*lun_list)
if rc == 0:
vol_details = out.split('\n')
lun = vol_details[0].split(' ')[3]
else:
msg = (_('Failed to list %s'), volumename)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
return lun
**** CubicPower OpenStack Study ****
def create_snapshot(self, snapshot):
"""Creates a snapshot."""
LOG.debug(_('Entering create_snapshot.'))
snapshotname = snapshot['name']
volumename = snapshot['volume_name']
LOG.info(_('Create snapshot: %(snapshot)s: volume: %(volume)s')
% {'snapshot': snapshotname,
'volume': volumename})
volume_lun = self._find_lun_id(volumename)
# defining CLI command
snap_create = ('snap', '-create',
'-res', volume_lun,
'-name', snapshotname,
'-allowReadWrite', 'yes')
# executing CLI command to create snapshot
out, rc = self._cli_execute(*snap_create)
LOG.debug(_('Create Snapshot: %(snapshotname)s Unity: %(out)s')
% {'snapshotname': snapshotname,
'out': out})
if rc != 0:
msg = (_('Failed to create snap %s'), snapshotname)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
**** CubicPower OpenStack Study ****
def delete_snapshot(self, snapshot):
"""Deletes a snapshot."""
LOG.debug(_('Entering delete_snapshot.'))
snapshotname = snapshot['name']
volumename = snapshot['volume_name']
LOG.info(_('Delete Snapshot: %(snapshot)s: volume: %(volume)s')
% {'snapshot': snapshotname,
'volume': volumename})
def _wait_for_snap_delete(snapshot, start_time):
# defining CLI command
snapshotname = snapshot['name']
volumename = snapshot['volume_name']
snap_destroy = ('snap', '-destroy', '-id', snapshotname, '-o')
# executing CLI command
out, rc = self._cli_execute(*snap_destroy)
LOG.debug(_('Delete Snapshot: Volume: %(volumename)s Snapshot: '
'%(snapshotname)s Output: %(out)s')
% {'volumename': volumename,
'snapshotname': snapshotname,
'out': out})
if rc not in [0, 9, 5]:
if rc == 13:
if int(time.time()) - start_time < \
self.timeout * 60:
LOG.info(_('Snapshot %s is in use'), snapshotname)
else:
msg = (_('Failed to destroy %s '
' because snapshot is in use.'), snapshotname)
LOG.error(msg)
raise exception.SnapshotIsBusy(data=msg)
else:
msg = (_('Failed to destroy %s'), snapshotname)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
else:
raise loopingcall.LoopingCallDone()
timer = loopingcall.FixedIntervalLoopingCall(
_wait_for_snap_delete, snapshot, int(time.time()))
timer.start(interval=self.wait_interval).wait()
**** CubicPower OpenStack Study ****
def _wait_for_snap_delete(snapshot, start_time):
# defining CLI command
snapshotname = snapshot['name']
volumename = snapshot['volume_name']
snap_destroy = ('snap', '-destroy', '-id', snapshotname, '-o')
# executing CLI command
out, rc = self._cli_execute(*snap_destroy)
LOG.debug(_('Delete Snapshot: Volume: %(volumename)s Snapshot: '
'%(snapshotname)s Output: %(out)s')
% {'volumename': volumename,
'snapshotname': snapshotname,
'out': out})
if rc not in [0, 9, 5]:
if rc == 13:
if int(time.time()) - start_time < \
self.timeout * 60:
LOG.info(_('Snapshot %s is in use'), snapshotname)
else:
msg = (_('Failed to destroy %s '
' because snapshot is in use.'), snapshotname)
LOG.error(msg)
raise exception.SnapshotIsBusy(data=msg)
else:
msg = (_('Failed to destroy %s'), snapshotname)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
else:
raise loopingcall.LoopingCallDone()
timer = loopingcall.FixedIntervalLoopingCall(
_wait_for_snap_delete, snapshot, int(time.time()))
timer.start(interval=self.wait_interval).wait()
**** CubicPower OpenStack Study ****
def create_volume_from_snapshot(self, volume, snapshot):
"""Creates a volume from a snapshot."""
LOG.debug(_('Entering create_volume_from_snapshot.'))
snapshotname = snapshot['name']
source_volume_name = snapshot['volume_name']
volumename = volume['name']
volumesize = snapshot['volume_size']
destvolumename = volumename + 'dest'
# Create a mount point, migrate data from source (snapshot) to
# destination volume. The destination volume is the only new volume
# to be created here.
LOG.info(_('Creating Destination Volume : %s ') % (destvolumename))
poolname = self.pool_name
thinness = self._get_provisioning_by_volume(volume)
# defining CLI command
lun_create = ('lun', '-create', '-type', thinness,
'-capacity', volumesize, '-sq', 'gb',
'-poolName', poolname,
'-name', destvolumename)
# executing CLI command
out, rc = self._cli_execute(*lun_create)
LOG.debug(_('Create temporary Volume: %(volumename)s '
'Output : %(out)s')
% {'volumename': destvolumename, 'out': out})
if rc != 0:
msg = (_('Command to create the destination volume failed'))
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
# defining CLI command
smp_create = ('lun', '-create', '-type', 'Snap',
'-primaryLunName', source_volume_name,
'-name', volumename)
# executing CLI command
out, rc = self._cli_execute(*smp_create)
LOG.debug(_('Create mount point : Volume: %(volumename)s '
'Source Volume: %(sourcevolumename)s Output: %(out)s')
% {'volumename': volumename,
'sourcevolumename': source_volume_name,
'out': out})
if rc != 0:
msg = (_('Failed to create SMP %s'), volumename)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
# defining CLI command
lun_attach = ('lun', '-attach',
'-name', volumename,
'-snapName', snapshotname)
# executing CLI command
out, rc = self._cli_execute(*lun_attach)
LOG.debug(_('Attaching mount point Volume: %(volumename)s '
'with Snapshot: %(snapshotname)s Output: %(out)s')
% {'volumename': volumename,
'snapshotname': snapshotname,
'out': out})
if rc != 0:
msg = (_('Failed to attach snapshotname %s'), snapshotname)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
source_vol_lun = self._find_lun_id(volumename)
dest_vol_lun = self._find_lun_id(destvolumename)
LOG.info(_('Migrating Mount Point Volume: %s ') % (volumename))
# defining CLI command
migrate_start = ('migrate', '-start',
'-source', source_vol_lun,
'-dest', dest_vol_lun,
'-rate', 'ASAP', '-o')
# executing CLI command
out, rc = self._cli_execute(*migrate_start)
LOG.debug(_('Migrate Mount Point Volume: %(volumename)s '
'Output : %(out)s')
% {'volumename': volumename,
'out': out})
if rc != 0:
msg = (_('Failed to start migrating SMP %s'), volumename)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
def _wait_for_sync_status(volumename, start_time):
lun_list = ('lun', '-list', '-name', volumename,
'-attachedSnapshot')
out, rc = self._cli_execute(*lun_list)
if rc == 0:
vol_details = out.split('\n')
snapshotname = vol_details[2].split(':')[1].strip()
if (snapshotname == 'N/A'):
raise loopingcall.LoopingCallDone()
else:
LOG.info(_('Waiting for the update on Sync status of %s'),
volumename)
if int(time.time()) - start_time >= self.timeout * 60:
msg = (_('Failed to really migrate %s'), volumename)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
timer = loopingcall.FixedIntervalLoopingCall(
_wait_for_sync_status, volumename, int(time.time()))
timer.start(interval=self.wait_interval).wait()
**** CubicPower OpenStack Study ****
def _wait_for_sync_status(volumename, start_time):
lun_list = ('lun', '-list', '-name', volumename,
'-attachedSnapshot')
out, rc = self._cli_execute(*lun_list)
if rc == 0:
vol_details = out.split('\n')
snapshotname = vol_details[2].split(':')[1].strip()
if (snapshotname == 'N/A'):
raise loopingcall.LoopingCallDone()
else:
LOG.info(_('Waiting for the update on Sync status of %s'),
volumename)
if int(time.time()) - start_time >= self.timeout * 60:
msg = (_('Failed to really migrate %s'), volumename)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
timer = loopingcall.FixedIntervalLoopingCall(
_wait_for_sync_status, volumename, int(time.time()))
timer.start(interval=self.wait_interval).wait()
**** CubicPower OpenStack Study ****
def create_cloned_volume(self, volume, src_vref):
"""Creates a clone of the specified volume."""
source_volume_name = src_vref['name']
volumesize = src_vref['size']
snapshotname = source_volume_name + '-temp-snapshot'
snapshot = {
'name': snapshotname,
'volume_name': source_volume_name,
'volume_size': volumesize,
}
# Create temp Snapshot
self.create_snapshot(snapshot)
try:
# Create volume
self.create_volume_from_snapshot(volume, snapshot)
except Exception:
msg = (_('Failed to create cloned volume %s'), volume['name'])
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
finally:
# Delete temp Snapshot
self.delete_snapshot(snapshot)
**** CubicPower OpenStack Study ****
def get_storage_group(self, hostname):
"""Returns the storage group for the host node."""
storage_groupname = hostname
sg_list = ('storagegroup', '-list', '-gname', storage_groupname)
out, rc = self._cli_execute(*sg_list)
if rc != 0:
LOG.debug(_('creating new storage group %s'), storage_groupname)
sg_create = ('storagegroup', '-create',
'-gname', storage_groupname)
out, rc = self._cli_execute(*sg_create)
LOG.debug(_('Create new storage group : %(storage_groupname)s, '
'Output: %(out)s')
% {'storage_groupname': storage_groupname,
'out': out})
if rc != 0:
msg = (_('Failed to create SG %s'), storage_groupname)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
# connecting the new storagegroup to the host
connect_host = ('storagegroup', '-connecthost',
'-host', hostname,
'-gname', storage_groupname,
'-o')
out, rc = self._cli_execute(*connect_host)
LOG.debug(_('Connect storage group : %(storage_groupname)s ,'
'To Host : %(hostname)s, Output : %(out)s')
% {'storage_groupname': storage_groupname,
'hostname': hostname,
'out': out})
if rc != 0:
msg = (_('Failed to connect %s'), hostname)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
return hostname
**** CubicPower OpenStack Study ****
def find_device_details(self, volume, storage_group):
"""Returns the Host Device number for the volume."""
allocated_lun_id = self._find_lun_id(volume["name"])
host_lun_id = -1
owner_sp = ""
lun_map = {}
sg_list = ('storagegroup', '-list', '-gname', storage_group)
out, rc = self._cli_execute(*sg_list)
if out.find('HLU/ALU Pairs') == -1:
LOG.info(_('NO LUNs in the storagegroup : %s ')
% (storage_group))
else:
sg_details = out.split('HLU/ALU Pairs:')[1]
sg_lun_details = sg_details.split('Shareable')[0]
lun_details = sg_lun_details.split('\n')
for data in lun_details:
if data not in ['', ' HLU Number ALU Number',
' ---------- ----------']:
data = data.strip()
items = data.split(' ')
lun_map[int(items[len(items) - 1])] = int(items[0])
for lun in lun_map.iterkeys():
if lun == int(allocated_lun_id):
host_lun_id = lun_map[lun]
LOG.debug(_('Host Lun Id : %s') % (host_lun_id))
break
# finding the owner SP for the LUN
lun_list = ('lun', '-list', '-l', allocated_lun_id, '-owner')
out, rc = self._cli_execute(*lun_list)
if rc == 0:
output = out.split('\n')
owner_sp = output[2].split('Current Owner: SP ')[1]
LOG.debug(_('Owner SP : %s') % (owner_sp))
device = {
'hostlunid': host_lun_id,
'ownersp': owner_sp,
'lunmap': lun_map,
}
return device
**** CubicPower OpenStack Study ****
def _get_host_lun_id(self, host_lun_id_list):
# Returns the host lun id for the LUN to be added
# in the storage group.
used_hlu_set = set(host_lun_id_list)
for hlu in self.hlu_set - used_hlu_set:
return hlu
return None
**** CubicPower OpenStack Study ****
def _add_lun_to_storagegroup(self, volume, storage_group):
storage_groupname = storage_group
volumename = volume['name']
allocated_lun_id = self._find_lun_id(volumename)
count = 0
while(count < 5):
device_info = self.find_device_details(volume, storage_group)
device_number = device_info['hostlunid']
if device_number < 0:
lun_map = device_info['lunmap']
if lun_map:
host_lun_id_list = lun_map.values()
if len(host_lun_id_list) >= self.max_luns:
msg = (_('The storage group has reached the '
'maximum capacity of LUNs. '
'Command to add LUN for volume - %s '
'in storagegroup failed') % (volumename))
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
host_lun_id = self._get_host_lun_id(host_lun_id_list)
if host_lun_id is None:
msg = (_('Unable to get new host lun id. Please '
'check if the storage group can accommodate '
'new LUN. '
'Command to add LUN for volume - %s '
'in storagegroup failed') % (volumename))
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
else:
host_lun_id = 1
addhlu = ('storagegroup', '-addhlu', '-o',
'-gname', storage_groupname,
'-hlu', host_lun_id,
'-alu', allocated_lun_id)
out, rc = self._cli_execute(*addhlu)
LOG.debug(_('Add ALU %(alu)s to SG %(sg)s as %(hlu)s. '
'Output: %(out)s')
% {'alu': allocated_lun_id,
'sg': storage_groupname,
'hlu': host_lun_id,
'out': out})
if rc == 0:
return host_lun_id
if rc == 66:
LOG.warn(_('Requested Host LUN Number already in use'))
count += 1
else:
LOG.warn(_('LUN was already added in the storage group'))
return device_number
if count == 5:
msg = (_('Failed to add %s into SG') % (volumename))
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
**** CubicPower OpenStack Study ****
def _remove_lun_from_storagegroup(self, device_number, storage_group):
storage_groupname = storage_group
removehlu = ('storagegroup', '-removehlu',
'-gname', storage_groupname,
'-hlu', device_number,
'-o')
out, rc = self._cli_execute(*removehlu)
LOG.debug(_('Remove %(hlu)s from SG %(sg)s. Output: %(out)s')
% {'hlu': device_number,
'sg': storage_groupname,
'out': out})
if rc != 0:
msg = (_('Failed to remove %(hlu)s from %(sg)s')
% {'hlu': device_number, 'sg': storage_groupname})
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
**** CubicPower OpenStack Study ****
def initialize_connection(self, volume, connector):
"""Initializes the connection and returns connection info."""
hostname = connector['host']
storage_group = self.get_storage_group(hostname)
device_number = self._add_lun_to_storagegroup(volume, storage_group)
return device_number
**** CubicPower OpenStack Study ****
def terminate_connection(self, volume, connector):
"""Disallow connection from connector."""
hostname = connector['host']
storage_group = self.get_storage_group(hostname)
device_info = self.find_device_details(volume, storage_group)
device_number = device_info['hostlunid']
if device_number < 0:
LOG.error(_('Could not locate the attached volume.'))
else:
self._remove_lun_from_storagegroup(device_number, storage_group)
**** CubicPower OpenStack Study ****
def _find_iscsi_protocol_endpoints(self, device_sp):
"""Returns the iSCSI initiators for a SP."""
initiator_address = []
connection_getport = ('connection', '-getport', '-sp', device_sp)
out, _rc = self._cli_execute(*connection_getport)
output = out.split('SP: ')
for port in output:
port_info = port.split('\n')
if port_info[0] == device_sp:
port_wwn = port_info[2].split('Port WWN:')[1].strip()
initiator_address.append(port_wwn)
LOG.debug(_('WWNs found for SP %(devicesp)s '
'are: %(initiator_address)s')
% {'devicesp': device_sp,
'initiator_address': initiator_address})
return initiator_address
**** CubicPower OpenStack Study ****
def _get_volumetype_extraspecs(self, volume):
specs = {}
type_id = volume['volume_type_id']
if type_id is not None:
specs = volume_types.get_volume_type_extra_specs(type_id)
return specs
**** CubicPower OpenStack Study ****
def _get_provisioning_by_volume(self, volume):
# By default, the user can not create thin LUN without thin
# provisioning enabler.
thinness = 'NonThin'
spec_id = 'storagetype:provisioning'
specs = self._get_volumetype_extraspecs(volume)
if specs and spec_id in specs:
provisioning = specs[spec_id].lower()
if 'thin' == provisioning:
thinness = 'Thin'
elif 'thick' != provisioning:
LOG.warning(_('Invalid value of extra spec '
'\'storagetype:provisioning\': %(provisioning)s')
% {'provisioning': specs[spec_id]})
else:
LOG.info(_('No extra spec \'storagetype:provisioning\' exist'))
return thinness