[arch-releng] Automagic Profiles Loader

Dieter Plaetinck dieter at plaetinck.be
Mon Apr 6 07:28:03 EDT 2009


On Mon, 6 Apr 2009 11:44:31 +1000
Jud <jud at judfilm.net> wrote:

> On Sun, 5 Apr 2009 16:54:00 +0200
> Dieter Plaetinck <dieter at plaetinck.be> wrote:
> 
> > On Mon, 6 Apr 2009 00:22:11 +1000
> > Jud <jud at judfilm.net> wrote:
> > 
> > > This code is to be automatically run from a custom Arch Boot
> > > Media, it will call aif with the best matching profile.
> > > 
> > > Comments and suggestions welcome.
> > > 
> > > #!/bin/bash
> > > # Proof of Concept - Automagic Profiles Loader
> > > #
> > > # BASIC HARDWARE DETECT
> > > #
> > > 
> > > # MAC address - output each device on separate line?; array?
> > > mac=$(ifconfig -a | awk '/HWaddr/ {print $NF, $1}')
> > > #echo $mac
> > > 
> > > # System Architecture - i686/x86_64
> > > # could use CARCH?
> > > arch=$(uname -m)
> > > #echo $arch
> > > 
> > > # CPU Brand, Model Name, Processors, Sockets, GHz, Family, Model,
> > > Stepping, Flags cpu=$(cat /proc/cpuinfo | awk '/^vendor_id/ {print
> > > $NF; exit}')
> > > #cpu=$(uname -i)
> > > cpu2=$(cat /proc/cpuinfo | grep "model name" | awk '{ for (i=4;
> > > i<=NF; i++) printf("%s ", $i); exit }')
> > > #cpu2=$(uname -p)
> > > cpu3=$(cat /proc/cpuinfo | grep -c processor)
> > > cpu3a=$(cat /proc/cpuinfo | grep "cpu cores" | awk '/^cpu/ {print
> > > $NF; exit}')
> > > cpu4=$(cat /proc/cpuinfo | grep -c physical) # need a better
> > > way; total sockets, ht?
> > > cpu5=$(cat /proc/cpuinfo | grep MHz | awk '/^cpu/ {printf
> > > ("%4.1f",$NF/1000); exit}')
> > > cpu5=${cpu5}GHz
> > > cpu6=$(cat /proc/cpuinfo | awk '/family/ {print $NF; exit}')
> > > cpu7=$(cat /proc/cpuinfo | awk '/^model/ {print $NF; exit}')
> > > cpu8=$(cat /proc/cpuinfo | awk '/^stepping/ {print $NF; exit}')
> > > cpu9=$(cat /proc/cpuinfo | grep flags | awk ' { for (i=3; i<=NF;
> > > i++) printf("%s ", $i);exit }')
> > > #echo $cpu $cpu2 $cpu3 $cpu3a $cpu4 $cpu5 $cpu6 $cpu6a $cpu7 $cpu8
> > > #echo $cpu9
> > > 
> > > # Mainboard Model Number, Chipset - need a much better way
> > > mb=$(dmesg | grep RSDT | awk '/^ACPI/ {print $6, $7}')
> > > #mb2=$(dmesg | grep RSDT)
> > > mb2=$(lspci | grep "Host Bridge")
> > > #echo $mb
> > > #echo $mb2
> > > 
> > > # Total RAM - GB
> > > mem=$(cat /proc/meminfo | awk '/^MemTotal/ {printf
> > > ("%5.1f",$2/1048576)}') mem=${mem/.0/}GB
> > > #echo $mem
> > > 
> > > # Hard Disk Capacity - GB
> > > #hdd=$(fdisk -l | grep /dev/sda | awk '/^Disk/
> > > {printf("%5.0f",$5/1000000000)}')
> > > hdd=$(cat /proc/partitions | grep sda | awk '/sda/
> > > {printf("%5.0f",$3/1000000); exit}')
> > > if [[ ${hdd:2:1} =~[1-9] && ${#hdd} -ge 3 ]]; then
> > > hdd2=$((${hdd:0:1}+1))$(echo "${hdd//[1-9]/0}" | sed
> > > 's/^.\{1\}//g') else
> > >  hdd2=$hdd
> > > fi
> > > hdd2=${hdd2}HD
> > > #echo $hdd $hdd2
> > > 
> > > # Video Card Vendor - Others?
> > > vga=$(lspci | grep VGA | tr "[:lower:]" "[:upper:]")
> > > for i in ATI NVIDIA INTEL; do
> > >   if [[ $vga == *${i}* ]]; then
> > >     vga=$i
> > >   fi
> > > done
> > > vga=VGA:$vga
> > > #echo $vga
> > > 
> > > # VirtualMachine - Am I inside the Matrix?
> > > for i in VBOX VMWARE XEN KVM; do
> > >   vm=$(dmesg | grep -i -o ${i})
> > >   if [[ $vm == *${i}* ]]; then
> > >     vm=${i}; exit 0
> > >   fi
> > > done
> > 
> > is there anything wrong with running in a vm? what's your goal here?
> > preventing your script to work when it's run in a vm?
> 
> No, nothing at all. My idea was to "know" as much about the system and
> provide "hooks" for future use.
Ok, it was just because you have "exit 0" when you detect a VM. but you
probably still need to clean that up...
> 
> Another idea was to detect the current installed OS on the HDD and
> provide hooks for the possibility of an automated install to create a
> Dual/Multi Boot system.
If you really think you need this, feel free to implement.  I don't
think I'll ever need this.
> 
> > > testline="$mac $arch $cpu $cpu2 $cpu3 $cpu4 $cpu5 $cpu6 $cpu7
> > > $cpu8 $cpu9 $mem $hdd2 $vga $vm"
> > > #echo $testline
> > > 
> > > 
> > > #
> > > # PROFILE SELECTOR
> > > #
> > > 
> > > #[ -r profiles ]
> > > cat profiles | while read line; do
> > >   # Skip Comments and Empty Lines
> > >   [[ ${line:0:1} == "#" ]] && continue
> > >   [[ -z "$line" ]] && continue
> > > 
> > >   # Profile Filename
> > >   if [[ ${line:0:1} == "[" ]] ; then
> > >     answer=$(echo ${line//[/} | cut -d] -f1-1); continue
> > "$answer?" a name like "$profile" might make more sense here.
> > 
> > >   else
> > >     # Profile Parameters
> > >     line=$(echo "$line" | cut -d \# -f1-1 | sed 's/[ \t]*$//')
> > >     result=""
> > >     # Match Engine
> > >     for each_name in $line; do
> > >       if [[ $testline == *$each_name* ]]; then
> > >         result=$(echo $result $each_name)
> > >       fi
> > >     done
> > >     # Complete Match?
> > >     if [[ $result == $line ]]; then
> > >       echo "Loading Profile..."
> > >       echo "aif -p automatic -c $answer"
> > maybe you could actually call aif.  but hey that's just an idea :)
> > Also I would not exit 0, but rather use the same exitcode as aif
> > itself. can be useful.
> 
> The "success" part of the script was just to show it selected the
> correct profile. My idea here is to have it run aif then send an email
> report and automatically reboot. 
> 
> > >       exit 0
> > >     fi
> > >  fi
> > > done
> > > 
> > > # End of File
> > 
> > I checked your sample config and it looks nice imho.
> > So it's all blocks of [profilename] with "matching rules" below it
> > right? 
> 
> Each line is a rule and it relates to a certain hardware
> configuration. Each rule can be as many of the tests to try and
> uniquely identify the system. The rule must match completely for the
> profile to be selected. There can be multiple rules per profile. At
> the moment the matching logic will only select the first complete
> rule, so generic type profiles should be at the bottom of the file.
> 
> Filenames: This is still very much in the air, atm I have "profiles"
> and not sure which directory it should live in. Any ideas, comments
> would be appreciated. For each profiles filename what would be better
> $profile, $profile.profile, $profile.aif, $profile.apl?

I'm not sure.. 
right now we use /usr/lib/aif/user/ for user modules
(libraries+procedures).  But I feel that configs/profiles don't really
belong there.
Another option could be /etc, but I think they don't belong there either
because they are not really config files like the others.
Maybe /var/lib/aif/profiles ?

Input very welcome for this.

I would not use any extension.

> 
> > I'm asking because I remember you said you wanted to be able to
> > reboot automatically if aif exited successfully.  So I was thinking
> > you could put such parameters like reboot_on_success in there.
> > (below the matching rules, on a per-profile basis). to make your
> > code able to recognize what is a matching rule and what's an option
> > you could maybe do like this (just an idea):
> > [profilename]
> > match matching rule 1
> > match matching rule 2
> > option variable value
> 
> I'd rather not have any options in the profiles file but never say
> never.
>  
> > Also i would avoid caps as much as possible, it always make it
> > easier in code if you can know you never need to convert between
> > upper and lowercase.
> 
> Thanks, this stage of the development is like "throwing mud at the
> wall". After trying to make it more robust and the obvious cleanups, I
> need to work out how to make this autoload after grub and still have
> the default options on the default boot media.
> 
> > PS: APL seems like a good name to me
> 
> Thanks.
>  
> > Dieter



More information about the arch-releng mailing list