tool_dev - OpenNebula/one-apps GitHub Wiki

Developer Information

Repository Structure

├── appliances             # src for "service appliances", containing the appliance logic
│   ├── example            # example appliance implementation logic
│   ├── Harbor             # Harbor Docker Registry appliance
│   ├── lib                # Ruby libraries for appliance service management
│   ├── MinIO              # MinIO storage solution appliance logic
│   ├── OneKE              # OneKE service logic
│   ├── scripts
│   ├── VRouter            # VRouter logic
│   └── Wordpress          # Logic for the WordPress appliance from the OpenNebula Marketplace
├── build
├── context-linux          # src for Linux content packages
├── context-windows        # src for Windows context packages
├── export                 # where built images are dumped to
│   ├── alma8.qcow2
│   ├── alpine318.qcow2
└── packer                 # Packer build scripts for each distribution
    ├── alma
    ├── alpine
    ├── alt
    ├── amazon
    ├── build.sh
    ├── debian
    ├── devuan
    ├── fedora
    ├── freebsd
    ├── ol
    ├── opensuse
    ├── plugins.pkr.hcl
    ├── postprocess.sh     # Script used by every appliance to remove any ID acquired during the build process from the VM
    ├── rhel
    ├── rocky
    ├── service_example
    ├── service_Harbor
    ├── service_MinIO
    ├── service_OneKE
    ├── service_OneKEa -> service_OneKE/
    ├── service_VRouter
    ├── service_Wordpress
    └── ubuntu

Appliance Build Process

Appliances are constructed using Packer.io templates, each tailored to accommodate the unique characteristics of various distributions. Within the packer directory, individual folders for each distribution contain:

  • A Packer template file
  • Customization scripts (*.sh files)
  • cloud-init.yaml user data (if required)
└── packer
    ├── alma
    │   ├── 10-upgrade-distro.sh
    │   ├── 11-update-grub.sh
    │   ├── 11-zzz.sh
    │   ├── 80-install-context.sh.8
    │   ├── 80-install-context.sh.9
    │   ├── 81-configure-ssh.sh
    │   ├── 98-collect-garbage.sh
    │   ├── alma.pkr.hcl                           # packer template
    │   ├── cloud-init.yml
    │   ├── plugins.pkr.hcl -> ../plugins.pkr.hcl
    │   └── variables.pkr.hcl

If there are multiple versions of the same distribution (as in the case of Debian 10, 11 and 12), a shared Packer template is used for all them, and the version number is passed to Packer as a parameter.

Whenever feasible, distributions with "cloud" images serve as the starting point, launched via cloud-init within the Packer Qemu Builder. In cases where "cloud" images aren't available, the default image is used, and an installer is executed.

Primarily, this stage focuses on installing "one-context" packages, updating packages, and removing redundant elements.

Subsequently, post-processing takes place within Packer. This involves the utilization of virt-sysprep and virt-sparsify.

Lastly, the image undergoes compression using qemu-img convert -c. While image compression can be optionally be performed within Packer, a separate final compression step often yields smaller image sizes.

Creating a New Appliance

To create a new appliance, you'll need to:

  • Create your custom appliance logic within a directory at ./appliances.
    • Use the provided set of Bash and Ruby libraries for the framework that handles interaction with one-context and streamlines the build process.
    • Define the logic for the install phase. This logic will be invoked when running the make <your_appliance_name> command.
    • Define the logic for the configure phase. This logic will be invoked when the appliance is instantiated as a VM by the OpenNebula Front-end.
  • Create a new set of Packer scripts for the appliance:
    • Link your custom appliance logic on the Packer entry point.
    • Source a base Linux distribution to extend from that as the base OS.
  • Add a Makefile and Makefile.cfg entry linking those Packer scripts.

Example Use Case: Database as a Service

An example appliance is provided at ./appliances/example. It will create a qcow2 image that holds a Database as a Service workload using MariaDB behind the scenes. To build it, run:

make service_example

This will:

  • Build the context packages if these are not already built.
  • Build the Alma8 Linux image if it is not already built. This appliance is based on AlmaLinux 8.
  • Build the service_example.qcow2 image in the ./export directory. The appliance build logic for this step is defined at ./appliances/example/example.sh within the function service_install.

This example.sh script is sourced by Packer at ./packer/service_example/example.pkr.hcl using the following code:

  provisioner "file" {
    source      = "appliances/example/example.sh"
    destination = "/etc/one-appliance/service.d/appliance.sh"
  }

The source code in this example is thoroughly commented; please refer to it for more details.

Using the New Appliance

To use the new appliance, create a VM template with the following contents:

CONTEXT=[
  NETWORK="YES",
  ONEAPP_DB_NAME="mariadb_database",
  ONEAPP_DB_PASSWORD="mariadb_user_password",
  ONEAPP_DB_ROOT_PASSWORD="mariadb_root_password",
  ONEAPP_DB_USER="mariadb_user",
  SSH_PUBLIC_KEY="$USER[SSH_PUBLIC_KEY]" ]
CPU="1"
DISK=[
  IMAGE_ID="9" ]
GRAPHICS=[
  LISTEN="0.0.0.0",
  TYPE="vnc" ]
MEMORY="1024"
NIC=[
  NETWORK_ID="0" ]
OS=[
  ARCH="x86_64" ]
VCPU="2"

Note the following attributes in the CONTEXT section:

  ONEAPP_DB_NAME="mariadb_database",
  ONEAPP_DB_PASSWORD="mariadb_user_password",
  ONEAPP_DB_ROOT_PASSWORD="mariadb_root_password",
  ONEAPP_DB_USER="mariadb_user",

These parameters define the information for connecting to the database.

When you instantiate this template, you should obtain a VM with a MariaDB server running a database that you can connect to. The logic for this process is defined at ./appliances/example/example.sh, within the function service_configure.

You can also modify this VM Template and use OpenNebula's User Inputs feature to create a Wizard where the end user can provide values for the VM parameters, making it possible to instantiate the VM through both the CLI and the web UI.