Contents:
All devices that work with Bosun are subclasses of this class.
You must provide the following class-level attributes and methods:
str or unicode human-readable name name of this device. This is displayed in the Bosun web interface.
list or tuple of ``int``s of TCP/IP ports that the service for this device runs on. This is used when scanning the network for devices.
Determine if this class can interact with the class running on the given host and port.
Parameters: |
|
---|---|
Returns: | True or False |
When implementing this, you should use detection_timeout on any network operations. For example, if using the requests library, do something like this:
try:
response = requests.get(url, timeout=cls.detection_timeout)
if my_test_condition:
return True
except (ConnectionError, Timeout):
pass
return False
list or tuple of strings, one for each field needed for authentication. For example, this might be ['username', 'password'] or ['secret_key']. These names will be used as the kwargs for authenticate().
If no authentication is required, set this to None.
Attempt to authenticate to the device using the given credentials.
This is not needed if credentials_field_names is None.
Parameters: | credentials – dict where keys are guaranteed to be credentials_field_names and values are the user’s authentication attempt |
---|---|
Returns: | True if authentication successful, False if not, or any other error occurs |
Get the UUID stored on the device.
Returns: | the UUID for this device |
---|---|
Return type: | str |
Store the UUID on the device as the given value.
Parameters: | value (str) – the UUID to store on the device |
---|
Perform whatever configuration needs to be done to ensure the device is communicating with Bosun. For example, this might configure the device to use one of the listeners, described below.
Test whether this device is configured to communicate with Bosun properly. Should test that whatever connect_to_bosun() does is correct.
Returns: | True or False |
---|
Once you have the basics down, you will want to describe the capabilites your device has, using the following decorators. When the decorated methods are called, they automatically send their return values to Crowsnest, which is why they may look naively simplistic.
Decorate a method that performs the named action. Decorated method must accept inputs for the named action as arguments and must return outputs.
Parameters: | name (str) – dot-separated name of this action, eg 'action.generic.power.get' |
---|
An example for setting and getting the power of a device:
@Device.action('action.generic.power.get')
def get_power(self):
# make whatever requests we need to determine the device's power
power_value = get_the_power()
# value must be ``True`` or ``False``
return {
'value': bool(power_value)
}
@Device.action('action.generic.power.set')
def set_power(self, value):
# according to capabilities, value is ``True`` or ``False``
if value:
# turn the power on for the device
pass
else:
# turn the power off for the device
pass
# there is nothing to return for this action
return {}
Decorate a method that emits the named event. Decorated method must return outputs for the named event.
An example for the power having changed:
@Device.emits('event.generic.power.changed')
def power_changed(self, value):
# pass the value along as ``True`` or ``False``
return {
'value': bool(value)
}
Or, possibly you need to query for the value:
@Device.emits('event.generic.power.changed')
def power_changed(self):
# query for the value
value = get_the_power()
# pass the value along as ``True`` or ``False``
return {
'value': bool(value)
}
So, you have an event method decorated using emits(), and it generates events on Crowsnest. How do you listen to the device for changes so you can generate these events? Listeners are the key to this.
Sets up a Flask route for the decorated method on Bosun’s HTTP server. Any time a request is received on this route, the decorated method is called.
For more detail on the parameters of this decorator, refer directly to Flask’s route API.
Returns: | bosunplugins.listeners.http.Route. |
---|
Note
rule is prepended with a class-safe prefix, to prevent collisions between routes on different Device classes. You can get the fully safe path by inspecting the path attribute of the decorated method. You can get the full URL by calling the get_url() method of the decorated method. More details about this are in bosunplugins.listeners.http.Route.
The decorated method must be a valid signature for Flask routes.
For example, to listen for an HTTP event indicating the power of a device has changed:
@Device.listeners.http.route('/power-changed')
def power_changed_handler(self):
# you have access to the Flask request object inside the Flask request contect
power_value = request.json['powerValue']
# send the power changed event with the value we just got
self.power_changed(power_value)
# return a proper Flask response
return '', 200
Set up a watched folder on Bosun’s FTP server. Any time a file is uploaded to the given path, the decorated method is called.
Parameters: | path (str) – path to watch |
---|---|
Returns: | bosunplugins.listeners.ftp.WatchedFolder |
Note
path is only the end of the full path. The given path is prepended with a fully safe and isolated path to prevent collisions between Device classes. You can get this fully safe path by inspecting the path attribute of the decorated method. You can get the full URL by calling the get_url() method of the decorated method. More details about this are in bosunplugins.listeners.ftp.WatchedFolder.
Signature of the decorated method must be:
def ftp_handler(self, filelike):
""" filelike is a StringIO instance of the uploaded file """
pass
While you develop your plugin, you can check that you are meeting basic requirements by running the following test method.
Tests that the subclass has overloaded every required method and attribute. Does some basic type checking as well.
Usage:
from myplugin import MyDevice
MyDevice.test_subclass()
The following attributes and methods may or may not be useful to you as you develop your plugin. They are all used internally, and it is highly recommended you do not overload them.
Use this to see what the UUID is for the device, anywhere except inside the get_uuid() and set_uuid() methods.
The hardware (MAC) address of the device.
The credentials for this device. May be None if we don’t know them.
bool attribute for whether we are authenticated for this device or not.
Crowsnest metadata for this device.
Returns True or False for whether this device is considered healthy or not.
Healthiness requires that we are authenticated successfully and the device is connected to Bosun.
A emit() decorated event generator for the heartbeat event all Crowsnest devices use.
Returns a dictionary representation of the device, suitable for serialization.
Result of using the Device.listeners.http.route() decorator.
If called, calls the decorated method.
Full safe path for this route.
Returns the full URL for this route, eg 'http://1.2.3.4:5000/safe/path/to/route'.
Result of using the Device.listeners.ftp.watched_folder() decorator.
If called, calls the decorated method.
Port the FTP server is running on.
Username to access the FTP server.
Password to access the FTP server.
Safe base path for the class.
Full path to the watched folder.
Returns URL for the base path, eg 'ftp://1.2.3.4:5001/safe/base/path'.
Returns the full URL for the watche folder, eg 'ftp://1.2.3.4:5001/safe/base/path/and/watched/folder'.