Automated Workflows
Users may wish to set up automatic processes that trigger when nodes are leased or returned. There are two high-level ways of setting up such automated workflows, with each being suitable for a different class of user. Both require the use of ESI Leap, and the configuration of ESI Leap notifications.
Event Configuration
In order for ESI Leap to emit notifications, ensure that the driver and transport_url are correctly configured under the [oslo_messaging_notifications] section in the esi-leap.conf
file. For example:
[oslo_messaging_notifications]
driver=messagingv2
transport_url=rabbit://<user>:<password>@<host>:<port>/?ssl=0
Once done, ESI Leap will emit a notification on the esi_leap_version_notifications topic in the RabbitMQ message bus whenever a lease is fulfilled, expired, or deleted. The list of notification types is as follows:
esi_leap.lease.fulfill.start
esi_leap.lease.fulfill.end
esi_leap.lease.fulfill.error
esi_leap.lease.delete.start
esi_leap.lease.delete.end
esi_leap.lease.delete.error
ESI Leap will now also store a truncated record of the event in the database. This event history is accessible by running openstack esi event list. Results are scoped to the user.
Monitoring Events for Automated Workflows
Monitoring RabbitMQ
The first option for automated workflows is to use the scripts provided in esi-event-actions to monitor the message bus. This method is only suitable for ESI operators.
Start by following the instructions in the README to install esi-event-actions. After installation, edit esi-event-action-listener.conf
and then run esi-event-action-listener.py. An example configuration file might be as follows:
# used to connect to RabbitMQ and monitor specific queues
[DEFAULT]
user = <user in transport_url>
password = <password in transport_url>
host = <host in transport_url>
port = <port in transport_url>
queues = esi_leap_versioned_notifications.info,esi_leap_versioned_notifications.error
# a section that specifies a script to run whenever the specified event is caught
[fulfill]
events = esi_leap.lease.fulfill.end
script = fulfill.sh
script_params = node_name,fulfill_time # values from the event payload to be passed into the script
filter_params = {"purpose": "test", "properties.vendor": "foo"} # filters on the event payload that must be fulfilled for the script to run
# a section that specifies a script to run whenever the specified event is caught
[delete]
events = esi_leap.lease.delete.end
script = delete.sh
script_params = node_name,expire_time # values from the event payload to be passed into the script
filter_params = {"purpose": "test", "properties.vendor": "foo"}} # filters on the event payload that must be fulfilled for the script to run
In this example, the [fulfill] and [delete] sections detail scripts that will be run when the specified events are caught, with filter_params providing additional filters based on the event payload. Upon detection of these events, the listener triggers the execution of fulfill.sh
and delete.sh
respectively, passing in values from the event payload specified by script_params. Note that dot notation may be used to access subdictionary values of the event payload.
Monitoring Event History
Tenant users are unlikely to have access to the message bus. An alternative is to monitor ESI Leap’s event history. This can be done through a simple python script that calls openstack esi event list with the –last-event-id parameter to ensure that events are not returned multiple times. For example:
import json
import subprocess
def run_openstack_command(cmd):
output_json = subprocess.check_output('%s --format json' % cmd, shell=True)
return json.loads(output_json)
def get_last_event_id(default_last_event_id=0, file_name='.esi-last-event-id'):
try:
with open(file_name, "r") as f:
last_event_id = int(f.read())
except FileNotFoundError:
last_event_id = default_last_event_id
except ValueError:
last_event_id = default_last_event_id
return last_event_id
def write_last_event_id(last_event_id, file_name='.esi-last-event-id'):
with open(file_name, "w") as f:
f.write(str(last_event_id))
def main():
last_event_id = get_last_event_id()
events = run_openstack_command('openstack esi event list --last-event-id %s' % last_event_id)
new_last_event_id = last_event_id
for event in events:
new_last_event_id = event['ID']
if event['Event Type'] == 'esi_leap.lease.fulfill.end':
node_uuid = event['Resource UUID']
lease_uuid = event['Object UUID']
lease = run_openstack_command('openstack esi lease show %s' % lease_uuid)
print("Lease %s with purpose %s on node %s started" % (lease_uuid, lease['purpose'], node_uuid))
elif event['Event Type'] == 'esi_leap.lease.delete.end':
node_uuid = event['Resource UUID']
lease_uuid = event['Object UUID']
print("Lease %s on node %s ended" % (lease_uuid, node_uuid))
write_last_event_id(new_last_event_id)
if __name__ == "__main__":
main()