269 """Abstract base class for common COMSTAR operations.""" |
270 """Abstract base class for common COMSTAR operations.""" |
270 __metaclass__ = abc.ABCMeta |
271 __metaclass__ = abc.ABCMeta |
271 |
272 |
272 def __init__(self, *args, **kwargs): |
273 def __init__(self, *args, **kwargs): |
273 super(STMFDriver, self).__init__(*args, **kwargs) |
274 super(STMFDriver, self).__init__(*args, **kwargs) |
|
275 |
|
276 def _stmf_execute(self, *cmd): |
|
277 """Handle the possible race during the local execution.""" |
|
278 tries = 0 |
|
279 while True: |
|
280 try: |
|
281 self._execute(*cmd) |
|
282 return |
|
283 except processutils.ProcessExecutionError as ex: |
|
284 tries = tries + 1 |
|
285 |
|
286 if tries >= self.configuration.num_shell_tries or \ |
|
287 'resource busy' not in ex.stderr: |
|
288 raise |
|
289 |
|
290 time.sleep(tries ** 2) |
274 |
291 |
275 def _check_target(self, target, protocol): |
292 def _check_target(self, target, protocol): |
276 """Verify if the target exists.""" |
293 """Verify if the target exists.""" |
277 (out, _err) = self._execute('/usr/sbin/stmfadm', 'list-target') |
294 (out, _err) = self._execute('/usr/sbin/stmfadm', 'list-target') |
278 |
295 |
381 def create_export(self, context, volume): |
398 def create_export(self, context, volume): |
382 """Export the volume.""" |
399 """Export the volume.""" |
383 zvol = self._get_zvol_path(volume) |
400 zvol = self._get_zvol_path(volume) |
384 |
401 |
385 # Create a Logical Unit (LU) |
402 # Create a Logical Unit (LU) |
386 self._execute('/usr/sbin/stmfadm', 'create-lu', zvol) |
403 self._stmf_execute('/usr/sbin/stmfadm', 'create-lu', zvol) |
387 luid = self._get_luid(volume) |
404 luid = self._get_luid(volume) |
388 if not luid: |
405 if not luid: |
389 msg = (_("Failed to create LU for volume '%s'") |
406 msg = (_("Failed to create LU for volume '%s'") |
390 % volume['name']) |
407 % volume['name']) |
391 raise exception.VolumeBackendAPIException(data=msg) |
408 raise exception.VolumeBackendAPIException(data=msg) |
392 |
409 |
393 # Create a target group and a target belonging to the target group |
410 # Create a target group and a target belonging to the target group |
394 target_group = 'tg-%s' % volume['name'] |
411 target_group = 'tg-%s' % volume['name'] |
395 self._execute('/usr/sbin/stmfadm', 'create-tg', target_group) |
412 self._stmf_execute('/usr/sbin/stmfadm', 'create-tg', target_group) |
396 |
413 |
397 target_name = '%s%s' % (self.configuration.iscsi_target_prefix, |
414 target_name = '%s%s' % (self.configuration.iscsi_target_prefix, |
398 volume['name']) |
415 volume['name']) |
399 self._execute('/usr/sbin/stmfadm', 'add-tg-member', '-g', |
416 self._stmf_execute('/usr/sbin/stmfadm', 'add-tg-member', '-g', |
400 target_group, target_name) |
417 target_group, target_name) |
401 |
418 |
402 self._execute('/usr/sbin/itadm', 'create-target', '-n', target_name) |
419 self._stmf_execute('/usr/sbin/itadm', 'create-target', '-n', |
|
420 target_name) |
403 assert self._check_target(target_name, 'iSCSI') |
421 assert self._check_target(target_name, 'iSCSI') |
404 |
422 |
405 # Add a view entry to the logical unit with the specified LUN, 8776 |
423 # Add a view entry to the logical unit with the specified LUN, 8776 |
406 if luid is not None: |
424 if luid is not None: |
407 self._execute('/usr/sbin/stmfadm', 'add-view', '-n', 8776, '-t', |
425 self._stmf_execute('/usr/sbin/stmfadm', 'add-view', '-n', 8776, |
408 target_group, luid) |
426 '-t', target_group, luid) |
409 |
427 |
410 def remove_export(self, context, volume): |
428 def remove_export(self, context, volume): |
411 """Remove an export for a volume. |
429 """Remove an export for a volume. |
412 |
430 |
413 All of the related elements about the volume, including the |
431 All of the related elements about the volume, including the |
420 |
438 |
421 # Remove the view entry |
439 # Remove the view entry |
422 if luid is not None: |
440 if luid is not None: |
423 view_lun = self._get_view_and_lun(luid) |
441 view_lun = self._get_view_and_lun(luid) |
424 if view_lun['view']: |
442 if view_lun['view']: |
425 self._execute('/usr/sbin/stmfadm', 'remove-view', '-l', |
443 self._stmf_execute('/usr/sbin/stmfadm', 'remove-view', '-l', |
426 luid, view_lun['view']) |
444 luid, view_lun['view']) |
427 |
445 |
428 # Remove the target and its target group |
446 # Remove the target and its target group |
429 if self._check_target(target_name, 'iSCSI'): |
447 if self._check_target(target_name, 'iSCSI'): |
430 self._execute('/usr/sbin/stmfadm', 'offline-target', target_name) |
448 self._stmf_execute('/usr/sbin/stmfadm', 'offline-target', |
431 self._execute('/usr/sbin/itadm', 'delete-target', '-f', |
449 target_name) |
432 target_name) |
450 self._stmf_execute('/usr/sbin/itadm', 'delete-target', '-f', |
|
451 target_name) |
433 |
452 |
434 if self._check_tg(target_group): |
453 if self._check_tg(target_group): |
435 self._execute('/usr/sbin/stmfadm', 'delete-tg', target_group) |
454 self._stmf_execute('/usr/sbin/stmfadm', 'delete-tg', target_group) |
436 |
455 |
437 # Remove the LU |
456 # Remove the LU |
438 if luid is not None: |
457 if luid is not None: |
439 self._execute('/usr/sbin/stmfadm', 'delete-lu', luid) |
458 self._stmf_execute('/usr/sbin/stmfadm', 'delete-lu', luid) |
440 |
459 |
441 def _get_iscsi_properties(self, volume): |
460 def _get_iscsi_properties(self, volume): |
442 """Get iSCSI configuration |
461 """Get iSCSI configuration |
443 |
462 |
444 Now we use the discovery address as the default approach to add |
463 Now we use the discovery address as the default approach to add |
469 properties['target_iqn'] = target_name |
488 properties['target_iqn'] = target_name |
470 properties['target_portal'] = ('%s:%d' % |
489 properties['target_portal'] = ('%s:%d' % |
471 (self.configuration.iscsi_ip_address, |
490 (self.configuration.iscsi_ip_address, |
472 self.configuration.iscsi_port)) |
491 self.configuration.iscsi_port)) |
473 view_lun = self._get_view_and_lun(luid) |
492 view_lun = self._get_view_and_lun(luid) |
474 if view_lun['lun']: |
493 if view_lun['lun'] is not None: |
475 properties['target_lun'] = view_lun['lun'] |
494 properties['target_lun'] = view_lun['lun'] |
476 properties['volume_id'] = volume['id'] |
495 properties['volume_id'] = volume['id'] |
477 |
496 |
478 auth = volume['provider_auth'] |
497 auth = volume['provider_auth'] |
479 if auth: |
498 if auth: |
604 def create_export(self, context, volume): |
623 def create_export(self, context, volume): |
605 """Export the volume.""" |
624 """Export the volume.""" |
606 zvol = self._get_zvol_path(volume) |
625 zvol = self._get_zvol_path(volume) |
607 |
626 |
608 # Create a Logical Unit (LU) |
627 # Create a Logical Unit (LU) |
609 self._execute('/usr/sbin/stmfadm', 'create-lu', zvol) |
628 self._stmf_execute('/usr/sbin/stmfadm', 'create-lu', zvol) |
610 luid = self._get_luid(volume) |
629 luid = self._get_luid(volume) |
611 if not luid: |
630 if not luid: |
612 msg = (_("Failed to create logic unit for volume '%s'") |
631 msg = (_("Failed to create logic unit for volume '%s'") |
613 % volume['name']) |
632 % volume['name']) |
614 raise exception.VolumeBackendAPIException(data=msg) |
633 raise exception.VolumeBackendAPIException(data=msg) |
624 "into the expected target group '%s'.") % |
643 "into the expected target group '%s'.") % |
625 (wwn, target_group)) |
644 (wwn, target_group)) |
626 raise exception.VolumeBackendAPIException(data=msg) |
645 raise exception.VolumeBackendAPIException(data=msg) |
627 |
646 |
628 # Create a target group for the wwn |
647 # Create a target group for the wwn |
629 self._execute('/usr/sbin/stmfadm', 'create-tg', target_group) |
648 self._stmf_execute('/usr/sbin/stmfadm', 'create-tg', target_group) |
630 |
649 |
631 # Enable the target and add it to the 'tg-wwn-xxx' group |
650 # Enable the target and add it to the 'tg-wwn-xxx' group |
632 self._execute('/usr/sbin/stmfadm', 'offline-target', |
651 self._stmf_execute('/usr/sbin/stmfadm', 'offline-target', |
633 'wwn.%s' % wwn) |
652 'wwn.%s' % wwn) |
634 self._execute('/usr/sbin/stmfadm', 'add-tg-member', '-g', |
653 self._stmf_execute('/usr/sbin/stmfadm', 'add-tg-member', '-g', |
635 target_group, 'wwn.%s' % wwn) |
654 target_group, 'wwn.%s' % wwn) |
636 self._execute('/usr/sbin/stmfadm', 'online-target', 'wwn.%s' % wwn) |
655 self._stmf_execute('/usr/sbin/stmfadm', 'online-target', |
|
656 'wwn.%s' % wwn) |
637 assert self._target_in_tg(wwn, target_group) |
657 assert self._target_in_tg(wwn, target_group) |
638 |
658 |
639 # Add a logical unit view entry |
659 # Add a logical unit view entry |
640 # TODO(Strony): replace the auto assigned LUN with '-n' option |
660 # TODO(Strony): replace the auto assigned LUN with '-n' option |
641 if luid is not None: |
661 if luid is not None: |
642 self._execute('/usr/sbin/stmfadm', 'add-view', '-t', |
662 self._stmf_execute('/usr/sbin/stmfadm', 'add-view', '-t', |
643 target_group, luid) |
663 target_group, luid) |
644 |
664 |
645 def remove_export(self, context, volume): |
665 def remove_export(self, context, volume): |
646 """Remove an export for a volume.""" |
666 """Remove an export for a volume.""" |
647 luid = self._get_luid(volume) |
667 luid = self._get_luid(volume) |
648 |
668 |
651 wwn = wwns[0] |
671 wwn = wwns[0] |
652 target_wwn = 'wwn.%s' % wwn |
672 target_wwn = 'wwn.%s' % wwn |
653 target_group = 'tg-wwn-%s' % wwn |
673 target_group = 'tg-wwn-%s' % wwn |
654 view_lun = self._get_view_and_lun(luid) |
674 view_lun = self._get_view_and_lun(luid) |
655 if view_lun['view']: |
675 if view_lun['view']: |
656 self._execute('/usr/sbin/stmfadm', 'remove-view', '-l', |
676 self._stmf_execute('/usr/sbin/stmfadm', 'remove-view', '-l', |
657 luid, view_lun['view']) |
677 luid, view_lun['view']) |
658 |
678 |
659 # Remove the target group when only one LU exists. |
679 # Remove the target group when only one LU exists. |
660 if self._only_lu(luid): |
680 if self._only_lu(luid): |
661 if self._check_target(target_wwn, 'Channel'): |
681 if self._check_target(target_wwn, 'Channel'): |
662 self._execute('/usr/sbin/stmfadm', 'offline-target', |
682 self._stmf_execute('/usr/sbin/stmfadm', 'offline-target', |
663 target_wwn) |
683 target_wwn) |
664 if self._check_tg(target_group): |
684 if self._check_tg(target_group): |
665 self._execute('/usr/sbin/stmfadm', 'delete-tg', |
685 self._stmf_execute('/usr/sbin/stmfadm', 'delete-tg', |
666 target_group) |
686 target_group) |
667 |
687 |
668 # Remove the LU |
688 # Remove the LU |
669 self._execute('/usr/sbin/stmfadm', 'delete-lu', luid) |
689 self._stmf_execute('/usr/sbin/stmfadm', 'delete-lu', luid) |
670 |
690 |
671 def _get_fc_properties(self, volume): |
691 def _get_fc_properties(self, volume): |
672 """Get Fibre Channel configuration. |
692 """Get Fibre Channel configuration. |
673 |
693 |
674 :target_discovered: boolean indicating whether discovery was used |
694 :target_discovered: boolean indicating whether discovery was used |
691 properties = {} |
711 properties = {} |
692 |
712 |
693 properties['target_discovered'] = True |
713 properties['target_discovered'] = True |
694 properties['target_wwn'] = wwns |
714 properties['target_wwn'] = wwns |
695 view_lun = self._get_view_and_lun(luid) |
715 view_lun = self._get_view_and_lun(luid) |
696 if view_lun['lun']: |
716 if view_lun['lun'] is not None: |
697 properties['target_lun'] = view_lun['lun'] |
717 properties['target_lun'] = view_lun['lun'] |
698 return properties |
718 return properties |
699 |
719 |
700 def initialize_connection(self, volume, connector): |
720 def initialize_connection(self, volume, connector): |
701 """Initializes the connection and returns connection info. |
721 """Initializes the connection and returns connection info. |