File: openstack-cluster-installer-agent

package info (click to toggle)
openstack-cluster-installer 43.0.18
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,484 kB
  • sloc: php: 19,127; sh: 18,142; ruby: 75; makefile: 31; xml: 8
file content (524 lines) | stat: -rwxr-xr-x 23,502 bytes parent folder | download | duplicates (2)
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
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
#!/bin/sh

set -e
#set -x

PRODUCT_NAME=$(dmidecode -t 1 | grep "Product Name" | sed -e "s/[ \t]*Product Name:[ ]*//"  -e "s/,//g")

# Use flock to avoid launching the agent twice at once
LOCKDIR=/var/run/lock
LOCKFILE=${LOCKDIR}/$(basename ${0})
if [ "${1}" = "--nolock" ] ; then
	shift
else
	echo "===> Claming lock for $0 in ${LOCKFILE}"
	if ! flock -w 120 -x ${LOCKFILE} $0 --nolock $@ ; then
		exit 1
	fi
	exit 0
fi

# We need the server to report to, otherwise this agent is useless
if [ -r /etc/oci/pxe-server-ip ] ; then
	PXE_SERVER_IP=$(cat /etc/oci/pxe-server-ip)
else
	echo "No /etc/oci/pxe-server-ip: refusing to start."
	exit 1
fi

# Check if the OCI server has port 80 open before doing anything
if netcat -z ${PXE_SERVER_IP} 80 ; then
	echo -n ""
else
	echo "Port 80 is not open on host ${PXE_SERVER_IP}: refusing to start."
	exit 1
fi

# Get a device name in the order proposed by /dev/disk/oci-sort
# instead of /dev/sdX. If the device isn't listed in /dev/disk/oci-sort
# this function just return the device name as found in /dev.
get_oci_sort_devname () {
	local devname
	devname=${1}
	# Attempt to find the "real" device name from /dev/disk/oci-sort
	if [ -d /dev/disk/oci-sort ] ; then
		for symlink in $(ls /dev/disk/oci-sort) ; do
			if [ ""$(basename $(realpath /dev/disk/oci-sort/${symlink})) = "${devname}" ] ; then
				RET=${symlink}
				return
			fi
		done
	fi
	RET=${devname}
	return
}

###################################
### START OF HARDWARD DISCOVERY ###
###################################
### Get all disks:

echo "===> Fetching block devices with lsblk"

TMPFILE=$(mktemp -t openstack-cluster-installer-agent.XXXXXX)
lsblk -b -l -d -J --exclude 2,7,11 -o +TRAN,MODEL  >${TMPFILE}
TMPFILE2=$(mktemp -t openstack-cluster-installer-agent.XXXXXX)
if [ "$(cat ${TMPFILE} | wc -l)" = "0" ] ; then
	# No disk present
	echo '{
   "blockdevices": [
   ],
' >${TMPFILE2}
else
	echo '{
   "blockdevices": [' >>$TMPFILE2
	FIRST=yes
	# Remove iscsi disks (probably cinder volume mounted on a compute node)
	# and any USB device (probably from the KVM over IP of the hardware IPMI)
	if [ "${PRODUCT_NAME}" = "DSS 1510" ] || [ "${PRODUCT_NAME}" = "DSS1510" ] || [ "${PRODUCT_NAME}" = "PowerEdge R420" ] || [ "${PRODUCT_NAME}" = "PowerEdge R440" ] ; then
		USB_FILTER='.tran != "iscsi"'
	else
		USB_FILTER='(.tran != "iscsi") and (.tran != "usb")'
	fi
	for devname in $(cat ${TMPFILE} | jq -r ".[\"blockdevices\"][] | select(${USB_FILTER}) | . [\"name\"]") ; do
		get_oci_sort_devname ${devname}
		reported_devname=${RET}
		devsize=$(cat ${TMPFILE} | jq -r '.["blockdevices"][] | select(.name == "'${devname}'") | . ["size"]')
		devmodel=$(cat ${TMPFILE} | jq -r '.["blockdevices"][] | select(.name == "'${devname}'") | . ["model"]')
		if [ "${FIRST}" = "yes" ] ; then
			FIRST=no
		else
			echo ',' >>$TMPFILE2
		fi
		echo -n '      { "name": "'${reported_devname}'", "realdev": "'${devname}'", "size": "'${devsize}'", "model": "'${devmodel}'" }' >>$TMPFILE2
	done
	echo '
   ],' >>$TMPFILE2
fi

if [ -x ""$(which storcli64) ] ; then
	STORCLI=storcli64
elif [ -x ""$(which storcli_x64) ] ; then
	STORCLI=storcli_x64
else
	STORCLI=""
fi

# Do we have hardware RAID (to configure with megacli) ?
LSPCI_OUT=$(lspci | grep -i MegaRAID | head -n 1)
if lshw -class storage -json 2>/dev/null | jq -r '.[]["id"]' | grep -q raid || echo "${LSPCI_OUT}" | grep -q MegaRAID; then
	if [ -x ""$(which "${STORCLI}") ] && ! ${STORCLI} /call/eall/sall show | grep -q "No Controller found" ; then
		echo "===> Fetching Storcli controller number"
		CTL_NUM=$(${STORCLI} /call show J | jq -r '.["Controllers"][]["Command Status"]["Controller"]')
		echo "===> Fetching Storcli block devices"
		for ENCLOSURE in $(${STORCLI} /c${CTL_NUM}/eall show J | jq -r '.["Controllers"][]["Response Data"]["Properties"][]["EID"]'); do
			TMP_ENC_SHOW=$(mktemp -t openstack-cluster-installer-agent-storcli-enclosure-show.XXXXXX)
			${STORCLI} /c${CTL_NUM}/e${ENCLOSURE}/sall show J >${TMP_ENC_SHOW}
			# In case no drive found, storcli will reply "Status": "Failure"
			if [ ""$(cat ${TMP_ENC_SHOW} | jq -r '.["Controllers"][]["Command Status"]["Status"]') = "Success" ] ; then
				for EID_SLT in $(cat ${TMP_ENC_SHOW} | jq -r '.["Controllers"][]["Response Data"]["Drive Information"][]["EID:Slt"]') ; do
					EID=$(echo ${EID_SLT} | cut -d: -f1)
					SLT=$(echo ${EID_SLT} | cut -d: -f2)
					TMP_SLOT_SHOW_ALL=$(mktemp -t openstack-cluster-installer-agent-storcli-slot-show-all.XXXXXX)
					${STORCLI} /c${CTL_NUM}/e${ENCLOSURE}/s${SLT} show all J >${TMP_SLOT_SHOW_ALL}
					MODEL=$(cat ${TMP_SLOT_SHOW_ALL} | jq -r '.["Controllers"][]["Response Data"]["Drive /c'${CTL_NUM}'/e'${ENCLOSURE}'/s'${SLT}' - Detailed Information"]["Drive /c'${CTL_NUM}'/e'${ENCLOSURE}'/s'${SLT}' Device attributes"]["Model Number"]' | sed 's/[[:blank:]]*$//')
					SERIAL=$(cat ${TMP_SLOT_SHOW_ALL} | jq -r '.["Controllers"][]["Response Data"]["Drive /c'${CTL_NUM}'/e'${ENCLOSURE}'/s'${SLT}' - Detailed Information"]["Drive /c'${CTL_NUM}'/e'${ENCLOSURE}'/s'${SLT}' Device attributes"]["SN"]' | sed 's/[[:blank:]]*$//')
					SECTOR_NUM_HEX=$(cat ${TMP_SLOT_SHOW_ALL} | jq -r '.["Controllers"][]["Response Data"]["Drive /c'${CTL_NUM}'/e'${ENCLOSURE}'/s'${SLT}' - Detailed Information"]["Drive /c'${CTL_NUM}'/e'${ENCLOSURE}'/s'${SLT}' Device attributes"]["Non Coerced size"]' | cut -d'[' -f2 | cut -d' ' -f1)
					SECTOR_NUM=$(printf "%d" ${SECTOR_NUM_HEX})
					# TODO: Fetch real sector size...
					SECTOR_SIZE=512
					SIZE=$(( ${SECTOR_NUM} * ${SECTOR_SIZE}))
					STATE=$(cat ${TMP_SLOT_SHOW_ALL} | jq -r '.["Controllers"][]["Response Data"]["Drive /c'${CTL_NUM}'/e'${ENCLOSURE}'/s'${SLT}'"][]["State"]')
					HDD_SPEC='{
		"controller": "'${CTL_NUM}'",
		"enclosure": "'${EID}'",
		"slot": "'${SLT}'",
		"model": "'${MODEL}'",
		"serial": "'${SERIAL}'",
		"size": "'${SIZE}'",
		"state": "'${STATE}'"
	}'
					rm -f ${TMP_SLOT_SHOW_ALL}
					if [ -n "${PHYSDEVS}" ] ; then
						PHYSDEVS="${PHYSDEVS},\n"
					fi
					PHYSDEVS="${PHYSDEVS}${HDD_SPEC}"
				done
			fi
			rm -f "${TMP_ENC_SHOW}"
		done
		echo '   "phys-blockdevices": [
		'${PHYSDEVS}'
	   ],' >>${TMPFILE2}
	elif [ -x ""$(which megacli) ] ; then
		echo "===> Fetching MegaRAID block devices"
		ENCLOSURE=$(megacli -EncInfo -aALL -NoLog | awk '/Device ID/ {print $4}' | head -n 1)
		PHYSDEVS=""
		for SLOT_NUM in $(megacli -pdlist -a0 -NoLog | grep "Slot Number:" | cut -d':' -f2 | awk '{print $1}') ; do
			MODEL=$(megacli -pdInfo -PhysDrv[${ENCLOSURE}:${SLOT_NUM}] -aall | grep "Inquiry Data:" | sed 's/Inquiry Data: //' | awk '{print substr($0,21,40)}' | sed -e 's/[ ]*$//' -e 's/^[ ]*//')
			SERIAL=$(megacli -pdInfo -PhysDrv[${ENCLOSURE}:${SLOT_NUM}] -aall | grep "Inquiry Data:" | sed 's/Inquiry Data: //' | awk '{print substr($0,0,21)}' | sed -e 's/[ ]*$//' -e 's/^[ ]*//')

			SECTOR_NUM_HEX=$(megacli -pdInfo -PhysDrv[${ENCLOSURE}:${SLOT_NUM}] -aall | grep "Non Coerced Size:" | sed 's/Non Coerced Size: //' | cut -d'[' -f2 | cut -d' ' -f1)
			SECTOR_NUM=$(printf "%d" ${SECTOR_NUM_HEX})
			SECTOR_SIZE=$(megacli -pdInfo -PhysDrv[${ENCLOSURE}:${SLOT_NUM}] -aall | grep "^Sector Size:" | sed 's/Sector Size://' | awk '{print $1}')
			if [ "${SECTOR_SIZE}" = 0 ] ; then
				SECTOR_SIZE=512
			fi
			SIZE=$(( ${SECTOR_NUM} * ${SECTOR_SIZE}))

			FULL_STATE=$(megacli -PDInfo -PhysDrv [${ENCLOSURE}:${SLOT_NUM}] -aALL -NoLog | grep -E '^Firmware state: ' | sed 's/Firmware state: //')
			STATE=$(echo ${FULL_STATE} | cut -d, -f1)
			SPUN=$(echo ${FULL_STATE} | cut -d, -f2 | awk '{$1=$1;print}')
			HDD_SPEC='{
		"controller": "0",
		"enclosure": "'${ENCLOSURE}'",
		"slot": "'${SLOT_NUM}'",
		"model": "'${MODEL}'",
		"serial": "'${SERIAL}'",
		"size": "'${SIZE}'",
		"state": "'${STATE}'"
	}'
			if [ -n "${PHYSDEVS}" ] ; then
				PHYSDEVS="${PHYSDEVS},\n"
			fi
			PHYSDEVS="${PHYSDEVS}${HDD_SPEC}"
		done
		echo '   "phys-blockdevices": [
		'${PHYSDEVS}'
	   ],' >>${TMPFILE2}
	fi
fi

echo -n "===> Fetching network device information: "

### Get all interface names
echo '   "interfaces": [' >>${TMPFILE2}
for i in $(ip link show | grep -v '^ ' | grep -v 'lo:' | cut -d' ' -f2 | cut -d: -f1 | grep -v vlan | grep -v -E 'bond|.*@.*|qvb.*|qvo.*|vxlan.*|tap.*|qbr.*|qr.*|sg-.*|ha-.*|ovs.*|qg-.*|sg-.*|fg-.*|ovs-system|br-ex|br-int|br-tun|vlan.*|usb.*|docker0|kube-ipvs0|nodelocaldns|idrac|cali.*@if\d|enx.*') ; do
	echo -n "$i "
	MAC_ADDR=$(ip link show dev $i | grep 'link/ether' | awk '{print $2}')
	NET_FIRMWARE_VERSION=$(ethtool -i $i | grep firmware-version: | awk -F"[, ]" '{print $2}')
	if [ -z "${NET_FIRMWARE_VERSION}" ] ; then
		NET_FIRMWARE_VERSION=$(ethtool -i $i | grep -E '^version:' | sed -e 's/^version: //' | awk '{print $1}')
	fi
	NET_DRIVER_NAME=$(ethtool -i $i | grep driver | sed -e 's/driver: //' | awk '{print $1}')
	LSHW_SPEED=$(lshw -class network -json 2>/dev/null | jq '.[] | select(.serial == "'${MAC_ADDR}'") | .capacity' | head -n 1)
	if [ -n "${LSHW_SPEED}" ] && [ "${LSHW_SPEED}" != "null" ] ; then
		ETH_SPEED=$(( ${LSHW_SPEED} / 1000000 ))
	else
		# If we can't find a speed, let's report it as 100 MBits/s
		ETH_SPEED=100
	fi

        # Find the neighbors using lldpcli
	switch_ifname_regex="^(en|ethernet|Gi|swp|vnet)"
	if lldpcli -f json show neighbors | jq -r '.[]["interface"] | keys[]' | grep -q $i ; then
		TMPFILE_LLDP=$(mktemp -t openstack-cluster-installer-agent.XXXXXX)
		lldpcli -f json show neighbors | jq -r '.[]["interface"] | "\(.'${i}')"' | grep -v null >${TMPFILE_LLDP}
		SWITCHPORT_NAME=$(cat ${TMPFILE_LLDP} | jq -r '.["port"]["descr"]')
		if ! echo "${SWITCHPORT_NAME}" | grep -q -E "${switch_ifname_regex}" ; then
			SWITCHPORT_NAME=$(cat ${TMPFILE_LLDP} | jq -r '.["port"]["id"]["value"]')
			if ! echo "${SWITCHPORT_NAME}" | grep -q -E "${switch_ifname_regex}" ; then
				SWITCHPORT_NAME='unknown'
			fi
		fi
		SWITCH_HOSTNAME=$(cat ${TMPFILE_LLDP} | jq -r '.["chassis"] | keys[]')
		rm -f ${TMPFILE_LLDP}
	elif lldpcli -f json show neighbors | jq -r '.[]["interface"][] | keys[]' | grep -q $i ; then
                TMPFILE_LLDP=$(mktemp -t openstack-cluster-installer-agent.XXXXXX)
                lldpcli -f json show neighbors | jq -r '.[]["interface"][] | "\(.'${i}')"' | grep -v null >${TMPFILE_LLDP}
                SWITCHPORT_NAME=$(cat ${TMPFILE_LLDP} | jq -r '.["port"]["descr"]')
		if ! echo "${SWITCHPORT_NAME}" | grep -q -E "${switch_ifname_regex}" ; then
			SWITCHPORT_NAME=$(cat ${TMPFILE_LLDP} | jq -r '.["port"]["id"]["value"]')
			if ! echo "${SWITCHPORT_NAME}" | grep -q -E "${switch_ifname_regex}" ; then
				SWITCHPORT_NAME='unknown'
			fi
		fi
                SWITCH_HOSTNAME=$(cat ${TMPFILE_LLDP} | jq -r '.["chassis"] | keys[]')
                rm -f ${TMPFILE_LLDP}
        else
                SWITCHPORT_NAME='unknown'
                SWITCH_HOSTNAME='unknown'
        fi
        echo '      {"name": "'${i}'", "macaddr": "'${MAC_ADDR}'", "max_speed": "'${ETH_SPEED}'", "switchport_name": "'${SWITCHPORT_NAME}'", "switch_hostname": "'${SWITCH_HOSTNAME}'", "firmware_version": "'${NET_FIRMWARE_VERSION}'", "driver": "'${NET_DRIVER_NAME}'" },' >>${TMPFILE2}
done
echo ""
NMU_LINES=$(cat ${TMPFILE2} | wc -l)
sed -i ${NMU_LINES}'s/,$//' ${TMPFILE2}
# End the section
echo '   ],' >>${TMPFILE2}

echo "===> Fetching baseboard info with dmidecode"

### Chassis serial number, product name, BIOS version, IPMI version, IPMI ip
SYSTEM_MANUFACTURER=$(dmidecode -s system-manufacturer)

SYSTEM_SERIAL=$(oci-system-serial)

PRODUCT_NAME=$(dmidecode -t 1 | grep "Product Name" | sed -e "s/[ \t]*Product Name:[ ]*//"  -e "s/,//g")
BIOS_VENDOR=$(dmidecode -s bios-vendor)
if [ "${SYSTEM_MANUFACTURER}" = "GIGABYTE" ] && [ "${PRODUCT_NAME}" = "MZ01-CE1-00" ] ; then
	SYSTEM_MANUFACTURER="Dataforge"
	PRODUCT_NAME="hydra-f"
fi
case ${BIOS_VENDOR} in
"GIGABYTE"|"HPE")
	BIOS_VERSION=$(dmidecode -s bios-revision)
;;
*)
	BIOS_VERSION=$(dmidecode -s bios-version)
;;
esac

echo "===> Fetching CPU info"
CPU_VENDOR=$(lscpu | grep "^Vendor ID:" | sed 's/Vendor ID:[ ]*//')
CPU_THREADS=$(lscpu | grep '^CPU(s):' | sed 's/CPU(s):[ ]*//')
CPU_CORE_PER_SOCKET=$(lscpu | grep '^Core(s) per socket:' | sed 's/Core(s) per socket:[ ]*//')
CPU_SOCKETS=$(lscpu | grep '^Socket(s):' | sed 's/Socket(s):[ ]*//')
CPU_MODEL_NAME=$(lscpu | grep '^Model name:' | sed 's/Model name:[ ]*//')
CPU_MHZ=$(lscpu | grep '^CPU MHz:' | sed 's/CPU MHz:[ ]*//')

echo "===> Fetching storage controllers"
TMPSTRAGE_CTRL=$(mktemp -t openstack-cluster-installer-agent_storage_ctrl.XXXXXX)
lshw -class storage -json 2>/dev/null >${TMPSTRAGE_CTRL}
echo '   "blkdev_ctrl": [' >>${TMPFILE2}
START=""
for store_ctrl_handle in $(cat ${TMPSTRAGE_CTRL} | jq -r '.[]["handle"]') ; do
	store_ctrl_id=$(cat ${TMPSTRAGE_CTRL} | jq -r  '.[] | select(.handle == "'${store_ctrl_handle}'") | .id')
	if cat ${TMPSTRAGE_CTRL} | jq -r  '.[] | select(.handle == "'${store_ctrl_handle}'")' | grep -q vendor ; then
		VENDOR=$(cat ${TMPSTRAGE_CTRL}| jq -r '.[] | select(.handle == "'${store_ctrl_handle}'") | .["vendor"]' | sed -e 's/,//' | head -n 1)
	else
		VENDOR="none"
	fi
	if cat ${TMPSTRAGE_CTRL} | jq -r  '.[] | select(.handle == "'${store_ctrl_handle}'")' | grep -q product ; then
		PRODUCT=$(cat ${TMPSTRAGE_CTRL}| jq -r '.[] | select(.handle == "'${store_ctrl_handle}'") | .["product"]' | sed -e 's/,//' | head -n 1)
	else
		PRODUCT="none"
	fi
	if [ "${store_ctrl_id}" = "nvme" ] ; then
		CTRL_TYPE="nvme"
		LOGICAL_NAME=$(cat ${TMPSTRAGE_CTRL} | jq -r  '.[] | select(.handle == "'${store_ctrl_handle}'") | .logicalname')
		BLKCTRL_FIRMWARE_VERSION=$(smartctl -a ${LOGICAL_NAME} | grep "Firmware Version:" | sed 's/Firmware Version://' | awk '{print $1}')
	elif [ "${PRODUCT}" = "MegaRAID 12GSAS/PCIe Secure SAS39xx" ] ; then
		CTRL_TYPE="LSI-raid"
		if [ -x ""$(which "${STORCLI}") ] ; then
			BLKCTRL_FIRMWARE_VERSION=$(${STORCLI} /call show J | jq -r '.["Controllers"][]["Response Data"]["FW Package Build"]')
		else
			BLKCTRL_FIRMWARE_VERSION="0.0.0"
		fi
	elif echo "${PRODUCT}" | grep -q -E 'MegaRAID' ; then
		CTRL_TYPE="LSI-raid"
		if [ -x ""$(which "${STORCLI}") ] ; then
			BLKCTRL_FIRMWARE_VERSION=$(storcli64 /call show J | jq '.["Controllers"][]["Response Data"]["FW Version"]' -r | head -n 1)
		else
			BLKCTRL_FIRMWARE_VERSION=$(megacli -Version -Ctrl -aall | grep "Fw Package Build :" | sed -e 's/Fw Package Build : //' | tail -n1)
		fi
	elif [ "${PRODUCT}" = "Smart Storage PQI SAS" ] || [ ""$(cat ${TMPSTRAGE_CTRL} | jq -r  '.[] | select(.handle == "'${store_ctrl_handle}'") | .["configuration"]["driver"]' | head -n 1) = "smartpqi" -a "${PRODUCT}" = "Adaptec" ] ; then
			CTRL_TYPE="SSA"
			PRODUCT="Smart Storage PQI SAS"
			SSA_SLOT_NUMBER=$(ssacli controller all show | head -n 2 | tail -n 1 | sed -r 's/.*(Slot [0-9]+).*/\1/' | sed 's/Slot //')
			BLKCTRL_FIRMWARE_VERSION=$(ssacli controller slot=${SSA_SLOT_NUMBER} show | grep "Firmware Version" | sed -e 's/   Firmware Version: //')
	else
		case "${PRODUCT}" in
		# r740xd with PERC H330-mini
		"SAS3008 PCI-Express Fusion-MPT SAS-3")
			CTRL_TYPE="LSI-noraid"
			BLKCTRL_FIRMWARE_VERSION=$(perccli show J | jq -r '.["Controllers"][]["Response Data"]["StoreLib IR3 Version"]')
		;;
		"Lewisburg SATA Controller [AHCI mode]")
			CTRL_TYPE="HP-JBOD"
			BLKCTRL_FIRMWARE_VERSION="0.0.0"
		;;
		*)
			CTRL_TYPE="none"
			BLKCTRL_FIRMWARE_VERSION="0.0.0"
		;;
		esac
	fi

	if [ -z "${store_ctrl_id}" ] ; then
		store_ctrl_id=None
	fi

	echo ${START}'      {"hwid": "'${store_ctrl_id}'", "vendor": "'${VENDOR}'", "product": "'${PRODUCT}'", "ctrl_type": "'${CTRL_TYPE}'", "firmware_version": "'${BLKCTRL_FIRMWARE_VERSION}'" }' >>${TMPFILE2}
	START=","
done
echo '   ],' >>${TMPFILE2}
rm -f ${TMPSTRAGE_CTRL}

echo "===> Fetching IPMI address and firmware versions"

IPMI_FIRMWARE_VERSION=$(ipmitool mc info | grep "Firmware Revision" | awk '{print $4}')
IPMI_DETECTED_IP=$(ipmitool lan print 1 | grep -E "IP Address[ ]*:" | sed 's/IP Address[ \t:]*//')

# Find out if we're on a Dell iDRAC system
LIFECYCLE_VERSION=0.0.0
if [ "${SYSTEM_MANUFACTURER}" = "Dell" ] || [ "${SYSTEM_MANUFACTURER}" = "Dell Inc." ] ; then
	# Due to some bugs on these old hardware, "ipmitool sdr elist mcloc" can simply hang,
	# so we avoid doing it and just double-guess the iDRAC model based on the product-name.
	# This is also much faster this way.
	if [ "${PRODUCT_NAME}" = "PowerEdge R610" ] || [ "${PRODUCT_NAME}" = "PowerEdge R410" ] ; then
		IPMI_TYPE="iDRAC6"
	elif [ "${PRODUCT_NAME}" = "PowerEdge R620" ] || [ "${PRODUCT_NAME}" = "PowerEdge R420" ] ; then
		IPMI_TYPE="iDRAC7"
	elif [ "${PRODUCT_NAME}" = "PowerEdge R630" ] || [ "${PRODUCT_NAME}" = "PowerEdge R430" ] ; then
		IPMI_TYPE="iDRAC8"
	elif [ "${PRODUCT_NAME}" = "PowerEdge R640" ] || [ "${PRODUCT_NAME}" = "PowerEdge R440" ] ; then
		IPMI_TYPE="iDRAC9"
	else
		IPMI_TYPE=$(ipmitool sdr elist mcloc | awk '{print $1}')
	fi
	case "${IPMI_TYPE}" in
	"iDRAC6")
		if [ -x /usr/bin/racadm ] ; then
			LIFECYCLE_VERSION=$(racadm getversion | grep "USC Version" | cut -d= -f2 | awk '{print $1}')
		fi
	;;
	"iDRAC7"|"iDRAC8"|"iDRAC9")
		if [ -x /usr/bin/racadm ] ; then
			LIFECYCLE_VERSION=$(racadm getversion | grep "Lifecycle Controller Version" | cut -d= -f2 | awk '{print $1}')
		fi
	;;
	"GPX")
		LIFECYCLE_VERSION=0.0.0
	;;
	*)
		LIFECYCLE_VERSION=0.0.0
	;;
	esac
fi

echo "===> Checking for firmware upgrades"

# Check if we need to upgrade the BIOS and IPMI
UPGRADE_CONFIG=/etc/oci/oci-firmware-upgrade-config.json
if [ -r ${UPGRADE_CONFIG} ] ; then
	# Spaces in product names are annoying, so we convert them to underscore
	PRODUCT_LIST=$(cat ${UPGRADE_CONFIG} | jq -r '. | keys[]' | sed 's/ /_/g' | tr '\n' ' ')
	for PRODUCT_NAME_TARGET in ${PRODUCT_LIST} ; do
		# If the current server type matches one of the product names listed in oci-firmware-upgrade-config.json
		if [ "${PRODUCT_NAME_TARGET}" = "$(echo ${PRODUCT_NAME} | sed 's/ /_/g')" ] ; then
			# Check if we have an upgrade for the BIOS
			BIOS_TARGET_VERSION=$(cat ${UPGRADE_CONFIG} | jq -r '.["'"${PRODUCT_NAME}"'"]["BIOS"]["version"]')
			if [ "${BIOS_TARGET_VERSION}" != "null" ] && dpkg --compare-versions "${BIOS_VERSION}" lt "${BIOS_TARGET_VERSION}" ; then
				SCRIPT_NAME=$(cat ${UPGRADE_CONFIG} | jq -r '.["'"${PRODUCT_NAME}"'"]["BIOS"]["script"]')
				if [ -x "${SCRIPT_NAME}" ] ; then
					BIOS_UPGRADE_SCRIPT=${SCRIPT_NAME}
					BIOS_UPGRADE_VERSION=${BIOS_TARGET_VERSION}
				fi
			fi
			# Check if we have an upgrade for IPMI
			IPMI_TARGET_VERSION=$(cat ${UPGRADE_CONFIG} | jq -r '.["'"${PRODUCT_NAME}"'"]["IPMI"]["version"]')
			if [ "${IPMI_TARGET_VERSION}" != "null" ] && dpkg --compare-versions "${IPMI_FIRMWARE_VERSION}" lt "${IPMI_TARGET_VERSION}" ; then
				SCRIPT_NAME=$(cat ${UPGRADE_CONFIG} | jq -r '.["'"${PRODUCT_NAME}"'"]["IPMI"]["script"]')
				if [ -x "${SCRIPT_NAME}" ] ; then
					IPMI_UPGRADE_SCRIPT=${SCRIPT_NAME}
					IPMI_UPGRADE_VERSION=${IPMI_TARGET_VERSION}
				fi
			fi
			LIFECYCLE_TARGET_VERSION=$(cat ${UPGRADE_CONFIG} | jq -r '.["'"${PRODUCT_NAME}"'"]["Lifecycle"]["version"]')
			if [ "${LIFECYCLE_TARGET_VERSION}" != "null" ] && [ "${LIFECYCLE_VERSION}" != "0.0.0" ] && dpkg --compare-versions "${LIFECYCLE_VERSION}" lt "${LIFECYCLE_TARGET_VERSION}" ; then
				SCRIPT_NAME=$(cat ${UPGRADE_CONFIG} | jq -r '.["'"${PRODUCT_NAME}"'"]["Lifecycle"]["script"]')
				if [ -x "${SCRIPT_NAME}" ] ; then
					LIFECYCLE_UPGRADE_SCRIPT=${SCRIPT_NAME}
					LIFECYCLE_UPGRADE_VERSION=${LIFECYCLE_TARGET_VERSION}
				fi
			fi
		fi
	done
fi

if [ -n "${IPMI_UPGRADE_VERSION}" ] ; then
	IPMI_FIRMWARE_VERSION="${IPMI_FIRMWARE_VERSION}->${IPMI_UPGRADE_VERSION}"
else
	if [ -n "${LIFECYCLE_UPGRADE_VERSION}" ] ; then
		LIFECYCLE_VERSION="${LIFECYCLE_VERSION}->${LIFECYCLE_UPGRADE_VERSION}"
	else
		if [ -n "${BIOS_UPGRADE_VERSION}" ] ; then
			BIOS_VERSION="${BIOS_VERSION}->${BIOS_UPGRADE_VERSION}"
		fi
	fi
fi

if [ -d /dev/disk/oci-sort ] ; then
	USE_OCI_SORT_DEV=yes
else
	USE_OCI_SORT_DEV=no
fi

SECURE_BOOT="no"
if [ -d /sys/firmware/efi ] ; then
	BOOT_UEFI="yes"
	if [ -x /usr/bin/mokutil ] ; then
		if mokutil --sb-state ; then
			SECB=$(mokutil --sb-state)
			if [ "${SECB}" = "SecureBoot enabled" ] ; then
				SECURE_BOOT="yes"
			fi
		else
			SECURE_BOOT="no"
		fi
	fi
else
	BOOT_UEFI="no"
fi

echo '   "machine": [' >>${TMPFILE2}
echo '      {"serial": "'${SYSTEM_SERIAL}'", "system_manufacturer": "'${SYSTEM_MANUFACTURER}'", "productname": "'${PRODUCT_NAME}'", "bios_version": "'${BIOS_VERSION}'", "dell_lifecycle_version": "'${LIFECYCLE_VERSION}'", "ipmi_firmware_version": "'${IPMI_FIRMWARE_VERSION}'", "ipmi_detected_ip": "'${IPMI_DETECTED_IP}'", "ladvd_report": "none", "use_oci_sort_dev":"'${USE_OCI_SORT_DEV}'", "cpu_vendor": "'${CPU_VENDOR}'", "cpu_threads": "'${CPU_THREADS}'", "cpu_core_per_socket": "'${CPU_CORE_PER_SOCKET}'", "cpu_sockets": "'${CPU_SOCKETS}'", "cpu_model_name": "'${CPU_MODEL_NAME}'", "cpu_mhz": "'${CPU_MHZ}'", "boot_uefi": "'${BOOT_UEFI}'", "secure_boot": "'${SECURE_BOOT}'"}' >>${TMPFILE2}
echo '   ],' >>${TMPFILE2}

### Get total amount of RAM
TOTAL_RAM=$(dmidecode -t memory |  awk '/Size: [0-9]/ {tmp=$2 ; if($3 == "GB") { tmp = $2 * 1024 }; t+=tmp;} END { print t}')
RAM_TYPE=$(dmidecode -t 17 | grep Type | head -n 1 | awk '{print $2}')
RAM_SPEED=$(dmidecode -t 17 | grep Speed | head -n 1 | awk '{print $2}')
RAM_MANUFACTURER=$(dmidecode -t 17 | grep Manufacturer | head -n 1 | awk '{print $2}')
echo '   "memory": [' >>${TMPFILE2}
	echo '      {"size": "'${TOTAL_RAM}'", "type": "'${RAM_TYPE}'", "speed": "'${RAM_SPEED}'", "manufacturer": "'${RAM_MANUFACTURER}'" }' >>${TMPFILE2}
echo '   ]' >>${TMPFILE2}
echo '}' >>${TMPFILE2}

echo "===> Will send this report to provisionning server:"
cat ${TMPFILE2}

echo "===> Calling curl (web server output):"
curl -s --header "Content-Type: application/json" -d @${TMPFILE2} http://${PXE_SERVER_IP}/oci/report.php

rm ${TMPFILE}

#############################################
### Process BIOS and IPMI firmware update ###
#############################################
if [ -x "${IPMI_UPGRADE_SCRIPT}" ] ; then
	${IPMI_UPGRADE_SCRIPT}
	exit 0
fi
if [ -x "${LIFECYCLE_UPGRADE_SCRIPT}" ] ; then
	${LIFECYCLE_UPGRADE_SCRIPT}
	exit 0
fi
if [ -x "${BIOS_UPGRADE_SCRIPT}" ] ; then
	${BIOS_UPGRADE_SCRIPT}
	exit 0
fi

if [ -r ${UPGRADE_CONFIG} ] ; then
	echo "===> Checking for block device controller upgrades"
	cat ${TMPFILE2} | jq -r '.["blkdev_ctrl"][]["product"]' | while read -r SERVER_IN_LIVE_FIRMWARE ; do
		cat /etc/oci/oci-firmware-upgrade-config.json  | jq -r '.["generic"]["block_device_controller"] | keys[]' | while read -r KNOWN_FIRMWARE ; do
			if [ "${SERVER_IN_LIVE_FIRMWARE}" = "${KNOWN_FIRMWARE}" ] ; then
				SERVER_IN_LIVE_FW_VERSION=$(cat ${TMPFILE2} | jq -r '.["blkdev_ctrl"][] | select(.product == "'"${SERVER_IN_LIVE_FIRMWARE}"'") | .firmware_version')
				KNOWN_FW_VERSION=$(cat /etc/oci/oci-firmware-upgrade-config.json | jq -r '.["generic"]["block_device_controller"]["'"${SERVER_IN_LIVE_FIRMWARE}"'"]["version"]')
				KNOWN_FW_SCRIPT=$(cat /etc/oci/oci-firmware-upgrade-config.json | jq -r '.["generic"]["block_device_controller"]["'"${SERVER_IN_LIVE_FIRMWARE}"'"]["script"]')
				if [ -x "${KNOWN_FW_SCRIPT}" ] && dpkg --compare-versions "${SERVER_IN_LIVE_FW_VERSION}" lt "${KNOWN_FW_VERSION}" ; then
					echo "Found to be needing upgrade: $SERVER_IN_LIVE_FIRMWARE"
					echo  "Version in server: ${SERVER_IN_LIVE_FW_VERSION} to be upgraded to: ${KNOWN_FW_VERSION}"
					echo "Script path: ${KNOWN_FW_SCRIPT}"
					${KNOWN_FW_SCRIPT}
					exit 0
				fi
			fi
		done
	done
fi

rm ${TMPFILE2}
echo "-> Done"