summaryrefslogblamecommitdiffstats
path: root/modules.d/dnbd3-rootfs/hooks/prepare-root-partition.sh
blob: bef92ce97a9a7207559db191d9822f54947c38d9 (plain) (tree)
1
2
3
4
5
6
7
8
                   

                                                                  

                                  

                                       
 










                                                                   
                                                        


                                                   
                                                           


                                                    

                                                            

                                                              




                      
                          
                        
                                     
                                                                        
                                                              

              
                  
                      


           
                            




                                                                     
  
                                  


                                                                      
  

                                                    
                           

                                                         


                                                            
  
 
        

                          
                                                                  
                                               


                                                                  
      

                                             




                                                       

           
    
 
           
                           


                                                                   

                                   

                                                               
  
                                                  
                                                              
  
                                   
                                                               
  
 
                                            


                                                       
 
           
                                                 
                                                          


                                                                            
                                                      






                                                                            
      
 
    

                                                   
                                        
                                                         


                                                                    
  
                                                      

           


                                                                
           
#!/usr/bin/env bash
type emergency_shell > /dev/null 2>&1 || source /lib/dracut-lib.sh
source /etc/openslx

export PATH="/usr/local/bin:$PATH"
export LD_LIBRARY_PATH="/usr/local/lib"


# hardcode dnbd device path
declare -rg _dnbd3_dev="/dev/dnbd0"

# all outputs are redirected to stderr, since this functions should
# only echo the path to the unpacked container to stdout.
container_unpack_xmount() {
    local in_device="$1"
    local out_path="/mnt/xmount"
    mkdir -p "$out_path"
    # check tools first
    if ! hash xmount systemd-preserve-process-marker; then
        warn "Missing xmount deps, will try raw..." 1>&2
    elif ! systemd-preserve-process-marker xmount \
            --in qemu "$in_device" \
            --out raw "$out_path" &>/dev/null; then
        warn "xmount call failed, assuming raw image." 1>&2
    else
        in_device="${out_path}/${_dnbd3_dev##*/}.dd"
    fi
    local out_device="$(losetup -f)"
    if ! losetup "$out_device" "$in_device" --partscan; then
        warn "Failed to attach '$in_device' to '$out_device'."
        return 1
    fi
    udevadm settle
    echo "$out_device"
}

container_unpack_xloop() {
    local in_device="$1"
    local out_device="$(xlosetup -f)"
    if ! xlosetup -r -t QCOW "$out_device" "$in_device" --partscan; then
        warn "Failed to attach '$in_device' to '$out_device'."
        return
    fi
    udevadm settle
    echo "$out_device"
}
# endregion

# region connect dnbd3 image
# Determine path to dnbd3 image: either on the kcl or via config file
declare -r KCL_DNBD3_IMAGE="$(getarg slx.stage4.path=)"
if [ -n "$KCL_DNBD3_IMAGE" ]; then
    SLX_DNBD3_IMAGE="$KCL_DNBD3_IMAGE"
    echo "SLX_DNBD3_IMAGE='$SLX_DNBD3_IMAGE'" >> /etc/openslx
fi
if [ -z "$SLX_DNBD3_IMAGE" ]; then
    emergency_shell "Failed to determine which DNBD3 image to use." \
        "It was neither specified on kernel command line nor in the" \
        "configuration file."
fi
declare -r KCL_DNBD3_RID="$(getarg slx.stage4.rid=)"
if [ -n "$KCL_DNBD3_RID" ]; then
    # specified on the KCL?
    SLX_DNBD3_RID="$KCL_DNBD3_RID"
    echo "SLX_DNBD3_RID='$SLX_DNBD3_RID'" >> /etc/openslx
fi
if [ -n "$SLX_DNBD3_RID" ]; then
    _dnbd3_client_additional_args=("--rid" "$SLX_DNBD3_RID")
fi

IFS=", "
for try in {1..5} ""; do
    if [ -z "$try" ]; then
        emergency_shell "Failed to connect '${SLX_DNBD3_IMAGE}'" \
            "(revision: ${SLX_DNBD3_RID:-0})" \
            "from one of '$SLX_DNBD3_SERVERS' to '$_dnbd3_dev'." \
            "Check if the image exists on one of the servers" \
            "and if any is reachable from this client."
    fi
    info "Trying hosts '$SLX_DNBD3_SERVERS'."
    if dnbd3-client \
            --host "$SLX_DNBD3_SERVERS" \
            --image "$SLX_DNBD3_IMAGE" \
            --device "$_dnbd3_dev" \
            "${_dnbd3_client_additional_args[@]}"; then
        break
    fi
    sleep 1
done

# endregion
# region unpack dnbd3 image
if ! [[ $SLX_QCOW_HANDLER =~ ^(kernel|xloop|xmount)?$ ]]; then
    emergency_shell "Unsupported QCOW handler: $SLX_QCOW_HANDLER" \
        "Use either 'xmount' or 'xloop'."
fi
if [ -z "$SLX_QCOW_HANDLER" ]; then
    SLX_QCOW_HANDLER="xloop"
    echo "SLX_QCOW_HANDLER='$SLX_QCOW_HANDLER'" >> /etc/openslx
fi
if [[ $SLX_QCOW_HANDLER =~ ^kernel|xloop$ ]]; then
    read_only_device="$(container_unpack_xloop "$_dnbd3_dev")"
fi
if [ -z "$read_only_device" ]; then
    read_only_device="$(container_unpack_xmount "$_dnbd3_dev")"
fi

# Fail fast if unpacking dnbd3 image failed.
if [ -z "$read_only_device" ]; then
    emergency_shell "Failed to unpack the qcow2 image!"
fi

# endregion
# region find system partition within dnbd3 image
if [ -z "$SLX_SYSTEM_PARTITION_PREPARATION_SCRIPT" ]; then
    # Find requested root partition - default to SLX_SYS label
    read_only_partition="$( slx-tools dev_find_partitions \
        "$read_only_device" "${SLX_SYSTEM_PARTITION_IDENTIFIER:-SLX_SYS}" )"
    if [ -z "$SLX_SYSTEM_PARTITION_IDENTIFIER" ]; then
        if [ -n "$read_only_partition" ]; then
            # Defaulting to SLX_SYS worked
            echo "SLX_SYSTEM_PARTITION_IDENTIFIER='SLX_SYS'" >> /etc/openslx
        else
            # Aussume there is no partition table
            read_only_partition="$read_only_device"
        fi
    fi

else
    eval "$SLX_SYSTEM_PARTITION_PREPARATION_SCRIPT"
fi
if [[ -z "$read_only_partition" ]]; then
    warn "Failed to find unique device with identifier" \
        "\"${SLX_SYSTEM_PARTITION_IDENTIFIER}\"; matched devices:" \
        "\"${read_only_partition}\""
    exit 1
fi
info "Using read-only partition: $read_only_partition"
# endregion

# region add rw layer to dnbd3 image
# don't be fooled to think we are done, the next part is crucial
dmsetup-slx-device "$read_only_partition"
# endregion