Mini Shell
"""
Module for working with the Zenoss API
.. versionadded:: 2016.3.0
:configuration: This module requires a 'zenoss' entry in the master/minion config.
For example:
.. code-block:: yaml
zenoss:
hostname: https://zenoss.example.com
username: admin
password: admin123
verify_ssl: True
ca_bundle: /etc/ssl/certs/ca-certificates.crt
"""
import logging
import re
import salt.utils.http
import salt.utils.json
log = logging.getLogger(__name__)
__virtualname__ = "zenoss"
def __virtual__():
"""
Only load if requests is installed
"""
return __virtualname__
ROUTERS = {
"MessagingRouter": "messaging",
"EventsRouter": "evconsole",
"ProcessRouter": "process",
"ServiceRouter": "service",
"DeviceRouter": "device",
"NetworkRouter": "network",
"TemplateRouter": "template",
"DetailNavRouter": "detailnav",
"ReportRouter": "report",
"MibRouter": "mib",
"ZenPackRouter": "zenpack",
}
def _session():
"""
Create a session to be used when connecting to Zenoss.
"""
config = __salt__["config.option"]("zenoss")
return salt.utils.http.session(
user=config.get("username"),
password=config.get("password"),
verify_ssl=config.get("verify_ssl", True),
ca_bundle=config.get("ca_bundle"),
headers={"Content-type": "application/json; charset=utf-8"},
)
def _router_request(router, method, data=None):
"""
Make a request to the Zenoss API router
"""
if router not in ROUTERS:
return False
req_data = salt.utils.json.dumps(
[dict(action=router, method=method, data=data, type="rpc", tid=1)]
)
config = __salt__["config.option"]("zenoss")
log.debug("Making request to router %s with method %s", router, method)
url = "{}/zport/dmd/{}_router".format(config.get("hostname"), ROUTERS[router])
response = _session().post(url, data=req_data)
# The API returns a 200 response code even whe auth is bad.
# With bad auth, the login page is displayed. Here I search for
# an element on the login form to determine if auth failed.
if re.search('name="__ac_name"', response.content):
log.error("Request failed. Bad username/password.")
raise Exception("Request failed. Bad username/password.")
return salt.utils.json.loads(response.content).get("result", None)
def _determine_device_class():
"""
If no device class is given when adding a device, this helps determine
"""
if __salt__["grains.get"]("kernel") == "Linux":
return "/Server/Linux"
def find_device(device=None):
"""
Find a device in Zenoss. If device not found, returns None.
Parameters:
device: (Optional) Will use the grain 'fqdn' by default
CLI Example:
.. code-block:: bash
salt '*' zenoss.find_device
"""
data = [{"uid": "/zport/dmd/Devices", "params": {}, "limit": None}]
all_devices = _router_request("DeviceRouter", "getDevices", data=data)
for dev in all_devices["devices"]:
if dev["name"] == device:
# We need to save the has for later operations
dev["hash"] = all_devices["hash"]
log.info("Found device %s in Zenoss", device)
return dev
log.info("Unable to find device %s in Zenoss", device)
return None
def device_exists(device=None):
"""
Check to see if a device already exists in Zenoss.
Parameters:
device: (Optional) Will use the grain 'fqdn' by default
CLI Example:
.. code-block:: bash
salt '*' zenoss.device_exists
"""
if not device:
device = __salt__["grains.get"]("fqdn")
if find_device(device):
return True
return False
def add_device(device=None, device_class=None, collector="localhost", prod_state=1000):
"""
A function to connect to a zenoss server and add a new device entry.
Parameters:
device: (Optional) Will use the grain 'fqdn' by default.
device_class: (Optional) The device class to use. If none, will determine based on kernel grain.
collector: (Optional) The collector to use for this device. Defaults to 'localhost'.
prod_state: (Optional) The prodState to set on the device. If none, defaults to 1000 ( production )
CLI Example:
.. code-block:: bash
salt '*' zenoss.add_device
"""
if not device:
device = __salt__["grains.get"]("fqdn")
if not device_class:
device_class = _determine_device_class()
log.info("Adding device %s to zenoss", device)
data = dict(
deviceName=device,
deviceClass=device_class,
model=True,
collector=collector,
productionState=prod_state,
)
response = _router_request("DeviceRouter", "addDevice", data=[data])
return response
def set_prod_state(prod_state, device=None):
"""
A function to set the prod_state in zenoss.
Parameters:
prod_state: (Required) Integer value of the state
device: (Optional) Will use the grain 'fqdn' by default.
CLI Example:
.. code-block:: bash
salt zenoss.set_prod_state 1000 hostname
"""
if not device:
device = __salt__["grains.get"]("fqdn")
device_object = find_device(device)
if not device_object:
return f"Unable to find a device in Zenoss for {device}"
log.info("Setting prodState to %d on %s device", prod_state, device)
data = dict(
uids=[device_object["uid"]],
prodState=prod_state,
hashcheck=device_object["hash"],
)
return _router_request("DeviceRouter", "setProductionState", [data])
Zerion Mini Shell 1.0