Deploy Image from Remote Server

Hi,

In some development cycle, we need to daily build images and deploy it to various hardware device (such as workstation, laptop and IoT boards, etc…).
Frequency to remove image, push image and wait image to sync to rack controller will increase our development cycle.

Thus, I wrote a hook script to download image from remote server, like:

# cat /etc/maas/preseeds/curtin_userdata_custom_amd64_generic_oem-image-mapping
#cloud-config
early_commands:
  pause-off: |
    #!/bin/bash
    if [ ! -e /home/ubuntu/url-replaced ]; then
      sudo touch /run/block-curtin-poweroff /tmp/block-poweroff /tmp/block-reboot
    fi
late_commands:
  redir-image-path: |
    #!/bin/bash
    set -x
    if [ ! -e /home/ubuntu/url-replaced ]; then
    {
      touch /home/ubuntu/url-replaced
      sudo DEBIAN_FRONTEND=noninteractive apt-get install -y sshpass

      # To get credential to access remote server
      # /usr/bin/sshpass ...
      # ...

      # To get a mapping table to know which image should be used on this MAC
      # ... git clone ...

      # To get the URL of image for this device
      URL=$(cat $(find oem-maas-images-map -name "$(cat /sys/class/net/$(arp| grep oem-taipei-staging-maas| awk '{print $NF}')/address)")| head -n 1)

      # Replace the URL of curtin config
      /bin/sed -i -e "s%^COMMAND.*$%$(awk -v link="dd-xz:$URL" 'BEGIN { FS=OFS=" " } $11 ~ /dd-xz:/ {$11 = "'\''"link"'\''"; print}' /var/lib/cloud/instance/scripts/part-001)%Ig" /var/lib/cloud/instance/scripts/part-001

      # Create a script to replace image later
      echo '#!/bin/bash' >> /home/ubuntu/redo-curtin.sh
      echo 'set -x' >> /home/ubuntu/redo-curtin.sh
      echo 'sleep 60' >> /home/ubuntu/redo-curtin.sh
      echo $(sudo grep "^COMMAND" /var/lib/cloud/instance/scripts/part-001) >> /home/ubuntu/redo-curtin.sh
      echo 'sudo rm /run/block-curtin-poweroff /tmp/block-poweroff /tmp/block-reboot' >> /home/ubuntu/redo-curtin.sh
      echo 'cd /curtin' >> /home/ubuntu/redo-curtin.sh
      echo 'sudo ./bin/${COMMAND[@]}' >> /home/ubuntu/redo-curtin.sh
      echo "id=\$(sudo cat /etc/cloud/cloud.cfg.d/91_kernel_cmdline_url.cfg| grep endpoint| awk -F \"'\" -v OFS=\"'\" '{print \$2}'| awk -F \"/\" '{print \$NF}')" >> /home/ubuntu/redo-curtin.sh
      echo 'wget --no-proxy http://192.168.101.1:5248/MAAS/metadata/latest/by-id/${id}/ --post-data op=netboot_off -O /dev/null' >> /home/ubuntu/redo-curtin.sh
      echo 'sudo reboot' >> /home/ubuntu/redo-curtin.sh

      # redo curtin again
      bash /home/ubuntu/redo-curtin.sh &
    } > /home/ubuntu/redir-image-path-output 2>&1
    fi

This implementation looks like ugly but very useful.
MaaS will store all images inside MaaS DB instead of store index only.
Therefore, our server usually have more than 250GB’s images inside DB and we plan to daily backup whole container because of node information is important.
The images is not important because those was daily built.

We would like to deploy image from remote source and without need to upload to MaaS.
Then we have above hook and works very well in v2.5 MaaS.

I would like to ask if MaaS could supports this kind of idea to avoid to upload images to MaaS to save storage. (simplestream still need to fetch all images from remote source).

Here is two suggestions could achieve this goal:

  1. Create a UI option when selecting image for deployment and allow user fill URL such as:
    ftp://…/jenkins_host/jobs/…/builds/lastSuccessfulBuild/archive/out/maas-compatiable-image.img.xz
  2. Use the curtin hook likes what we did and
    2.1. Support a hook or config or CLI for user to pass private information (e.g. credential) to target device through cloud-init
    2.2. Support a hook or config or CLI to customize /var/lib/cloud/instance/scripts/part-001