VM Resource Manager

VM Resource Manager API Reference

Public interface for interacting with the VM Resource Manager. These functions should be callable with only information available from experiment Control.

firewheel.vm_resource_manager.api.add_experiment_start_time(start=None)[source]

Set the start time of the currently running experiment. All parameters to this function are only present to enable unit testing and may be safely ignored.

Parameters:

start (ExperimentStart) – ExperimentStart instance to use as a database. Present for unit testing, safely ignored.

Returns:

A datetime object containing the start time for the currently running experiment. The time is defined to be in the UTC time zone.

Return type:

datetime.datetime

firewheel.vm_resource_manager.api.add_vm(server_uuid, server_name, control_ip, use_vm_manager=True, mapping=None, log=None)[source]

Add a VM to the vm resource database.

The VM is in the default vm resource state (uninitialized) after insertion.

Parameters:
  • server_uuid (str) – The uuid of the VM, as specified in the Control graph.

  • server_name (str) – The name of the system, as specified in the Control graph.

  • control_ip (str) – The address for this VM on the control network.

  • use_vm_manager (bool) – This VM uses the VM Resource Manager. If False, the vm resource state is set to ‘N/A’ and the VM is subsequently ignored for VM Resource Manager calculations like experiment start time. Default is True.

  • mapping (firewheel.vm_resource_manager.vm_mapping.VMMapping) – VMMapping instance to use as a database. Present for unit testing, safely ignored.

  • log (logging.Logger) – An optional logger that can to output results.

firewheel.vm_resource_manager.api.add_vm_resource_file(filename, store=None, log=None)[source]

Add a file to the VmResourceStore.

Parameters:
  • filename (str) – The path to the (locally stored) file to add to the VmResourceStore.

  • store (VmResourceStore) – VmResourceStore instance to use as a database. Present for unit testing, safely ignored.

  • log (logging.Logger) – An optional logger that can to output results.

firewheel.vm_resource_manager.api.destroy_all(mapping=None, schedule=None, start=None, log=None, ignore_grpc_connection_errors=False)[source]

Clears the VMMapping, Schedule, and ExperimentStart databases.

All arguments are only present to enable unit testing and may be safely ignored.

Parameters:
  • mapping (firewheel.vm_resource_manager.vm_mapping.VMMapping) – VMMapping instance to use as a database. Present for unit testing, safely ignored.

  • schedule (ScheduleDb) – ScheduleDb instance to use as a database. Present for unit testing, safely ignored.

  • start (ExperimentStart) – ExperimentStart instance to use as a database. Present for unit testing, safely ignored.

  • log (logging.Logger) – An optional logger that can to output results.

  • ignore_grpc_connection_errors (bool) – Whether to ignore gRPC errors or not.

Raises:

ConnectionError – If ignore_grpc_connection_errors=False and there is an error connecting to the gRPC server.

firewheel.vm_resource_manager.api.get_experiment_launch_time(start=None)[source]

Get the launch time of the currently running experiment. All parameters to this function are only present to enable unit testing and may be safely ignored.

Parameters:

start (ExperimentStart) – ExperimentStart instance to use as a database. Present for unit testing, safely ignored.

Returns:

A datetime object containing the launch time for the currently running experiment. The time is defined to be in the UTC time zone. None if no launch time has been determined yet.

Return type:

datetime.datetime

firewheel.vm_resource_manager.api.get_experiment_start_time(start=None)[source]

Get the start time of the currently running experiment. All parameters to this function are only present to enable unit testing and may be safely ignored.

Parameters:

start (ExperimentStart) – ExperimentStart instance to use as a database. Present for unit testing, safely ignored.

Returns:

A datetime object containing the start time for the currently running experiment. The time is defined to be in the UTC time zone. None if no start time has been determined yet.

Return type:

datetime.datetime

firewheel.vm_resource_manager.api.get_experiment_time_since_start(start=None)[source]

Get the time since the experiment configured. All parameters to this function are only present to enable unit testing and may be safely ignored.

Parameters:

start (ExperimentStart) – ExperimentStart instance to use as a database. Present for unit testing, safely ignored.

Returns:

The time in seconds since when the experiment configured. None if experiment hasn’t started yet.

Return type:

int

firewheel.vm_resource_manager.api.get_experiment_time_to_start(start=None)[source]

Get the time it took for the experiment to configure. All parameters to this function are only present to enable unit testing and may be safely ignored.

Parameters:

start (ExperimentStart) – ExperimentStart instance to use as a database. Present for unit testing, safely ignored.

Returns:

The time in seconds from when the experiment launched to configured. None if experiment hasn’t started yet.

Return type:

int

firewheel.vm_resource_manager.api.get_vm_states(filter_state=None, mapping=None, log=None)[source]

Get the current vm resources state of all known VMs.

Parameters:
Returns:

A dictionary keyed on the VM server name, with string values for the vm resources state.

Return type:

dict

firewheel.vm_resource_manager.api.get_vm_times(filter_time=None, mapping=None, log=None)[source]

Get the current negative times of known VMs.

Parameters:
Returns:

Dictionary keyed on server name, values of the current negative time for that VM.

Return type:

dict

firewheel.vm_resource_manager.api.set_experiment_launch_time(start=None)[source]

Set the launch time of the currently running experiment. All parameters to this function are only present to enable unit testing and may be safely ignored.

Parameters:

start (ExperimentStart) – ExperimentStart instance to use as a database. Present for unit testing, safely ignored.

Returns:

A datetime object containing the launch time for the currently running experiment. The time is defined to be in the UTC time zone.

Return type:

datetime.datetime

firewheel.vm_resource_manager.api.vm_resource_list(store=None, log=None)[source]

List the available vm resources in the VmResourceStore. All parameters to this function all only present to enable unit testing and may be safely ignored.

Parameters:
  • store (VmResourceStore) – VmResourceStore instance to use as a database. Present for unit testing, safely ignored.

  • log (logging.Logger) – An optional logger that can to output results.

Returns:

A list of (unique) file names in the VmResourceStore.

Return type:

list

experiment_start.py

Subsystem to determine and report an experiment start time.

class firewheel.vm_resource_manager.experiment_start.ExperimentStart(hostname='', port=50051, db='prod')[source]

Bases: object

Interface to determine and report an experiment start time. Different start times may reported as desired, but a consistent value will always be reported as the start time. If no start times have yet been reported, a value of None will be reported.

This is currently implemented using the GRPC database as a synchronization mechanism: the current time is reported and recorded into the DB. When determining the consistent start time value, the values from the DB are sorted and the first-recorded returned.

__del__()[source]

Attempt to gracefully close our database connection as we are destroyed.

__init__(hostname='', port=50051, db='prod')[source]

All arguments are present only for unit testing and may be safely ignored.

Parameters:
  • hostname (str) – The GRPC server IP/hostname.

  • port (int) – The GRPC server port.

  • db (str) – The GRPC database.

add_start_time()[source]

Report the current time as a new start time for the database. May be called arbitrary many times without affecting the consistency of the time returned by get_start_time().

Returns:

A datetime object representing the time value as added to the database: 1-second resolution, UTC.

Return type:

datetime.datetime

clear_start_time()[source]

Clear the current start time. The system is then uninitialized until a new time is reported–after this call, get_start_time() returns None until add_start_time() is called.

Returns:

The response dictionary from GRPC initializing the start time.

Return type:

dict

close()[source]

Safely close the gRPC connection (if it exists at all).

get_launch_time()[source]

Return the experiment launch time.

Returns:

datetime object representing the start time (in UTC), 1-second resolution or None is no launch time has been reported yet.

Return type:

datetime.datetime

get_start_time()[source]

Return a consistent value for the experiment start time, as determined by the reported times using add_start_time().

Returns:

datetime object representing the start time (in UTC), 1-second resolution or None is no start time has been reported yet.

Return type:

datetime.datetime

get_time_since_start()[source]

Get the amount of time that has elapsed since the experiment has been configured.

Returns:

The time in seconds since when the experiment configured or None if experiment hasn’t started yet.

Return type:

int

get_time_to_start()[source]

Get the amount of time it takes from when an experiment is launched to when it is configured.

Returns:

The time in seconds from when the experiment launched to configured. or None if experiment hasn’t started yet.

Return type:

int

set_launch_time()[source]

Set the experiment launch time.

Returns:

A datetime object representing the time value as added to the database: 1-second resolution, UTC.

Return type:

datetime.datetime

schedule_db.py

Subsystem for the storage and retrieval of vm_resource schedules.

class firewheel.vm_resource_manager.schedule_db.ScheduleDb(cache_name='schedules', log=None)[source]

Bases: object

Class to represent the experiment schedule database. This is currently backed by a minimega store, but the interface should remain general enough that this could change without modifying users of this class.

__init__(cache_name='schedules', log=None)[source]

Initialize the ScheduleDb.

All arguments are present only for unit testing and may be safely ignored.

Parameters:
  • cache_name (str) – Override the default minimega cache dir.

  • log (firewheel.lib.log.Log) – Override the default FIREWHEEL log.

Raises:

RuntimeError – If there is an invalid value for FileStore connections.

batch_put(sched_list, broadcast=False)[source]

Add a schedule entry for a particular VM.

Parameters:
  • sched_list (list) – List of {‘server_name’: <value>, ‘text’: <value>}

  • broadcast (bool) – Whether to have all nodes update their cache to include the new files.

close()[source]

Close the ScheduleDb. Currently, this is unused.

destroy_all()[source]

Remove the schedule for a particular VM.

destroy_one(server_name)[source]

Remove the schedule for a particular VM.

Parameters:

server_name (str) – The name of the VM whose schedule will be removed.

get(server_name)[source]

Retrieve the schedule for a particular VM.

Parameters:

server_name (str) – The name of the VM to retrieve the schedule for.

Returns:

The decoded schedule as a string on success, None if there is no entry for the specified VM.

Return type:

str

Raises:

Exception – If minimega has an error.

list_all(pattern=None)[source]

Retrieve the schedule for a particular VM.

Parameters:

pattern (str) – The pattern to match filenames against.

Returns:

List of matching schedule dictionaries on success.

Return type:

list

Raises:

Exception – If minimega has an error.

put(server_name, text, vm_resources_ip, broadcast=True)[source]

Add a schedule entry for a particular VM.

Parameters:
  • server_name (str) – The name of the VM to assign this schedule to.

  • text (str) – The schedule to assign to the VM.

  • vm_resources_ip (str) – The IP of the VM.

  • broadcast (bool) – Whether to have all nodes update their cache to include the new files.

Raises:

Exception – If minimega has an error.

exception firewheel.vm_resource_manager.schedule_db.ScheduleDbTimeoutError[source]

Bases: Exception

An exception for general time outs.

schedule_entry.py

class firewheel.vm_resource_manager.schedule_entry.ScheduleEntry(start_time, ignore_failure=False)[source]

Bases: object

This class is the base class for all types of schedule entries. It is in this class that all necessary instance variables are declared. It is important that all variables within the base_objects.ScheduleEntry be instance variables, as opposed to class variables. This is because a VM’s schedule (i.e. base_objects.VmResourceSchedule, which contains a list of base_objects.ScheduleEntry objects) is serialized via pickle and passed to the VM Resource Handler. Only instance variables get preserved through the pickle process.

Schedule entries have a set of general instance variables. The type of schedule entry determines which variables are required. The only variable that all ScheduleEntries require is start_time. This class is not intended to be used directly, but through its subclasses.

__init__(start_time, ignore_failure=False)[source]

Create a new ScheduleEntry

start_time

Relative time to handle the VM resource. (See Start Time for more details).

Type:

int

ignore_failure

Whether or not to let the VM resource handler exit if this entry fails.

Type:

bool

executable

Name of the executable to run.

Type:

str

arguments

Arguments to pass to the executable.

Type:

str

data

List of dictionaries specifying required files:

Paths can be either absolute or relative to the VMR.

Dictionary to drop specified content on VM
{
    "location": <string>, # Path on VM to place content
    "content":  <string>, # Content to be placed at location
    "executable": <bool>  # Optionally set file's executable flag
}

Dictionary to load a file into the VM
{
    "location": <string>, # Path on VM to place file
    "filename": <string>, # Name of file to be loaded on the VM
    "executable": <bool>  # Optionally set file's executable flag
}
Type:

list(dict)

Parameters:
  • start_time (int) – VM resource scheduled start time

  • ignore_failure (bool) – Whether or not to let the VM resource handler exit if this entry fails.

Raises:

ValueError – If a start time of 0 is provided.

__str__()[source]

A custom string method for ScheduleEntry Objects.

Returns:

A string representation of a ScheduleEntry.

Return type:

str

add_content(location, content, executable=False)[source]

Add a block of content to be loaded into the VM at the specified location.

Parameters:
  • location (str) – Path inside the VM to write the provided content, including filename. This path can be absolute or relative to the VM resource.

  • content (str) – Content to be written or a callback function that will return a string.

  • executable (bool, optional) – Set the new file’s executable flag. Defaults to False.

add_file(location, filename, executable=False)[source]

Drop a file on the VM at the specified location. This file needs to be available to FIREWHEEL. This only happens when the files are included in the list of “vm_resources” that are specified in a model component’s MANIFEST file.

Parameters:
  • location (str) – Path inside the VM to write the file, including filename This path can be absolute or relative to the VM resource.

  • filename (str) – Name of file in the vm_resource’s database to be written.

  • executable (bool, optional) – Boolean for setting the new file’s executable flag. Defaults to False.

add_file_transfer(location, interval=30, destination=None)[source]

Specifies that a file or directory needs to be monitored and pulled off the VM.

Note

If specifying a destination, the FIREWHEEL group (if any) must have permissions to modify and write to that directory. See the system configuration options to add FIREWHEEL group permissions.

Parameters:
  • location (str) – Path inside the VM to the file or directory to be monitored and pulled off the VM.

  • interval (int, optional) – Interval specifying how often to check for file or directory updates.

  • destination (str, optional) – Absolute path on compute node of the directory where transferred files are to be placed: <destination>/<vm_name>/<location>. If no destination is provided, files will be written to <logging.root_dir>/transfers/. See _transfer_data for more details.

add_pause(duration)[source]

Add data to the schedule entry that indicates that it should pause all following events. The duration (seconds) can be any positive number where a duration of math.inf indicates a break event which requires a resume to occur prior to advancing the schedule.

Note

To ensure the exact ordering of events within a time-window (e.g. multiple events scheduled at the same time) the pause/break is technically added at the start_time + sys.float_info.min.

Parameters:

duration (float) – The duration (seconds) of the pause where math.inf is an break event.

Raises:

ValueError – If the duration is not positive.

append_arguments(arguments)[source]

Append an argument to be passed on the command line to the executable

Parameters:

arguments (str or list) – A space-separated string or list of strings of arguments to be passed on the command line to the executable.

Raises:

TypeError – If the arguments an not in a valid format.

set_executable(path, arguments=None)[source]

Specify the name of a program to run within the VM.

Parameters:
  • path (str) – Path inside the VM to the program to be run.

  • arguments (str or list, optional) – Arguments to pass on the command line to the program. Defaults to None.

Raises:

RuntimeError – If the executable name is not a string.

schedule_event.py

class firewheel.vm_resource_manager.schedule_event.ScheduleEvent(event_type, data)[source]

Bases: object

These objects get added to the event queue and processed by the VM Resource Handler launcher.

__init__(event_type, data)[source]

Create an event.

Parameters:
__lt__(other)[source]

Comparison function. If two events have the same start time then the ScheduleEvents will be compared on insert into the priority queue. If both event have the same start time then it doesn’t matter which one gets put first in the queue, they will all be processed at the same time regardless. Therefore, just return True every time to create an arbitrary order of the ScheduleEvents in the priority queue.

Parameters:

other (int) – A value for comparison. This argument is ignored.

Returns:

True

Return type:

bool

get_data()[source]

Get the event’s data

Returns:

The event data.

Return type:

object

get_type()[source]

Get the type of event.

Returns:

Event type

Return type:

enum

class firewheel.vm_resource_manager.schedule_event.ScheduleEventType(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: Enum

The possible types of allowed schedule events.

EMPTY_SCHEDULE = 1
EXIT = 4
EXPERIMENT_START_TIME_SET = 0
NEW_ITEM = 2
PAUSE = 5
RESUME = 6
TRANSFER = 3
UNKNOWN = 7

schedule_updater.py

class firewheel.vm_resource_manager.schedule_updater.ScheduleUpdater(config, priority_queue, condition, vm_resource_store, schedule_db, repository_db, log, log_filename, load_balance_factor, interval_time=5)[source]

Bases: Thread

ScheduleUpdater checks for updates to a VM’s schedule at specified intervals.

It then passes those updates to the main processing loop via a queue.PriorityQueue of ScheduleEvents.

__init__(config, priority_queue, condition, vm_resource_store, schedule_db, repository_db, log, log_filename, load_balance_factor, interval_time=5)[source]

Initialize the updater class.

Parameters:
  • config (dict) – config for the VM

  • priority_queue (PriorityQueue) – Queue to place new vm_resource events to get picked up by the VMResourceHandler

  • condition (Condition) – Lock for the priority queue

  • vm_resource_store (VmResourceStore) – A resource store to use.

  • schedule_db (ScheduleDb) – A ScheduleDb to use.

  • repository_db (RepositoryDb) – A RepositoryDb to use.

  • log (Logger) – The vm_resource launcher’s logger for output

  • log_filename (str) – A filename for the log.

  • load_balance_factor (float) – Amount of time to scale sleeps by.

  • interval_time (int) – Amount of time to sleep between checking for updates

_run()[source]

Main loop for the thread. Checks for updates and adds events to the event queue for processing by the VM Resource Handler. The logic for this function gets rather complex and provides for the ability to accommodate all event types include PAUSE and RESUME events.

enqueue_event(priority, event)[source]

Put a single event in the priority queue to pass information back to the main processing loop.

Parameters:
  • priority (int) – The priority of the event.

  • event (ScheduleEvent) – Event to be processed.

get_schedule(name)[source]

Get the schedule for a specified VM.

Note

In general, loading pickle data can have some serious security implications. Please review Security for more details.

Parameters:

name (str) – Name of the VM.

Returns:

List of ScheduleEntry objects.

Return type:

list

Raises:

RuntimeError – If there is an exception getting the schedule.

get_start_time()[source]

Queries the database to see if a start time for the experiment has been set.

Returns:

Experiment start time if available, None if start time has

not been set yet

Return type:

int

run()[source]

Main loop for the thread. Checks for updates and adds events to the event queue for processing by the vm_resource launcher. queue for processing by the VM Resource Handler. The logic for this function gets rather complex and provides for the ability to accommodate all event types include PAUSE and RESUME events.

stop_thread()[source]

Tell the thread to stop. This is used for unit testing.

utils.py

Utility functions for common high-level operations performed by the Vm Resource Manager.

These are high-level functions that may be useful in Modules, but should not be needed outside the VM Resource Manager and its Modules.

firewheel.vm_resource_manager.utils.get_vm_count_not_ready(mapping=None, log=None)[source]

Returns the number of VMs not in the “configured” or “N/A” states. These VMs are not ready in the sense that they are not prepared to begin the experiment (set an experiment schedule start time). For reference: The configured state means the bootstrap vm_resource has completed all negative-start-time vm_resources and checked in as ready and the N/A state means there is no vm_resource system present on a VM.

Parameters:
Returns:

Count of the number of VMs not in the “configured” or

”N/A” vm_resources state.

Return type:

str

firewheel.vm_resource_manager.utils.set_vm_state(vm_uuid, new_state, mapping=None, log=None)[source]

Set the vm_resources state of a given VM.

Parameters:
  • vm_uuid (str) – The UUID of the VM to set the state of.

  • new_state (str) – A string representing the new vm_resources state of the VM. There is no validation for strings matching expected states.

  • mapping (firewheel.vm_resource_manager.vm_mapping.VMMapping) – VMMapping instance to use as a database. Present for unit testing, safely ignored.

  • log (logging.Logger) – An optional logger that can to output results.

Raises:

RuntimeError – If the VMMapping database could not be created.

firewheel.vm_resource_manager.utils.set_vm_time(vm_uuid, new_time, mapping=None, log=None)[source]

Set the current time reported by a VM.

Parameters:
Raises:

RuntimeError – If the VMMapping database could not be created.

vm_mapping.py

Interface to the mapping between VMs, their current (vm resource) state, and other metadata.

class firewheel.vm_resource_manager.vm_mapping.VMMapping(hostname='', port=50051, db='prod')[source]

Bases: object

Database interface for the mapping between VM name, VM control IP, and vm_resources state or other metadata.

Access may use name or IP as a key.

__del__()[source]

Attempt to gracefully close our database connection as we are destroyed.

__init__(hostname='', port=50051, db='prod')[source]

All arguments are present only for unit testing and may be safely ignored.

Parameters:
  • hostname (str) – The GRPC server IP/hostname.

  • port (int) – The GRPC server port.

  • db (str) – The GRPC database.

batch_put(server_list)[source]

Add a list of VM information to the database as a batch update. Each entry in the list is a dictionary specifying the relevant information.

Parameters:

server_list (list) –

List of dictionaries where each entry looks like:

{
    'server_uuid': '',
    'server_name': '',
    'state': '',
    'current_time': '',
    'control_ip': ''
}

Default values apply to the state and current_time fields. These values match those in put(). Only server_uuid and server_name fields are required for each entry in the list.

close()[source]

Close the connection to the GRPC client.

destroy_all()[source]

Remove all content from the database.

destroy_one(server_uuid)[source]

Remove a single entry from the database.

Parameters:

server_uuid (str) – UUID for the entry to remove.

get(server_uuid=None)[source]

Retrieve a single entry from the database. This can only retrieve by using the server_uuid.

Parameters:

server_uuid (str) – UUID of the VM to be retrieved.

Returns:

Dictionary with the information about the VM as stored. Includes current vm_resource state for the VM.

Return type:

dict

Raises:

ValueError – If the server_uuid is not provided.

get_all(filter_time=None, filter_state=None, project_dict=None, length=False)[source]

Retrieve multiple entries from the database. May filter on current (relative) time or vm resource state.

NOTE: This will not allow filtering for VMs where the time has been not been initialized yet, since both that condition and no filter is represented with None.

Parameters:
  • filter_time (int) – Only return VM information when the current relative time matches this value.

  • filter_state (str) – Only return VM information when the current vm resource state matches this value.

  • project_dict (dict) – Only return VM information from these keys.

  • length (bool) – Should the function return how many VMs are in the list or should it return the list itself.

Returns:

If length is False, return a list of dictionaries, where each dictionary is the same as would be returned for the VM if retrieved using get(). If length is True, returns the length of the list.

Return type:

list

get_count_vm_not_ready()[source]

Get the number of VMs that are not yet in the “Configured” state.

Returns:

The count of VMs which are not in the “Configured” state.

Return type:

int

prepare_put(entry)[source]

Validate that the provided entry has the necessary fields and if it does not, provide details or raise an error in the case of a required field. The two required fields are server_uuid and server_name.

Parameters:

entry (dict) –

A dictionary which contains a subset of the following fields:

{
    'server_uuid': '',
    'server_name': '',
    'state': '',
    'current_time': '',
    'control_ip': ''
}

Default values apply to state, current_time, and control_ip fields. These values match those in put(). Only server_uuid and server_name fields are required for each entry in the list.

Returns:

An entry dictionary which can be put into the database.

Return type:

dict

Raises:
  • ValueError – If the entry does not contain the server_uuid field.

  • ValueError – If the entry does not contain the server_name field.

put(server_uuid, server_name, state='uninitialized', current_time='', server_address='')[source]

Add a set of new VM information to the database.

Parameters:
  • server_uuid (str) – UUID of the VM.

  • server_name (str) – Hostname of the VM.

  • state (str) – Vm Resource state the VM starts in. Defaults to the configured default state (located in the FIREWHEEL configuration).

  • current_time (str) – The current (relative) time for the VM. Defaults to ‘’, meaning the VM has not contacted the server yet.

  • server_address (str) – The control_ip of the host where the VM Resource is found.

set_vm_state_by_uuid(uuid, state)[source]

Set the VMs current state based on the passed in information.

Parameters:
  • uuid (str) – UUID of the VM.

  • state (str) – The new state for the VM.

Returns:

Dictionary representation of the updated firewheel_grpc_pb2.VMMapping.

Return type:

dict

set_vm_time_by_uuid(uuid, time)[source]

Set the VMs current time based on the passed in information.

Parameters:
  • uuid (str) – UUID of the VM.

  • time (str) – The new (relative) time for the VM.

Returns:

Dictionary representation of the updated firewheel_grpc_pb2.VMMapping.

Return type:

dict

vm_resource_handler.py

This module contains the class enable the vm_resource_handler to run. This runs as a process for each VM that is launched with FIREWHEEL and controls the interaction with the QEMU Guest Agent.

class firewheel.vm_resource_manager.vm_resource_handler.VMResourceHandler(config, check_interval=10)[source]

Bases: object

Main class for communicating with a VM. Kicks off the ScheduleUpdater thread and handles all ScheduleEvents and their side effects.

__init__(config, check_interval=10)[source]
Parameters:
  • config (dict) – VM configuration.

  • check_interval (int) – Seconds between checks for an updated schedule This gets passed to the ScheduleUpdater. Defaults to 10.

static _check_driver(obj)[source]
_import_drivers()[source]

Import available drivers from the driver directory.

Walk the drivers directory looking for all available drivers that can talk to a booted VM. A qualifying driver must be a subclass of the abstract driver class, implementing all required methods of the driver interface.

Returns:

A set of available driver classes.

Return type:

set

_print_stream(output, stream, stream_name)[source]
_run()[source]

This is the main processing loop for the VMResourceHandler.

It kicks off the ScheduleUpdater thread and threads to run the individual vm_resources.

_run_vm_resource(schedule_entry, queue=None)[source]

Function to handle starting a VM resource.

Parameters:
  • schedule_entry (ScheduleEntry) – ScheduleEntry object specifying the VM resource to run.

  • queue (Queue) – Queue to pass messages, specifically reboot requests, back to the main processing loop. Defaults to None.

_transfer_data(name, location, interval=None, destination=None)[source]

The helper function which transfers data from the VM to the physical host based on the input parameters.

Parameters:
  • name (str) – The name of file to transfer.

  • location (str) – The full absolute path of where the file is located on the VM.

  • interval (int) – How often to transfer the data in seconds.

  • destination (str) – The full, absolute path of where to put the file on the physical host.

Raises:
  • RuntimeError – If the transfer path is not absolute.

  • RuntimeError – If it is unable to list files at the location.

check_for_reboot(reboot_filepath)[source]

Check if the reboot file exists and a reboot is needed.

Parameters:

reboot_filepath (str) – The path to the reboot file on the VM.

Returns:

True if the reboot file exists and a reboot is required, otherwise False.

Return type:

bool

connect_to_driver()[source]

Instantiate the driver class to communicate to the VM

Returns:

True if the driver is connected, False otherwise.

Return type:

bool

get_events()[source]

Get all eligible events from the priority queue.

Returns:

List of events that are ready to be processed.

Return type:

list (ScheduleEvent)

import_driver()[source]

Walk through all the available drivers and find the one that matches the type of VM that has been booted.

Returns:

The driver class that matches the VM’s type

Return type:

object

load_files_in_target(schedule_entry)[source]

Copy the vm_resource file to the VM’s local cache so that it is available when the vm_resource gets called.

Parameters:

schedule_entry (ScheduleEntry) – The schedule entry to be copied into the VM.

Returns:

Success or failure of loading files into the VM.

Return type:

bool

log_json(content)[source]

Print any JSON line in vm_resource output to the json log.

Parameters:

content (str or dict) – Buffer from agent output.

preload_files()[source]

This method loads all VM Resources into the VM before the schedule is executed. This minimizes the number of after-boot disk alterations. This is particularly important for Windows VMs as, in our experience, Windows does not appear to appreciate having files modified or created on disk immediately after a reboot.

print_output(schedule_entry, pid)[source]

Print any output from an vm_resource to the log.

Parameters:
  • schedule_entry (ScheduleEntry) – ScheduleEntry object specifying the VM resource to run.

  • pid (int) – The PID of the VM resource process within the VM.

reboot()[source]

Reboot the VM. Function doesn’t return until the driver can communicate with the VM again.

run()[source]

Run the VMResourceHandler.

run_vm_resource(schedule_entry, queue=None)[source]

Wrapper around the logic of running an vm_resource.

The new thread calls this wrapper, which can output errors to the log file. This gives a convenient way to pass information back to the user via the log (with few good alternatives).

Parameters:
  • schedule_entry (ScheduleEntry) – ScheduleEntry object specifying the VM resource to run.

  • queue (Queue) – Queue to pass messages, specifically reboot requests, back to the main processing loop. Defaults to None.

set_current_time(cur_time)[source]

Tell the infrastructure the current configuration time of the VM.

Parameters:

cur_time (int) – Current VM schedule time

set_state(state)[source]

Tell the infrastructure the state of the VM. If the state is ‘configured’, then check to see if this VM is the last VM to be configured. If it is the last VM to be configured, then set the experiment start time.

Parameters:

state (str) – State of the VM

stop(exitcode)[source]

Stop the vm resource handler. This is used for unit testing.

Parameters:

exitcode (int) – exit code to use when exiting the program

transfer_data(name, location, interval=None, destination=None)[source]

Transfer data from the VM to the physical host based on the input parameters.

Parameters:
  • name (str) – The name of file to transfer.

  • location (str) – The full absolute path of where the file is located on the VM.

  • interval (int) – How often to transfer the data in seconds.

  • destination (str) – The full, absolute path of where to put the file on the physical host.

vm_resource_store.py

class firewheel.vm_resource_manager.vm_resource_store.VmResourceStore(store='vm_resources', decompress=False)[source]

Bases: FileStore

A repository for VM resources that uses the minimega FileStore for easy access on all hosts in a Firewheel cluster.

__annotations__ = {}
__init__(store='vm_resources', decompress=False)[source]

Initialize the VmResourceStore.

Parameters:
  • store (str) – The name of the resource store. Defaults to “vm_resources”.

  • decompress (bool) – Whether to decompress files. Defaults to False.

abstract_driver.py

class firewheel.vm_resource_manager.abstract_driver.AbstractDriver(config, log)[source]

Bases: ABC

An abstract driver class for communicating with all in-VM agents that work with FIREWHEEL. All driver-specific implementation is left to subclasses.

_EXEC_ERROR_MSG = '`execute` returned `None` indicating an error has occurred.'
__abstractmethods__ = frozenset({'_write', 'close', 'connect', 'exec_status', 'execute', 'file_flush', 'get_engine', 'get_os', 'get_time', 'network_get_interfaces', 'ping', 'read_file', 'reboot', 'set_time', 'set_user_password', 'store_captured_output', 'sync', 'write_from_file'})
__annotations__ = {}
__init__(config, log)[source]

An abstract driver class for communicating with all in-VM agents that work with FIREWHEEL. All driver-specific implementation is left to subclasses.

log

Logger for output

Type:

Logger

driver

Object for speaking QMP over the serial port to the QGA process in the VM

Type:

object

lock

Only one connection to the serial port is allowed, therefore access to the port needs to be thread safe.

Type:

threading.Condition

target_os

The operating system of the VM.

Type:

str

used_agent_paths

Agents need a unique directory to hold their relevant files. This keeps track of paths that have already been used.

Type:

str

output_cache

The output cache is a cache of all output resulting from calling programs within a VM. This data lives as long as the process runs. It allows streaming output from an agent to be collected and agent output to be requested multiple times if needed. The output cache has the following format:

{
    <pid>: {
        'exited': True or False,
        'exitcode': <integer status code>,
        'signal': <Optional: signal or unhandled exception code>,
        'stdout': <Optional: output from stdout>,
        'stdout_trunc': <Optional: True if stdout was truncated>,
        'stderr': <Optional: output from stderr>,
        'stderr_trunc': <Optional: True if stder was truncated>
    }
}

The output cache is cleared on system reboot.

Type:

dict

Parameters:
  • config (dict) – vm config which is used to find the Virtio serial port socket that the guest agent uses to communicate to the VM with.

  • log (logging.Logger) – A logger which can be used by this class.

Raises:

FileNotFoundError – If no path was given to the QGA serial device.

_abc_impl = <_abc._abc_data object>
_delete_parent_directories(directory)[source]

Delete the directory and any (empty) parent directories.

Recursively delete the given directory and all parent directories until encountering a directory that is not empty.

Parameters:

directory (PurePosixPath) – The directory to remove. Parent directories of this directory will also be deleted if otherwise empty.

_get_stream(stream_name, pid)[source]

Set a set of information from a given stream (stdout, stderr, etc.).

Parameters:
  • stream_name (str) – The name of the stream.

  • pid (int) – The process ID for the stream.

Returns:

Get the information from the given stream (stdout, stderr, etc.)

Return type:

str

_reset_cache()[source]
abstract _write(filename, data, mode='w')[source]

Write the provided data at the provided filename within the guest VM.

Parameters:
  • filename (str) – name of the file to open for writing.

  • data (str) – String of content to write to the file.

  • mode (str) – Mode for writing to the file. 'w' or 'a'.

Raises:

NotImplementedError – This should be implemented by a subclass.

append(filename, content)[source]

Append to a file within the guest VM.

Parameters:
  • filename (str) – name of the file to open for writing on the VM.

  • content (str) – String of content to write to the file.

Returns:

True or False indicating success.

Return type:

bool

abstract close()[source]

Close the connection to the socket used for agent.

Raises:

NotImplementedError – This should be implemented by a subclass.

abstract connect()[source]

This method sets up the driver connection with the agent within the VM so that they can communicate. It then should call sync(). The return value of this method is typically a random synchronization token used in the sync request/response exchange.

Raises:

NotImplementedError – This should be implemented by a subclass.

connected(timeout=10)[source]

Check that the driver is currently connected to the guest agent inside the VM.

Parameters:

timeout (int) – Timeout in seconds to wait for a response from the VM.

Returns:

Empty dictionary on success, throws an exception on timeout.

Return type:

dict

Raises:

Exception – Happens on timeout.

create_directories(directory)[source]

The guest agent does not allow interacting with a new file if the file’s path does not exist. Therefore, this function creates the path for a file if it does not exist.

Parameters:

directory (str) – The absolute path for a directory.

Returns:

True or False indicating success. A value of None means that the execution attempt (performed on the VM) failed.

Return type:

bool

create_paths(schedule_entry)[source]

Since the paths that need to be created are dependent on what the driver accepts (i.e. QGA doesn’t want C: to be prepended on Windows paths, but the agent needs the path to the reboot file, which will need the drive letter prepended to the path) it is the driver’s job to determine the paths for the agent.

Parameters:

schedule_entry (ScheduleEntry) – The schedule_entry object.

deconflict_agent_path(path)[source]

Create unique path names for agents.

Parameters:

path (str) – Desired path name.

Returns:

A pathlib.Path object which is unique.

Return type:

Path

delete_file(path)[source]

Delete a file inside the VM.

Parameters:

path (str) – Absolute path of the file to be deleted.

Returns:

True or False indicating success. A value of None means that the execution attempt (performed on the VM) failed.

Return type:

bool

evaluate_process_success(pid, interval=1)[source]

Wait for a process to complete, and return a success indicator.

Parameters:
  • pid (int) – The process PID to query for an exit code.

  • interval (int) – The time (in seconds) to wait between queries. The default is to wait for one second.

Returns:

True if the process was successful (exit code 0), otherwise

False.

Return type:

bool

abstract exec_status(pid)[source]

Get the status of a program that was run. It should return a dictionary with the exit code and other information about the status (STDOUT, STDERR, etc.)

Parameters:

pid (int) – The PID that for the process that was returned from guest-exec-status.

Raises:

NotImplementedError – This should be implemented by a subclass.

abstract execute(path, arg=None, env=None, input_data=None, capture_output=True)[source]

Run a program inside the guest VM. This should return process’s PID on success or None on failure.

Parameters:
  • path (str) – Path or executable name to execute.

  • arg (str) – Argument list to pass to executable. Must be a list or string. Defaults to None.

  • env (list) – Environment variables to pass to executable. List of “<key>=<value>” strings. Defaults to None.

  • input_data (str) – Data to be passed to process stdin. Defaults to None.

  • capture_output (bool) – Flag to enable capture of stdout/stderr. Defaults to True.

Raises:

NotImplementedError – This should be implemented by a subclass.

file_exists(path)[source]

Check if a file exists inside the VM. If a user used a shell-globbing wildcard (e.g. *) in the path (and shell-globbing is supported by the VM) then this function only checks to see if at least one file matching the wildcard exists.

Parameters:

path (str) – Absolute path for the file to be checked.

Returns:

Indicates existence of the file inside the VM. A value of None means that the execution attempt (performed on the VM) failed.

Return type:

bool

abstract file_flush(handle)[source]

Flush a file to disk inside the guest VM

Parameters:

handle (File) – file handle returned from guest-file-open.

Raises:

NotImplementedError – This should be implemented by a subclass.

abstract static get_engine()[source]

Get the virtualization engine that this driver supports.

Raises:

NotImplementedError – This should be implemented by a subclass.

get_exitcode(pid)[source]

Query for the exit code of a process run via exec_status.

Parameters:

pid (int) – The process PID to query for an exit code.

Returns:

The exit code if the process has exited and it is known, otherwise None.

Return type:

int

get_files(path, timestamp=None)[source]

Get all filenames at a specified path.

Parameters:
  • path (str) – Absolute path for the file/directory to be walked.

  • timestamp (str) – A date that can be used to compare against the file. This function will find files with a modification time newer than the one passed in.

Returns:

A list of filenames at the specified location or None if an error occurs.

Return type:

list

abstract get_os()[source]

Get the Operating System details for the VM. It should return the “pretty” name for the OS.

Raises:

NotImplementedError – This should be implemented by a subclass.

get_stderr(pid)[source]

Query for the standard error of a process run via exec_status.

Parameters:

pid (int) – The process PID for the desired output.

Returns:

The stderr buffer if available, otherwise None.

Return type:

str

get_stdout(pid)[source]

Query for the standard output of a process run via exec_status.

Parameters:

pid (int) – The process PID for the desired output.

Returns:

The stdout buffer if available, otherwise None.

Return type:

str

abstract get_time()[source]

Get the time inside the VM in nanoseconds since the epoch.

Raises:

NotImplementedError – This should be implemented by a subclass.

make_file_executable(path)[source]

If the guest VM is not a Windows VM then set the executable flag for the file at the provided path.

Parameters:

path (str) – Path in guest VM to file to be set executable.

Returns:

True or False indicating success. A value of None means that the execution attempt (performed on the VM) failed.

Return type:

bool

abstract network_get_interfaces()[source]

Gets a list of network interface info. This is typically returned as a list of JSON objects.

Raises:

NotImplementedError – This should be implemented by a subclass.

abstract ping(timeout=10)[source]

Check if connection to the in-VM agent was successful.

Parameters:

timeout (int) – The time in seconds until the socket times out.

Raises:

NotImplementedError – This should be implemented by a subclass.

abstract read_file(filename, local_destination, mode='rb')[source]

Read a file from a VM and put it onto the physical host.

Parameters:
  • filename (str) – The file to read from inside the VM. This should be the full path.

  • local_destination (pathlib.PurePosixPath) – The path on the physical host where the file should be read to.

  • mode (str) – The mode of reading the file. Defaults to 'rb'.

Raises:

NotImplementedError – This should be implemented by a subclass.

abstract reboot()[source]

Reboot the VM.

abstract set_time()[source]

Set the time in the VM to the current host time.

Raises:

NotImplementedError – This should be implemented by a subclass.

abstract set_user_password(username, password)[source]

Sets a user’s password.

Parameters:
  • username (str) – The user account that will have its password changed.

  • password (str) – A new password for the user account.

Raises:

NotImplementedError – This should be implemented by a subclass.

abstract store_captured_output(pid, output)[source]

Store output from a VM program.

Hold on to output that has been returned from a program that was run inside the VM via the exec method.

Parameters:
  • pid (int) – The PID for the process that produced the output.

  • output (str) – The processed returned output to be cached.

Raises:

NotImplementedError – This should be implemented by a subclass.

abstract sync(timeout=5)[source]

Synchronize the buffer for the agent. This method should return a random synchronization token used in the sync request/response

Parameters:

timeout (int) – Socket timeout in seconds. Defaults to 5.

Raises:

NotImplementedError – This should be implemented by a subclass.

wait_for_exitcode(pid, interval=1)[source]

Repeatedly query for the exit code of a process run via exec_status.

Parameters:
  • pid (int) – The process PID to query for an exit code.

  • interval (int) – The time (in seconds) to wait between queries. The default is to wait for one second.

Returns:

The exit code if the process has exited.

Return type:

int

write(filename, data, mode='w')[source]

Write the provided data at the provided filename within the guest VM.

This will also create required directories in the filename’s path.

Parameters:
  • filename (str) – name of the file to open for writing.

  • data (str) – String of content to write to the file.

  • mode (str) – Mode for writing to the file. 'w' or 'a'.

Returns:

True or False indicating success.

Return type:

bool

abstract write_from_file(filename, local_filename, mode='w')[source]

Given a local filename, open that file to read its data and write that data to a location (provided in filename) in the guest VM.

Parameters:
  • filename (str) – The name of the file to open for writing.

  • local_filename (str) – Filename of the file containing data to send to the VM.

  • mode (str) – Mode for writing to the file. 'w' or 'a'.

Raises:

NotImplementedError – This should be implemented by a subclass.

Qemu Guest Agent Driver API Reference

class firewheel.vm_resource_manager.drivers.qemu_guest_agent_driver.QemuGuestAgentDriver(config, log)[source]

Bases: AbstractDriver

Driver class for the QEMU Guest Agent (QGA). This class can communicate to a QGA inside a VM via a serial port.

__abstractmethods__ = frozenset({})
__annotations__ = {}
__init__(config, log)[source]
Parameters:
  • config (dict) – vm config which is used to find the Virtio serial port socket that the guest agent uses to communicate to the VM with.

  • log (logging.Logger) – A logger which can be used by this class.

_abc_impl = <_abc._abc_data object>
_prep_async_exec(path, arg=None, env=None, input_data=None, capture_output=True)[source]

Run a program inside the guest VM.

Parameters:
  • path (str) – Path or executable name to execute.

  • arg (str) – Argument list to pass to executable. Must be a list or string. Defaults to None.

  • env (list) – Environment variables to pass to executable. List of “<key>=<value>” strings. Defaults to None.

  • input_data (str) – Data to be passed to process stdin. Defaults to None.

  • capture_output (bool) – Flag to enable capture of stdout/stderr. Defaults to True.

Returns:

The process’s PID is returned on success or None on failure.

Return type:

int

_write(filename, data, mode='w')[source]

Write the provided data at the provided filename within the guest VM.

Parameters:
  • filename (str) – name of the file to open for writing.

  • data (str) – String of content to write to the file.

  • mode (str) – Mode for writing to the file. 'w' or 'a'.

Returns:

True or False indicating success.

Return type:

bool

async_exec(path, arg=None, env=None, input_data=None, capture_output=True)[source]

Run a program inside the guest VM as an async process.

Parameters:
  • path (str) – Path or executable name to execute.

  • arg (str) – Argument list to pass to executable. Must be a list or string. Defaults to None.

  • env (list) – Environment variables to pass to executable. List of “<key>=<value>” strings. Defaults to None.

  • input_data (str) – Data to be passed to process stdin. Defaults to None.

  • capture_output (bool) – Flag to enable capture of stdout/stderr. Defaults to True.

Returns:

The process’s PID is returned on success or None on failure.

Return type:

int

close()[source]

Close the connection to the socket used for guest agent.

connect()[source]

This method sets up the QMP connection with the QGA within the VM so that they can communicate. It then calls sync().

Returns:

A random synchronization token used in the guest-sync request/response exchange.

Return type:

int

Raises:
  • OSError – If an error occurs while connecting to the QGA.

  • OSError – If an error occurs while syncing.

exec_status(pid)[source]

Get the status of a program that was run using guest-exec-status.

Parameters:

pid (int) – The PID that for the process that was returned from guest-exec-status.

Returns:

The dictionary with the exit code and other information

returned from the guest-exec-status command.

Return type:

dict

Raises:
  • TimeoutError – If the QGA status check times out.

  • OSError – If the QGA fails to execute the guest-exec-status command.

execute(path, arg=None, env=None, input_data=None, capture_output=True)[source]

Run a program inside the guest VM.

Parameters:
  • path (str) – Path or executable name to execute.

  • arg (str) – Argument list to pass to executable. Must be a list or string. Defaults to None.

  • env (list) – Environment variables to pass to executable. List of “<key>=<value>” strings. Defaults to None.

  • input_data (str) – Data to be passed to process stdin. Defaults to None.

  • capture_output (bool) – Flag to enable capture of stdout/stderr. Defaults to True.

Returns:

The process’s PID is returned on success or None on failure.

Return type:

int

file_flush(handle)[source]

Flush a file to disk inside the guest VM

Parameters:

handle (File) – file handle returned from guest-file-open.

file_write_content(handle, content)[source]

Given content (i.e. ASCII data), write the content to a file inside the VM. The given handle is a handle to an open file inside the guest VM.

Parameters:
  • handle (File) – File handle returned from guest-file-open.

  • content (str) – Content to write to file handle.

Returns:

True on success, False on failure.

Return type:

bool

file_write_from_file(handle, filename)[source]

Given a local filename, read the contents from that file and write them to the provided file handle. The file handle is a handle to an open file within the guest VM.

Parameters:
  • handle (File) – file handle returned from guest-file-open.

  • filename (str) – Name of file to read content from and then send to the VM.

Returns:

True on success, False on failure.

Return type:

bool

Raises:
static get_engine()[source]

Get the virtualization engine that this driver supports.

Returns:

The name of the virtualization engine that this driver supports. Currently this is only ‘QemuVM’.

Return type:

str

get_os()[source]

Get the Operating System details for the VM.

Returns:

The “pretty” name for the OS.

Return type:

str

Raises:

OSError – Unable to get OS info.

get_time()[source]

Get the time inside the VM.

Returns:

Time in nanoseconds since the epoch.

Return type:

int

network_get_interfaces()[source]

Gets a list of network interface info.

Returns:

List of GuestNetworkInfo JSON objects.

Return type:

list

ping(timeout=10)[source]

Use the guest-ping command to check if connection to the guest agent was successful.

Parameters:

timeout (int) – The time in seconds until the socket times out.

Returns:

Indicates if successfully connected to guest agent.

Return type:

bool

read_file(filename, local_destination, mode='rb')[source]

Read a file from a VM and put it onto the physical host.

QGA has issues detecting EOF on Windows VMs. Therefore, if two reads from the file have the exact same data (e.g. 4K bytes per read) this method makes an assumption that all the data has been read. This approach can possibly cause issues. For example, if the file has two chunks of 4K bytes that are the same but then additional data, this will truncate the reading of the file. For that reason, we only apply this method for Windows VMs. If this becomes an issue with a particular experiment, it is possible to change the default number of bytes from 4K to a higher number (up to 48MB). You can see https://qemu-project.gitlab.io/qemu/interop/qemu-ga-ref.html#qapidoc-47 for more details.

Parameters:
  • filename (str) – The file to read from inside the VM. This should be the full path.

  • local_destination (pathlib.PurePosixPath) – The path on the physical host where the file should be read to.

  • mode (str) – The mode of reading the file. Defaults to 'rb'.

Returns:

True if the read was successful, False otherwise.

Return type:

bool

Raises:
reboot()[source]

Reboot the VM.

set_time()[source]

Set the time in the VM to the current host time.

set_user_password(username, password)[source]

Sets a user’s password.

Parameters:
  • username (str) – The user account that will have its password changed.

  • password (str) – A new password for the user account.

store_captured_output(pid, output)[source]

Store output from a VM program.

Hold on to output that has been returned from a program that was run inside the VM via the async_exec method.

Parameters:
  • pid (int) – The PID for the process that produced the output.

  • output (str) – The processed returned output to be cached.

sync(timeout=5)[source]

Use the guest-sync command to synchronize the buffer.

This works by putting a marker into the buffer and then draining the buffer until the marker is returned. Once the marker has been returned, the buffer is then synchronized.

Parameters:

timeout (int) – Socket timeout in seconds. Defaults to 5.

Returns:

A random synchronization token used in the guest-sync request/response exchange. If the sync fails, returns None.

Return type:

int

Raises:

EnvironmentError – When the QEMU Guest Agent not alive yet.

write_from_file(filename, local_filename, mode='w')[source]

Given a local filename, open that file to read its data and write that data to a location (provided in filename) in the guest VM.

Parameters:
  • filename (str) – The name of the file to open for writing.

  • local_filename (str) – Filename of the file containing data to send to the VM.

  • mode (str) – Mode for writing to the file. 'w' or 'a'.

Returns:

True or False indicating success.

Return type:

bool

Raises:

OSError – If an issue occurs writing the file.