components/openstack/cinder/files/solaris/zfs.py
changeset 2162 0fee3eccf153
parent 1944 56ac2df1785b
child 3998 5bd484384122
equal deleted inserted replaced
2161:1848847f6fbf 2162:0fee3eccf153
    19 Drivers for Solaris ZFS operations in local and iSCSI modes
    19 Drivers for Solaris ZFS operations in local and iSCSI modes
    20 """
    20 """
    21 
    21 
    22 import abc
    22 import abc
    23 import os
    23 import os
       
    24 import time
    24 
    25 
    25 from oslo.config import cfg
    26 from oslo.config import cfg
    26 
    27 
    27 from cinder import exception
    28 from cinder import exception
    28 from cinder.image import image_utils
    29 from cinder.image import image_utils
   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.