Skip to content

Using Hooks

You can use hooks in SolusVM 2 to automatically run custom scripts before or after specific events take place.

In a nutshell, here's how hooks in SolusVM 2 work:

  • You can create a special directory on the management node and/or any compute resources. You can have a hook tied to a specific event behave differently on compute resources A and B, and be absent altogether from compute resource C.

  • In the directory, you need to place one or more executable files containing a custom script. Custom scripts can be written in Bash, PHP, Python, Golang, Java, or any other programming language able to parse a JSON file passed to it.

  • Every time one of the supported events, such as a virtual server being rebooted, takes place for a virtual server, SolusVM 2 executes all custom scripts found on the management node or compute resource hosting that virtual server. You can find the complete list of supported events further in this topic. You cannot create hooks for unsupported events. Every configured hook is triggered twice per event: before and after the event takes place. Hooks are triggered regardless of whether a supported event is initiated via the GUI, CLI, or API.

  • When a hook is triggered, SolusVM 2 passes to it a JSON object containing the following information: the type of the event, whether the hook was triggered before or after the event, and also certain relevant data, such as the ID of the virtual server in question.

For example, when a new virtual server is being created, the "virtual server created" event is triggered. It passes, among other data, the newly created virtual server's IP address. You can create a custom script that would parse the incoming JSON object, take that data, and use it to create the necessary firewall rules on the compute resource hosting it.

Creating a Hook

We recommend using a single file as the starting point, which will determine which other scripts or commands to execute.

To create a hook on the management node or compute resource:

  1. Log in to the management node or compute resource via SSH as the "root" user.
  2. Create a directory named /usr/local/solus/hooks/ if it does not exist.

    mkdir /usr/local/solus/hooks/

  3. Create a file and paste your custom script into the file. You can give the file any name you want, for example, "hook.sh".

    touch /usr/local/solus/hooks/hook.sh

  4. Make the file executable.

    chmod +x /usr/local/solus/hooks/hook.sh

Your hook is now created. The executable will be run every time a supported event takes place. You cannot configure SolusVM 2 to only run specific executables for specific events. The custom script must be able to parse the JSON object and perform certain action(s) depending on its contents.

When a supported event takes place, all configures hooks (if any) are triggered. The action is paused on the SolusVM 2 side until all custom scripts have exited, or until one minute has passed, whichever comes first. So, for example, here's what happens when a virtual server is restarted, and there are one or more hooks configured on the management node or compute resource hosting that virtual server:

  1. The command to restart the virtual server is given via the GUI, CLI, or API.
  2. SolusVM 2 runs all executables in the /usr/local/solus/hooks/ directory, passing to each one the JSON object containing all relevant information, including the supported event ID and the "pre" stage indicator.
  3. All executables exit or a minute passes.
  4. The virtual server is restarted.
  5. SolusVM 2 runs all executables in the /usr/local/solus/hooks/ directory, passing to each one the JSON object containing all relevant information, including the supported event ID and the "post" stage indicator.

Note

Do not place any files other than hooks in the /usr/local/solus/hooks/ directory.

JSON Object Anatomy

Your hook must expect data on stdin (standard input) in valid JSON format. Every time a triggering event takes place, a JSON object containing all relevant data is passed to every binary in the /usr/local/solus/hooks/ directory. Here's what this object may look like:

{
    "action": "server-restart",
    "stage": "pre",
    "data": {
      "uuid": "c7ee19aa-2722-4139-9223-60ed4baf09e2",
      "virtualization_type": "kvm"
    }
  }

Here, "action" specifies what kind of event triggered the hook (in this case, a virtual server being restarted), "stage" specifies whether the event is about to happen or has just happened (in this case, the former), and "data" specifies information relevant to the event (in this case, virtual server ID and its virtualization type). So, the object in question tells us that the KVM based virtual server with the ID "c7ee19aa-2722-4139-9223-60ed4baf09e2" is about to be restarted, and the custom script called by the hook can, for example, be used to notify the virtual server's owner.

The "action", "stage", and "data" keys are always present.

  • The "stage" key can only have the "pre" and "post" values.

  • The "action" key can have a number of values corresponding to the supported events.

    • "server-create"
    • "server-delete"
    • "server-migrate"
    • "server-reinstall"
    • "server-restart"
    • "server-start"
    • "server-stop"
    • "server-network-create"
    • "server-network-delete"
    • "server-network-update"
  • The "data" object includes a number of keys that can have different values. One or more specific keys correspond to each specific "action" key. For example, a JSON object corresponding to a virtual server being restarted (the "server-restart" action) always will include the "uuid" and "virtualization_type" keys within the "data" object, and never any others.

Note

A single event may trigger multiple hooks. For example, creating a new virtual server triggers both the "server-create" and the "server-network-create" hooks.

Note

If an event fails during execution (for example, a virtual server cannot be created), only the "pre" hooks will be triggered, but not the "post" hooks.

Hook Examples

Bash example

  1. Log in to the management node or compute resource via SSH as the "root" user.
  2. Create a directory named /usr/local/solus/hooks/ if it does not exist.

    mkdir /usr/local/solus/hooks/

  3. Create a file.

    touch /usr/local/solus/hooks/hook.sh

  4. Make it executable.

    chmod +x /usr/local/solus/hooks/hook.sh

  5. Paste the following content into the file.

    #!/bin/bash
    set -xEeuo pipefail
    
    tfile=$(mktemp /tmp/hook_test_$(date "+%Y-%m-%d-%H-%M-%S-%N")_XXX)
    
    cat /dev/stdin | jq > $tfile
    
  6. Install the "jq" program on the server.

    apt install jq or dnf install jq

Python example

  1. Log in to the management node or compute resource via SSH as the "root" user.
  2. Create a directory named /usr/local/solus/hooks/ if it does not exist.

    mkdir /usr/local/solus/hooks/

  3. Create a file.

    touch /usr/local/solus/hooks/hook.py

  4. Make it executable.

    chmod +x /usr/local/solus/hooks/hook.py

  5. Paste the following content into the file.

    #!/usr/bin/env python3
    import sys
    import json
    
    ACTION_SERVER_RESTART = "server-restart"
    STAGE_PRE = "pre"
    STAGE_POST = "post"
    
    event = json.loads(sys.stdin.read())
    
    
    def handle_server_restart_pre(event_data):
        print(f'Server going restart: {event_data["uuid"]}')
    
    
    def handle_server_restart_post(event_data):
        print(f'Server was restarted: {event_data["uuid"]}')
    
    
    action = event["action"]
    stage = event["stage"]
    data = event["data"]
    
    if ACTION_SERVER_RESTART == action:
        if STAGE_PRE == stage:
            handle_server_restart_pre(data)
            sys.exit(0)
        if STAGE_POST == stage:
            handle_server_restart_post(data)
            sys.exit(0)
    
  6. Install the "json" module on the server.

    python -c "help('modules')"

Testing your hook

  1. Log in to the management node or compute resource via SSH as the "root" user.
  2. Pass a JSON object to your hook, for example:

    echo '{
    "action": "server-restart",
    "stage": "pre",
    "data":
    
    { "uuid": "c7ee19aa-2722-4139-9223-60ed4baf09e2", "virtualization_type": "kvm" }
    }' | /usr/local/solus/hooks/hook.sh
    
Back to top