components/openstack/cinder/files/solaris/zfs.py
branchs11u3-sru
changeset 7787 26bcbec7afce
parent 6035 c9748fcc32de
equal deleted inserted replaced
7784:531789214c7c 7787:26bcbec7afce
     1 # vim: tabstop=4 shiftwidth=4 softtabstop=4
     1 # vim: tabstop=4 shiftwidth=4 softtabstop=4
     2 # Copyright (c) 2012 OpenStack LLC.
     2 # Copyright (c) 2012 OpenStack LLC.
     3 # All Rights Reserved.
     3 # All Rights Reserved.
     4 #
     4 #
     5 # Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
     5 # Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
     6 #
     6 #
     7 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
     7 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
     8 #    not use this file except in compliance with the License. You may obtain
     8 #    not use this file except in compliance with the License. You may obtain
     9 #    a copy of the License at
     9 #    a copy of the License at
    10 #
    10 #
   963                   'zfs_volume_base': self.configuration.zfs_volume_base,
   963                   'zfs_volume_base': self.configuration.zfs_volume_base,
   964                   'san_info': san_info})
   964                   'san_info': san_info})
   965 
   965 
   966         return status
   966         return status
   967 
   967 
   968     def check_for_setup_error(self):
   968     def do_setup(self, context):
   969         """Check the setup error."""
   969         """Check wwns and setup the target group."""
   970         wwns = self._get_wwns()
   970         self.wwns = self._get_wwns()
   971         if not wwns:
   971         if not self.wwns:
   972             msg = (_("Could not determine fibre channel world wide "
   972             msg = (_("Could not determine fibre channel world wide "
   973                      "node names."))
   973                      "node names."))
   974             raise exception.VolumeBackendAPIException(data=msg)
   974             raise exception.VolumeBackendAPIException(data=msg)
       
   975 
       
   976         self.tg = 'tg-wwn-%s' % self.wwns[0]
       
   977         if not self._check_tg(self.tg):
       
   978             self._setup_tg(self.tg)
   975 
   979 
   976     def _get_wwns(self):
   980     def _get_wwns(self):
   977         """Get the FC port WWNs of the host."""
   981         """Get the FC port WWNs of the host."""
   978         (out, _err) = self._execute('/usr/sbin/fcinfo', 'hba-port', '-t')
   982         (out, _err) = self._execute('/usr/sbin/fcinfo', 'hba-port', '-t')
   979 
   983 
   984                 LOG.debug(_("Got the FC port WWN '%s'") % wwn)
   988                 LOG.debug(_("Got the FC port WWN '%s'") % wwn)
   985                 wwns.append(wwn)
   989                 wwns.append(wwn)
   986 
   990 
   987         return wwns
   991         return wwns
   988 
   992 
   989     def _check_wwn_tg(self, wwn):
   993     def _get_target_wwns(self, tg):
   990         """Check if the target group 'tg-wwn-xxx' exists."""
   994         """Get the target members in the tg."""
   991         (out, _err) = self._execute('/usr/sbin/stmfadm', 'list-tg')
   995         (out, _err) = self._execute('/usr/sbin/stmfadm', 'list-tg',
   992 
   996                                     '-v', tg)
       
   997 
       
   998         wwns = []
   993         for line in [l.strip() for l in out.splitlines()]:
   999         for line in [l.strip() for l in out.splitlines()]:
   994             if line.startswith("Target Group:") and wwn in line:
  1000             if line.startswith("Member:"):
   995                 tg = line.split()[-1]
  1001                 wwn = line.split()[-1]
   996                 break
  1002                 target_wwn = wwn.split('.')[-1]
   997         else:
  1003                 wwns.append(target_wwn)
   998             LOG.debug(_("The target group 'tg-wwn-%s' doesn't exist.") % wwn)
  1004         return wwns
   999             tg = None
  1005 
  1000 
  1006     def _setup_tg(self, tg):
  1001         return tg
  1007         """Setup the target group."""
       
  1008         self._stmf_execute('/usr/sbin/stmfadm', 'create-tg', tg)
       
  1009 
       
  1010         # Add free target wwns into the target group
       
  1011         for wwn in self.wwns:
       
  1012             if not self._target_in_tg(wwn, None):
       
  1013                 target_wwn = 'wwn.%s' % wwn
       
  1014                 try:
       
  1015                     self._stmf_execute('/usr/sbin/stmfadm', 'offline-target',
       
  1016                                        target_wwn)
       
  1017                     self._stmf_execute('/usr/sbin/stmfadm', 'add-tg-member',
       
  1018                                        '-g', tg, target_wwn)
       
  1019                     self._stmf_execute('/usr/sbin/stmfadm', 'online-target',
       
  1020                                        target_wwn)
       
  1021                     assert self._check_target(wwn, 'Channel') == 'Online'
       
  1022 
       
  1023                 except:
       
  1024                     LOG.error(_LE("Failed to add and online the target '%s'.")
       
  1025                               % (target_wwn))
       
  1026 
       
  1027         target_wwns = self._get_target_wwns(tg)
       
  1028         if not target_wwns:
       
  1029             msg = (_("No target members exist in the target group '%s'.")
       
  1030                    % tg)
       
  1031             raise exception.VolumeBackendAPIException(data=msg)
  1002 
  1032 
  1003     def _only_lu(self, lu):
  1033     def _only_lu(self, lu):
  1004         """Check if the LU is the only one."""
  1034         """Check if the LU is the only one."""
  1005         (out, _err) = self._execute('/usr/sbin/stmfadm', 'list-lu', '-v')
  1035         (out, _err) = self._execute('/usr/sbin/stmfadm', 'list-lu', '-v')
  1006         linecount = 0
  1036         linecount = 0
  1023         if tg is not None:
  1053         if tg is not None:
  1024             (out, _err) = self._execute('/usr/sbin/stmfadm', 'list-tg',
  1054             (out, _err) = self._execute('/usr/sbin/stmfadm', 'list-tg',
  1025                                         '-v', tg)
  1055                                         '-v', tg)
  1026         else:
  1056         else:
  1027             (out, _err) = self._execute('/usr/sbin/stmfadm', 'list-tg', '-v')
  1057             (out, _err) = self._execute('/usr/sbin/stmfadm', 'list-tg', '-v')
  1028 
       
  1029         for line in [l.strip() for l in out.splitlines()]:
  1058         for line in [l.strip() for l in out.splitlines()]:
  1030             if line.startswith("Member:") and target in line:
  1059             if line.startswith("Member:") and target in line:
  1031                 return True
  1060                 return True
  1032         LOG.debug(_("The target '%s' is not in any target group.") % target)
  1061         LOG.debug(_("The target '%s' is not in %s target group.") %
       
  1062                   (target, tg if tg else 'any'))
  1033         return False
  1063         return False
       
  1064 
       
  1065     def _force_lip_wwn(self):
       
  1066         """Force the link to reinitialize."""
       
  1067         target_wwns = self._get_target_wwns(self.tg)
       
  1068         for target_wwn in target_wwns:
       
  1069             self._stmf_execute('/usr/sbin/fcadm', 'force-lip', target_wwn)
  1034 
  1070 
  1035     def create_export(self, context, volume):
  1071     def create_export(self, context, volume):
  1036         """Export the volume."""
  1072         """Export the volume."""
  1037         # If the volume is already exported there is nothing to do, as we
  1073         # If the volume is already exported there is nothing to do, as we
  1038         # simply export volumes and they are universally available.
  1074         # simply export volumes and they are universally available.
  1045                 msg = (_("Failed to create logical unit for volume '%s' due "
  1081                 msg = (_("Failed to create logical unit for volume '%s' due "
  1046                          "to an existing LU id but no view.") % volume['name'])
  1082                          "to an existing LU id but no view.") % volume['name'])
  1047                 raise exception.VolumeBackendAPIException(data=msg)
  1083                 raise exception.VolumeBackendAPIException(data=msg)
  1048 
  1084 
  1049         zvol = self._get_zvol_path(volume)
  1085         zvol = self._get_zvol_path(volume)
  1050 
       
  1051         # Create a Logical Unit (LU)
  1086         # Create a Logical Unit (LU)
  1052         self._stmf_execute('/usr/sbin/stmfadm', 'create-lu', zvol)
  1087         self._stmf_execute('/usr/sbin/stmfadm', 'create-lu', zvol)
  1053         luid = self._get_luid(volume)
  1088         luid = self._get_luid(volume)
  1054         if not luid:
  1089         if not luid:
  1055             msg = (_("Failed to create logic unit for volume '%s'")
  1090             msg = (_("Failed to create logic unit for volume '%s'")
  1056                    % volume['name'])
  1091                    % volume['name'])
  1057             raise exception.VolumeBackendAPIException(data=msg)
  1092             raise exception.VolumeBackendAPIException(data=msg)
  1058 
  1093 
  1059         wwns = self._get_wwns()
  1094         # setup the target group if it doesn't exist.
  1060         wwn = wwns[0]
  1095         if not self._check_tg(self.tg):
  1061         target_group = self._check_wwn_tg(wwn)
  1096             self._setup_tg(self.tg)
  1062         if target_group is None:
       
  1063             target_group = 'tg-wwn-%s' % wwn
       
  1064             if self._target_in_tg(wwn, None):
       
  1065                 msg = (_("Target WWN '%s' has been found in another"
       
  1066                          "target group, so it will not be added "
       
  1067                          "into the expected target group '%s'.") %
       
  1068                        (wwn, target_group))
       
  1069                 raise exception.VolumeBackendAPIException(data=msg)
       
  1070 
       
  1071             # Create a target group for the wwn
       
  1072             self._stmf_execute('/usr/sbin/stmfadm', 'create-tg', target_group)
       
  1073 
       
  1074             # Enable the target and add it to the 'tg-wwn-xxx' group
       
  1075             self._stmf_execute('/usr/sbin/stmfadm', 'offline-target',
       
  1076                                'wwn.%s' % wwn)
       
  1077             self._stmf_execute('/usr/sbin/stmfadm', 'add-tg-member', '-g',
       
  1078                                target_group, 'wwn.%s' % wwn)
       
  1079 
       
  1080         # Add a logical unit view entry
  1097         # Add a logical unit view entry
  1081         # TODO(Strony): replace the auto assigned LUN with '-n' option
  1098         self._stmf_execute('/usr/sbin/stmfadm', 'add-view', '-t',
  1082         if luid is not None:
  1099                            self.tg, luid)
  1083             self._stmf_execute('/usr/sbin/stmfadm', 'add-view', '-t',
  1100         self._force_lip_wwn()
  1084                                target_group, luid)
       
  1085             self._stmf_execute('/usr/sbin/stmfadm', 'online-target',
       
  1086                                'wwn.%s' % wwn)
       
  1087         assert self._target_in_tg(wwn, target_group)
       
  1088 
  1101 
  1089     def remove_export(self, context, volume):
  1102     def remove_export(self, context, volume):
  1090         """Remove an export for a volume."""
  1103         """Remove an export for a volume."""
  1091         luid = self._get_luid(volume)
  1104         luid = self._get_luid(volume)
  1092 
  1105 
  1093         if luid is not None:
  1106         if luid is not None:
  1094             wwns = self._get_wwns()
  1107             target_group = self.tg
  1095             wwn = wwns[0]
       
  1096             target_wwn = 'wwn.%s' % wwn
       
  1097             target_group = 'tg-wwn-%s' % wwn
       
  1098             view_lun = self._get_view_and_lun(luid)
  1108             view_lun = self._get_view_and_lun(luid)
  1099             if view_lun['view']:
  1109             if view_lun['view']:
  1100                 self._stmf_execute('/usr/sbin/stmfadm', 'remove-view', '-l',
  1110                 self._stmf_execute('/usr/sbin/stmfadm', 'remove-view', '-l',
  1101                                    luid, view_lun['view'])
  1111                                    luid, view_lun['view'])
  1102 
  1112 
  1103             # Remove the target group when only one LU exists.
  1113             # Remove the target group when the LU to be deleted is last one
       
  1114             # exposed by the target group.
  1104             if self._only_lu(luid):
  1115             if self._only_lu(luid):
  1105                 if self._check_target(target_wwn, 'Channel') == 'Online':
       
  1106                     self._stmf_execute('/usr/sbin/stmfadm', 'offline-target',
       
  1107                                        target_wwn)
       
  1108                 if self._check_tg(target_group):
  1116                 if self._check_tg(target_group):
  1109                     self._stmf_execute('/usr/sbin/stmfadm', 'delete-tg',
  1117                     self._stmf_execute('/usr/sbin/stmfadm', 'delete-tg',
  1110                                        target_group)
  1118                                        target_group)
  1111 
  1119 
  1112             # Remove the LU
  1120             # Remove the LU
  1118         :target_discovered:    boolean indicating whether discovery was used
  1126         :target_discovered:    boolean indicating whether discovery was used
  1119         :target_wwn:           the world wide name of the FC port target
  1127         :target_wwn:           the world wide name of the FC port target
  1120         :target_lun:           the lun assigned to the LU for the view entry
  1128         :target_lun:           the lun assigned to the LU for the view entry
  1121 
  1129 
  1122         """
  1130         """
  1123         wwns = self._get_wwns()
       
  1124         if not wwns:
       
  1125             msg = (_("Could not determine fibre channel world wide "
       
  1126                      "node names."))
       
  1127             raise exception.VolumeBackendAPIException(data=msg)
       
  1128 
       
  1129         luid = self._get_luid(volume)
  1131         luid = self._get_luid(volume)
  1130         if not luid:
  1132         if not luid:
  1131             msg = (_("Failed to get logic unit for volume '%s'")
  1133             msg = (_("Failed to get logic unit for volume '%s'")
  1132                    % volume['name'])
  1134                    % volume['name'])
  1133             raise exception.VolumeBackendAPIException(data=msg)
  1135             raise exception.VolumeBackendAPIException(data=msg)
  1134 
  1136 
  1135         properties = {}
  1137         properties = {}
  1136 
  1138 
  1137         properties['target_discovered'] = True
  1139         properties['target_discovered'] = True
  1138         properties['target_wwn'] = wwns
  1140         properties['target_wwn'] = self._get_target_wwns(self.tg)
  1139         view_lun = self._get_view_and_lun(luid)
  1141         view_lun = self._get_view_and_lun(luid)
  1140         if view_lun['lun'] is not None:
  1142         if view_lun['lun'] is not None:
  1141             properties['target_lun'] = view_lun['lun']
  1143             properties['target_lun'] = view_lun['lun']
  1142         return properties
  1144         return properties
  1143 
  1145