"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "cinder/volume/drivers/dell_emc/xtremio.py" between
cinder-15.5.0.tar.gz and cinder-15.6.0.tar.gz

About: OpenStack Cinder (Core Service: Block Storage) provides persistent block storage to running instances. Its pluggable driver architecture facilitates the creation and management of block storage devices.
The "Train" series (maintained release).

xtremio.py  (cinder-15.5.0):xtremio.py  (cinder-15.6.0)
skipping to change at line 34 skipping to change at line 34
1.0.3 - update logging level, add translation 1.0.3 - update logging level, add translation
1.0.4 - support for FC zones 1.0.4 - support for FC zones
1.0.5 - add support for XtremIO 4.0 1.0.5 - add support for XtremIO 4.0
1.0.6 - add support for iSCSI multipath, CA validation, consistency groups, 1.0.6 - add support for iSCSI multipath, CA validation, consistency groups,
R/O snapshots, CHAP discovery authentication R/O snapshots, CHAP discovery authentication
1.0.7 - cache glance images on the array 1.0.7 - cache glance images on the array
1.0.8 - support for volume retype, CG fixes 1.0.8 - support for volume retype, CG fixes
1.0.9 - performance improvements, support force detach, support for X2 1.0.9 - performance improvements, support force detach, support for X2
1.0.10 - option to clean unused IGs 1.0.10 - option to clean unused IGs
1.0.11 - add support for multiattach 1.0.11 - add support for multiattach
1.0.12 - add support for ports filtering
""" """
import json import json
import math import math
import random import random
import requests import requests
import string import string
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log as logging from oslo_log import log as logging
skipping to change at line 85 skipping to change at line 86
default=100, default=100,
help='Number of volumes created from each cached glance image'), help='Number of volumes created from each cached glance image'),
cfg.BoolOpt('xtremio_clean_unused_ig', cfg.BoolOpt('xtremio_clean_unused_ig',
default=False, default=False,
help='Should the driver remove initiator groups with no ' help='Should the driver remove initiator groups with no '
'volumes after the last connection was terminated. ' 'volumes after the last connection was terminated. '
'Since the behavior till now was to leave ' 'Since the behavior till now was to leave '
'the IG be, we default to False (not deleting IGs ' 'the IG be, we default to False (not deleting IGs '
'without connected volumes); setting this parameter ' 'without connected volumes); setting this parameter '
'to True will remove any IG after terminating its ' 'to True will remove any IG after terminating its '
'connection to the last volume.')] 'connection to the last volume.'),
cfg.ListOpt('xtremio_ports',
default=[],
help='Allowed ports. Comma separated list of XtremIO '
'iSCSI IPs or FC WWNs (ex. 58:cc:f0:98:49:22:07:02) '
'to be used. If option is not set all ports are allowed.')
]
CONF.register_opts(XTREMIO_OPTS, group=configuration.SHARED_CONF_GROUP) CONF.register_opts(XTREMIO_OPTS, group=configuration.SHARED_CONF_GROUP)
RANDOM = random.Random() RANDOM = random.Random()
OBJ_NOT_FOUND_ERR = 'obj_not_found' OBJ_NOT_FOUND_ERR = 'obj_not_found'
VOL_NOT_UNIQUE_ERR = 'vol_obj_name_not_unique' VOL_NOT_UNIQUE_ERR = 'vol_obj_name_not_unique'
VOL_OBJ_NOT_FOUND_ERR = 'vol_obj_not_found' VOL_OBJ_NOT_FOUND_ERR = 'vol_obj_not_found'
ALREADY_MAPPED_ERR = 'already_mapped' ALREADY_MAPPED_ERR = 'already_mapped'
SYSTEM_BUSY = 'system_is_busy' SYSTEM_BUSY = 'system_is_busy'
TOO_MANY_OBJECTS = 'too_many_objs' TOO_MANY_OBJECTS = 'too_many_objs'
skipping to change at line 414 skipping to change at line 421
port_address in port_addresses) port_address in port_addresses)
initiators = self.req('initiators', initiators = self.req('initiators',
data={'filter': init_filter, data={'filter': init_filter,
'full': 1, 'prop': 'ig-id'})['initiators'] 'full': 1, 'prop': 'ig-id'})['initiators']
return list(set(ig_id['ig-id'][XTREMIO_OID_INDEX] return list(set(ig_id['ig-id'][XTREMIO_OID_INDEX]
for ig_id in initiators)) for ig_id in initiators))
class XtremIOVolumeDriver(san.SanDriver): class XtremIOVolumeDriver(san.SanDriver):
"""Executes commands relating to Volumes.""" """Executes commands relating to Volumes."""
VERSION = '1.0.11' VERSION = '1.0.12'
# ThirdPartySystems wiki # ThirdPartySystems wiki
CI_WIKI_NAME = "EMC_XIO_CI" CI_WIKI_NAME = "EMC_XIO_CI"
driver_name = 'XtremIO' driver_name = 'XtremIO'
MIN_XMS_VERSION = [3, 0, 0] MIN_XMS_VERSION = [3, 0, 0]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(XtremIOVolumeDriver, self).__init__(*args, **kwargs) super(XtremIOVolumeDriver, self).__init__(*args, **kwargs)
self.configuration.append_config_values(XTREMIO_OPTS) self.configuration.append_config_values(XTREMIO_OPTS)
skipping to change at line 438 skipping to change at line 445
self.cluster_id = (self.configuration.safe_get('xtremio_cluster_name') self.cluster_id = (self.configuration.safe_get('xtremio_cluster_name')
or '') or '')
self.provisioning_factor = \ self.provisioning_factor = \
volume_utils.get_max_over_subscription_ratio( volume_utils.get_max_over_subscription_ratio(
self.configuration.max_over_subscription_ratio, self.configuration.max_over_subscription_ratio,
supports_auto=False) supports_auto=False)
self.clean_ig = (self.configuration.safe_get('xtremio_clean_unused_ig') self.clean_ig = (self.configuration.safe_get('xtremio_clean_unused_ig')
or False) or False)
self._stats = {} self._stats = {}
self.allowed_ports = [
port.strip().lower() for port in
self.configuration.safe_get('xtremio_ports')
]
self.client = XtremIOClient3(self.configuration, self.cluster_id) self.client = XtremIOClient3(self.configuration, self.cluster_id)
@staticmethod @staticmethod
def get_driver_options(): def get_driver_options():
return XTREMIO_OPTS return XTREMIO_OPTS
def _obj_from_result(self, res): def _obj_from_result(self, res):
typ, idx = res['links'][0]['href'].split('/')[-2:] typ, idx = res['links'][0]['href'].split('/')[-2:]
return self.client.req(typ, idx=int(idx))['content'] return self.client.req(typ, idx=int(idx))['content']
skipping to change at line 1053 skipping to change at line 1064
def _create_ig(self, name): def _create_ig(self, name):
# create an initiator group to hold the initiator # create an initiator group to hold the initiator
data = {'ig-name': name} data = {'ig-name': name}
self.client.req('initiator-groups', 'POST', data) self.client.req('initiator-groups', 'POST', data)
try: try:
return self.client.req('initiator-groups', name=name)['content'] return self.client.req('initiator-groups', name=name)['content']
except exception.NotFound: except exception.NotFound:
raise (exception.VolumeBackendAPIException raise (exception.VolumeBackendAPIException
(data=_("Failed to create IG, %s") % name)) (data=_("Failed to create IG, %s") % name))
def _port_is_allowed(self, port):
"""Check if port is in allowed ports list.
If allowed ports are empty then all ports are allowed.
:param port: iSCSI IP/FC WWN to check
:return: is port allowed
"""
if not self.allowed_ports:
return True
return port.lower() in self.allowed_ports
@interface.volumedriver @interface.volumedriver
class XtremIOISCSIDriver(XtremIOVolumeDriver, driver.ISCSIDriver): class XtremIOISCSIDriver(XtremIOVolumeDriver, driver.ISCSIDriver):
"""Executes commands relating to ISCSI volumes. """Executes commands relating to ISCSI volumes.
We make use of model provider properties as follows: We make use of model provider properties as follows:
``provider_location`` ``provider_location``
if present, contains the iSCSI target information in the same if present, contains the iSCSI target information in the same
format as an ietadm discovery format as an ietadm discovery
i.e. '<ip>:<port>,<portal> <target IQN>' i.e. '<ip>:<port>,<portal> <target IQN>'
skipping to change at line 1169 skipping to change at line 1193
:volume_id: the id of the volume (currently used by xen) :volume_id: the id of the volume (currently used by xen)
:auth_method:, :auth_username:, :auth_password: :auth_method:, :auth_username:, :auth_password:
the authentication details. Right now, either auth_method is not the authentication details. Right now, either auth_method is not
present meaning no authentication, or auth_method == `CHAP` present meaning no authentication, or auth_method == `CHAP`
meaning use CHAP with the specified credentials. meaning use CHAP with the specified credentials.
multiple connection return multiple connection return
:target_iqns, :target_portals, :target_luns, which contain lists of :target_iqns, :target_portals, :target_luns, which contain lists of
multiple values. The main portal information is also returned in multiple values. The main portal information is also returned in
:target_iqn, :target_portal, :target_lun for backward compatibility. :target_iqn, :target_portal, :target_lun for backward compatibility.
""" """
portals = self.client.get_iscsi_portals() iscsi_portals = self.client.get_iscsi_portals()
if not portals: allowed_portals = []
msg = _("XtremIO not configured correctly, no iscsi portals found") for iscsi_portal in iscsi_portals:
LOG.error(msg) iscsi_portal['ip-addr'] = iscsi_portal['ip-addr'].split('/')[0]
raise exception.VolumeDriverException(message=msg) if self._port_is_allowed(iscsi_portal['ip-addr']):
portal = RANDOM.choice(portals) allowed_portals.append(iscsi_portal)
if not allowed_portals:
msg = _("There are no accessible iSCSI targets on the "
"system.")
raise exception.VolumeBackendAPIException(data=msg)
portal = RANDOM.choice(allowed_portals)
portal_addr = ('%(ip)s:%(port)d' % portal_addr = ('%(ip)s:%(port)d' %
{'ip': portal['ip-addr'].split('/')[0], {'ip': portal['ip-addr'],
'port': portal['ip-port']}) 'port': portal['ip-port']})
tg_portals = ['%(ip)s:%(port)d' % {'ip': p['ip-addr'].split('/')[0], tg_portals = ['%(ip)s:%(port)d' % {'ip': p['ip-addr'],
'port': p['ip-port']} 'port': p['ip-port']}
for p in portals] for p in allowed_portals]
properties = {'target_discovered': False, properties = {'target_discovered': False,
'target_iqn': portal['port-address'], 'target_iqn': portal['port-address'],
'target_lun': lunmap['lun'], 'target_lun': lunmap['lun'],
'target_portal': portal_addr, 'target_portal': portal_addr,
'target_iqns': [p['port-address'] for p in portals], 'target_iqns': [
p['port-address'] for p in allowed_portals
],
'target_portals': tg_portals, 'target_portals': tg_portals,
'target_luns': [lunmap['lun']] * len(portals)} 'target_luns': [lunmap['lun']] * len(allowed_portals)}
return properties return properties
def _get_initiator_names(self, connector): def _get_initiator_names(self, connector):
return [connector['initiator']] return [connector['initiator']]
def _get_ig_name(self, connector): def _get_ig_name(self, connector):
return connector['initiator'] return connector['initiator']
@interface.volumedriver @interface.volumedriver
class XtremIOFCDriver(XtremIOVolumeDriver, class XtremIOFCDriver(XtremIOVolumeDriver,
skipping to change at line 1210 skipping to change at line 1241
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(XtremIOFCDriver, self).__init__(*args, **kwargs) super(XtremIOFCDriver, self).__init__(*args, **kwargs)
self.protocol = 'FC' self.protocol = 'FC'
self._targets = None self._targets = None
def get_targets(self): def get_targets(self):
if not self._targets: if not self._targets:
try: try:
targets = self.client.get_fc_up_ports() targets = self.client.get_fc_up_ports()
self._targets = [target['port-address'].replace(':', '') allowed_targets = []
for target in targets] for target in targets:
if self._port_is_allowed(target['port-address']):
allowed_targets.append(
target['port-address'].replace(':', '')
)
if not allowed_targets:
msg = _("There are no accessible Fibre Channel targets "
"on the system.")
raise exception.VolumeBackendAPIException(data=msg)
self._targets = allowed_targets
except exception.NotFound: except exception.NotFound:
raise (exception.VolumeBackendAPIException raise (exception.VolumeBackendAPIException
(data=_("Failed to get targets"))) (data=_("Failed to get targets")))
return self._targets return self._targets
def _get_free_lun(self, igs): def _get_free_lun(self, igs):
luns = [] luns = []
for ig in igs: for ig in igs:
luns.extend(lm['lun'] for lm in luns.extend(lm['lun'] for lm in
self.client.req('lun-maps', self.client.req('lun-maps',
 End of changes. 12 change blocks. 
15 lines changed or deleted 55 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)