summaryrefslogblamecommitdiffstats
path: root/builder/dnbd3-rootfs/hooks/prepare-root-partition.sh
blob: e5881ca092baae35e17e985dcfd003021c422843 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                   
                
                                                        
                                

                      



                                    
           
                                 
 


                                     
                      
                 
       
             
                                    

                                                                            

                                                                               
        
                     

             

                 
 
                                
                                                                                    
                                                             
          
  


                                   
                                    



                                                                             
                                                              















                                                                 
 
                                         






                                                                          
                           
                                                         
                  
                                   
  
 









                                                                         
    
           
 
                                  






                                                                 
                          
                                        
                                      
 
                            
                                                   
   
 
                                                                   
                                    
                                        
                                                          
                      
      
    
                                    
                                     
                                                                         
      


                                                   
  




                                                           
               
 


                                           

                                                           
                                                           
                                                                               
             
                    
                                                                
                                                                                             
                                                       


                                                                     

            
                     





                                                     
#!/usr/bin/env bash
# region imports
type getarg >/dev/null 2>&1 || source /lib/dracut-lib.sh
source "/usr/lib/rebash/core.sh"
core.import exceptions
exceptions.activate
core.import utils
core.import logging
logging.set_commands_log_level debug
logging.set_log_level debug
# endregion
( # subshell for variable scoping

SLX_SERVER_BASE="$(getargs slxbase=)"
source /etc/openslx

# region connect dnbd3
IFS_backup="$IFS"
IFS=","
return_code=1
for host in ${SLX_DNBD3_SERVERS}; do
    logging.info "Trying host '$host'."
    if systemd-preserve-process-marker dnbd3-client --host "$host" --image \
        "${SLX_SERVER_BASE#/}${SLX_DNBD3_IMAGE}" --device "$SLX_DNBD3_DEVICE" \
        --rid "$SLX_DNBD3_RID"
    then
        return_code=0
        break
    fi
done
IFS="$IFS_backup"

if [[ $return_code != 0 ]]; then
    logging.warn "Failed to connect '${SLX_SERVER_BASE#/}${SLX_DNBD3_IMAGE}' from" \
        "one of '$SLX_DNBD3_SERVERS' to '$SLX_DNBD3_DEVICE'."
    exit 1
fi
# endregion

# region detect read-only partition
read_only_device="$SLX_DNBD3_DEVICE"
if ! qemu-img info --output json "$read_only_device" | grep '"format": "raw"'
then
    read_only_device='/dev/nbd0'
    systemd-preserve-process-marker qemu-nbd --connect="$read_only_device" \
        "$SLX_DNBD3_DEVICE" --read-only --persistent --nocache

    # XXX better way to wait for the device to be made?
    i=0
    while [ ! -b "$read_only_device" ]; do
        [ $i -ge 20 ] && exit 1
        if [ $UDEVVERSION -ge 143 ]; then
            udevadm settle --exit-if-exists="$read_only_device"
        else
            sleep 0.1
        fi
        i=$(($i + 1))
    done

    # NBD doesn't emit uevents when it gets connected, so kick it
    echo change > /sys/block/nbd0/uevent
    udevadm settle

    # wait for partitions TODO make nicer
    #touch $read_only_device
    #udevadm settle
else
    # workaround to detect partitions on raw disks
    # can be omited when the dnbd3 kernel module supports it (like the nbd
    # kernel module with parameter 'max_part')
    loop_device="$(losetup -f)"
    touch $read_only_device
    losetup "$loop_device" "$read_only_device" --partscan
    udevadm settle
    read_only_device="$loop_device"
fi

for i in 0.5 1 2; do
    if read_only_partition=$(utils.find_block_device \
            "$SLX_SYSTEM_PARTITION_IDENTIFIER" "$read_only_device"); then
        break
    else
        logging.warn "Failed to find unique device with identifier" \
            "'${SLX_SYSTEM_PARTITION_IDENTIFIER}'; matched devices:" \
            "'${read_only_partition}'"
        sleep $i
    fi
done
# endregion

# region detect writable partition
if ! persistent_device=$(utils.find_block_device \
        "$SLX_WRITABLE_DEVICE_IDENTIFIER"); then
    logging.warn "Failed to find unique device with identifier" \
        "'${SLX_WRITABLE_DEVICE_IDENTIFIER}'; matched devices:" \
        "'${persistent_device}'"
fi

# TODO move somewhere else
#tmp_device="$(utils.find_block_device \
    #'$SLX_TMP_PARTITION_IDENTIFIER')"

#if [ -n $tmp_device ]; then
    #mount --type auto "$tmp_device" "$NEWROOT/tmp"
#fi

persistent='N' # 'P' for persistent storage, 'N' for not persistent
if [ -n "$persistent_device" ]; then
    writable_device="$persistent_device"
    if [ "$SLX_WRITABLE_DEVICE_PERSISTENT" = "yes" ]; then
        persistent='P'
    fi
else
    ramdisk_size="$SLX_RAMDISK_SIZE"
    if [ "$ramdisk_size" = "" ]; then
        ramdisk_size="$(cat /proc/meminfo | awk '/MemTotal/ {print $2}')"
    fi
    modprobe brd max_part=1 rd_size="$ramdisk_size"
    writable_device='/dev/ram0'
    persistent='N'
fi

# persistent storage on a filesystem (e.g. usb stick)
# writable_device="$(losetup -f)"
#dd if=/dev/zero of=persistent_storage.img bs=1k count=1000
#losetup "$writable_device" persistent_storage.img
#persistent='P'

# endregion

# region combine devices with device mapper
partition_size="$(blockdev --getsz "$read_only_partition")"
writable_partition_name='root'
logging.info "Using read-only device: $read_only_partition"
logging.info "Using writable device $writable_device, persistency: $persistent"
chunksize='1'
modprobe dm_snapshot
dmsetup create "$writable_partition_name" --noudevsync --table \
    "0 $partition_size snapshot $read_only_partition $writable_device $persistent $chunksize"
dmsetup mknodes --noudevsync "$writable_partition_name"
# TODO remove
echo 'IgnoreOnIsolate=true' >> /usr/lib/systemd/system/sockets.target
# end TODO
# endregion
) || exit $?
exceptions.deactivate
# region vim modline

# vim: set tabstop=4 shiftwidth=4 expandtab:
# vim: foldmethod=marker foldmarker=region,endregion:

# endregion