ansible/monitoring/logicmonitor.py

2169 lines
74 KiB
Python

#!/usr/bin/python
"""LogicMonitor Ansible module for managing Collectors, Hosts and Hostgroups
Copyright (C) 2015 LogicMonitor
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA"""
import datetime
import os
import platform
import socket
import sys
import types
import urllib
HAS_LIB_JSON = True
try:
import json
# Detect the python-json library which is incompatible
# Look for simplejson if that's the case
try:
if (
not isinstance(json.loads, types.FunctionType) or
not isinstance(json.dumps, types.FunctionType)
):
raise ImportError
except AttributeError:
raise ImportError
except ImportError:
try:
import simplejson as json
except ImportError:
print(
'\n{"msg": "Error: ansible requires the stdlib json or ' +
'simplejson module, neither was found!", "failed": true}'
)
HAS_LIB_JSON = False
except SyntaxError:
print(
'\n{"msg": "SyntaxError: probably due to installed simplejson ' +
'being for a different python version", "failed": true}'
)
HAS_LIB_JSON = False
RETURN = '''
---
success:
description: flag indicating that execution was successful
returned: success
type: boolean
sample: True
...
'''
DOCUMENTATION = '''
---
module: logicmonitor
short_description: Manage your LogicMonitor account through Ansible Playbooks
description:
- LogicMonitor is a hosted, full-stack, infrastructure monitoring platform.
- This module manages hosts, host groups, and collectors within your LogicMonitor account.
version_added: "2.2"
author: Ethan Culler-Mayeno, Jeff Wozniak
notes:
- You must have an existing LogicMonitor account for this module to function.
requirements: ["An existing LogicMonitor account", "Linux"]
options:
target:
description:
- The type of LogicMonitor object you wish to manage.
- "Collector: Perform actions on a LogicMonitor collector"
- NOTE You should use Ansible service modules such as 'service' or 'supervisorctl' for managing the Collector 'logicmonitor-agent' and 'logicmonitor-watchdog' services. Specifically, you'll probably want to start these services after a Collector add and stop these services before a Collector remove.
- "Host: Perform actions on a host device"
- "Hostgroup: Perform actions on a LogicMonitor host group"
- NOTE Host and Hostgroup tasks should always be performed via local_action. There are no benefits to running these tasks on the remote host and doing so will typically cause problems.
required: true
default: null
choices: ['collector', 'host', 'datsource', 'hostgroup']
action:
description:
- The action you wish to perform on target
- "Add: Add an object to your LogicMonitor account"
- "Remove: Remove an object from your LogicMonitor account"
- "Update: Update properties, description, or groups (target=host) for an object in your LogicMonitor account"
- "SDT: Schedule downtime for an object in your LogicMonitor account"
required: true
default: null
choices: ['add', 'remove', 'update', 'sdt']
company:
description:
- The LogicMonitor account company name. If you would log in to your account at "superheroes.logicmonitor.com" you would use "superheroes"
required: true
default: null
user:
description:
- A LogicMonitor user name. The module will authenticate and perform actions on behalf of this user
required: true
default: null
password:
description:
- The password of the specified LogicMonitor user
required: true
default: null
collector:
description:
- The fully qualified domain name of a collector in your LogicMonitor account.
- This is required for the creation of a LogicMonitor host (target=host action=add)
- This is required for updating, removing or scheduling downtime for hosts if 'displayname' isn't specified (target=host action=update action=remove action=sdt)
required: false
default: null
hostname:
description:
- The hostname of a host in your LogicMonitor account, or the desired hostname of a device to manage.
- Optional for managing hosts (target=host)
required: false
default: 'hostname -f'
displayname:
description:
- The display name of a host in your LogicMonitor account or the desired display name of a device to manage.
- Optional for managing hosts (target=host)
required: false
default: 'hostname -f'
description:
description:
- The long text description of the object in your LogicMonitor account
- Optional for managing hosts and host groups (target=host or target=hostgroup; action=add or action=update)
required: false
default: ""
properties:
description:
- A dictionary of properties to set on the LogicMonitor host or host group.
- Optional for managing hosts and host groups (target=host or target=hostgroup; action=add or action=update)
- This parameter will add or update existing properties in your LogicMonitor account or
required: false
default: {}
groups:
description:
- A list of groups that the host should be a member of.
- Optional for managing hosts (target=host; action=add or action=update)
required: false
default: []
id:
description:
- ID of the datasource to target
- Required for management of LogicMonitor datasources (target=datasource)
required: false
default: null
fullpath:
description:
- The fullpath of the host group object you would like to manage
- Recommend running on a single Ansible host
- Required for management of LogicMonitor host groups (target=hostgroup)
required: false
default: null
alertenable:
description:
- A boolean flag to turn alerting on or off for an object
- Optional for managing all hosts (action=add or action=update)
required: false
default: true
choices: [true, false]
starttime:
description:
- The time that the Scheduled Down Time (SDT) should begin
- Optional for managing SDT (action=sdt)
- Y-m-d H:M
required: false
default: Now
duration:
description:
- The duration (minutes) of the Scheduled Down Time (SDT)
- Optional for putting an object into SDT (action=sdt)
required: false
default: 30
...
'''
EXAMPLES = '''
# example of adding a new LogicMonitor collector to these devices
---
- hosts: collectors
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: Deploy/verify LogicMonitor collectors
become: yes
logicmonitor:
target=collector
action=add
company={{ company }}
user={{ user }}
password={{ password }}
#example of adding a list of hosts into monitoring
---
- hosts: hosts
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: Deploy LogicMonitor Host
# All tasks except for target=collector should use local_action
local_action: >
logicmonitor
target=host
action=add
collector='mycompany-Collector'
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
groups="/servers/production,/datacenter1"
properties="{'snmp.community':'secret','dc':'1', 'type':'prod'}"
#example of putting a datasource in SDT
---
- hosts: localhost
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: SDT a datasource
# All tasks except for target=collector should use local_action
local_action: >
logicmonitor
target=datasource
action=sdt
id='123'
duration=3000
starttime='2017-03-04 05:06'
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
#example of creating a hostgroup
---
- hosts: localhost
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: Create a host group
# All tasks except for target=collector should use local_action
local_action: >
logicmonitor
target=hostgroup
action=add
fullpath='/servers/development'
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
properties="{'snmp.community':'commstring', 'type':'dev'}"
#example of putting a list of hosts into SDT
---
- hosts: hosts
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: SDT hosts
# All tasks except for target=collector should use local_action
local_action: >
logicmonitor
target=host
action=sdt
duration=3000
starttime='2016-11-10 09:08'
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
collector='mycompany-Collector'
#example of putting a host group in SDT
---
- hosts: localhost
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: SDT a host group
# All tasks except for target=collector should use local_action
local_action: >
logicmonitor
target=hostgroup
action=sdt
fullpath='/servers/development'
duration=3000
starttime='2017-03-04 05:06'
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
#example of updating a list of hosts
---
- hosts: hosts
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: Update a list of hosts
# All tasks except for target=collector should use local_action
local_action: >
logicmonitor
target=host
action=update
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
collector='mycompany-Collector'
groups="/servers/production,/datacenter5"
properties="{'snmp.community':'commstring','dc':'5'}"
#example of updating a hostgroup
---
- hosts: hosts
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: Update a host group
# All tasks except for target=collector should use local_action
local_action: >
logicmonitor
target=hostgroup
action=update
fullpath='/servers/development'
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
properties="{'snmp.community':'hg', 'type':'dev', 'status':'test'}"
#example of removing a list of hosts from monitoring
---
- hosts: hosts
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: Remove LogicMonitor hosts
# All tasks except for target=collector should use local_action
local_action: >
logicmonitor
target=host
action=remove
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
collector='mycompany-Collector'
#example of removing a host group
---
- hosts: hosts
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: Remove LogicMonitor development servers hostgroup
# All tasks except for target=collector should use local_action
local_action: >
logicmonitor
target=hostgroup
action=remove
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
fullpath='/servers/development'
- name: Remove LogicMonitor servers hostgroup
# All tasks except for target=collector should use local_action
local_action: >
logicmonitor
target=hostgroup
action=remove
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
fullpath='/servers'
- name: Remove LogicMonitor datacenter1 hostgroup
# All tasks except for target=collector should use local_action
local_action: >
logicmonitor
target=hostgroup
action=remove
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
fullpath='/datacenter1'
- name: Remove LogicMonitor datacenter5 hostgroup
# All tasks except for target=collector should use local_action
local_action: >
logicmonitor
target=hostgroup
action=remove
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
fullpath='/datacenter5'
### example of removing a new LogicMonitor collector to these devices
---
- hosts: collectors
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: Remove LogicMonitor collectors
become: yes
logicmonitor:
target=collector
action=remove
company={{ company }}
user={{ user }}
password={{ password }}
#complete example
---
- hosts: localhost
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: Create a host group
local_action: >
logicmonitor
target=hostgroup
action=add
fullpath='/servers/production/database'
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
properties="{'snmp.community':'commstring'}"
- name: SDT a host group
local_action: >
logicmonitor
target=hostgroup
action=sdt
fullpath='/servers/production/web'
duration=3000
starttime='2012-03-04 05:06'
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
- hosts: collectors
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: Deploy/verify LogicMonitor collectors
logicmonitor:
target: collector
action: add
company: {{ company }}
user: {{ user }}
password: {{ password }}
- name: Place LogicMonitor collectors into 30 minute Scheduled downtime
logicmonitor: target=collector action=sdt company={{ company }}
user={{ user }} password={{ password }}
- name: Deploy LogicMonitor Host
local_action: >
logicmonitor
target=host
action=add
collector=agent1.ethandev.com
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
properties="{'snmp.community':'commstring', 'dc':'1'}"
groups="/servers/production/collectors, /datacenter1"
- hosts: database-servers
remote_user: '{{ username }}'
vars:
company: 'mycompany'
user: 'myusername'
password: 'mypassword'
tasks:
- name: deploy logicmonitor hosts
local_action: >
logicmonitor
target=host
action=add
collector=monitoring.dev.com
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
properties="{'snmp.community':'commstring', 'type':'db', 'dc':'1'}"
groups="/servers/production/database, /datacenter1"
- name: schedule 5 hour downtime for 2012-11-10 09:08
local_action: >
logicmonitor
target=host
action=sdt
duration=3000
starttime='2012-11-10 09:08'
company='{{ company }}'
user='{{ user }}'
password='{{ password }}'
'''
class LogicMonitor(object):
def __init__(self, module, **params):
self.__version__ = "1.0-python"
self.module = module
self.module.debug("Instantiating LogicMonitor object")
self.check_mode = False
self.company = params["company"]
self.user = params["user"]
self.password = params["password"]
self.fqdn = socket.getfqdn()
self.lm_url = "logicmonitor.com/santaba"
self.__version__ = self.__version__ + "-ansible-module"
def rpc(self, action, params):
"""Make a call to the LogicMonitor RPC library
and return the response"""
self.module.debug("Running LogicMonitor.rpc")
param_str = urllib.urlencode(params)
creds = urllib.urlencode(
{"c": self.company,
"u": self.user,
"p": self.password})
if param_str:
param_str = param_str + "&"
param_str = param_str + creds
try:
url = ("https://" + self.company + "." + self.lm_url +
"/rpc/" + action + "?" + param_str)
# Set custom LogicMonitor header with version
headers = {"X-LM-User-Agent": self.__version__}
# Set headers
f = open_url(url, headers=headers)
raw = f.read()
resp = json.loads(raw)
if resp["status"] == 403:
self.module.debug("Authentication failed.")
self.fail(msg="Error: " + resp["errmsg"])
else:
return raw
except IOError:
self.fail(msg="Error: Unknown exception making RPC call")
def do(self, action, params):
"""Make a call to the LogicMonitor
server \"do\" function"""
self.module.debug("Running LogicMonitor.do...")
param_str = urllib.urlencode(params)
creds = (urllib.urlencode(
{"c": self.company,
"u": self.user,
"p": self.password}))
if param_str:
param_str = param_str + "&"
param_str = param_str + creds
try:
self.module.debug("Attempting to open URL: " +
"https://" + self.company + "." + self.lm_url +
"/do/" + action + "?" + param_str)
f = open_url(
"https://" + self.company + "." + self.lm_url +
"/do/" + action + "?" + param_str)
return f.read()
except IOError:
# self.module.debug("Error opening URL. " + ioe)
self.fail("Unknown exception opening URL")
def get_collectors(self):
"""Returns a JSON object containing a list of
LogicMonitor collectors"""
self.module.debug("Running LogicMonitor.get_collectors...")
self.module.debug("Making RPC call to 'getAgents'")
resp = self.rpc("getAgents", {})
resp_json = json.loads(resp)
if resp_json["status"] is 200:
self.module.debug("RPC call succeeded")
return resp_json["data"]
else:
self.fail(msg=resp)
def get_host_by_hostname(self, hostname, collector):
"""Returns a host object for the host matching the
specified hostname"""
self.module.debug("Running LogicMonitor.get_host_by_hostname...")
self.module.debug("Looking for hostname " + hostname)
self.module.debug("Making RPC call to 'getHosts'")
hostlist_json = json.loads(self.rpc("getHosts", {"hostGroupId": 1}))
if collector:
if hostlist_json["status"] == 200:
self.module.debug("RPC call succeeded")
hosts = hostlist_json["data"]["hosts"]
self.module.debug(
"Looking for host matching: hostname " + hostname +
" and collector " + str(collector["id"]))
for host in hosts:
if (host["hostName"] == hostname and
host["agentId"] == collector["id"]):
self.module.debug("Host match found")
return host
self.module.debug("No host match found")
return None
else:
self.module.debug("RPC call failed")
self.module.debug(hostlist_json)
else:
self.module.debug("No collector specified")
return None
def get_host_by_displayname(self, displayname):
"""Returns a host object for the host matching the
specified display name"""
self.module.debug("Running LogicMonitor.get_host_by_displayname...")
self.module.debug("Looking for displayname " + displayname)
self.module.debug("Making RPC call to 'getHost'")
host_json = (json.loads(self.rpc("getHost",
{"displayName": displayname})))
if host_json["status"] == 200:
self.module.debug("RPC call succeeded")
return host_json["data"]
else:
self.module.debug("RPC call failed")
self.module.debug(host_json)
return None
def get_collector_by_description(self, description):
"""Returns a JSON collector object for the collector
matching the specified FQDN (description)"""
self.module.debug(
"Running LogicMonitor.get_collector_by_description..."
)
collector_list = self.get_collectors()
if collector_list is not None:
self.module.debug("Looking for collector with description {0}" +
description)
for collector in collector_list:
if collector["description"] == description:
self.module.debug("Collector match found")
return collector
self.module.debug("No collector match found")
return None
def get_group(self, fullpath):
"""Returns a JSON group object for the group matching the
specified path"""
self.module.debug("Running LogicMonitor.get_group...")
self.module.debug("Making RPC call to getHostGroups")
resp = json.loads(self.rpc("getHostGroups", {}))
if resp["status"] == 200:
self.module.debug("RPC called succeeded")
groups = resp["data"]
self.module.debug("Looking for group matching " + fullpath)
for group in groups:
if group["fullPath"] == fullpath.lstrip('/'):
self.module.debug("Group match found")
return group
self.module.debug("No group match found")
return None
else:
self.module.debug("RPC call failed")
self.module.debug(resp)
return None
def create_group(self, fullpath):
"""Recursively create a path of host groups.
Returns the id of the newly created hostgroup"""
self.module.debug("Running LogicMonitor.create_group...")
res = self.get_group(fullpath)
if res:
self.module.debug("Group {0} exists." + fullpath)
return res["id"]
if fullpath == "/":
self.module.debug("Specified group is root. Doing nothing.")
return 1
else:
self.module.debug("Creating group named " + fullpath)
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
parentpath, name = fullpath.rsplit('/', 1)
parentgroup = self.get_group(parentpath)
parentid = 1
if parentpath == "":
parentid = 1
elif parentgroup:
parentid = parentgroup["id"]
else:
parentid = self.create_group(parentpath)
h = None
# Determine if we're creating a group from host or hostgroup class
if hasattr(self, '_build_host_group_hash'):
h = self._build_host_group_hash(
fullpath,
self.description,
self.properties,
self.alertenable)
h["name"] = name
h["parentId"] = parentid
else:
h = {"name": name,
"parentId": parentid,
"alertEnable": True,
"description": ""}
self.module.debug("Making RPC call to 'addHostGroup'")
resp = json.loads(
self.rpc("addHostGroup", h))
if resp["status"] == 200:
self.module.debug("RPC call succeeded")
return resp["data"]["id"]
elif resp["errmsg"] == "The record already exists":
self.module.debug("The hostgroup already exists")
group = self.get_group(fullpath)
return group["id"]
else:
self.module.debug("RPC call failed")
self.fail(
msg="Error: unable to create new hostgroup \"" +
name + "\".\n" + resp["errmsg"])
def fail(self, msg):
self.module.fail_json(msg=msg, changed=self.change, failed=True)
def exit(self, changed):
self.module.debug("Changed: " + changed)
self.module.exit_json(changed=changed, success=True)
def output_info(self, info):
self.module.debug("Registering properties as Ansible facts")
self.module.exit_json(changed=False, ansible_facts=info)
class Collector(LogicMonitor):
def __init__(self, params, module=None):
"""Initializor for the LogicMonitor Collector object"""
self.change = False
self.params = params
LogicMonitor.__init__(self, module, **params)
self.module.debug("Instantiating Collector object")
if self.params['description']:
self.description = self.params['description']
else:
self.description = self.fqdn
self.info = self._get()
self.installdir = "/usr/local/logicmonitor"
self.platform = platform.system()
self.is_64bits = sys.maxsize > 2**32
self.duration = self.params['duration']
self.starttime = self.params['starttime']
if self.info is None:
self.id = None
else:
self.id = self.info["id"]
def create(self):
"""Idempotent function to make sure that there is
a running collector installed and registered"""
self.module.debug("Running Collector.create...")
self._create()
self.get_installer_binary()
self.install()
def remove(self):
"""Idempotent function to make sure that there is
not a running collector installed and registered"""
self.module.debug("Running Collector.destroy...")
self._unreigster()
self.uninstall()
def get_installer_binary(self):
"""Download the LogicMonitor collector installer binary"""
self.module.debug("Running Collector.get_installer_binary...")
arch = 32
if self.is_64bits:
self.module.debug("64 bit system")
arch = 64
else:
self.module.debug("32 bit system")
if self.platform == "Linux" and self.id is not None:
self.module.debug("Platform is Linux")
self.module.debug("Agent ID is " + str(self.id))
installfilepath = (self.installdir +
"/logicmonitorsetup" +
str(self.id) + "_" + str(arch) +
".bin")
self.module.debug("Looking for existing installer at " +
installfilepath)
if not os.path.isfile(installfilepath):
self.module.debug("No previous installer found")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
self.module.debug("Downloading installer file")
# attempt to create the install dir before download
self.module.run_command("mkdir " + self.installdir)
try:
f = open(installfilepath, "w")
installer = (self.do("logicmonitorsetup",
{"id": self.id,
"arch": arch}))
f.write(installer)
f.closed
except:
self.fail(msg="Unable to open installer file for writing")
f.closed
else:
self.module.debug("Collector installer already exists")
return installfilepath
elif self.id is None:
self.fail(
msg="Error: There is currently no collector " +
"associated with this device. To download " +
" the installer, first create a collector " +
"for this device.")
elif self.platform != "Linux":
self.fail(
msg="Error: LogicMonitor Collector must be " +
"installed on a Linux device.")
else:
self.fail(
msg="Error: Unable to retrieve the installer from the server")
def install(self):
"""Execute the LogicMonitor installer if not
already installed"""
self.module.debug("Running Collector.install...")
if self.platform == "Linux":
self.module.debug("Platform is Linux")
installer = self.get_installer_binary()
if self.info is None:
self.module.debug("Retriving collector information")
self.info = self._get()
if not os.path.exists(self.installdir + "/agent"):
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
self.module.debug("Setting installer file permissions")
os.chmod(installer, 484) # decimal for 0o744
self.module.debug("Executing installer")
ret_code, out, err = self.module.run_command(installer + " -y")
if ret_code != 0:
self.fail(msg="Error: Unable to install collector: " + err)
else:
self.module.debug("Collector installed successfully")
else:
self.module.debug("Collector already installed")
else:
self.fail(
msg="Error: LogicMonitor Collector must be " +
"installed on a Linux device")
def uninstall(self):
"""Uninstall LogicMontitor collector from the system"""
self.module.debug("Running Collector.uninstall...")
uninstallfile = self.installdir + "/agent/bin/uninstall.pl"
if os.path.isfile(uninstallfile):
self.module.debug("Collector uninstall file exists")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
self.module.debug("Running collector uninstaller")
ret_code, out, err = self.module.run_command(uninstallfile)
if ret_code != 0:
self.fail(
msg="Error: Unable to uninstall collector: " + err)
else:
self.module.debug("Collector successfully uninstalled")
else:
if os.path.exists(self.installdir + "/agent"):
(self.fail(
msg="Unable to uninstall LogicMonitor " +
"Collector. Can not find LogicMonitor " +
"uninstaller."))
def sdt(self):
"""Create a scheduled down time
(maintenance window) for this host"""
self.module.debug("Running Collector.sdt...")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
duration = self.duration
starttime = self.starttime
offsetstart = starttime
if starttime:
self.module.debug("Start time specified")
start = datetime.datetime.strptime(starttime, '%Y-%m-%d %H:%M')
offsetstart = start
else:
self.module.debug("No start time specified. Using default.")
start = datetime.datetime.utcnow()
# Use user UTC offset
self.module.debug("Making RPC call to 'getTimeZoneSetting'")
accountresp = json.loads(self.rpc("getTimeZoneSetting", {}))
if accountresp["status"] == 200:
self.module.debug("RPC call succeeded")
offset = accountresp["data"]["offset"]
offsetstart = start + datetime.timedelta(0, offset)
else:
self.fail(msg="Error: Unable to retrieve timezone offset")
offsetend = offsetstart + datetime.timedelta(0, int(duration)*60)
h = {"agentId": self.id,
"type": 1,
"notifyCC": True,
"year": offsetstart.year,
"month": offsetstart.month-1,
"day": offsetstart.day,
"hour": offsetstart.hour,
"minute": offsetstart.minute,
"endYear": offsetend.year,
"endMonth": offsetend.month-1,
"endDay": offsetend.day,
"endHour": offsetend.hour,
"endMinute": offsetend.minute}
self.module.debug("Making RPC call to 'setAgentSDT'")
resp = json.loads(self.rpc("setAgentSDT", h))
if resp["status"] == 200:
self.module.debug("RPC call succeeded")
return resp["data"]
else:
self.module.debug("RPC call failed")
self.fail(msg=resp["errmsg"])
def site_facts(self):
"""Output current properties information for the Collector"""
self.module.debug("Running Collector.site_facts...")
if self.info:
self.module.debug("Collector exists")
props = self.get_properties(True)
self.output_info(props)
else:
self.fail(msg="Error: Collector doesn't exit.")
def _get(self):
"""Returns a JSON object representing this collector"""
self.module.debug("Running Collector._get...")
collector_list = self.get_collectors()
if collector_list is not None:
self.module.debug("Collectors returned")
for collector in collector_list:
if collector["description"] == self.description:
return collector
else:
self.module.debug("No collectors returned")
return None
def _create(self):
"""Create a new collector in the associated
LogicMonitor account"""
self.module.debug("Running Collector._create...")
if self.platform == "Linux":
self.module.debug("Platform is Linux")
ret = self.info or self._get()
if ret is None:
self.change = True
self.module.debug("System changed")
if self.check_mode:
self.exit(changed=True)
h = {"autogen": True,
"description": self.description}
self.module.debug("Making RPC call to 'addAgent'")
create = (json.loads(self.rpc("addAgent", h)))
if create["status"] is 200:
self.module.debug("RPC call succeeded")
self.info = create["data"]
self.id = create["data"]["id"]
return create["data"]
else:
self.fail(msg=create["errmsg"])
else:
self.info = ret
self.id = ret["id"]
return ret
else:
self.fail(
msg="Error: LogicMonitor Collector must be " +
"installed on a Linux device.")
def _unreigster(self):
"""Delete this collector from the associated
LogicMonitor account"""
self.module.debug("Running Collector._unreigster...")
if self.info is None:
self.module.debug("Retrieving collector information")
self.info = self._get()
if self.info is not None:
self.module.debug("Collector found")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
self.module.debug("Making RPC call to 'deleteAgent'")
delete = json.loads(self.rpc("deleteAgent",
{"id": self.id}))
if delete["status"] is 200:
self.module.debug("RPC call succeeded")
return delete
else:
# The collector couldn't unregister. Start the service again
self.module.debug("Error unregistering collecting. " +
delete["errmsg"])
self.fail(msg=delete["errmsg"])
else:
self.module.debug("Collector not found")
return None
class Host(LogicMonitor):
def __init__(self, params, module=None):
"""Initializor for the LogicMonitor host object"""
self.change = False
self.params = params
self.collector = None
LogicMonitor.__init__(self, module, **self.params)
self.module.debug("Instantiating Host object")
if self.params["hostname"]:
self.module.debug("Hostname is " + self.params["hostname"])
self.hostname = self.params['hostname']
else:
self.module.debug("No hostname specified. Using " + self.fqdn)
self.hostname = self.fqdn
if self.params["displayname"]:
self.module.debug("Display name is " + self.params["displayname"])
self.displayname = self.params['displayname']
else:
self.module.debug("No display name specified. Using " + self.fqdn)
self.displayname = self.fqdn
# Attempt to host information via display name of host name
self.module.debug("Attempting to find host by displayname " +
self.displayname)
info = self.get_host_by_displayname(self.displayname)
if info is not None:
self.module.debug("Host found by displayname")
# Used the host information to grab the collector description
# if not provided
if (not hasattr(self.params, "collector") and
"agentDescription" in info):
self.module.debug("Setting collector from host response. " +
"Collector " + info["agentDescription"])
self.params["collector"] = info["agentDescription"]
else:
self.module.debug("Host not found by displayname")
# At this point, a valid collector description is required for success
# Check that the description exists or fail
if self.params["collector"]:
self.module.debug(
"Collector specified is " +
self.params["collector"]
)
self.collector = (self.get_collector_by_description(
self.params["collector"]))
else:
self.fail(msg="No collector specified.")
# If the host wasn't found via displayname, attempt by hostname
if info is None:
self.module.debug("Attempting to find host by hostname " +
self.hostname)
info = self.get_host_by_hostname(self.hostname, self.collector)
self.info = info
self.properties = self.params["properties"]
self.description = self.params["description"]
self.starttime = self.params["starttime"]
self.duration = self.params["duration"]
self.alertenable = self.params["alertenable"]
if self.params["groups"] is not None:
self.groups = self._strip_groups(self.params["groups"])
else:
self.groups = None
def create(self):
"""Idemopotent function to create if missing,
update if changed, or skip"""
self.module.debug("Running Host.create...")
self.update()
def get_properties(self):
"""Returns a hash of the properties
associated with this LogicMonitor host"""
self.module.debug("Running Host.get_properties...")
if self.info:
self.module.debug("Making RPC call to 'getHostProperties'")
properties_json = (json.loads(self.rpc("getHostProperties",
{'hostId': self.info["id"],
"filterSystemProperties": True})))
if properties_json["status"] == 200:
self.module.debug("RPC call succeeded")
return properties_json["data"]
else:
self.module.debug("Error: there was an issue retrieving the " +
"host properties")
self.module.debug(properties_json["errmsg"])
self.fail(msg=properties_json["status"])
else:
self.module.debug(
"Unable to find LogicMonitor host which matches " +
self.displayname + " (" + self.hostname + ")"
)
return None
def set_properties(self, propertyhash):
"""update the host to have the properties
contained in the property hash"""
self.module.debug("Running Host.set_properties...")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
self.module.debug("Assigning property hash to host object")
self.properties = propertyhash
def add(self):
"""Add this device to monitoring
in your LogicMonitor account"""
self.module.debug("Running Host.add...")
if self.collector and not self.info:
self.module.debug("Host not registered. Registering.")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
h = self._build_host_hash(
self.hostname,
self.displayname,
self.collector,
self.description,
self.groups,
self.properties,
self.alertenable)
self.module.debug("Making RPC call to 'addHost'")
resp = json.loads(self.rpc("addHost", h))
if resp["status"] == 200:
self.module.debug("RPC call succeeded")
return resp["data"]
else:
self.module.debug("RPC call failed")
self.module.debug(resp)
return resp["errmsg"]
elif self.collector is None:
self.fail(msg="Specified collector doesn't exist")
else:
self.module.debug("Host already registered")
def update(self):
"""This method takes changes made to this host
and applies them to the corresponding host
in your LogicMonitor account."""
self.module.debug("Running Host.update...")
if self.info:
self.module.debug("Host already registed")
if self.is_changed():
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
h = (self._build_host_hash(
self.hostname,
self.displayname,
self.collector,
self.description,
self.groups,
self.properties,
self.alertenable))
h["id"] = self.info["id"]
h["opType"] = "replace"
self.module.debug("Making RPC call to 'updateHost'")
resp = json.loads(self.rpc("updateHost", h))
if resp["status"] == 200:
self.module.debug("RPC call succeeded")
else:
self.module.debug("RPC call failed")
self.fail(msg="Error: unable to update the host.")
else:
self.module.debug(
"Host properties match supplied properties. " +
"No changes to make."
)
return self.info
else:
self.module.debug("Host not registed. Registering")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
return self.add()
def remove(self):
"""Remove this host from your LogicMonitor account"""
self.module.debug("Running Host.remove...")
if self.info:
self.module.debug("Host registered")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
self.module.debug("Making RPC call to 'deleteHost'")
resp = json.loads(self.rpc("deleteHost",
{"hostId": self.info["id"],
"deleteFromSystem": True,
"hostGroupId": 1}))
if resp["status"] == 200:
self.module.debug(resp)
self.module.debug("RPC call succeeded")
return resp
else:
self.module.debug("RPC call failed")
self.module.debug(resp)
self.fail(msg=resp["errmsg"])
else:
self.module.debug("Host not registered")
def is_changed(self):
"""Return true if the host doesn't
match the LogicMonitor account"""
self.module.debug("Running Host.is_changed")
ignore = ['system.categories', 'snmp.version']
hostresp = self.get_host_by_displayname(self.displayname)
if hostresp is None:
hostresp = self.get_host_by_hostname(self.hostname, self.collector)
if hostresp:
self.module.debug("Comparing simple host properties")
if hostresp["alertEnable"] != self.alertenable:
return True
if hostresp["description"] != self.description:
return True
if hostresp["displayedAs"] != self.displayname:
return True
if (self.collector and
hasattr(self.collector, "id") and
hostresp["agentId"] != self.collector["id"]):
return True
self.module.debug("Comparing groups.")
if self._compare_groups(hostresp) is True:
return True
propresp = self.get_properties()
if propresp:
self.module.debug("Comparing properties.")
if self._compare_props(propresp, ignore) is True:
return True
else:
self.fail(
msg="Error: Unknown error retrieving host properties")
return False
else:
self.fail(msg="Error: Unknown error retrieving host information")
def sdt(self):
"""Create a scheduled down time
(maintenance window) for this host"""
self.module.debug("Running Host.sdt...")
if self.info:
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
duration = self.duration
starttime = self.starttime
offset = starttime
if starttime:
self.module.debug("Start time specified")
start = datetime.datetime.strptime(starttime, '%Y-%m-%d %H:%M')
offsetstart = start
else:
self.module.debug("No start time specified. Using default.")
start = datetime.datetime.utcnow()
# Use user UTC offset
self.module.debug("Making RPC call to 'getTimeZoneSetting'")
accountresp = (json.loads(self.rpc("getTimeZoneSetting", {})))
if accountresp["status"] == 200:
self.module.debug("RPC call succeeded")
offset = accountresp["data"]["offset"]
offsetstart = start + datetime.timedelta(0, offset)
else:
self.fail(
msg="Error: Unable to retrieve timezone offset")
offsetend = offsetstart + datetime.timedelta(0, int(duration)*60)
h = {"hostId": self.info["id"],
"type": 1,
"year": offsetstart.year,
"month": offsetstart.month - 1,
"day": offsetstart.day,
"hour": offsetstart.hour,
"minute": offsetstart.minute,
"endYear": offsetend.year,
"endMonth": offsetend.month - 1,
"endDay": offsetend.day,
"endHour": offsetend.hour,
"endMinute": offsetend.minute}
self.module.debug("Making RPC call to 'setHostSDT'")
resp = (json.loads(self.rpc("setHostSDT", h)))
if resp["status"] == 200:
self.module.debug("RPC call succeeded")
return resp["data"]
else:
self.module.debug("RPC call failed")
self.fail(msg=resp["errmsg"])
else:
self.fail(msg="Error: Host doesn't exit.")
def site_facts(self):
"""Output current properties information for the Host"""
self.module.debug("Running Host.site_facts...")
if self.info:
self.module.debug("Host exists")
props = self.get_properties()
self.output_info(props)
else:
self.fail(msg="Error: Host doesn't exit.")
def _build_host_hash(self,
hostname,
displayname,
collector,
description,
groups,
properties,
alertenable):
"""Return a property formated hash for the
creation of a host using the rpc function"""
self.module.debug("Running Host._build_host_hash...")
h = {}
h["hostName"] = hostname
h["displayedAs"] = displayname
h["alertEnable"] = alertenable
if collector:
self.module.debug("Collector property exists")
h["agentId"] = collector["id"]
else:
self.fail(
msg="Error: No collector found. Unable to build host hash.")
if description:
h["description"] = description
if groups is not None and groups is not []:
self.module.debug("Group property exists")
groupids = ""
for group in groups:
groupids = groupids + str(self.create_group(group)) + ","
h["hostGroupIds"] = groupids.rstrip(',')
if properties is not None and properties is not {}:
self.module.debug("Properties hash exists")
propnum = 0
for key, value in properties.iteritems():
h["propName" + str(propnum)] = key
h["propValue" + str(propnum)] = value
propnum = propnum + 1
return h
def _verify_property(self, propname):
"""Check with LogicMonitor server to
verify property is unchanged"""
self.module.debug("Running Host._verify_property...")
if self.info:
self.module.debug("Host is registered")
if propname not in self.properties:
self.module.debug("Property " + propname + " does not exist")
return False
else:
self.module.debug("Property " + propname + " exists")
h = {"hostId": self.info["id"],
"propName0": propname,
"propValue0": self.properties[propname]}
self.module.debug("Making RCP call to 'verifyProperties'")
resp = json.loads(self.rpc('verifyProperties', h))
if resp["status"] == 200:
self.module.debug("RPC call succeeded")
return resp["data"]["match"]
else:
self.fail(
msg="Error: unable to get verification " +
"from server.\n%s" % resp["errmsg"])
else:
self.fail(
msg="Error: Host doesn't exist. Unable to verify properties")
def _compare_groups(self, hostresp):
"""Function to compare the host's current
groups against provided groups"""
self.module.debug("Running Host._compare_groups")
g = []
fullpathinids = hostresp["fullPathInIds"]
self.module.debug("Building list of groups")
for path in fullpathinids:
if path != []:
h = {'hostGroupId': path[-1]}
hgresp = json.loads(self.rpc("getHostGroup", h))
if (hgresp["status"] == 200 and
hgresp["data"]["appliesTo"] == ""):
g.append(path[-1])
if self.groups is not None:
self.module.debug("Comparing group lists")
for group in self.groups:
groupjson = self.get_group(group)
if groupjson is None:
self.module.debug("Group mismatch. No result.")
return True
elif groupjson['id'] not in g:
self.module.debug("Group mismatch. ID doesn't exist.")
return True
else:
g.remove(groupjson['id'])
if g != []:
self.module.debug("Group mismatch. New ID exists.")
return True
self.module.debug("Groups match")
def _compare_props(self, propresp, ignore):
"""Function to compare the host's current
properties against provided properties"""
self.module.debug("Running Host._compare_props...")
p = {}
self.module.debug("Creating list of properties")
for prop in propresp:
if prop["name"] not in ignore:
if ("*******" in prop["value"] and
self._verify_property(prop["name"])):
p[prop["name"]] = self.properties[prop["name"]]
else:
p[prop["name"]] = prop["value"]
self.module.debug("Comparing properties")
# Iterate provided properties and compare to received properties
for prop in self.properties:
if (prop not in p or
p[prop] != self.properties[prop]):
self.module.debug("Properties mismatch")
return True
self.module.debug("Properties match")
def _strip_groups(self, groups):
"""Function to strip whitespace from group list.
This function provides the user some flexibility when
formatting group arguments """
self.module.debug("Running Host._strip_groups...")
return map(lambda x: x.strip(), groups)
class Datasource(LogicMonitor):
def __init__(self, params, module=None):
"""Initializor for the LogicMonitor Datasource object"""
self.change = False
self.params = params
LogicMonitor.__init__(self, module, **params)
self.module.debug("Instantiating Datasource object")
self.id = self.params["id"]
self.starttime = self.params["starttime"]
self.duration = self.params["duration"]
def sdt(self):
"""Create a scheduled down time
(maintenance window) for this host"""
self.module.debug("Running Datasource.sdt...")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
duration = self.duration
starttime = self.starttime
offsetstart = starttime
if starttime:
self.module.debug("Start time specified")
start = datetime.datetime.strptime(starttime, '%Y-%m-%d %H:%M')
offsetstart = start
else:
self.module.debug("No start time specified. Using default.")
start = datetime.datetime.utcnow()
# Use user UTC offset
self.module.debug("Making RPC call to 'getTimeZoneSetting'")
accountresp = json.loads(self.rpc("getTimeZoneSetting", {}))
if accountresp["status"] == 200:
self.module.debug("RPC call succeeded")
offset = accountresp["data"]["offset"]
offsetstart = start + datetime.timedelta(0, offset)
else:
self.fail(msg="Error: Unable to retrieve timezone offset")
offsetend = offsetstart + datetime.timedelta(0, int(duration)*60)
h = {"hostDataSourceId": self.id,
"type": 1,
"notifyCC": True,
"year": offsetstart.year,
"month": offsetstart.month-1,
"day": offsetstart.day,
"hour": offsetstart.hour,
"minute": offsetstart.minute,
"endYear": offsetend.year,
"endMonth": offsetend.month-1,
"endDay": offsetend.day,
"endHour": offsetend.hour,
"endMinute": offsetend.minute}
self.module.debug("Making RPC call to 'setHostDataSourceSDT'")
resp = json.loads(self.rpc("setHostDataSourceSDT", h))
if resp["status"] == 200:
self.module.debug("RPC call succeeded")
return resp["data"]
else:
self.module.debug("RPC call failed")
self.fail(msg=resp["errmsg"])
class Hostgroup(LogicMonitor):
def __init__(self, params, module=None):
"""Initializor for the LogicMonitor host object"""
self.change = False
self.params = params
LogicMonitor.__init__(self, module, **self.params)
self.module.debug("Instantiating Hostgroup object")
self.fullpath = self.params["fullpath"]
self.info = self.get_group(self.fullpath)
self.properties = self.params["properties"]
self.description = self.params["description"]
self.starttime = self.params["starttime"]
self.duration = self.params["duration"]
self.alertenable = self.params["alertenable"]
def create(self):
"""Wrapper for self.update()"""
self.module.debug("Running Hostgroup.create...")
self.update()
def get_properties(self, final=False):
"""Returns a hash of the properties
associated with this LogicMonitor host"""
self.module.debug("Running Hostgroup.get_properties...")
if self.info:
self.module.debug("Group found")
self.module.debug("Making RPC call to 'getHostGroupProperties'")
properties_json = json.loads(self.rpc(
"getHostGroupProperties",
{'hostGroupId': self.info["id"],
"finalResult": final}))
if properties_json["status"] == 200:
self.module.debug("RPC call succeeded")
return properties_json["data"]
else:
self.module.debug("RPC call failed")
self.fail(msg=properties_json["status"])
else:
self.module.debug("Group not found")
return None
def set_properties(self, propertyhash):
"""Update the host to have the properties
contained in the property hash"""
self.module.debug("Running Hostgroup.set_properties")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
self.module.debug("Assigning property has to host object")
self.properties = propertyhash
def add(self):
"""Idempotent function to ensure that the host
group exists in your LogicMonitor account"""
self.module.debug("Running Hostgroup.add")
if self.info is None:
self.module.debug("Group doesn't exist. Creating.")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
self.create_group(self.fullpath)
self.info = self.get_group(self.fullpath)
self.module.debug("Group created")
return self.info
else:
self.module.debug("Group already exists")
def update(self):
"""Idempotent function to ensure the host group settings
(alertenable, properties, etc) in the
LogicMonitor account match the current object."""
self.module.debug("Running Hostgroup.update")
if self.info:
if self.is_changed():
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
h = self._build_host_group_hash(
self.fullpath,
self.description,
self.properties,
self.alertenable)
h["opType"] = "replace"
if self.fullpath != "/":
h["id"] = self.info["id"]
self.module.debug("Making RPC call to 'updateHostGroup'")
resp = json.loads(self.rpc("updateHostGroup", h))
if resp["status"] == 200:
self.module.debug("RPC call succeeded")
return resp["data"]
else:
self.module.debug("RPC call failed")
self.fail(msg="Error: Unable to update the " +
"host.\n" + resp["errmsg"])
else:
self.module.debug(
"Group properties match supplied properties. " +
"No changes to make"
)
return self.info
else:
self.module.debug("Group doesn't exist. Creating.")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
return self.add()
def remove(self):
"""Idempotent function to ensure the host group
does not exist in your LogicMonitor account"""
self.module.debug("Running Hostgroup.remove...")
if self.info:
self.module.debug("Group exists")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
self.module.debug("Making RPC call to 'deleteHostGroup'")
resp = json.loads(self.rpc("deleteHostGroup",
{"hgId": self.info["id"]}))
if resp["status"] == 200:
self.module.debug(resp)
self.module.debug("RPC call succeeded")
return resp
elif resp["errmsg"] == "No such group":
self.module.debug("Group doesn't exist")
else:
self.module.debug("RPC call failed")
self.module.debug(resp)
self.fail(msg=resp["errmsg"])
else:
self.module.debug("Group doesn't exist")
def is_changed(self):
"""Return true if the host doesn't match
the LogicMonitor account"""
self.module.debug("Running Hostgroup.is_changed...")
ignore = []
group = self.get_group(self.fullpath)
properties = self.get_properties()
if properties is not None and group is not None:
self.module.debug("Comparing simple group properties")
if (group["alertEnable"] != self.alertenable or
group["description"] != self.description):
return True
p = {}
self.module.debug("Creating list of properties")
for prop in properties:
if prop["name"] not in ignore:
if ("*******" in prop["value"] and
self._verify_property(prop["name"])):
p[prop["name"]] = (
self.properties[prop["name"]])
else:
p[prop["name"]] = prop["value"]
self.module.debug("Comparing properties")
if set(p) != set(self.properties):
return True
else:
self.module.debug("No property information received")
return False
def sdt(self, duration=30, starttime=None):
"""Create a scheduled down time
(maintenance window) for this host"""
self.module.debug("Running Hostgroup.sdt")
self.module.debug("System changed")
self.change = True
if self.check_mode:
self.exit(changed=True)
duration = self.duration
starttime = self.starttime
offset = starttime
if starttime:
self.module.debug("Start time specified")
start = datetime.datetime.strptime(starttime, '%Y-%m-%d %H:%M')
offsetstart = start
else:
self.module.debug("No start time specified. Using default.")
start = datetime.datetime.utcnow()
# Use user UTC offset
self.module.debug("Making RPC call to 'getTimeZoneSetting'")
accountresp = json.loads(self.rpc("getTimeZoneSetting", {}))
if accountresp["status"] == 200:
self.module.debug("RPC call succeeded")
offset = accountresp["data"]["offset"]
offsetstart = start + datetime.timedelta(0, offset)
else:
self.fail(
msg="Error: Unable to retrieve timezone offset")
offsetend = offsetstart + datetime.timedelta(0, int(duration)*60)
h = {"hostGroupId": self.info["id"],
"type": 1,
"year": offsetstart.year,
"month": offsetstart.month-1,
"day": offsetstart.day,
"hour": offsetstart.hour,
"minute": offsetstart.minute,
"endYear": offsetend.year,
"endMonth": offsetend.month-1,
"endDay": offsetend.day,
"endHour": offsetend.hour,
"endMinute": offsetend.minute}
self.module.debug("Making RPC call to setHostGroupSDT")
resp = json.loads(self.rpc("setHostGroupSDT", h))
if resp["status"] == 200:
self.module.debug("RPC call succeeded")
return resp["data"]
else:
self.module.debug("RPC call failed")
self.fail(msg=resp["errmsg"])
def site_facts(self):
"""Output current properties information for the Hostgroup"""
self.module.debug("Running Hostgroup.site_facts...")
if self.info:
self.module.debug("Group exists")
props = self.get_properties(True)
self.output_info(props)
else:
self.fail(msg="Error: Group doesn't exit.")
def _build_host_group_hash(self,
fullpath,
description,
properties,
alertenable):
"""Return a property formated hash for the
creation of a hostgroup using the rpc function"""
self.module.debug("Running Hostgroup._build_host_hash")
h = {}
h["alertEnable"] = alertenable
if fullpath == "/":
self.module.debug("Group is root")
h["id"] = 1
else:
self.module.debug("Determining group path")
parentpath, name = fullpath.rsplit('/', 1)
parent = self.get_group(parentpath)
h["name"] = name
if parent:
self.module.debug("Parent group " +
str(parent["id"]) + " found.")
h["parentID"] = parent["id"]
else:
self.module.debug("No parent group found. Using root.")
h["parentID"] = 1
if description:
self.module.debug("Description property exists")
h["description"] = description
if properties != {}:
self.module.debug("Properties hash exists")
propnum = 0
for key, value in properties.iteritems():
h["propName" + str(propnum)] = key
h["propValue" + str(propnum)] = value
propnum = propnum + 1
return h
def _verify_property(self, propname):
"""Check with LogicMonitor server
to verify property is unchanged"""
self.module.debug("Running Hostgroup._verify_property")
if self.info:
self.module.debug("Group exists")
if propname not in self.properties:
self.module.debug("Property " + propname + " does not exist")
return False
else:
self.module.debug("Property " + propname + " exists")
h = {"hostGroupId": self.info["id"],
"propName0": propname,
"propValue0": self.properties[propname]}
self.module.debug("Making RCP call to 'verifyProperties'")
resp = json.loads(self.rpc('verifyProperties', h))
if resp["status"] == 200:
self.module.debug("RPC call succeeded")
return resp["data"]["match"]
else:
self.fail(
msg="Error: unable to get verification " +
"from server.\n%s" % resp["errmsg"])
else:
self.fail(
msg="Error: Group doesn't exist. Unable to verify properties")
def selector(module):
"""Figure out which object and which actions
to take given the right parameters"""
if module.params["target"] == "collector":
target = Collector(module.params, module)
elif module.params["target"] == "host":
# Make sure required parameter collector is specified
if ((module.params["action"] == "add" or
module.params["displayname"] is None) and
module.params["collector"] is None):
module.fail_json(
msg="Parameter 'collector' required.")
target = Host(module.params, module)
elif module.params["target"] == "datasource":
# Validate target specific required parameters
if module.params["id"] is not None:
# make sure a supported action was specified
if module.params["action"] == "sdt":
target = Datasource(module.params, module)
else:
errmsg = ("Error: Unexpected action \"" +
module.params["action"] + "\" was specified.")
module.fail_json(msg=errmsg)
elif module.params["target"] == "hostgroup":
# Validate target specific required parameters
if module.params["fullpath"] is not None:
target = Hostgroup(module.params, module)
else:
module.fail_json(
msg="Parameter 'fullpath' required for target 'hostgroup'")
else:
module.fail_json(
msg="Error: Unexpected target \"" + module.params["target"] +
"\" was specified.")
if module.params["action"].lower() == "add":
action = target.create
elif module.params["action"].lower() == "remove":
action = target.remove
elif module.params["action"].lower() == "sdt":
action = target.sdt
elif module.params["action"].lower() == "update":
action = target.update
else:
errmsg = ("Error: Unexpected action \"" + module.params["action"] +
"\" was specified.")
module.fail_json(msg=errmsg)
action()
module.exit_json(changed=target.change)
def main():
TARGETS = [
"collector",
"host",
"datasource",
"hostgroup"]
ACTIONS = [
"add",
"remove",
"sdt",
"update"]
module = AnsibleModule(
argument_spec=dict(
target=dict(required=True, default=None, choices=TARGETS),
action=dict(required=True, default=None, choices=ACTIONS),
company=dict(required=True, default=None),
user=dict(required=True, default=None),
password=dict(required=True, default=None, no_log=True),
collector=dict(required=False, default=None),
hostname=dict(required=False, default=None),
displayname=dict(required=False, default=None),
id=dict(required=False, default=None),
description=dict(required=False, default=""),
fullpath=dict(required=False, default=None),
starttime=dict(required=False, default=None),
duration=dict(required=False, default=30),
properties=dict(required=False, default={}, type="dict"),
groups=dict(required=False, default=[], type="list"),
alertenable=dict(required=False, default="true", choices=BOOLEANS)
),
supports_check_mode=True
)
if HAS_LIB_JSON is not True:
module.fail_json(msg="Unable to load JSON library")
selector(module)
from ansible.module_utils.basic import *
from ansible.module_utils.urls import *
from ansible.module_utils.urls import open_url
if __name__ == "__main__":
main()