#!/bin/bash # # Author: Georg Voell - georg.voell@standby.cloud # Version: @(#)disk-management 3.2.0 12.08.2024 (c)2024 Standby.cloud # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ # # This script can be used free of charge. Use it as is or customize as needed. It is not guaranteed to be # error free and you will not be reimbursed for any damage it may cause. # #@ Format and mount attached disks. Only Linux supported yet (Solaris planned). #@ #@Usage: disk-management [options] [auto] #@ Options: #@ -h, --help : Displays helptext. #@ -v, --version: Displays the version of the script. #@ -n, --nocli : Don't use CLI - just use OS tools. In this case, disks have to be paravirtualized to be found. #@ If parameter auto is given, don't ask questions # # Exit codes: # 01: Unknown or wrong parameter and only LINUX supported and script needs to be executed with ROOT privileges. # 02: Unknown cloud_id. # 03: No 'opc' / 'oci' to use. # 99: User interrupt. # # See also: # **bootstrap**(1), **user-management**(1), **key-management**(1), **install-scripts**(1) # # ToDo: # # - Working with --profile $username # # Known bugs: # # Update history: # # V 3.0.0 15.07.2020 New version # V 3.0.1 01.10.2020 Format checked on Ubuntu # V 3.0.2 28.05.2021 New parameter -n # V 3.1.0 05.06.2023 New copyright # V 3.1.1 08.09.2023 Check if we can use "fdisk -l" # V 3.2.0 12.08.2024 New minor version # # Find executable bash library and source it lib=`which lib.bash 2>/dev/null | sed 's|^no 'lib.bash' in .*||'` if [ "$lib" != "" ]; then source "$lib" else progdir=`dirname "$0"` if [ -r "${progdir}/lib.bash" ]; then source "${progdir}/lib.bash" else echo "Unexpected error: Unable to locate bash library 'lib.bash'." exit 1 fi fi # Set some defaults infofolder="/usr/local/share/info" cloudfile="${infofolder}/cloud.json" toolsfile=".admintools" # userfile="${infofolder}/user.json" # Source environment variables if [ -r "${HOME}/$toolsfile" ]; then source "${HOME}/$toolsfile" else if [ -r "${infofolder}/$toolsfile" ]; then source "${infofolder}/$toolsfile" else export OCI_CLI_AUTH="instance_principal" fi fi # Do extra cleanup function ExtraCleanup() { filecheck -rm ${scratchfile}.pfm # Vomumes in platform filecheck -rm ${scratchfile}.dsk # Disks (found by OS) filecheck -rm ${scratchfile}.rai # Raid Systems filecheck -rm ${scratchfile}.vol filecheck -rm ${scratchfile}.inf filecheck -rm ${scratchfile}.dfk # Filesystem } # List all RAID function LinuxListAllRaids() { # check if we have madm available mdadm=`filecheck -x mdadm` raidfile="/proc/mdstat" if [ -f "$raidfile" ]; then grep '^md[0-9]' "$raidfile" | sort > $scratchfile result=`filecheck -s $scratchfile` if [ "$result" != "" ]; then printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" "raid" "active" "level" "disks" "label" "array-size" "device-size" \ "block-size" "state" "active-devices" "working-devices" "failed-devices" "spare-devices" > ${scratchfile}.rai while read -r line; do raid=`echo "$line" | cut -d' ' -f1` rstat=`echo "$line" | cut -d' ' -f3` rlevel=`echo "$line" | cut -d' ' -f4` rdisks=`echo "$line" | cut -d' ' -f5- | tr ' ' ','` diskname=`echo "$rdisks" | cut -d'[' -f1` if [ "$diskname" != "" -a -f "${scratchfile}.pfm" ]; then blocks=`grep " /dev/$diskname " ${scratchfile}.pfm | cut -d' ' -f7` label=`grep " /dev/$diskname " ${scratchfile}.pfm | cut -d' ' -f8` else blocks="" label="" fi if [ "$mdadm" != "" -a "$raid" != "" ]; then $mdadm --detail "/dev/$raid" > ${scratchfile}.dsk result=`filecheck -s ${scratchfile}.dsk` if [ "$result" != "" ]; then arrsize=`grep 'Array Size :' ${scratchfile}.dsk | cut -d':' -f2 | cut -d' ' -f2` devsize=`grep 'Used Dev Size :' ${scratchfile}.dsk | cut -d':' -f2 | cut -d' ' -f2` state=`grep 'State :' ${scratchfile}.dsk | cut -d':' -f2 | cut -d' ' -f2- | tr -d ' '` activedev=`grep 'Active Devices :' ${scratchfile}.dsk | cut -d':' -f2 | cut -d' ' -f2` workingdev=`grep 'Working Devices :' ${scratchfile}.dsk | cut -d':' -f2 | cut -d' ' -f2` faileddev=`grep 'Failed Devices :' ${scratchfile}.dsk | cut -d':' -f2 | cut -d' ' -f2` sparedev=`grep 'Spare Devices :' ${scratchfile}.dsk | cut -d':' -f2 | cut -d' ' -f2` else arrsize="" devsize="" state="" activedev="" workingdev="" faileddev="" sparedev="" fi fi if [ "$blocks" != "" -a "$devsize" != "" ]; then let "cblocks=$blocks-$raidspace" if [ $cblocks -gt $devsize ]; then raidextendable=1 fi fi printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" "/dev/$raid" "$rstat" "$rlevel" "$rdisks" "$label" "$arrsize" "$devsize" \ "$blocks" "$state" "$activedev" "$workingdev" "$faileddev" "$sparedev" >> ${scratchfile}.rai done < $scratchfile printf "\nRAID found:\n\n" print-table --import ${scratchfile}.rai fi fi } function CheckRaidsLinux() { # check if we have madm available mdadm=`filecheck -x mdadm` LinuxListAllRaids # Check for volume groups result=`filecheck -sl ${scratchfile}.pfm` if [ "$result" != "" -a "$mdadm" != "" ]; then printf "" > $scratchfile while read -r line; do device=`echo "$line" | cut -d' ' -f1` if [ "$device" != "device" ]; then disk=`ls -l "$device" 2>/dev/null` if [ "$disk" != "" ]; then disk=`echo "$disk" | cut -d'>' -f2` if [ "$disk" != "" ]; then disk=/dev/`basename "$disk"` fi fi ro=`echo "$line" | cut -d' ' -f4` dlabel=`echo "$line" | cut -d' ' -f6` blocks=`echo "$line" | cut -d' ' -f7` vgname=`echo "$line" | cut -d' ' -f8` if [ "$vgname" != "" ]; then printf "%s\t%s\t%s\t%s\t%s\t%s\n" "$vgname" "$device" "$disk" "$dlabel" "$ro" "$blocks" >> $scratchfile fi fi done < ${scratchfile}.pfm result=`filecheck -s $scratchfile` if [ "$result" != "" ]; then printf "%s\t%s\t%s\t%s\t%s\t%s\n" "vg-name" "device" "disk" "label" "is-read-only" "blocks" > ${scratchfile}.vol sort $scratchfile >> ${scratchfile}.vol stat=0 if [ "$param" != "auto" ]; then printf "\nVolume Groups found:\n\n" print-table --import ${scratchfile}.vol confirm "\nDo you want to create a RAID?" --yes "y/[yes]" --no "n/no" stat=$? printf "\n" fi if [ $stat -eq 0 ]; then ### ToDo: other than 3 devices $mdadm --create /dev/md0 --level=5 --raid-devices=3 /dev/sdb /dev/sdc /dev/sdd LinuxListAllRaids else echo "Skipping RAID creation." fi fi filecheck -rm $scratchfile filecheck -rm ${scratchfile}.vol fi if [ "$mdadm" != "" -a $raidextendable -gt 0 ]; then stat=0 if [ "$param" != "auto" ]; then confirm "\nSome RAID can be extended. Extend now?" --yes "y/[yes]" --no "n/no" stat=$? printf "\n" fi if [ $stat -eq 0 ]; then while read -r line; do raid=`echo "$line" | cut -d' ' -f1` devsize=`echo "$line" | cut -d' ' -f7` blocks=`echo "$line" | cut -d' ' -f8` if [ "$blocks" != "" -a "$devsize" != "" ]; then let "cblocks=$blocks-$raidspace" if [ $cblocks -gt $devsize ]; then $mdadm --grow "$raid" --size=max fi fi done < ${scratchfile}.rai LinuxListAllRaids else echo "Leaving RAID unchanged." fi fi } # List all disks function LinuxListAllDisks() { # check if we have blkid and lsblk available blkid=`filecheck -x blkid` lsblk=`filecheck -x lsblk` partfile="/proc/partitions" if [ "$blkid" != "" -a -f "$partfile" ]; then printf "disk\tschema\ttype\tlabel\tblocks\tbytes\tdiskLabel\tuuid\tpartUuid/subUuid\tfsType\tmountpoint\n" > ${scratchfile}.dsk for disk in `cat "$partfile" | grep -v '^major' | grep -v '^$' | tr -s ' ' | cut -d' ' -f5 | sort`; do case "$disk" in loop[0-9]) schema="loop" ;; md[0-9]) schema="raid" ;; nvme*) schema="nvme" ;; dm-[0-9]) schema="lvm" ;; xvd[b-z][0-9]* | sd[a-z][0-9]*) schema="part" ;; xvd[b-z] | sd[a-z]) schema="disk" ;; *) schema="other" ;; esac # Get infos from partfile dinfo=`grep " $disk$" "$partfile"` blocks=`echo $dinfo | cut -d' ' -f3` let "bytes=$blocks*1024" uuid="" partuuid="" subuuid="" ftype="" label="" ptype="" plabel="" # Get infos from blkid $blkid -o "export" "/dev/$disk" > $scratchfile result=`filecheck -s $scratchfile` if [ "$result" != "" ]; then devname=`grep '^DEVNAME=' $scratchfile | sed 's|^DEVNAME=||'` uuid=`grep '^UUID=' $scratchfile | sed 's|^UUID=||'` partuuid=`grep '^PARTUUID=' $scratchfile | sed 's|^PARTUUID=||'` subuuid=`grep '^UUID_SUB=' $scratchfile | sed 's|^UUID_SUB=||'` if [ "$partuuid" = "" -a "$subuuid" != "" ]; then partuuid="$subuuid" fi ftype=`grep '^TYPE=' $scratchfile | sed 's|^TYPE=||'` label=`grep '^LABEL=' $scratchfile | sed 's|^LABEL=||'` ptype=`grep '^PTTYPE=' $scratchfile | sed 's|^PTTYPE=||'` if [ "$schema" = "part" ]; then plabel=`grep '^PARTLABEL=' $scratchfile | sed 's|^PARTLABEL=||'` else if [ "$schema" = "raid" -a -f "${scratchfile}.rai" ]; then ptype=`grep "^$devname " ${scratchfile}.rai | cut -d' ' -f3` # Raid level plabel=`grep "^$devname " ${scratchfile}.rai | cut -d' ' -f5` # Raid label / Volume Group Name else if [ "$schema" = "disk" -a -f "${scratchfile}.pfm" ]; then plabel=`grep " $devname " ${scratchfile}.pfm | cut -d' ' -f6` # Disk label fi fi fi else devname="/dev/$disk" fi # Get mountpoint from lsblk if [ "$lsblk" != "" -a "$devname" != "" -a "$uuid" != "" ]; then mountpoint=`$lsblk -o "UUID,MOUNTPOINT" "$devname" | grep "^$uuid" | tr -s ' ' | cut -d' ' -f2` if [ "$mountpoint" = "" -a "$ftype" != "LVM2_member" ]; then mountpoint="unused" fi else mountpoint="" fi if [ "$devname" != "disk" -a "$ptype" = "" -a "$ftype" = "" ]; then # Only format disks that are greater then 4096 blocks if [ $bytes -gt 4194304 ]; then ftype="unformatted" fi fi printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" \ "$devname" "$schema" "$ptype" "$plabel" "$blocks" "$bytes" "$label" "$uuid" "$partuuid" "$ftype" "$mountpoint" >> ${scratchfile}.dsk done printf "\nDisks, partitions or RAID found (including boot):\n\n" grepres=`grep ' unformatted ' ${scratchfile}.dsk` if [ "$grepres" != "" ]; then print-table --import ${scratchfile}.dsk --red "unformatted" else print-table --import ${scratchfile}.dsk --red "unused" fi # Cleanup filecheck -rm $scratchfile fi } # Fix GPT partition table if it is not at the end of partition with parted function CheckFixGPTLinux() { disk=${1} # Check if we have parted available parted=`filecheck -x parted` partprobe=`filecheck -x partprobe` if [ "$disk" != "" -a "$parted" != "" ]; then # We test for errors in english language SAVEDLANG="$LANG" LANG="en_US.UTF-8" # en $parted -s "$disk" print > $scratchfile 2>&1 if [ -f $scratchfile ]; then ptable=`grep "^Partition Table:" $scratchfile | sed 's|^Partition Table: ||'` errmsg=`grep "^Error: The backup GPT table is not at the end of the disk" $scratchfile` warnmsg=`grep "^Warning: Not all of the space available to $disk appears to be used" $scratchfile` str=`grep "xfs$" $scratchfile | tail -1` # Get the last xfs partition if [ "$ptable" = "gpt" -a "$errmsg" != "" -a "$warnmsg" != "" ]; then if [ "$str" != "" ]; then partnr=`echo $str | cut -d' ' -f1` stat=0 if [ "$param" != "auto" ]; then confirm "\nNot all of the space available to '$disk' appears to be used. Fix partition table and resize partition '${disk}$partnr'?" --yes "y/[yes]" --no "n/no" stat=$? printf "\n" fi if [ $stat -eq 0 ]; then # Fix the problem $parted "$disk" print Fix Fix > /dev/null 2>&1 stat=$? if [ $stat -eq 0 ]; then printf "p\nd\n$partnr\nn\n$partnr\n\n\nw\nq\n" > $scratchfile $fdisk "$disk" < $scratchfile >/dev/null 2>&1 partfixed=1 stat=$? if [ $stat -eq 0 ]; then echo "Partition table fixed." else echo "Could not fix partition table." fi # Need partprobe to change running disk $partprobe "$disk" fi else echo "Leaving disk unchanged." fi fi fi fi # Cleanup LANG="$SAVEDLANG" rm -f $scratchfile fi } # Check all partitions function CheckPartitionsLinux() { dprefix=${1} if [ -r "${scratchfile}.dsk" ]; then printf "disk\tschema\tptype\n" > ${scratchfile}.vol while read -r line; do disk=`echo "$line" | cut -d' ' -f1` schema=`echo "$line" | cut -d' ' -f2` ptype=`echo "$line" | cut -d' ' -f3` if [ "$disk" != "disk" -a "$schema" = "disk" -a "$ptype" = "gpt" ]; then printf '%s\t%s\t%s\n' "$disk" "$schema" "$ptype" >> ${scratchfile}.vol fi done < ${scratchfile}.dsk result=`filecheck -sl ${scratchfile}.vol` if [ "$result" != "" ]; then lines=`cat ${scratchfile}.vol | wc -l` partfixed=0 i=2 while [ $i -le $lines ]; do line=`sed -n "${i}p" < ${scratchfile}.vol` disk=`echo "$line" | cut -d' ' -f1` # Check if partition table needs to be fixed CheckFixGPTLinux "$disk" let "i+=1" done if [ $partfixed -gt 0 ]; then LinuxListAllDisks fi fi filecheck -rm ${scratchfile}.vol fi } # Create a list with all iscsi disks function CheckISCSIDisks() { # Check if we have iscsiadm available iscsiadm=`filecheck -x iscsiadm` if [ "$iscsiadm" != "" ]; then # Create file with all currently attached iscsi volumes $iscsiadm -m node 2>/dev/null > $scratchfile result=`filecheck -s $scratchfile` if [ "$result" != "" ]; then printf "startup\ttpgt\tipv4\tport\tiqn\n" > ${scratchfile}.inf while read -r line; do ipv4=`echo "$line" | cut -d':' -f1` str=`echo "$line" | cut -d':' -f2-` port=`echo "$str" | cut -d',' -f1` str=`echo "$str" | cut -d',' -f2-` tpgt=`echo "$str" | cut -d' ' -f1` iqn=`echo "$str" | cut -d' ' -f2-` startup=`$iscsiadm -m node --targetname "$iqn" | grep '^node.startup' | sed 's|^node.startup = ||'` printf '%s\t%s\t%s\t%s\t%s\n' "$startup" "$tpgt" "$ipv4" "$port" "$iqn" >> ${scratchfile}.inf done < $scratchfile if [ "$param" != "auto" ]; then printf "\nAssigned ISCSI volumes found (including boot):\n\n" print-table --import ${scratchfile}.inf fi fi filecheck -rm $scratchfile fi } function CreateDiskList() { result=`filecheck -sl ${scratchfile}.vol` if [ "$result" != "" ]; then printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" "device" "disk" "attachmentType" "isReadOnly" "isShareable" "name" "blocks" "vgName" \ "ipv4" "port" "iqn" "filesystem" "mountpoint" "owner" > ${scratchfile}.pfm while read -r line; do device=`echo "$line" | cut -d' ' -f1` if [ "$device" != "device" ]; then volid=`echo "$line" | cut -d' ' -f2` at=`echo "$line" | cut -d' ' -f3 | tr "[:upper:]" "[:lower:]"` ro=`echo "$line" | cut -d' ' -f4 | tr "[:upper:]" "[:lower:]"` sharable=`echo "$line" | cut -d' ' -f5 | tr "[:upper:]" "[:lower:]"` if [ "$at" = "iscsi" ]; then ipv4=`echo "$line" | cut -d' ' -f6` port=`echo "$line" | cut -d' ' -f7` iqn=`echo "$line" | cut -d' ' -f8` else ipv4="" port="" iqn="" fi disk="" if [ "$device" != "None" -a "$device" != "" ]; then disk=`ls -l "$device" 2>/dev/null` fi if [ "$disk" = "" ]; then # Device was not specified if [ "$iqn" != "" ]; then # Try to identify disk by iqn disk=`ls -l /dev/disk/by-path/*${iqn}* 2>/dev/null` fi fi if [ "$disk" != "" ]; then disk=`echo "$disk" | cut -d'>' -f2-` if [ "$disk" != "" ]; then disk=/dev/`basename "$disk"` fi fi # Preset name="" bytes="" vgname="" filesystemtag="" mountpointtag="" ownertag="" if [ "$volid" != "" ]; then $oci bv volume get --output json --volume-id "$volid" 2>/dev/null > $scratchfile else echo "" > $scratchfile fi result=`filecheck -sl $scratchfile` if [ "$result" != "" ]; then ls=`cat $scratchfile | browse-json --select 1 --quiet lifecycleState | tolower` if [ "$ls" = "available" ]; then filesystemtag=`cat $scratchfile | browse-json --select 1 --quiet definedTags/DiskManagement/Filesystem` mountpointtag=`cat $scratchfile | browse-json --select 1 --quiet definedTags/DiskManagement/Mountpoint` ownertag=`cat $scratchfile | browse-json --select 1 --quiet definedTags/DiskManagement/Owner` name=`cat $scratchfile | browse-json --select 1 --quiet displayName` mbsize=`cat $scratchfile | browse-json --select 1 --quiet sizeInMBs` let "blocks=${mbsize}*1024" vgid=`cat $scratchfile | browse-json --select 1 --quiet volumeGroupId` if [ "$vgid" != "null" ]; then $oci bv volume-group get --volume-group-id "$vgid" --output json 2>/dev/null > $scratchfile else echo "" > $scratchfile fi result=`filecheck -sl $scratchfile` if [ "$result" != "" ]; then vgname=`cat $scratchfile | browse-json --select 1 --quiet displayName` else vgname="" fi fi fi if [ "$disk" = "" -a "$at" = "iscsi" ]; then disk="unassigned" fi printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" "$device" "$disk" "$at" "$ro" "$sharable" "$name" "$blocks" "$vgname" "$ipv4" \ "$port" "$iqn" "$filesystemtag" "$mountpointtag" "$ownertag" >> ${scratchfile}.pfm fi done < ${scratchfile}.vol fi } # Check if there are are attached disks (OCI) function CheckPlatformOCI() { instid=${1} # Check if we have to attach iscsi volumes if [ "$instid" != "" ]; then # Get all attached volumes (from instance) $oci compute volume-attachment list --output json --all --instance-id $instid \ --query 'data[?contains("lifecycle-state",`ATTACHED`)]' 2>/dev/null > $scratchfile result=`filecheck -sl $scratchfile` if [ "$result" != "" ]; then printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" "device" "volumeId" "attachmentType" "isReadOnly" "isShareable" "ipv4" "port" "iqn" > ${scratchfile}.vol cat "$scratchfile" \ | convert-json "device,volumeId,attachmentType,isReadOnly,isShareable,ipv4,port,iqn" --quiet --noheader --output "tsv" \ | sort >> ${scratchfile}.vol CreateDiskList result=`filecheck -sl ${scratchfile}.pfm` if [ "$result" != "" ]; then if [ "$param" != "auto" ]; then printf "\nInstance attached volumes found (excluding boot):\n\n" print-table --import ${scratchfile}.pfm --red "unassigned" fi # Create file with all currently attached iscsi volumes CheckISCSIDisks stat=0 hadextend=0 if [ "$param" != "auto" ]; then unassigned=`grep " unassigned " ${scratchfile}.pfm` if [ "$unassigned" != "" ]; then confirm "\nVolumes found that are not in assigned ICSCI list. Assign them?" --yes "y/[yes]" --no "n/no" stat=$? fi fi if [ $stat -eq 0 ]; then while read -r line; do disk=`echo "$line" | cut -d' ' -f2` at=`echo "$line" | cut -d' ' -f3 | tr "[:upper:]" "[:lower:]"` ipv4=`echo "$line" | cut -d' ' -f9` port=`echo "$line" | cut -d' ' -f10` iqn=`echo "$line" | cut -d' ' -f11` if [ "$disk" = "unassigned" ]; then # Volume is not attached with iscsiadm - do it now $iscsiadm -m node -o new -T $iqn -p ${ipv4}:$port >> $logfile 2>&1 $iscsiadm -m node -T $iqn -o update -n node.startup -v automatic >> $logfile 2>&1 $iscsiadm -m node -T $iqn -p ${ipv4}:$port -l >> $logfile 2>&1 hadextend=1 fi done < ${scratchfile}.pfm # Create file again with all currently attached iscsi volumes if [ $hadextend -gt 0 -a "$param" != "auto" ]; then CheckISCSIDisks ### CreateDiskList fi fi filecheck -rm ${scratchfile}.inf fi # filecheck -rm ${scratchfile}.pfm fi filecheck -rm $scratchfile fi } # Check if boot-disk size changed function CheckBootDisk() { local change=${1} local resultstr="no" local iscsi=`filecheck -x oci-iscsi-config` local growfs=`filecheck -x /usr/libexec/oci-growfs` resultstr="no" if [ "$change" = "yes" -o "$change" = "no" ]; then # dd iflag=direct if=/dev/oracleoci/oraclevda of=/dev/null count=1 # echo "1" | tee /sys/class/block/`readlink /dev/oracleoci/oraclevda | cut -d'/' -f 2`/device/rescan > /dev/null 2>&1 # if [ "$iscsi" != "" ]; then # $iscsi sync > ${scratchfile}.dfk 2>&1 # fi if [ "$growfs" != "" ]; then $growfs --${change} > ${scratchfile}.dfk 2>&1 if [ "$change" = "no" ]; then resultstr=`grep "^CHANGE:" ${scratchfile}.dfk` if [ "$resultstr" != "" ]; then resultstr="yes" else resultstr="no" fi else resultstr="yes" fi fi fi echo "$resultstr" } # Create list of filesystems function PrintFilesystemLinux() { isextendable=0 # Check if we have df available df=`filecheck -x df` partfile="/proc/partitions" if [ "$df" != "" ]; then $df -l -T -B 1 | grep "^/dev/" | tr -s ' ' | sort > $scratchfile result=`filecheck -s $scratchfile` if [ "$result" != "" ]; then result=`CheckBootDisk "no"` printf "disk\ttype\tsize\textendable\tused\tmountpoint\n" > ${scratchfile}.dfk while read -r line; do disk=`echo "$line" | cut -d' ' -f1` ftype=`echo "$line" | cut -d' ' -f2` size=`echo "$line" | cut -d' ' -f3` used=`echo "$line" | cut -d' ' -f6` mp=`echo "$line" | cut -d' ' -f7` if [ -r "$partfile" -a "$disk" != "" ]; then dname=`basename "$disk"` str=`grep "$dname$" "$partfile"` blocks=`echo $str | cut -d' ' -f3` # let "bytes=$size+512*$diskspace" if [ "$blocks" != "" ]; then let "bytes=$size+1024*$diskspace" let "dsize=$blocks*1024" if [ $dsize -gt $bytes -a "$ftype" = "xfs" ]; then extendable="yes" isextendable=1 else extendable="no" fi else if [ "$dname" = "ocivolume-root" ]; then extendable="$result" if [ "$extendable" = "yes" ]; then isextendable=1 fi else if [ "$dname" = "ocivolume-oled" ]; then extendable="no" else extendable="unknown" fi fi fi else # let "bytes=blocks*1024+512*1048576" # This is just a guess 536870912 / 20119552 19648 / 225280 220 # 209715200 + 8589934592 + 41209036800 = 50008686592 # 209489920 + 8073408512 + 41188917248 = 49471815680 + 536870912 = 50008686592 extendable="unknown" fi printf '%s\t%s\t%s\t%s\t%s\t%s\n' "$disk" "$ftype" "$size" "$extendable" "$used" "$mp" >> ${scratchfile}.dfk done < $scratchfile if [ "$param" != "auto" ]; then printf "\nMounted disks, partitions or RAID with filesystms found (including boot):\n\n" print-table --import ${scratchfile}.dfk --red "yes" --yellow "unknown" fi fi filecheck -rm $scratchfile else echo "No 'df' in PATH." fi } # Create list of filesystems and check if it can grow (Linux) function CheckFilesystemLinux() { PrintFilesystemLinux stat=0 if [ "$param" != "auto" ]; then if [ $isextendable -gt 0 ]; then confirm "\nDisks found that were resized. Extend filesystem?" --yes "y/[yes]" --no "n/no" stat=$? printf "\n" else stat=1 fi else if [ $isextendable -eq 0 ]; then stat=1 fi fi growfs=`filecheck -x xfs_growfs` if [ $stat -eq 0 -a "$growfs" != "" ]; then while read -r line; do disk=`echo "$line" | cut -d' ' -f1` ftype=`echo "$line" | cut -d' ' -f2` ext=`echo "$line" | cut -d' ' -f4` mp=`echo "$line" | cut -d' ' -f6` dname=`basename "$disk"` if [ "$ext" = "yes" -a "$mp" != "" ]; then if [ "$dname" = "ocivolume-root" ]; then result=`CheckBootDisk "yes"` if [ "$result" = "yes" ]; then echo "Filesystem '$mp' extended." else echo "Unable to extend filesystem '$mp'." fi else if [ "$ftype" = "xfs" ]; then $growfs -d "$mp" > /dev/null 2>&1 stat=$? if [ $stat -eq 0 ]; then echo "Filesystem '$mp' extended." else echo "Unable to extend filesystem '$mp'." fi fi fi fi done < ${scratchfile}.dfk if [ "$param" != "auto" ]; then PrintFilesystemLinux fi fi filecheck -rm ${scratchfile}.dfk } # Check if disks were resized function CheckResizedDisks() { dprefix=${1} if [ "$fdisk" != "" ]; then $fdisk -l 2>&1 | grep "Disk $dprefix" | sort > $scratchfile result=`filecheck -s $scratchfile` if [ "$result" != "" ]; then i=1 while read -r line; do disk=`echo "$line" | cut -d':' -f1 | sed 's|^Disk ||'` if [ "$disk" != "" ]; then diskbase=`basename "$disk"` dd iflag=direct if=$disk of=/dev/null count=$i 2>/dev/null echo "$i" | tee /sys/class/block/${diskbase}/device/rescan >/dev/null fi # let "i+=1" done < $scratchfile fi filecheck -rm $scratchfile fi } # Linux: Partition and format all disks (that are not already formatted) function CheckFormatLinux() { dprefix=${1} if [ -r "${scratchfile}.dsk" ]; then printf "disk\tschema\tptype\tplabel\tbytes\tuuid\ttype\n" > ${scratchfile}.vol while read -r line; do disk=`echo "$line" | cut -d' ' -f1` schema=`echo "$line" | cut -d' ' -f2` ptype=`echo "$line" | cut -d' ' -f3` plabel=`echo "$line" | cut -d' ' -f4` bytes=`echo "$line" | cut -d' ' -f6` uuid=`echo "$line" | cut -d' ' -f8` ftype=`echo "$line" | cut -d' ' -f10` if [ "$ftype" = "unformatted" ]; then printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\n' "$disk" "$schema" "$ptype" "$plabel" "$bytes" "$uuid" "$ftype" >> ${scratchfile}.vol fi done < ${scratchfile}.dsk result=`filecheck -sl ${scratchfile}.vol` if [ "$result" != "" ]; then lines=`cat ${scratchfile}.vol | wc -l` stat=0 if [ "$param" != "auto" ]; then confirm "\nDisks or Partitions found with size greater 4096 blocks that are not formatted. Format them?" --yes "y/[yes]" --no "n/no" stat=$? printf "\n" fi if [ $stat -eq 0 ]; then ### ToDo: Get filesystem from tag mkfs=`filecheck -x mkfs.xfs` # uuidgen=`filecheck -x uuidgen` if [ "$mkfs" != "" ]; then i=2 while [ $i -le $lines ]; do line=`sed -n "${i}p" < ${scratchfile}.vol` disk=`echo "$line" | cut -d' ' -f1` schema=`echo "$line" | cut -d' ' -f2` ptype=`echo "$line" | cut -d' ' -f3` plabel=`echo "$line" | cut -d' ' -f4` bytes=`echo "$line" | cut -d' ' -f5` uuid=`echo "$line" | cut -d' ' -f6` ftype=`echo "$line" | cut -d' ' -f7` label="" ro="no" if [ "$disk" != "" ]; then if [ -f ${scratchfile}.pfm ]; then if [ "$schema" = "raid" ]; then label="$plabel" else bdisk=`basename "$disk"` str=`ls -l /dev/oracleoci | grep "/$bdisk$"` if [ "$str" != "" ]; then device="/dev/oracleoci/"`echo $str | cut -d' ' -f9` str=`grep "^$device " ${scratchfile}.pfm` label=`echo "$str" | cut -d' ' -f6` ro=`echo "$str" | cut -d' ' -f4` fi fi fi if [ "$ro" = "no" ]; then if [ "$label" != "" ]; then $mkfs -q "$disk" -L "$label" stat=$? else # uuid=`$uuidgen` # $mkfs -q -m "uuid=$uuid" "$disk" $mkfs -q "$disk" stat=$? fi if [ $stat -eq 0 ]; then echo "Disk '$disk' formatted." else echo "Unable to format disk '$disk'." fi else echo "Disk '$disk' is read-only. Formatting skipped." fi else echo "Disk not found." fi let "i+=1" done LinuxListAllDisks else echo "No 'mkfs.xfs' in PATH." fi else echo "Leaving disks unchanged." fi fi filecheck -rm ${scratchfile}.vol fi } # Linux: Partition and format all disks (that are not already formatted) function FormatLinux2() { dprefix=${1} # Check if we have blkid available blkid=`filecheck -x blkid` if [ "$fdisk" != "" -a "$blkid" != "" ]; then # Create list of all formatted disks $blkid | sort > $scratchfile result=`filecheck -s $scratchfile` if [ "$result" != "" ]; then printf "disk\tuuid\ttype\n" > ${scratchfile}.inf while read -r line; do disk=`echo "$line" | cut -d':' -f1` str=`echo "$line" | cut -d':' -f2-` par1=`echo $str | cut -d' ' -f1` par2=`echo $str | cut -d' ' -f2` par3=`echo $str | cut -d' ' -f3` par4=`echo $str | cut -d' ' -f4` result=`echo $par1 | grep '^UUID="'` if [ "$result" != "" ]; then uuid=`echo $par1 | cut -d'"' -f2` ftype=`echo $par2 | cut -d'"' -f2` else uuid=`echo $par2 | cut -d'"' -f2` ftype=`echo $par3 | cut -d'"' -f2` fi printf '%s\t%s\t%s\n' "$disk" "$uuid" "$ftype" >> ${scratchfile}.inf done < $scratchfile fi # Check all disks $fdisk -l 2>&1 | grep "Disk $dprefix" > $scratchfile result=`filecheck -s $scratchfile` if [ "$result" != "" ]; then haveunformatted=0 haveresized=0 printf "disk\tsize\tbytes\tsectors\tpart\ttype\n" > ${scratchfile}.vol while read -r line; do disk=`echo "$line" | cut -d':' -f1 | sed 's|^Disk ||'` str=`echo "$line" | cut -d':' -f2-` size=`echo "$str" | cut -d',' -f1` bytes=`echo "$str" | cut -d',' -f2 | sed 's| bytes$||'` sectors=`echo "$str" | cut -d',' -f3 | sed 's| sectors$||'` part=`$fdisk -l "$disk" 2>&1 | grep "^Disk label type:" | sed 's|^Disk label type: ||'` if [ "$part" != "" ]; then ispart="yes" schema="linux" ftype="" else ispart="no" schema="" ftype=`grep "^$disk " ${scratchfile}.inf | cut -d' ' -f3` if [ "$ftype" = "" ]; then haveunformatted=1 fi fi printf '%s\t%s\t%s\t%s\t%s\t%s\n' "$disk" "$size" "$bytes" "$sectors" "$part" "$ftype" >> ${scratchfile}.vol done < $scratchfile stat=0 if [ "$param" != "auto" ]; then printf "\nDisks found (including boot):\n\n" print-table --import ${scratchfile}.vol printf "\nFormatted disks or partitions found (including boot):\n\n" print-table --import ${scratchfile}.inf if [ $haveunformatted -gt 0 ]; then confirm "\nDisks found that are not formatted. Format them?" --yes "y/[yes]" --no "n/no" stat=$? fi fi if [ $haveunformatted -gt 0 -a $stat -eq 0 ]; then # Need that as input for fdisk printf "n\np\n1\n\n\nw\n" > $scratchfile # Check if we have mkfs and uuidgen available # mkfs=`filecheck -x mkfs.ext4` mkfs=`filecheck -x mkfs.xfs` uuidgen=`filecheck -x uuidgen` if [ "$mkfs" != "" -a "$uuidgen" != "" ]; then while read -r line; do disk=`echo "$line" | cut -d' ' -f1` part=`echo "$line" | cut -d' ' -f5` # if [ "$part" = "" ]; then # # $fdisk "$disk" < $scratchfile # uuid=`$uuidgen` # # $mkfs -j -O extent -U "$uuid" "${disk}1" # $mkfs -m uuid=$uuid "$disk" # fi done < ${scratchfile}.vol fi fi filecheck -rm ${scratchfile}.vol fi filecheck -rm $scratchfile fi } # Solaris: Partition and format all disks (that are not already formatted) function CheckFormatSolaris() { echo "ToDo: Format Solaris" } function CheckMountDisksLinux() { local dprefix=${1} local mountpoint="" local owner="" if [ -r "${scratchfile}.dsk" ]; then printf "disk\tschema\tptype\tbytes\tuuid\ttype\tmountpoint\n" > ${scratchfile}.vol while read -r line; do disk=`echo "$line" | cut -d' ' -f1` schema=`echo "$line" | cut -d' ' -f2` ptype=`echo "$line" | cut -d' ' -f3` bytes=`echo "$line" | cut -d' ' -f6` uuid=`echo "$line" | cut -d' ' -f8` ftype=`echo "$line" | cut -d' ' -f10` mp=`echo "$line" | cut -d' ' -f11` if [ "$disk" != "disk" -a "$mp" = "unused" -a "$uuid" != "" -a "$ftype" != "linux_raid_member" ]; then if [ "$schema" = "disk" -a "$ptype" = "" -o "$schema" = "raid" -o "$schema" = "part" ]; then printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\n' "$disk" "$schema" "$ptype" "$bytes" "$uuid" "$ftype" "$mp" >> ${scratchfile}.vol fi fi done < ${scratchfile}.dsk result=`filecheck -sl ${scratchfile}.vol` if [ "$result" != "" ]; then lines=`cat ${scratchfile}.vol | wc -l` stat=0 if [ "$param" != "auto" ]; then confirm "\nDisks, partitions or RAID found that are not mounted. Mount them?" --yes "y/[yes]" --no "n/no" stat=$? printf "\n" fi if [ $stat -eq 0 ]; then mounttab="/etc/fstab" if [ -f "$mounttab" ]; then i=2 while [ $i -le $lines ]; do line=`sed -n "${i}p" < ${scratchfile}.vol` disk=`echo "$line" | cut -d' ' -f1` schema=`echo "$line" | cut -d' ' -f2` ptype=`echo "$line" | cut -d' ' -f3` bytes=`echo "$line" | cut -d' ' -f4` uuid=`echo "$line" | cut -d' ' -f5` ftype=`echo "$line" | cut -d' ' -f6` mp=`echo "$line" | cut -d' ' -f7` mountpoint="/mnt/$uuid" if [ "$disk" != "" ]; then mountpointtag=`grep " $disk " ${scratchfile}.pfm | cut -d' ' -f13` if [ "$mountpointtag" != "" ]; then mountpoint="$mountpointtag" fi ownertag=`grep " $disk " ${scratchfile}.pfm | cut -d' ' -f14` if [ "$ownertag" != "" ]; then owner="$ownertag" fi fi # Check if disk is already in mounttab result=`grep "^UUID=$uuid" "$mounttab"` if [ "$result" = "" ]; then printf 'UUID=%s\t%s\t%s\t%s\t0\t2\n' "$uuid" "$mountpoint" "$ftype" "defaults,noatime,_netdev" >> $mounttab fi # Check if mountpoint exists if [ ! -d "$mountpoint" ]; then mkdir -p "$mountpoint" fi mount "$mountpoint" 2>/dev/null stat=$? if [ $stat -eq 0 ]; then echo "Disk '$disk' mounted." else echo "Unable to moount disk '$disk'." fi # Check if we have to change owner if [ $stat -eq 0 -a "$owner" != "" ]; then chown "$owner" "$mountpoint" fi let "i+=1" done LinuxListAllDisks else printf "\nNo '$mounttab' found.\n" fi fi fi filecheck -rm ${scratchfile}.vol fi } function CheckDisks() { dprefix=${1} case "$OS" in Linux) CheckRaidsLinux LinuxListAllDisks CheckPartitionsLinux $dprefix CheckFormatLinux $dprefix CheckMountDisksLinux $dprefix CheckFilesystemLinux ;; SunOS) CheckFormatSolaris ;; *) exitcode=5 errormsg $exitcode "Unsupported OS '$OS'. Exiting." esac } # Check if there are unformatted attached disks (OCI) function CheckDisksOCI() { dname="/dev/sd" if [ "$nocli" = false ]; then CheckPlatformOCI $instanceid fi CheckResizedDisks $dname CheckDisks $dname } # Check if there are unformatted attached disks (OPC) function CheckDisksOPC() { dname="/dev/xvd" CheckDisks $dname } # Get infos about the cloud user #function WriteUserfile() { # cloudid=${1} # configfile="" # # if [ "$cloudid" = "ORACLE-OCI" ]; then # configfile=".oci/config.json" # else # if [ "$cloudid" = "ORACLE-OPC" ]; then # configfile=".opc/config.json" # fi # fi # # if [ "$configfile" != "" ]; then # for user in opc ubuntu oracle; do # config=$(eval echo "~${user}/$configfile") # if [ -f "$config" ]; then # printf '{\n "cloud_user": "%s",\n "user_config": "%s"\n}\n' $user $config # return # fi # done # fi #} # Check if we are running on Linux and have root privileges. if [ "$OS" != "Linux" ]; then errstr="This script only supports LINUX." elif [ "$USER" != "root" ]; then # Try sudo check-sudo stat=$? if [ $stat -eq 0 ]; then printf 'sudo -n "%s"' "$script" > $scratchfile while [ $# -gt 0 ]; do pname=${1} printf ' "%s"' "$pname" >> $scratchfile shift done # Execute script chmod 700 $scratchfile $scratchfile stat=$? # Cleanup rm -f $scratchfile exit $stat else # Need root privileges errstr="Root privileges needed to continue." fi fi # Preset raidspace=132096 diskspace=1048576 cloudid="" instanceid="" # clouduser="opc" # username="default" # userconfig="" isextendable=0 raidextendable=0 partfixed=0 nocli=false param="" # Check parameters: Loop until all parameters are used up while [ $# -gt 0 ]; do pname=${1} case "$pname" in -v | --version) shift showversion=true ;; -h | --help) shift showhelp=true ;; -n | --nocli) shift nocli=true ;; *) shift paramck=`echo "$pname" | grep '^-'` # Parameters don't begin with '-' if [ "$paramck" != "" ]; then errstr="Unknown option '$pname'." else if [ "$param" = "" -a "$paramck" = "" ]; then param=`echo "$pname" | tolower` else errstr="Unknown additional parameter: '$pname'." fi fi esac done # Display help or error message DisplayHelp # Main # Check if we could use "fdisk -l" fdisk=`filecheck -x fdisk` if [ "$fdisk" != "" ]; then "$fdisk" -l >/dev/null 2>&1 stat=$? if [ $stat -ne 0 ]; then fdisk="" fi fi if [ "$USER" = "root" ]; then # Logfile if [ "$LOGFILE" != "" ]; then logfile="$LOGFILE" else logdir="/var/log" if [ -d "$logdir" ]; then mkdir -m 0755 -p "$logdir" fi logfile="${logdir}/${progstr}.log" touch $logfile fi # Create infofolder, if it does not exists if [ ! -d "$infofolder" ]; then mkdir -m 0755 -p "$infofolder" fi # Get infos about the cloud (if we don't have already an info file) if [ ! -f "$cloudfile" ]; then get-cloud --output json > $cloudfile chmod 644 $cloudfile fi result=`filecheck -sl "$cloudfile"` if [ "$result" != "" ]; then cloudid=`cat "$cloudfile" | browse-json --raw --quiet --select 1 "cloud_id"` instanceid=`cat "$cloudfile" | browse-json --raw --quiet --select 1 "instance_id"` else filecheck -rm "$cloudfile" fi # Get infos about the cloud user (if we don't have already an info file) # if [ ! -f "$userfile" ]; then # WriteUserfile $cloudid > "$userfile" # fi # # result=`filecheck -sl "$userfile"` # if [ "$result" != "" ]; then # clouduser=`cat "$userfile" | browse-json "cloud_user"` # userconfig=`cat "$userfile" | browse-json "user_config"` # else # filecheck -rm "$userfile" # fi # # if [ "$userconfig" != "" ]; then # result=`filecheck -sl $userconfig` # if [ "$result" != "" ]; then # username=`cat "$userconfig" | browse-json "keys/username"` # fi # fi if [ "$cloudid" = "ORACLE-OCI" ]; then if [ "$nocli" = false ]; then oci=`filecheck -x oci` if [ "$oci" = "" ]; then exitcode=3 errormsg $exitcode "($progstr) OCI CLI 'oci' not in PATH." else echo "n" | $oci os ns get > $scratchfile 2>&1 stat=$? if [ $stat -eq 0 ]; then # namespace=`browse-json "data" --import $scratchfile --quiet` namespace=`cat $scratchfile | norm-json --select 1 --quiet` if [ "$namespace" == "" ]; then exitcode=4 errormsg $exitcode "($progstr) OCI CLI 'oci' not configured correct." fi else exitcode=4 errormsg $exitcode "($progstr) OCI CLI 'oci' not configured correct. Status: '$stat'." fi fi fi # Do the work if [ $exitcode -eq 0 ]; then CheckDisksOCI fi else if [ "$cloudid" = "ORACLE-OPC" ]; then if [ "$nocli" = false ]; then opc=`filecheck -x opc` if [ "$opc" = "" ]; then exitcode=3 errormsg $exitcode "($progstr) OPC CLI 'opc' not in PATH." fi fi # Do the work if [ $exitcode -eq 0 ]; then CheckDisksOPC fi else exitcode=2 errormsg $exitcode "Unable to determine 'cloud_id'. Exiting." fi fi fi # Cleanup and exit Cleanup exit $exitcode