147
149
def check_for_setup_error(self):
148
"""Returns an error if prerequisites aren't met"""
150
"""Returns an error if prerequisites aren't met."""
149
151
if not self.run_local:
150
152
if not (FLAGS.san_password or FLAGS.san_private_key):
151
raise exception.Error(_('Specify san_password or '
153
raise exception.NovaException(_('Specify san_password or '
152
154
'san_private_key'))
154
156
# The san_ip must always be set, because we use it for the target
155
157
if not (FLAGS.san_ip):
156
raise exception.Error(_("san_ip must be set"))
158
raise exception.NovaException(_("san_ip must be set"))
159
161
def _collect_lines(data):
452
455
LOG.debug(_("CLIQ command returned %s"), out)
454
result_xml = ElementTree.fromstring(out)
457
result_xml = etree.fromstring(out)
455
458
if check_cliq_result:
456
459
response_node = result_xml.find("response")
457
460
if response_node is None:
458
461
msg = (_("Malformed response to CLIQ command "
459
462
"%(verb)s %(cliq_args)s. Result=%(out)s") %
461
raise exception.Error(msg)
464
raise exception.NovaException(msg)
463
466
result_code = response_node.attrib.get("result")
592
603
def local_path(self, volume):
593
604
# TODO(justinsb): Is this needed here?
594
raise exception.Error(_("local_path not supported"))
596
def ensure_export(self, context, volume):
597
"""Synchronously recreates an export for a logical volume."""
598
return self._do_export(context, volume, force_create=False)
600
def create_export(self, context, volume):
601
return self._do_export(context, volume, force_create=True)
603
def _do_export(self, context, volume, force_create):
604
"""Supports ensure_export and create_export"""
605
volume_info = self._cliq_get_volume_info(volume['name'])
607
is_shared = 'permission.authGroup' in volume_info
611
should_export = False
613
if force_create or not is_shared:
615
# Check that we have a project_id
616
project_id = volume['project_id']
618
project_id = context.project_id
621
#TODO(justinsb): Use a real per-project password here
622
chap_username = 'proj_' + project_id
623
# HP/Lefthand requires that the password be >= 12 characters
624
chap_password = 'project_secret_' + project_id
626
msg = (_("Could not determine project for volume %s, "
630
raise exception.Error(msg)
633
should_export = False
637
cliq_args['volumeName'] = volume['name']
638
cliq_args['chapName'] = chap_username
639
cliq_args['targetSecret'] = chap_password
641
self._cliq_run_xml("assignVolumeChap", cliq_args)
643
model_update['provider_auth'] = ("CHAP %s %s" %
644
(chap_username, chap_password))
648
def remove_export(self, context, volume):
649
"""Removes an export for a logical volume."""
651
cliq_args['volumeName'] = volume['name']
653
self._cliq_run_xml("unassignVolume", cliq_args)
605
raise exception.NovaException(_("local_path not supported"))
607
def initialize_connection(self, volume, connector):
608
"""Assigns the volume to a server.
610
Assign any created volume to a compute node/host so that it can be
611
used from that host. HP VSA requires a volume to be assigned
614
This driver returns a driver_volume_type of 'iscsi'.
615
The format of the driver data is defined in _get_iscsi_properties.
616
Example return value::
619
'driver_volume_type': 'iscsi'
621
'target_discovered': True,
622
'target_iqn': 'iqn.2010-10.org.openstack:volume-00000001',
623
'target_portal': '127.0.0.0.1:3260',
630
cliq_args['volumeName'] = volume['name']
631
cliq_args['serverName'] = connector['host']
632
self._cliq_run_xml("assignVolumeToServer", cliq_args)
634
iscsi_properties = self._get_iscsi_properties(volume)
636
'driver_volume_type': 'iscsi',
637
'data': iscsi_properties
640
def terminate_connection(self, volume, connector):
641
"""Unassign the volume from the host."""
643
cliq_args['volumeName'] = volume['name']
644
cliq_args['serverName'] = connector['host']
645
self._cliq_run_xml("unassignVolumeToServer", cliq_args)
656
648
class SolidFireSanISCSIDriver(SanISCSIDriver):