803
810
matches.append(entry)
814
class ZadaraBEDriver(ISCSIDriver):
815
"""Performs actions to configure Zadara BE module."""
817
def _is_vsa_volume(self, volume):
818
return volume_types.is_vsa_volume(volume['volume_type_id'])
820
def _is_vsa_drive(self, volume):
821
return volume_types.is_vsa_drive(volume['volume_type_id'])
823
def _not_vsa_volume_or_drive(self, volume):
824
"""Returns True if volume is not VSA BE volume."""
825
if not volume_types.is_vsa_object(volume['volume_type_id']):
826
LOG.debug(_("\tVolume %s is NOT VSA volume"), volume['name'])
831
def check_for_setup_error(self):
832
"""No setup necessary for Zadara BE."""
835
""" Volume Driver methods """
836
def create_volume(self, volume):
837
"""Creates BE volume."""
838
if self._not_vsa_volume_or_drive(volume):
839
return super(ZadaraBEDriver, self).create_volume(volume)
841
if self._is_vsa_volume(volume):
842
LOG.debug(_("\tFE VSA Volume %s creation - do nothing"),
846
if int(volume['size']) == 0:
847
sizestr = '0' # indicates full-partition
849
sizestr = '%s' % (int(volume['size']) << 30) # size in bytes
851
# Set the qos-str to default type sas
853
volume_type = volume_types.get_volume_type(None,
854
volume['volume_type_id'])
855
if volume_type is not None:
856
qosstr = volume_type['extra_specs']['drive_type'] + \
857
("_%s" % volume_type['extra_specs']['drive_size'])
860
for i in volume.get('volume_metadata'):
861
if i['key'] == 'to_vsa_id':
866
self._sync_exec('/var/lib/zadara/bin/zadara_sncfg',
869
'--pname', volume['name'],
874
except exception.ProcessExecutionError:
875
LOG.debug(_("VSA BE create_volume for %s failed"), volume['name'])
878
LOG.debug(_("VSA BE create_volume for %s succeeded"), volume['name'])
880
def delete_volume(self, volume):
881
"""Deletes BE volume."""
882
if self._not_vsa_volume_or_drive(volume):
883
return super(ZadaraBEDriver, self).delete_volume(volume)
885
if self._is_vsa_volume(volume):
886
LOG.debug(_("\tFE VSA Volume %s deletion - do nothing"),
891
self._sync_exec('/var/lib/zadara/bin/zadara_sncfg',
893
'--pname', volume['name'],
896
except exception.ProcessExecutionError:
897
LOG.debug(_("VSA BE delete_volume for %s failed"), volume['name'])
900
LOG.debug(_("VSA BE delete_volume for %s suceeded"), volume['name'])
902
def local_path(self, volume):
903
if self._not_vsa_volume_or_drive(volume):
904
return super(ZadaraBEDriver, self).local_path(volume)
906
if self._is_vsa_volume(volume):
907
LOG.debug(_("\tFE VSA Volume %s local path call - call discover"),
909
return super(ZadaraBEDriver, self).discover_volume(None, volume)
911
raise exception.Error(_("local_path not supported"))
913
def ensure_export(self, context, volume):
914
"""ensure BE export for a volume"""
915
if self._not_vsa_volume_or_drive(volume):
916
return super(ZadaraBEDriver, self).ensure_export(context, volume)
918
if self._is_vsa_volume(volume):
919
LOG.debug(_("\tFE VSA Volume %s ensure export - do nothing"),
924
iscsi_target = self.db.volume_get_iscsi_target_num(context,
926
except exception.NotFound:
927
LOG.info(_("Skipping ensure_export. No iscsi_target " +
928
"provisioned for volume: %d"), volume['id'])
932
ret = self._common_be_export(context, volume, iscsi_target)
933
except exception.ProcessExecutionError:
937
def create_export(self, context, volume):
938
"""create BE export for a volume"""
939
if self._not_vsa_volume_or_drive(volume):
940
return super(ZadaraBEDriver, self).create_export(context, volume)
942
if self._is_vsa_volume(volume):
943
LOG.debug(_("\tFE VSA Volume %s create export - do nothing"),
947
self._ensure_iscsi_targets(context, volume['host'])
948
iscsi_target = self.db.volume_allocate_iscsi_target(context,
952
ret = self._common_be_export(context, volume, iscsi_target)
954
raise exception.ProcessExecutionError
957
def remove_export(self, context, volume):
958
"""Removes BE export for a volume."""
959
if self._not_vsa_volume_or_drive(volume):
960
return super(ZadaraBEDriver, self).remove_export(context, volume)
962
if self._is_vsa_volume(volume):
963
LOG.debug(_("\tFE VSA Volume %s remove export - do nothing"),
968
iscsi_target = self.db.volume_get_iscsi_target_num(context,
970
except exception.NotFound:
971
LOG.info(_("Skipping remove_export. No iscsi_target " +
972
"provisioned for volume: %d"), volume['id'])
976
self._sync_exec('/var/lib/zadara/bin/zadara_sncfg',
978
'--pname', volume['name'],
979
'--tid', iscsi_target,
982
except exception.ProcessExecutionError:
983
LOG.debug(_("VSA BE remove_export for %s failed"), volume['name'])
986
def create_snapshot(self, snapshot):
987
"""Nothing required for snapshot"""
988
if self._not_vsa_volume_or_drive(volume):
989
return super(ZadaraBEDriver, self).create_snapshot(volume)
993
def delete_snapshot(self, snapshot):
994
"""Nothing required to delete a snapshot"""
995
if self._not_vsa_volume_or_drive(volume):
996
return super(ZadaraBEDriver, self).delete_snapshot(volume)
1000
""" Internal BE Volume methods """
1001
def _common_be_export(self, context, volume, iscsi_target):
1003
Common logic that asks zadara_sncfg to setup iSCSI target/lun for
1006
(out, err) = self._sync_exec(
1007
'/var/lib/zadara/bin/zadara_sncfg',
1009
'--pname', volume['name'],
1010
'--tid', iscsi_target,
1014
result_xml = ElementTree.fromstring(out)
1015
response_node = result_xml.find("Sn")
1016
if response_node is None:
1017
msg = "Malformed response from zadara_sncfg"
1018
raise exception.Error(msg)
1020
sn_ip = response_node.findtext("SnIp")
1021
sn_iqn = response_node.findtext("IqnName")
1022
iscsi_portal = sn_ip + ":3260," + ("%s" % iscsi_target)
1025
model_update['provider_location'] = ("%s %s" %
1030
def _get_qosgroup_summary(self):
1031
"""gets the list of qosgroups from Zadara BE"""
1033
(out, err) = self._sync_exec(
1034
'/var/lib/zadara/bin/zadara_sncfg',
1035
'get_qosgroups_xml',
1038
except exception.ProcessExecutionError:
1039
LOG.debug(_("Failed to retrieve QoS info"))
1043
result_xml = ElementTree.fromstring(out)
1044
for element in result_xml.findall('QosGroup'):
1046
# get the name of the group.
1047
# If we cannot find it, forget this element
1048
group_name = element.findtext("Name")
1052
# loop through all child nodes & fill up attributes of this group
1053
for child in element.getchildren():
1054
# two types of elements - property of qos-group & sub property
1055
# classify them accordingly
1057
qos_group[child.tag] = int(child.text) \
1058
if child.text.isdigit() else child.text
1061
for subchild in child.getchildren():
1062
subelement[subchild.tag] = int(subchild.text) \
1063
if subchild.text.isdigit() else subchild.text
1064
qos_group[child.tag] = subelement
1066
# Now add this group to the master qos_groups
1067
qos_groups[group_name] = qos_group
1071
def get_volume_stats(self, refresh=False):
1072
"""Return the current state of the volume service. If 'refresh' is
1073
True, run the update first."""
1075
drive_info = self._get_qosgroup_summary()
1076
return {'drive_qos_info': drive_info}