This file is indexed.

/usr/share/pyshared/tcm_dump.py is in lio-utils 3.1+git2.fd0b34fd-2.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 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
 66
 67
 68
 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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
189
190
191
192
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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
#!/usr/bin/python

import os, sys, shutil
import subprocess as sub
from subprocess import Popen, PIPE
import string
import re
import datetime, time
from optparse import OptionParser

import tcm_node
import tcm_pscsi
import tcm_iblock
import tcm_ramdisk
import tcm_fileio

import lio_dump
import tcm_fabric

tcm_root = "/sys/kernel/config/target/core"

def tcm_dump_hba_devices():
	pass

def tcm_dump_configfs(option, opt_str, value, parser):

	if not os.path.isdir(tcm_root):
		print "Unable to access tcm_root: " + tcm_root
		sys.exit(1)

	print "modprobe target_core_mod"

	# Loop through ALUA Logical Unit Groups
	# Note that the 'default_lu_gp' is automatically created when
	# target_core_mod is loaded.
	print "#### ALUA Logical Unit Groups"
	for lu_gp in os.listdir(tcm_root + "/alua/lu_gps"):	
		if lu_gp == "default_lu_gp":
			continue

		print "mkdir -p " + tcm_root + "/alua/lu_gps/" + lu_gp
		lu_gp_id_file = tcm_root + "/alua/lu_gps/" + lu_gp + "/lu_gp_id"
		p = os.open(lu_gp_id_file, 0)
		value = os.read(p, 8)
		os.close(p)
		if not value:
			continue
		print "echo " + value.rstrip() + " > " + lu_gp_id_file

	# Loop through HBA list
	for f in os.listdir(tcm_root):
		if f == "alua":
			continue;
		
#		print "mkdir -p " + tcm_root + "/" + f

		dev_root = tcm_root + "/" + f + "/"
		for g in os.listdir(dev_root):
			if g == "hba_info" or g == "hba_mode":
				continue;
			
			# Dump device aka storage object
			print "#### Parameters for TCM subsystem plugin storage object reference"
			
			# Generate subsystem dependent configfs ops for association to
		 	# an target_core_mod storage object.
			result = re.search('pscsi_', f)
			if result:
				dev = dev_root + g
				params = tcm_pscsi.pscsi_get_params(dev)
				if not params:
					continue
				print "tcm_node --establishdev " + f + "/" + g + " " + str(params)
			result = re.search('iblock_', f)
			if result:
				dev = dev_root + g
				params = tcm_iblock.iblock_get_params(dev)
				if not params:
					continue
				print "tcm_node --establishdev " + f + "/" + g + " " + str(params)
			result = re.search('rd_dr_', f)
			if result:
				dev = dev_root + g
				params = tcm_ramdisk.rd_get_params(dev)	
				if not params:
					continue
				print "tcm_node --establishdev " + f + "/" + g + " " + str(params)
			result = re.search('rd_mcp_', f)
			if result:
				dev = dev_root + g
				params = tcm_ramdisk.rd_get_params(dev)
				if not params:
					continue
				print "tcm_node --establishdev " + f + "/" + g + " " + str(params)
			result = re.search('fileio_', f)
			if result:
				dev = dev_root + g
				params = tcm_fileio.fd_get_params(dev)
				if not params:
					continue
				print "tcm_node --establishdev " + f + "/" + g + " " + str(params)

			# Dump T10 VP Unit Serial for all non Target_Core_Mod/pSCSI objects
			result = re.search('pscsi_', f)
			if not result:
				unit_serial_file = dev_root + g + "/wwn/vpd_unit_serial"
				p = os.open(unit_serial_file, 0)
				value = os.read(p, 512)
				off = value.index('Number: ')
				off += 8 # Skip over "Number: " 
				unit_serial = value[off:]
				# Note that this will handle read, parse and set any PR APTPL metadata
				print "tcm_node --setunitserialwithmd " + f + "/" + g + " " + unit_serial.rstrip()
				os.close(p)

			# Dump device object alias
			alias_file = dev_root + g + "/alias"
			p = open(alias_file, 'r')
			value = p.read(512)
			value = value.rstrip()
			p.close()
			if value:
				print "echo -n \"" + value + "\" > " + dev_root + g + "/alias"

			# Dump ALUA Logical Unit Group
			lu_gp_file = dev_root + g + "/alua_lu_gp"
			p = os.open(lu_gp_file, 0)
			value = os.read(p, 512)
			os.close(p)
			if value:
				lu_gp_tmp = value.split('\n')
				lu_gp_out = lu_gp_tmp[0]
				off = lu_gp_out.index('Alias: ')
				off += 7 # Skip over "Alias: "
				lu_gp_name = lu_gp_out[off:]
				# Only need to dump if storage object is NOT part of
				# the 'default_lu_gp'
				if not re.search(lu_gp_name, 'default_lu_gp'):
					print "echo " + lu_gp_name + " > " + lu_gp_file

			# Loop through ALUA Target Port Groups 
			if os.path.isdir(dev_root + g + "/alua/") == True:
				print "#### ALUA Target Port Groups"
				for tg_pt_gp in os.listdir(dev_root + g + "/alua/"):
					tg_pt_gp_id_file = dev_root + g + "/alua/" + tg_pt_gp + "/tg_pt_gp_id"
					p = os.open(tg_pt_gp_id_file, 0)
					value = os.read(p, 8)
					os.close(p)
					if not value:
						continue
					print "tcm_node --addaluatpgwithmd " + f + "/" + g + " " + tg_pt_gp + " " + value.rstrip()
					# Dump the ALUA types
					tg_pt_gp_type_file = dev_root + g + "/alua/" + tg_pt_gp + "/alua_access_type"
					p = os.open(tg_pt_gp_type_file, 0)
					value = os.read(p, 32)
					os.close(p)
					if value:
						value = value.rstrip()
						alua_type = 0

						if re.search('Implict and Explict', value):
							alua_type = 3
						elif re.search('Explict', value):
							alua_type = 2
						elif re.search('Implict', value):
							alua_type = 1

						print "echo " + str(alua_type) + " > " + tg_pt_gp_type_file

					# Dump the preferred bit
					tg_pt_gp_pref_file = dev_root + g + "/alua/" + tg_pt_gp + "/preferred"
					p = os.open(tg_pt_gp_pref_file, 0)
					value = os.read(p, 8)
					os.close(p)
					if value:
						print "echo " + value.rstrip() + " > " + tg_pt_gp_pref_file
					# Dump the Active/NonOptimized Delay
					tg_pt_gp_nonop_delay_file = dev_root + g + "/alua/" + tg_pt_gp + "/nonop_delay_msecs"
					p = os.open(tg_pt_gp_nonop_delay_file, 0)
					value = os.read(p, 8)
					os.close(p)
					if value:
						print "echo " + value.rstrip() + " > " + tg_pt_gp_nonop_delay_file
					# Dump the Transition Delay
					tg_pt_gp_trans_delay_file = dev_root + g + "/alua/" + tg_pt_gp + "/trans_delay_msecs"
					p = os.open(tg_pt_gp_trans_delay_file, 0)
					value = os.read(p, 8)
					os.close(p)
					if value:
						print "echo " + value.rstrip() + " > " + tg_pt_gp_trans_delay_file

			# Dump device attributes
			print "#### Attributes for " + dev_root + g
			dev_attrib_root = dev_root + g + "/attrib/"
			for h in os.listdir(dev_attrib_root):
				# The hw_* prefixed attributes are RO
				if h == "hw_queue_depth":
					continue
				if h == "hw_max_sectors":
					continue
				if h == "hw_block_size":
					continue
				# Do not change block-size for target_core_mod/pSCSI
				if h == "block_size":
					result = re.search('pscsi_', f)
					if result:
						continue

				attrib_file = dev_attrib_root + h
				p = os.open(attrib_file, 0)
				value = os.read(p, 8)
				print "echo " + value.rstrip() + " > " + attrib_file
				os.close(p)

			# Dump snapshot attributes
			snap_attrib_root = dev_root + g + "/snap/"
			if (os.path.isdir(snap_attrib_root) == False):
				continue

			snap_enabled = 0
			enabled_attr_file = snap_attrib_root + "enabled"
			p = open(enabled_attr_file, 'rU')
			if not p:
				continue
			value = p.read()
			enabled = value.rstrip()
			p.close()
			if enabled != "1":
				continue

			snap_enabled = 1
			print "#### Snapshot Attributes for " + dev_root + g
			for s in os.listdir(snap_attrib_root):
				if s == "pid":
					continue
				if s == "usage":
					continue
				if s == "enabled":
					continue

				attrib_file = snap_attrib_root + s
				p = open(attrib_file, 'rU')
				value = p.read()
				p.close()
				attr_val = value.rstrip()
				print "echo " + attr_val + " > " + attrib_file

			if snap_enabled == 1:
				print "tcm_node --lvsnapstart " + f + "/" + g

def tcm_backup_to_file(option, opt_str, value, parser):
	datetime = str(value)
	
	if not os.path.isdir(tcm_root):
		print "Unable to access tcm_root: " + tcm_root
		sys.exit(1)

	backup_dir = "/etc/target/backup"
	if not os.path.isdir(backup_dir):
		op = "mkdir " + backup_dir
		ret = os.system(op)
		if ret:
			print "Unable to open backup_dir"
			sys.exit(1)

	op = "tcm_dump --stdout"
	p = sub.Popen(op, shell=True, stdout=sub.PIPE).stdout
	if not p:
		print "Unable to dump Target_Core_Mod/ConfigFS running state"
		sys.exit(0)

	print "Making backup of Target_Core_Mod/ConfigFS with timestamp: " + datetime 
	backup_file = backup_dir + "/tcm_backup-" + datetime + ".sh"
	if os.path.isfile(backup_file):
		print "Target_Core_Mod backup_file: " + backup_file + "already exists, exiting"
		p.close()
		sys.exit(1)

	back = open(backup_file, 'w')

	line = p.readline()
	while line:
		print >>back, line.rstrip()
		line = p.readline()

	p.close()
	back.close()
	return backup_file

def tcm_full_backup(option, opt_str, value, parser):
	overwrite = str(value)

	now = datetime.datetime.now()
	tmp = str(now)
	tmp2 = tmp.split(' ')
	timestamp = tmp2[0] + "_" + tmp2[1]

	tcm_file = "/etc/target/tcm_start.sh"
	lio_file = "/etc/target/lio_start.sh"
	lio_active = 0

	ret = tcm_fabric.fabric_backup_to_file_all(timestamp)
	if ret:
		print "Unable to backup tcm_fabric.modules"	
	
	if os.path.isdir("/sys/kernel/config/target/iscsi"):
		lio_file_new = lio_dump.lio_backup_to_file(None, None, timestamp, None)
		if not lio_file_new:
			sys.exit(1)
		lio_active = 1
		print "Generated LIO-Target config: " + lio_file_new


	tcm_file_new = tcm_backup_to_file(None, None, timestamp, None)
	if not tcm_file_new:
		sys.exit(1)

	print "Generated Target_Core_Mod config: " + tcm_file_new
	
	if overwrite != "1":
		print "Not updating default config"
		return

	if lio_active:
		ret = shutil.copyfile(lio_file_new, lio_file)
		if ret:
			print "Unable to copy " + lio_file_new
			sys.exit(1)
		print "Successfully updated default config " + lio_file

	ret = shutil.copyfile(tcm_file_new, tcm_file)
	if ret:
		print "Unable to copy " + tcm_file_new
		sys.exit(1)

	print "Successfully updated default config " + tcm_file 

def tcm_overwrite_default(option, opt_str, value, parser):

	input = raw_input("Are you sure you want to overwrite the default configuration? Type 'yes': ")
	if input != "yes":
		sys.exit(0)

	val = "1"
	tcm_full_backup(None, None, val, None)

def main():
	
	parser = OptionParser()
	parser.add_option("--b","--backup", action="callback", callback=tcm_full_backup, nargs=1,
		type="string", dest="OVERWRITE", help="Do backup of TCM and storage fabric modules, and optionally overwrite default config data")
	parser.add_option("--o","--overwrite", action="callback", callback=tcm_overwrite_default, nargs=0,
		help="Overwrite default config data of TCM and storage fabric modules")
	parser.add_option("--s","--stdout", action="callback", callback=tcm_dump_configfs, nargs=0,
		help="Dump running Target_Core_Mod/ConfigFS syntax to STDOUT")
	parser.add_option("--t", "--tofile", action="callback", callback=tcm_backup_to_file, nargs=1,
		type="string", dest="DATE_TIME", help="Backup running Target_Core_Mod/ConfigFS syntax to /etc/target/backup/tcm_backup-<DATE_TIME>.sh")

	(options, args) = parser.parse_args()
	if len(sys.argv) == 1:
		parser.print_help()
		sys.exit(0)
	elif not re.search('--', sys.argv[1]):
		print "Unknown CLI option: " + sys.argv[1]
		sys.exit(1)

if __name__ == "__main__":
        main()