Class: COMStar
- Inherits:
-
Object
- Object
- COMStar
- Defined in:
- lib/SANStore/iSCSI/comstar.rb
Overview
Defines a class capable of creating iSCSI shares using the new COMStar framework. This classes uses the various command line tools, not the C API.
Class Method Summary collapse
-
.delete_target(target_name) ⇒ Object
Delete an iSCSI target.
-
.list_vols ⇒ Object
List the current iSCSI targets defined on this host.
-
.LUToVolMap ⇒ Object
Walks over the list of Logical Units, working out where the ZFS volume backing the LU is.
-
.new_target(volume_path, volume_guid) ⇒ Object
Create a new, ready to use, iSCSI target.
-
.TargetToGUIDMap ⇒ Object
Walks over the list of iSCSI targets, looking for the store GUID (stored in the target alias field).
Class Method Details
.delete_target(target_name) ⇒ Object
Delete an iSCSI target. This returns the name of the underlying ZFS store in case the caller wants to delete that as well
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/SANStore/iSCSI/comstar.rb', line 69 def self.delete_target(target_name) # Before we kill the target, get the store GUID so that we can clean up properly target_map = self.TargetToGUIDMap target_guid = target_map[target_name] # Get the maps of the LU identifers to the underlying stores vol_map = self.LUToVolMap # Look for the store with the GUID of the target we want to delete SANStore::CLI::Logger.instance.log_level(:low, :info, "Looking for the name of the volume #{target_guid} backing #{target_name}") vol_name = "" vol_store = "" vol_map.each{|key, value| if value[:guid] == target_guid then # We have found the right entry, so update the name of the # volume store and the name of the volume backing it vol_name = key vol_store = value[:data_file] break end } # Abort if we can't find what we are looking for if vol_name.empty? or vol_store.empty? then SANStore::CLI::Logger.instance.log_level(:high, :error, "Could not delete the file system for the iSCSI target. The target has been removed, but the file system is still around!") return "" end # Delete the target (and force any clients off the soon to die share) SANStore::CLI::Logger.instance.log_level(:low, :warning, "Closing all sessions for #{target_name}") target = %x[itadm delete-target -f #{target_name}] # Now unlink the SCSI logical unit, so that we can free the underlying ZFS volume SANStore::CLI::Logger.instance.log_level(:low, :delete, "Removing logical units associated with the deleted target") disk_target = %x[sbdadm delete-lu #{vol_name}] # The file store is now ready for deletion. We will tell the caller what to remove, but we # don't actually do this ourselves (file systems are someone elses problem) return vol_store end |
.list_vols ⇒ Object
List the current iSCSI targets defined on this host
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/SANStore/iSCSI/comstar.rb', line 112 def self.list_vols raw_list = %x[itadm list-target] # Create a hash for the final list of targets target_list = Array.new # Run through the raw list of targets target_array = raw_list.split(/$/) target_array.delete_at(0) target_array.each{|row| row_fragments = row.split row_hash = Hash.new row_hash[:name] = row_fragments[0] row_hash[:state] = row_fragments[1] row_hash[:sessions] = row_fragments[2] target_list << row_hash } # return the list to the caller return target_list end |
.LUToVolMap ⇒ Object
Walks over the list of Logical Units, working out where the ZFS volume backing the LU is. Returns a hash, giving the correct backing store for each LU
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/SANStore/iSCSI/comstar.rb', line 193 def self.LUToVolMap # Get the raw map SANStore::CLI::Logger.instance.log_level(:low, :info, "Finding the backing stores for the logical units") raw_list = %x[stmfadm list-lu -v] raw_map = raw_list.split(/$/) # Create a hash from this map map_hash = Hash.new map_index = nil map_entry = nil raw_index = 0 while raw_index < raw_map.length do # Is this line the start of a new LU entry if raw_map[raw_index].index(/LU Name\:/) then # Store the old entry unless map_entry.nil? then map_hash[map_index] = map_entry end # Create a new map entry map_entry = Hash.new map_index = raw_map[raw_index].partition(/LU Name\:/)[2].strip else # Split the line to find the key and value entry = raw_map[raw_index].partition(/\s?\:\s/) case entry[0].strip when "Alias" map_entry[:guid] = entry[2].strip when "Data File" map_entry[:data_file] = entry[2].strip end end raw_index += 1 end # Add the last entry unless map_entry.nil? then map_hash[map_index] = map_entry end # Return the hash map return map_hash end |
.new_target(volume_path, volume_guid) ⇒ Object
Create a new, ready to use, iSCSI target. Functionally this is command is equivalent to the old “shareiscsi=on” ZFS volume property.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/SANStore/iSCSI/comstar.rb', line 25 def self.new_target(volume_path, volume_guid) # Create a new disk target for the ZFS volume SANStore::CLI::Logger.instance.log_level(:low, :create, "New SCSI block device at /dev/zvol/rdsk/#{volume_path}") disk_target = %x[sbdadm create-lu /dev/zvol/rdsk/#{volume_path}] # Get the ID of the new disk target from the output of the # target creation command id = disk_target.split(/$/)[4].split[0] SANStore::CLI::Logger.instance.log_level(:low, :info, "Using #{id} as the logical unit identifier") # Modify the just created logical unit to include the path of the # volume backing it. This makes it much easier to get rid of the # relevant volume later SANStore::CLI::Logger.instance.log_level(:low, :update, "Storing the volume GUID as the logical unit alias") modify_lu = %x[stmfadm modify-lu --lu-prop alias=#{volume_guid} #{id}] # Create a new target group SANStore::CLI::Logger.instance.log_level(:low, :create, "Creating target group #{id}") %x[stmfadm create-tg #{id}] # Link the new disk target to the iSCSI framework SANStore::CLI::Logger.instance.log_level(:low, :update, "Attaching logical unit #{id} into the iSCSI framework") vol_frame = %x[stmfadm add-view --target-group #{id} #{id}] # Create the target... SANStore::CLI::Logger.instance.log_level(:low, :create, "iSCSI block target") target = %x[itadm create-target] target_name = target.split[1] # Store the volume GUID as the alias so we can find it later SANStore::CLI::Logger.instance.log_level(:low, :update, "Storing the volume GUID as the iSCSI target alias") %x[itadm modify-target --alias #{volume_guid} #{target_name}] # Add the new target to the correct target group SANStore::CLI::Logger.instance.log_level(:low, :update, "Adding the target #{target_name} to its target group") %x[svcadm disable stmf; sleep 2; stmfadm add-tg-member -g #{id} #{target_name}; svcadm enable stmf] # Return the target name to the caller return target_name end |
.TargetToGUIDMap ⇒ Object
Walks over the list of iSCSI targets, looking for the store GUID (stored in the target alias field). Returns a map of the target names and associated aliases
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/SANStore/iSCSI/comstar.rb', line 139 def self.TargetToGUIDMap # Get the raw map SANStore::CLI::Logger.instance.log_level(:low, :info, "Finding the GUID's associated with iSCSI targets") raw_list = %x[stmfadm list-target -v] raw_map = raw_list.split(/$/) # Create a hash from this map map_hash = Hash.new map_index = nil map_entry = nil raw_index = 0 while raw_index < raw_map.length do # Is this line the start of a new target entry if raw_map[raw_index].index(/Target\:/) then # Store the old entry unless map_entry.nil? then map_hash[map_index] = map_entry end # Create a new map entry map_entry = String.new map_index = raw_map[raw_index].partition(/Target\:/)[2].strip else # Split the line to find the key and value entry = raw_map[raw_index].partition(/\s?\:\s/) case entry[0].strip when "Alias" map_entry = entry[2].strip end end raw_index += 1 end # Add the last entry unless map_entry.nil? then map_hash[map_index] = map_entry end # Return the hash map return map_hash end |