def main():
    # Connect to SWIS
    server = 'localhost'
    username = '******'
    password = ''
    swis = SwisClient(server, username, password)

    # Disable/Enable CBQoS Sources
    node_caption = 'My testing router'
    query_results = swis.query(
        'SELECT NodeID FROM Orion.Nodes WHERE Caption = @nodecaption_par',
        nodecaption_par=node_caption)
    node_id = query_results['results'][0]['NodeID']
    query_results = swis.query(
        'SELECT Uri FROM Orion.Netflow.CBQoSSource WHERE NodeID = @nodeid_par',
        nodeid_par=node_id)
    enabled_flag = False  # Change this value to True if you want to enable sources
    props = {'Enabled': enabled_flag}

    for row in query_results['results']:
        swis.update(row['Uri'], **props)

    # Print results
    query_results = swis.query(
        'SELECT CBQoSSourceID FROM Orion.Netflow.CBQoSSource WHERE NodeID = @nodeid_par and Enabled = @enabled_par',
        nodeid_par=node_id,
        enabled_par=enabled_flag)
    print(
        'Changed enabled status to {0} for {1} CBQoS sources for node with ID {2}'
        .format(enabled_flag, len(query_results['results']), node_id))
def main():
    npm_server = 'localhost'
    username = '******'
    password = ''

    swis = SwisClient(npm_server, username, password)
    print("Custom Property Update Test:")
    results = swis.query("SELECT Uri FROM Orion.Nodes WHERE NodeID=@id",
                         id=1)  # set valid NodeID!
    uri = results['results'][0]['Uri']

    swis.update(uri + '/CustomProperties', City='Austin')
    obj = swis.read(uri + '/CustomProperties')
    print(obj)
def main():
    npm_server = 'localhost'
    username = '******'
    password = ''

    swis = SwisClient(npm_server, username, password)
    print("Custom Property Update Test:")
    results = swis.query(
        "SELECT Uri FROM Orion.Nodes WHERE NodeID=@id",
        id=1)  # set valid NodeID!
    uri = results['results'][0]['Uri']

    swis.update(uri + '/CustomProperties', City='Austin')
    obj = swis.read(uri + '/CustomProperties')
    print (obj)
Beispiel #4
0
def main():
    # Connect to SWIS
    server = 'localhost'
    username = '******'
    password = ''
    swis = SwisClient(server, username, password)

    alert_name = 'NTA Alert on machine-hostname'
    query_results = swis.query(
        'Select Uri FROM Orion.AlertConfigurations WHERE Name = @alertname_par',
        alertname_par=alert_name)
    uri = query_results['results'][0]['Uri']

    # Disable alert
    props = {'Enabled': False}
    swis.update(uri, **props)

    # Enable alert
    props = {'Enabled': True}
    swis.update(uri, **props)
def main():
    # Connect to SWIS
    server = 'localhost'
    username = '******'
    password = ''
    swis = SwisClient(server, username, password)

    # List available Orion Settings
    # Uncomment if you want to get  all available Orion Settings
    # query_results = swis.query('SELECT SettingID, Name, Description, Units, Minimum, Maximum, CurrentValue, DefaultValue, Hint FROM Orion.Settings')
    # pprint.pprint(query_results['results'])

    setting_id = 'CBQoS_Enabled'
    query_results = swis.query('SELECT Uri FROM Orion.Settings WHERE SettingID = @settingid_par', settingid_par=setting_id)
    uri = query_results['results'][0]['Uri']
    props = {
        'CurrentValue': 0   # Change this value to 1 to enable setting
    }
    swis.update(uri, **props)
    query_results = swis.query('SELECT SettingID, Name, Description, Units, Minimum, Maximum, CurrentValue, DefaultValue, Hint FROM Orion.Settings WHERE SettingID = @settingid_par', settingid_par=setting_id)
    print('Status of the setting {0} after the change'.format(setting_id))
    pprint.pprint(query_results['results'])
Beispiel #6
0
class NodeManager:
    def __init__(self, username, password):

        # Change 'orion' to your Orion NPM server name or IP.
        self._swis = SwisClient('orion', username, password)

    def add_node(self, **node):
        self._node_element(**node)
        self._node_pollers()
        self._node_custom_props(**node)
        self._poll()
        self._node_ncm(**node)

    def _node_element(self, **node):

        # Extract IP Address and node name from node variables
        ip_address = node['IP_Address']
        node_name = node['Caption']

        # Setup properties for the new node
        props = {
            'IPAddress': ip_address,
            'EngineID': 5,
            'ObjectSubType': 'SNMP',
            'SNMPVersion': 3,
            'Caption': node_name,
            'SNMPV3AuthKey': 'YourKey',  # Enter your key here
            'SNMPv3AuthKeyIsPwd': True,
            'SNMPv3AuthMethod': 'SHA1',
            'SNMPv3PrivKey': 'YourKey',  # Enter your key here
            'SNMPv3PrivKeyIsPwd': True,
            'SNMPv3PrivMethod': 'AES128',
            'SNMPV3Username': '******'  # Enter your SNMPv3 Username here
        }

        # Create the node
        print("Adding node {}... ".format(props['IPAddress']), end="")
        self._results = self._swis.create('Orion.Nodes', **props)
        print("DONE!")

        # Extract nodeID from the results
        self._nodeid = self._parse_node(self._results)

    def _parse_node(self, results):
        return re.search('(\d+)$', self._results).group(0)

    def _node_pollers(self):

        # Setup poller status for the node
        pollers_enabled = {
            'N.Status.ICMP.Native': True,
            'N.Status.SNMP.Native': False,
            'N.ResponseTime.ICMP.Native': True,
            'N.ResponseTime.SNMP.Native': False,
            'N.Details.SNMP.Generic': True,
            'N.Uptime.SNMP.Generic': True,
            'N.Cpu.SNMP.HrProcessorLoad': True,
            'N.Memory.SNMP.NetSnmpReal': True,
            'N.AssetInventory.Snmp.Generic': True,
            'N.Topology_Layer3.SNMP.ipNetToMedia': False,
            'N.Routing.SNMP.Ipv4CidrRoutingTable': False
        }

        pollers = []
        for k in pollers_enabled:
            pollers.append({
                'PollerType': k,
                'NetObject': 'N:' + self._nodeid,
                'NetObjectType': 'N',
                'NetObjectID': self._nodeid,
                'Enabled': pollers_enabled[k]
            })

        # Add node to pollers
        for poller in pollers:
            print("  Adding poller type: {} with status {}... ".format(
                poller['PollerType'], poller['Enabled']),
                  end="")
            response = self._swis.create('Orion.Pollers', **poller)
            print("DONE!")

    def _node_custom_props(self, **node):

        # Copy 'node' dict to new dict 'props' and remove keys not relative to custom properties
        props = node
        ignore_keys = ('IPAddress', 'Caption', 'NodeGroup', 'DeviceTemplate',
                       'ConnectionProfile')
        for k in ignore_keys:
            props.pop(k, None)

        # Add custom properties to node
        for k, v in props.items():
            print("  Adding custom property: {} with value {}... ".format(
                k, v),
                  end="")
            self._swis.update(self._results + '/CustomProperties', **{k: v})
            print("DONE!")

    def _poll(self):

        # Poll the node
        print("  Polling node... ", end="")
        self._swis.invoke('Orion.Nodes', 'PollNow', 'N:' + self._nodeid)
        print("DONE!")

    def _node_ncm(self, **node):

        # Add node to NCM
        self._swis.invoke('Cirrus.Nodes', 'AddNodeToNCM', self._nodeid)

        # Lookup the NCM NodeID, which is a Guid
        ncmNodeID = self._swis.query(
            'SELECT NodeID FROM Cirrus.Nodes WHERE CoreNodeID=@node',
            node=self._nodeid)['results'][0]['NodeID']

        # Fetch the NCM Node object
        ncmNode = self._swis.invoke('Cirrus.Nodes', 'GetNode', ncmNodeID)

        # Modify our local copy of the NCM Node object
        ncmNode['ConnectionProfile'] = node['ConnectionProfile']
        ncmNode['DeviceTemplate'] = node['DeviceTemplate']
        ncmNode['NodeGroup'] = node['NodeGroup']

        # Commit our changes
        print("  Adding node to NCM... ", end="")
        self._swis.invoke('Cirrus.Nodes', 'UpdateNode', ncmNode)
        print("DONE!")
Beispiel #7
0
class OrionBaseAction(Action):
    def __init__(self, config):
        super(OrionBaseAction, self).__init__(config)

        self.client = None

        if "orion_host" not in self.config:
            raise ValueError("Orion host details not in the config.yaml")
        elif "orion_user" not in self.config:
            raise ValueError("Orion user details not in the config.yaml")
        elif "orion_password" not in self.config:
            raise ValueError("Orion password details not in the config.yaml")

    def connect(self):
        """
        Connect to the Orion server listed in the config.
        """

        self.client = SwisClient(self.config['orion_host'],
                                 self.config['orion_user'],
                                 self.config['orion_password'])

        return self.config['orion_label']

    def get_node(self, node):
        """
        Get an OrionNode object
        """

        orion_node = OrionNode()

        if is_ip(node):
            query_for_where = "IPAddress"
        else:
            query_for_where = "Caption"

        swql = """SELECT NodeID, Uri, IPAddress, Caption
        FROM Orion.Nodes
        WHERE {}=@query_on""".format(query_for_where)
        kargs = {'query_on': node}
        data = self.query(swql, **kargs)

        if 'results' not in data:
            msg = "No results from Orion: {}".format(data)
            self.logger.info(msg)
            raise Exception(msg)

        if len(data['results']) == 1:
            try:
                orion_node.npm_id = data['results'][0]['NodeID']
                orion_node.uri = data['results'][0]['Uri']
                orion_node.ip_address = data['results'][0]['IPAddress']
                orion_node.caption = data['results'][0]['Caption']
            except IndexError:
                pass
        elif len(data['results']) >= 2:
            self.logger.debug(
                "Muliple Nodes match '{}' Caption: {}".format(
                    node, data))
            raise ValueError("Muliple Nodes match '{}' Caption".format(
                node))

        if orion_node.npm:
            swql = """SELECT NodeID
            FROM Cirrus.Nodes
            WHERE CoreNodeID=@CoreNodeID"""
            kargs = {'CoreNodeID': orion_node.npm_id}
            data = self.query(swql, **kargs)

            # Don't raise an exception if this fails.
            # The platform may not haev NCM installed.
            if 'results' not in data:
                msg = "No results from Orion NCM: {}".format(data)
                self.logger.info(msg)
            elif len(data['results']) == 1:
                try:
                    orion_node.ncm_id = data['results'][0]['NodeID']
                except IndexError:
                    pass

        return orion_node

    def query(self, swql, **kargs):
        """
        Run SWQL against the Orion Platform.
        """
        return self.client.query(swql, **kargs)

    def invoke(self, entity, verb, *args):
        """
        Run an Invoke against the Orion Platform.
        """
        return self.client.invoke(entity, verb, *args)

    def create(self, entity, **kargs):
        """
        Run an Create against the Orion Platform.
        """
        return self.client.create(entity, **kargs)

    def read(self, uri):
        """
        Run an Read against the Orion Platform.
        """
        return self.client.read(uri)

    def update(self, uri, **kargs):
        """
        Run an Update against the Orion Platform.
        """
        return self.client.update(uri, **kargs)

    def delete(self, uri):
        """
        Run an Delete of an URI against the Orion Platform.
        """
        return self.client.delete(uri)

    def get_snmp_community(self, community):
        """
        Return the correct SNMP comminity to use.
        """
        if community == "customer":
            return self.config['snmp_customer']
        elif community == "internal":
            return self.config['snmp_internal']
        elif community is None:
            return self.config['snmp_default']
        else:
            return community

    def get_snmp_cred_id(self, community):
        """
        Look up an SNMP community in the config and then look up
        the Orion ID for the Credential.
        """

        # Check if the community should be replaced.
        name = self.get_snmp_community(community)

        swql = """SELECT ID FROM Orion.Credential
        WHERE CredentialType=@CredentialType and Name=@name"""

        kargs = {'CredentialType':
                 'SolarWinds.Orion.Core.Models.Credentials.SnmpCredentialsV2',
                 'name': name}
        orion_data = self.query(swql, **kargs)

        if len(orion_data['results']) == 1:
            return orion_data['results'][0]['ID']
        else:
            msg = "Could not get ID for community in Orion.Credential: {}".format(
                community)
            send_user_error(msg)
            raise ValueError(msg)

    def get_engine_id(self, poller):
        """
        Takes a poller name (or primary) and returns the EngineID for
        the poller.

        Raises: ValueError on an invaild poller.

        Returns: The EngineID (int)
        """

        if poller == "primary":
            return 1
        else:
            swql = """SELECT EngineID, ServerName, IP, ServerType
            FROM Orion.Engines
            WHERE ServerName=@poller"""
            kargs = {'poller': poller}
            data = self.query(swql, **kargs)

            if len(data['results']) == 1:
                return data['results'][0]['EngineID']
            else:
                send_user_error("Invalid poller name")
                raise ValueError("Invalid poller name")

    def get_ncm_transfer_results(self, transfer_id, sleep_delay=10):
        """
        Gets the completed (waits until finished). NCM job transfer status
        from Orion.

        Retruns: The completed status.
        """
        ts = {}
        while True:
            swql = """SELECT TransferID, NodeID, Action, RequestedConfigType,
            RequestedScript, RequestedReboot, ConfigID, TransferProtocol,
            Status, ErrorMessage, DeviceOutput, DateTime, UserName
            FROM NCM.TransferResults
            WHERE TransferID=@transfer_id"""
            kargs = {'transfer_id': transfer_id}

            transfer_data = self.query(swql, **kargs)
            status = transfer_data['results'][0]['Status']

            if status == 1:
                time.sleep(sleep_delay)
            elif status == 2:
                ts['status'] = "Complete"
                break
            elif status == 3:
                ts['status'] = "Error"
                break
            else:
                ts['status'] = "Unknown"
                break

        ts['RequestedScript'] = transfer_data['results'][0]['RequestedScript']
        ts['RequestedReboot'] = transfer_data['results'][0]['RequestedReboot']
        ts['ErrorMessage'] = transfer_data['results'][0]['ErrorMessage']
        ts['DeviceOutput'] = transfer_data['results'][0]['DeviceOutput']
        ts['UserName'] = transfer_data['results'][0]['UserName']

        return ts
Beispiel #8
0
class OrionBaseAction(Action):
    def __init__(self, config):
        super(OrionBaseAction, self).__init__(config)

        self.client = None

        if "orion_host" not in self.config:
            raise ValueError("Orion host details not in the config.yaml")
        elif "orion_user" not in self.config:
            raise ValueError("Orion user details not in the config.yaml")
        elif "orion_password" not in self.config:
            raise ValueError("Orion password details not in the config.yaml")

    def connect(self):
        """
        Connect to the Orion server listed in the config.
        """

        self.client = SwisClient(self.config['orion_host'],
                                 self.config['orion_user'],
                                 self.config['orion_password'])

        return self.config['orion_label']

    def get_node(self, node):
        """
        Get an OrionNode object
        """

        orion_node = OrionNode()

        if is_ip(node):
            query_for_where = "IPAddress"
        else:
            query_for_where = "Caption"

        swql = """SELECT NodeID, Uri, IPAddress, Caption
        FROM Orion.Nodes
        WHERE {}=@query_on""".format(query_for_where)
        kargs = {'query_on': node}
        data = self.query(swql, **kargs)

        if 'results' not in data:
            msg = "No results from Orion: {}".format(data)
            self.logger.info(msg)
            raise Exception(msg)

        if len(data['results']) == 1:
            try:
                orion_node.npm_id = data['results'][0]['NodeID']
                orion_node.uri = data['results'][0]['Uri']
                orion_node.ip_address = data['results'][0]['IPAddress']
                orion_node.caption = data['results'][0]['Caption']
            except IndexError:
                pass
        elif len(data['results']) >= 2:
            self.logger.debug("Muliple Nodes match '{}' Caption: {}".format(
                node, data))
            raise ValueError("Muliple Nodes match '{}' Caption".format(node))

        if orion_node.npm:
            swql_ncm = """SELECT NodeID
            FROM Cirrus.Nodes
            WHERE CoreNodeID=@CoreNodeID"""
            kargs = {'CoreNodeID': orion_node.npm_id}
            try:
                data_ncm = self.query(swql_ncm, **kargs)
            except requests.exceptions.HTTPError:
                # Create an empty dict to allow remaining code to fail gracefully
                data_ncm = {}
                self.logger.info("Connection to NCM failed. NCM not installed")

            # Don't raise an exception if this fails.
            # The platform may not have NCM installed.
            if 'results' not in data_ncm:
                msg = "No results from Orion NCM: {}".format(data_ncm)
                self.logger.info(msg)
            elif len(data_ncm['results']) == 1:
                try:
                    orion_node.ncm_id = data_ncm['results'][0]['NodeID']
                except IndexError:
                    pass

            data_agent = self.get_agent(orion_node.npm_id)

            if data_agent:
                try:
                    orion_node.agent_id = data_agent['AgentID']
                    orion_node.agent_uri = data_agent['Uri']
                except IndexError:
                    pass

        return orion_node

    def get_agent(self, query_param):
        """ Searches for an agent by the ip address or the
        node_id
        """
        if is_ip(query_param):
            query_for_where = "IP"
        elif isinstance(query_param, int):
            query_for_where = "NodeId"
        else:
            query_for_where = "Name"

        swql_agent = """SELECT AgentID, Uri
        FROM Orion.AgentManagement.Agent
        WHERE {}=@query_on""".format(query_for_where)
        kargs = {'query_on': query_param}
        data_agent = self.query(swql_agent, **kargs)

        # Since there might not always be an agent we
        # will not raise if the results do not return anything
        if 'results' not in data_agent or len(data_agent['results']) == 0:
            msg = "No Orion Agent found: {}".format(data_agent)
            self.logger.info(msg)
            return None

        if len(data_agent['results']) >= 2:
            self.logger.debug("Muliple Agents match '{}' Caption: {}".format(
                query_param, data_agent))
            raise ValueError(
                "Muliple Agents match '{}' Caption".format(query_param))

        return data_agent['results'][0]

    def query(self, swql, **kargs):
        """
        Run SWQL against the Orion Platform.
        """
        return self.client.query(swql, **kargs)

    def invoke(self, entity, verb, *args):
        """
        Run an Invoke against the Orion Platform.
        """
        return self.client.invoke(entity, verb, *args)

    def create(self, entity, **kargs):
        """
        Run an Create against the Orion Platform.
        """
        return self.client.create(entity, **kargs)

    def read(self, uri):
        """
        Run an Read against the Orion Platform.
        """
        return self.client.read(uri)

    def update(self, uri, **kargs):
        """
        Run an Update against the Orion Platform.
        """
        return self.client.update(uri, **kargs)

    def delete(self, uri):
        """
        Run an Delete of an URI against the Orion Platform.
        """
        return self.client.delete(uri)

    def get_snmp_community(self, community):
        """
        Return the correct SNMP comminity to use.
        """
        if community == "customer":
            return self.config['snmp_customer']
        elif community == "internal":
            return self.config['snmp_internal']
        elif community is None:
            return self.config['snmp_default']
        else:
            return community

    def get_snmp_cred_id(self, community):
        """
        Look up an SNMP community in the config and then look up
        the Orion ID for the Credential.
        """

        # Check if the community should be replaced.
        name = self.get_snmp_community(community)

        swql = """SELECT ID FROM Orion.Credential
        WHERE CredentialType=@CredentialType and Name=@name"""

        kargs = {
            'CredentialType':
            'SolarWinds.Orion.Core.Models.Credentials.SnmpCredentialsV2',
            'name': name
        }
        orion_data = self.query(swql, **kargs)

        if len(orion_data['results']) == 1:
            return orion_data['results'][0]['ID']
        else:
            msg = "Could not get ID for community in Orion.Credential: {}".format(
                community)
            send_user_error(msg)
            raise ValueError(msg)

    def get_engine_id(self, poller):
        """
        Takes a poller name (or primary) and returns the EngineID for
        the poller.

        Raises: ValueError on an invaild poller.

        Returns: The EngineID (int)
        """

        if poller == "primary":
            return 1
        else:
            swql = """SELECT EngineID, ServerName, IP, ServerType
            FROM Orion.Engines
            WHERE ServerName=@poller"""
            kargs = {'poller': poller}
            data = self.query(swql, **kargs)

            if len(data['results']) == 1:
                return data['results'][0]['EngineID']
            else:
                send_user_error("Invalid poller name")
                raise ValueError("Invalid poller name")

    def get_ncm_transfer_results(self, transfer_id, sleep_delay=10):
        """
        Gets the completed (waits until finished). NCM job transfer status
        from Orion.

        Retruns: The completed status.
        """
        ts = {}
        while True:
            swql = """SELECT TransferID, NodeID, Action, RequestedConfigType,
            RequestedScript, RequestedReboot, ConfigID, TransferProtocol,
            Status, ErrorMessage, DeviceOutput, DateTime, UserName
            FROM NCM.TransferResults
            WHERE TransferID=@transfer_id"""
            kargs = {'transfer_id': transfer_id}

            transfer_data = self.query(swql, **kargs)
            status = transfer_data['results'][0]['Status']

            if status == 1:
                time.sleep(sleep_delay)
            elif status == 2:
                ts['status'] = "Complete"
                break
            elif status == 3:
                ts['status'] = "Error"
                break
            else:
                ts['status'] = "Unknown"
                break

        ts['RequestedScript'] = transfer_data['results'][0]['RequestedScript']
        ts['RequestedReboot'] = transfer_data['results'][0]['RequestedReboot']
        ts['ErrorMessage'] = transfer_data['results'][0]['ErrorMessage']
        ts['DeviceOutput'] = transfer_data['results'][0]['DeviceOutput']
        ts['UserName'] = transfer_data['results'][0]['UserName']

        return ts
Beispiel #9
0
class OrionBaseAction(Action):
    def __init__(self, config):
        super(OrionBaseAction, self).__init__(config)

        self.client = None

        if "orion" not in self.config:
            raise ValueError("Orion host details not in the config.yaml")

    def connect(self, platform):
        """
        Connect to an Orion platform from the packs config.yaml.
        """
        if platform is None:
            try:
                platform = self.config['defaults']['platform']
            except IndexError:
                send_user_error("No default Orion platform.")
                raise ValueError("No default Orion platform.")

        self.logger.debug("Connecting to Orion platform: {}".format(platform))

        try:
            self.client = SwisClient(
                self.config['orion'][platform]['host'],
                self.config['orion'][platform]['user'],
                self.config['orion'][platform]['password'])
        except KeyError:
            raise ValueError("Orion host details not in the config.yaml")

        return platform

    def get_node(self, node):
        """
        Get an OrionNode object
        """

        orion_node = OrionNode()

        if is_ip(node):
            query_for_where = "IPAddress"
        else:
            query_for_where = "Caption"

        swql = """SELECT NodeID, Uri, IPAddress, Caption
        FROM Orion.Nodes
        WHERE {}=@query_on""".format(query_for_where)
        kargs = {'query_on': node}
        data = self.query(swql, **kargs)

        if 'results' not in data:
            msg = "No results from Orion: {}".format(data)
            self.logger.info(msg)
            raise Exception(msg)

        if len(data['results']) == 1:
            try:
                orion_node.npm_id = data['results'][0]['NodeID']
                orion_node.uri = data['results'][0]['Uri']
                orion_node.ip_address = data['results'][0]['IPAddress']
                orion_node.caption = data['results'][0]['Caption']
            except IndexError:
                pass
        elif len(data['results']) >= 2:
            self.logger.debug(
                "Muliple Nodes match '{}' Caption: {}".format(
                    node, data))
            raise ValueError("Muliple Nodes match '{}' Caption".format(
                node))

        if orion_node.npm:
            swql = """SELECT NodeID
            FROM Cirrus.Nodes
            WHERE CoreNodeID=@CoreNodeID"""
            kargs = {'CoreNodeID': orion_node.npm_id}
            data = self.query(swql, **kargs)

            # Don't raise an exception if this fails.
            # The platform may not haev NCM installed.
            if 'results' not in data:
                msg = "No results from Orion NCM: {}".format(data)
                self.logger.info(msg)
            elif len(data['results']) == 1:
                try:
                    orion_node.ncm_id = data['results'][0]['NodeID']
                except IndexError:
                    pass

        return orion_node

    def query(self, swql, **kargs):
        """
        Run SWQL against the Orion Platform.
        """
        return self.client.query(swql, **kargs)

    def invoke(self, entity, verb, *args):
        """
        Run an Invoke against the Orion Platform.
        """
        return self.client.invoke(entity, verb, *args)

    def create(self, entity, **kargs):
        """
        Run an Create against the Orion Platform.
        """
        return self.client.create(entity, **kargs)

    def read(self, uri):
        """
        Run an Read against the Orion Platform.
        """
        return self.client.read(uri)

    def update(self, uri, **kargs):
        """
        Run an Update against the Orion Platform.
        """
        return self.client.update(uri, **kargs)

    def delete(self, uri):
        """
        Run an Delete of an URI against the Orion Platform.
        """
        return self.client.delete(uri)

    def get_snmp_community(self, community, std_community):
        """
        Return the correct SNMP comminity to use.
        """
        if community is not None:
            return community
        elif std_community is not None:
            try:
                return self.config['defaults']['snmp'][std_community]
            except KeyError:
                raise ValueError("Invalid standard community")
        elif std_community is None:
            raise ValueError("Need one of community or std_community")

    def get_snmp_cred_id(self, community):
        """
        Look up an SNMP community in the config and then look up
        the Orion ID for the Credential.
        """

        # Check if community is a know standard, otherwise
        # use it as the community.
        try:
            name = self.get_snmp_community(None, community)
        except ValueError:
            name = community

        swql = """SELECT ID FROM Orion.Credential
        WHERE CredentialType=@CredentialType and Name=@name"""

        kargs = {'CredentialType':
                 'SolarWinds.Orion.Core.Models.Credentials.SnmpCredentialsV2',
                 'name': name}
        orion_data = self.query(swql, **kargs)

        if len(orion_data['results']) == 1:
            return orion_data['results'][0]['ID']
        else:
            msg = "Could not get ID for community in Orion.Credential: {}".format(
                community)
            send_user_error(msg)
            raise ValueError(msg)

    def get_engine_id(self, poller):
        """
        Takes a poller name (or primary) and returns the EngineID for
        the poller.

        Raises: ValueError on an invaild poller.

        Returns: The EngineID (int)
        """

        if poller == "primary":
            return 1
        else:
            swql = """SELECT EngineID, ServerName, IP, ServerType
            FROM Orion.Engines
            WHERE ServerName=@poller"""
            kargs = {'poller': poller}
            data = self.query(swql, **kargs)

            if len(data['results']) == 1:
                return data['results'][0]['EngineID']
            else:
                send_user_error("Invalid poller name")
                raise ValueError("Invalid poller name")

    def get_ncm_transfer_results(self, transfer_id, sleep_delay=10):
        """
        Gets the completed (waits until finished). NCM job transfer status
        from Orion.

        Retruns: The completed status.
        """
        ts = {}
        while True:
            swql = """SELECT TransferID, NodeID, Action, RequestedConfigType,
            RequestedScript, RequestedReboot, ConfigID, TransferProtocol,
            Status, ErrorMessage, DeviceOutput, DateTime, UserName
            FROM NCM.TransferResults
            WHERE TransferID=@transfer_id"""
            kargs = {'transfer_id': transfer_id}

            transfer_data = self.query(swql, **kargs)
            status = transfer_data['results'][0]['Status']

            if status == 1:
                time.sleep(sleep_delay)
            elif status == 2:
                ts['status'] = "Complete"
                break
            elif status == 3:
                ts['status'] = "Error"
                break
            else:
                ts['status'] = "Unknown"
                break

        ts['RequestedScript'] = transfer_data['results'][0]['RequestedScript']
        ts['RequestedReboot'] = transfer_data['results'][0]['RequestedReboot']
        ts['ErrorMessage'] = transfer_data['results'][0]['ErrorMessage']
        ts['DeviceOutput'] = transfer_data['results'][0]['DeviceOutput']
        ts['UserName'] = transfer_data['results'][0]['UserName']

        return ts
Beispiel #10
0
class Orion():

    def __init__(self):
        
        # start the connection
        self.server = 'server fqdn or ip'
        self.username = '******'
        self.password = '******'

        self.con = SwisClient(self.server,self.username,self.password)

        requests.packages.urllib3.disable_warnings()  

    def get_all_juniper_node_ids(self, **kwargs):

        self.q = self.con.query('SELECT NodeID,Caption FROM Orion.Nodes WHERE Vendor LIKE @vendor', vendor='Juniper%')
        return self.q

    def get_all_cisco_node_ids(self, **kwargs):

        self.q = self.con.query('SELECT NodeID,Caption FROM Orion.Nodes WHERE Vendor LIKE @vendor', vendor='Cisco')
        return self.q

    def npm_add_node(self, **kwargs):

        s = Settings()
        settings = s.get_all_settings()

        # first check this device isn't already in Orion
        self.ip_check = self.con.query('SELECT NodeID FROM Orion.Nodes WHERE IPAddress=@ip_address', ip_address=kwargs.get('ip_address'))
        self.hostname_check = self.con.query('SELECT NodeID FROM Orion.Nodes WHERE Caption=@hostname', hostname=kwargs.get('hostname'))
        if len(self.ip_check['results']) > 0 or len(self.hostname_check['results']) > 0:

            # if this is greater than 0, then the device already exists in orion
            return

        else:

            # assign the device poperties for adding to the database
            # support only for SNMPv2 at this stage
            self.properties = {
                'Caption': kwargs.get('hostname'),
                'IPAddress': kwargs.get('ip_address'),
                'DynamicIP': False,
                'EngineID': kwargs.get('engine_id') or 1, 
                'Status': 1,
                'Allow64BitCounters': 1,
                'ObjectSubType': 'SNMP',
                'SNMPVersion': kwargs.get('snmp_version') or 2,
                'Community': kwargs.get('community'),
                # Set NextRediscovery to now + 2 mins so that rediscovery happens at the next rediscovery interval, default 30mins
                'NextRediscovery': datetime.datetime.now() + datetime.timedelta(minutes = 2)
            }

            # create the node
            self.results = self.con.create('Orion.Nodes', **self.properties)

            # get the NodeID
            self.node_id = re.search('(\d+)$', self.results).group(0)

            # setup device pollers
            self.pollers_enabled = {
                'N.Status.ICMP.Native': True,
                'N.Status.SNMP.Native': False,
                'N.ResponseTime.ICMP.Native': True,
                'N.ResponseTime.SNMP.Native': False,
                'N.Details.SNMP.Generic': True,
                'N.Uptime.SNMP.Generic': True,
                'N.Cpu.SNMP.HrProcessorLoad': True,
                'N.Memory.SNMP.NetSnmpReal': True,
                'N.AssetInventory.Snmp.Generic': True,
                'N.Topology_Layer3.SNMP.ipNetToMedia': False,
                'N.Routing.SNMP.Ipv4CidrRoutingTable': False
            }  

            # create a list of dictionarys for each poller
            self.pollers = []
            for self.k in self.pollers_enabled:
                self.pollers.append(
                    {
                        'PollerType': self.k,
                        'NetObject': 'N:' + self.node_id,
                        'NetObjectType': 'N',
                        'NetObjectID': self.node_id,
                        'Enabled': self.pollers_enabled[self.k]
                    }
                )

            # loop through pollers and turn them on
            for self.poller in self.pollers:
                 self.response = self.con.create('Orion.Pollers', **self.poller)

            # add the custom properties
            self.results = self.con.query(
                "SELECT Uri FROM Orion.Nodes WHERE NodeID=@id",
                id=self.node_id
            )

            # grab the uri - whatever this is
            self.uri = self.results['results'][0]['Uri']

            # update the custom properties
            self.con.update(
                self.uri + '/CustomProperties',
                City = kwargs.get('city'),
                Site = kwargs.get('site'),
                Network = kwargs.get('network')
            )

            return self.node_id

    def npm_add_interfaces(self, node_id):

        # run interface discovery
        self.interfaces = self.con.invoke('Orion.NPM.Interfaces', 'DiscoverInterfacesOnNode', node_id)
        # imports only interfaces with a description
        # alternatively any physical Cisco interfaces with and up status could be added
        self.descr_only = [
            self.x for self.x
            in self.interfaces['DiscoveredInterfaces']
            if re.search('\xb7', self.x['Caption'])
        ]

        # add the interfaces
        self.execute = self.con.invoke(
            'Orion.NPM.Interfaces',
            'AddInterfacesOnNode',
            node_id,
            self.descr_only,
            'AddDefaultPollers'
        )

    def npm_poll_now(self, node_id, **kwargs):
        self.con.invoke('Orion.Nodes', 'PollNow', 'N:%s' % self.node_id)

    def ncm_add_node(self, node_id, **kwargs):

        s = Settings()
        settings = s.get_all_settings()

        # check that device isn't already managed in Orion NCM
        self.ip_check = self.con.query('SELECT NodeID FROM Cirrus.Nodes WHERE AgentIP=@ip_address', ip_address=kwargs.get('ip_address'))
        self.hostname_check = self.con.query('SELECT NodeID FROM Cirrus.Nodes WHERE NodeCaption=@hostname', hostname=kwargs.get('hostname'))
        if len(self.ip_check['results']) > 0 or len(self.hostname_check['results']) > 0:
            
            # if this is greater than 0, then the device already exists in orion
            return

        else:

            self.con.invoke('Cirrus.Nodes', 'AddNodeToNCM', node_id)

            # now update the selected columns to ensure we can log into this device
            # first using rhe NodeID from Orion.NPM get the Guid
            self.ncm_node_id = self.con.query('SELECT NodeID FROM Cirrus.Nodes WHERE CoreNodeID=@node', node=node_id)['results'][0]['NodeID']  

            # fetch the NCM Node Object
            self.ncm_node_data = self.con.invoke('Cirrus.Nodes', 'GetNode', self.ncm_node_id)

            # verfify that the submitted connection_profile exists
            # if it doesn't set the profile to '-1'
            self.profiles = self.con.invoke('Cirrus.Nodes', 'GetAllConnectionProfiles')
            for self.pro in self.profiles:
                if self.pro['ID'] == kwargs.get('connection_profile'):
                    self.connection_profile_id = kwargs.get('connection_profile')
                else:
                    self.connection_profile_id = -1

            # modify the device properties but only if the submitted profile is valid
            if self.connection_profile_id != -1:
                self.ncm_node_data['Username'] = ''
                self.ncm_node_data['Password'] = ''
                self.ncm_node_data['ConnectionProfile'] = self.connection_profile_id 

             # Commit our changes  
            self.con.invoke('Cirrus.Nodes', 'UpdateNode', self.ncm_node_data)

    def ncm_get_guid(self, hostname):
        # used to determine the guid for a hostname as it exists in Orion NCM
        self.node_id = self.con.query("SELECT NodeID FROM Cirrus.Nodes WHERE NodeCaption=@node", node=hostname)
        if self.node_id is not None:
            return self.node_id
        else:
            return False


    def ncm_download_configs(self, hostname):
        # cannot be called until a device has been discovered, this action in Orion depends on a known sysObjectID OID

        # get the System.Guid[] into a list, if submitted as a simple string the API errors out
        # HTTPError: 400 Client Error: Verb Cirrus.ConfigArchive.DownloadConfig cannot unpackage parameter 0 with type System.Guid[] \
        # for url: https://lab-win2012.it-ninja.xyz:17778/SolarWinds/InformationService/v3/Json/Invoke/Cirrus.ConfigArchive/DownloadConfig
        self.node_ids = []
        self.node_data = self.con.query("SELECT NodeID FROM Cirrus.Nodes WHERE NodeCaption=@node", node=hostname)
        self.node_ids.append(self.node_data['results'][0]['NodeID'])

        configs = ['Active', 'Set', 'Rescue']
        for c in configs:
            self.con.invoke("Cirrus.ConfigArchive",  "DownloadConfig", self.node_ids, c)

    def get_connection_profiles(self):
        self.profiles = self.con.invoke('Cirrus.Nodes', 'GetAllConnectionProfiles')
        return self.profiles

    def ncm_remove_node(self, hostname):
        # used to unmange a node from Orion NCM
        # called pre-delete node from Orion NPM
        self.node_id = self.ncm_get_guid(hostname)
        if self.node_id is not False:
            self.con.invoke("Cirrus.Nodes",  "RemoveNode", self.node_id)

    def npm_get_uri(self, hostname):
        # used to get the node_id of a pre-existing node in Orion NPM

        self.node_uri = self.con.query("SELECT Uri FROM Orion.Nodes WHERE Caption=@hostname", hostname=hostname)
        return self.node_uri

    def npm_delete_node(self, hostname):
        
        # get the devices uri.  This is a list of dictionaries
        self.node_uri = self.npm_get_uri(hostname)
        # call swis to delete the node
        if self.node_uri is not False:
            self.con.delete(self.node_uri['results'][0]['Uri'])
Beispiel #11
0
def main(ip, ctrel, pci, province, sbu, sitename):
    npm_server = ''
    username = ''
    password = ''

    target_node_ip = ip
    snmpv3_credential_id = 6
    orion_engine_id = 1

    swis = SwisClient(npm_server, username, password)
    print("Add an SNMP v3 node:")

    corePluginContext = {
        'BulkList': [{
            'Address': target_node_ip
        }],
        'Credentials': [{
            'CredentialID': snmpv3_credential_id,
            'Order': 1
        }],
        'WmiRetriesCount': 0,
        'WmiRetryIntervalMiliseconds': 1000
    }

    corePluginConfig = swis.invoke('Orion.Discovery',
                                   'CreateCorePluginConfiguration',
                                   corePluginContext)

    discoveryProfile = {
        'Name': 'API discovery',
        'EngineID': orion_engine_id,
        'JobTimeoutSeconds': 3600,
        'SearchTimeoutMiliseconds': 5000,
        'SnmpTimeoutMiliseconds': 5000,
        'SnmpRetries': 2,
        'RepeatIntervalMiliseconds': 1800,
        'SnmpPort': 161,
        'HopCount': 0,
        'PreferredSnmpVersion': 'SNMP3',
        'DisableIcmp': False,
        'AllowDuplicateNodes': False,
        'IsAutoImport': True,
        'IsHidden': True,
        'PluginConfigurations': [{
            'PluginConfigurationItem': corePluginConfig
        }]
    }

    print("Running discovery...")
    discoveryProfileID = swis.invoke('Orion.Discovery', 'StartDiscovery',
                                     discoveryProfile)
    print("Returned discovery profile id {}".format(discoveryProfileID))

    running = True
    while running:
        try:
            query = "SELECT Status FROM Orion.DiscoveryProfiles WHERE ProfileID = " + str(
                discoveryProfileID)
            status = swis.query(query)['results'][0]['Status']
            print("##")
        except:
            running = False
    print('Done with discovery')

    batchresults = swis.query(
        "SELECT Result, ResultDescription, ErrorMessage, BatchID FROM Orion.DiscoveryLogs WHERE ProfileID=@id",
        id=discoveryProfileID)
    batchid = batchresults['results'][0]['BatchID']
    nodeidresults = swis.query(
        "SELECT DisplayName,NetObjectID FROM Orion.DiscoveryLogItems WHERE BatchID=@id",
        id=batchid)
    netobjectid = nodeidresults['results'][0]['NetObjectID']
    nodeid = netobjectid.split(':')[1]
    print(nodeid)

    #enablehardwarehealth
    hardwarehealth = swis.invoke('Orion.HardwareHealth.HardwareInfoBase',
                                 'EnableHardwareHealth', netobjectid, 9)
    #add pollers
    pollers_enabled = {
        'N.Topology_Vlans.SNMP.VtpVlan': True,
        'N.Topology_Layer2.SNMP.Dot1dTpFdbNoVLANs': True,
        'N.Topology_CDP.SNMP.cdpCacheTable': True,
        'N.Topology_STP.SNMP.Dot1dStp': True,
        'N.Topology_PortsMap.SNMP.Dot1dBaseNoVLANs': True,
        'N.Topology_Layer3.SNMP.ipNetToMedia': True,
        'N.VRFRouting.SNMP.MPLSVPNStandard': True,
    }

    pollers = []
    for k in pollers_enabled:
        pollers.append({
            'PollerType': k,
            'NetObject': 'N:' + nodeid,
            'NetObjectType': 'N',
            'NetObjectID': nodeid,
            'Enabled': pollers_enabled[k]
        })

    for poller in pollers:
        print("  Adding poller type: {} with status {}... ".format(
            poller['PollerType'], poller['Enabled']),
              end="")
        response = swis.create('Orion.Pollers', **poller)
        print("DONE!")

    #update custom properties
    customresults = swis.query("SELECT Uri FROM Orion.Nodes WHERE NodeID=@id",
                               id=nodeid)
    uri = customresults['results'][0]['Uri']

    #swis.update(uri + '/CustomProperties', City='Brampton')
    #swis.update(uri + '/CustomProperties', Comments='Test Device')
    swis.update(uri + '/CustomProperties', CTREL_Code=ctrel)
    swis.update(uri + '/CustomProperties', PCI=pci)
    #swis.update(uri + '/CustomProperties', Postal_Code='L7A4B4')
    swis.update(uri + '/CustomProperties', Province=province)
    swis.update(uri + '/CustomProperties', SBU=sbu)
    #swis.update(uri + '/CustomProperties', Site_Contact='Anesh')
    #swis.update(uri + '/CustomProperties', Site_Contact_Number='666-666-666')
    #swis.update(uri + '/CustomProperties', Site_ID='666')
    swis.update(uri + '/CustomProperties', Site_Name=sitename)
    #swis.update(uri + '/CustomProperties', Site_Type='PROD')
    #swis.update(uri + '/CustomProperties', Street_Address='AJ Distrubution')
    swis.update(uri + '/CustomProperties', Support_Team='Corp Network')

    obj = swis.read(uri + '/CustomProperties')
    print(obj)
def run_module():
    # define available arguments/parameters a user can pass to the module
    module_args = dict(subnet=dict(type='str', required=True),
                       orion_server=dict(type='str', required=True),
                       orion_username=dict(type='str', required=True),
                       orion_password=dict(type='str',
                                           required=True,
                                           no_log=True),
                       new_ip_status=dict(type='str',
                                          required=False,
                                          default='Used'),
                       new_ip_comment=dict(type='str',
                                           required=False,
                                           default='Updated by Ansible'),
                       ping_test=dict(type='bool',
                                      required=False,
                                      default=True),
                       retry_limit=dict(type='int', required=False, default=5))

    # seed the result dict in the object
    # we primarily care about changed and state
    # change is if this module effectively modified the target
    # state will include any data that you want your module to pass back
    # for consumption, for example, in a subsequent task
    result = dict(ip_address='')

    # the AnsibleModule object will be our abstraction working with Ansible
    # this includes instantiation, a couple of common attr would be the
    # args/params passed to the execution, as well as if the module
    # supports check mode
    module = AnsibleModule(argument_spec=module_args, supports_check_mode=True)

    # Check for ORION
    if not HAS_ORION:
        module.fail_json(
            msg="orionsdk is required for this module. please install it")

    # if the user is working with this module in only check mode we do not
    # want to make any changes to the environment, just return the current
    # state with no modifications
    if module.check_mode:
        module.exit_json(**result)

    # Send Request for top {retry_limit} IP Addresses
    swis = SwisClient(module.params['orion_server'],
                      module.params['orion_username'],
                      module.params['orion_password'])
    try:
        query = "SELECT TOP {0} I.Status, I.IPAddress, I.DisplayName, Uri, I.Comments FROM IPAM.IPNode I WHERE Status=2 AND I.Subnet.DisplayName = @subnet".format(
            str(module.params['retry_limit']))
        results = swis.query(query, subnet=module.params['subnet'])
    except Exception as e:
        module.fail_json(
            msg=
            "Failed to query Orion. Check orion_server, orion_username, and orion_password: {0}"
            .format(str(e)),
            **result)

    # Find a Valid/Free IP from the request
    for i in range(module.params['retry_limit']):

        # Check if there was a valid request
        if not results["results"][i]:
            continue

        # Perform a Ping Test
        if module.params['ping_test']:
            #ping_cmd = "/usr/bin/ping {}".format(results["results"][i]['IPAddress'])
            #ping_cmd = "/usr/bin/ping 10.227.201.100"
            #module.fail_json(msg=ping_cmd, **result)
            ping_response = subprocess.check_output(
                ['ping', '-c', '1', '10.227.201.100'])
            module.fail_json(msg="Ping Response for {1} is {0}".format(
                ping_response, results["results"][i]['IPAddress']),
                             **result)
            if ping_response == 0:
                print("{0} is Alive".format(
                    results["results"][i]['IPAddress']))
                module.fail_json(msg="{0} is Alive".format(
                    results["results"][i]['IPAddress']),
                                 **result)
                continue
            else:
                print("{0} is Not Alive".format(
                    results["results"][i]['IPAddress']))
                module.fail_json(msg="{0} is Not Alive".format(
                    results["results"][i]['IPAddress']),
                                 **result)
                ip_address = results["results"][i]['IPAddress']
                uri = results["results"][i]['Uri']
                break
        else:
            ip_address = results["results"][i]['IPAddress']
            uri = results["results"][i]['Uri']
            break

    # Did we get an OK IP Address?
    if ip_address:
        # Set the Status
        try:
            swis.update(uri, Status=module.params['new_ip_status'])
        except Exception as e:
            module.fail_json(msg="Failed to update status: {0}".format(str(e)),
                             **result)

        # Set the Comments
        try:
            swis.update(uri,
                        Comments="{0}".format(module.params['new_ip_comment']))
        except Exception as e:
            module.fail_json(msg="Failed to update comment: {0}".format(
                str(e)),
                             **result)

        # Set SkipScan to False
        try:
            swis.update(uri, SkipScan=False)
        except Exception as e:
            module.fail_json(msg="Failed to set SkipScan to False: {0}".format(
                str(e)),
                             **result)

        # Set the Module Result
        result['ip_address'] = ip_address
        result['changed'] = True
    else:
        module.fail_json(msg="Failed to find an unused IP Address", **result)

    # Exit Module
    module.exit_json(**result)
Beispiel #13
0
def create_node(name_tid, ip_address, oob_ip_address):
    npm_server = 'serverip'
    username = '******'
    password = '******'

    swis = SwisClient(npm_server, username, password)
    print("Adding node with ping..")

    # # fill these in for the node you want to add!
    # name_tid = 'xxxxxxx'
    # ip_address = '1.1.1.1'
    # oob_ip_address = '2.2.2.2'
    #    community = 'public'

    # set up property bag for the new node
    props = {
        'Caption': name_tid,
        'IPAddress': ip_address,
        'EngineID': 1,
        'ObjectSubType': 'ICMP',
    }

    print("Adding node {}... ".format(props['IPAddress']), end="")
    results = swis.create('Orion.Nodes', **props)
    print("DONE!")

    # extract the nodeID from the result
    nodeid = re.search('(\d+)$', results).group(0)

    # add extra custom properites :D
    custom_props = {
        'MY_PROPERTY_1': oob_ip_address,
        'MY_PROPERTY_2': 'client name',
    }

    for k, v in custom_props.items():
        swis.update(results + '/CustomProperties', **{k: v})

    pollers_enabled = {
        'N.Status.ICMP.Native': True,
        'N.Status.SNMP.Native': False,
        'N.ResponseTime.ICMP.Native': True,
        # 'N.ResponseTime.SNMP.Native': False,
        # 'N.Details.SNMP.Generic': False,
        # 'N.Uptime.SNMP.Generic': False,
        # 'N.Cpu.SNMP.HrProcessorLoad': False,
        # 'N.Memory.SNMP.NetSnmpReal': False,
        # 'N.AssetInventory.Snmp.Generic': False,
        # 'N.Topology_Layer3.SNMP.ipNetToMedia': False,
        # 'N.Routing.SNMP.Ipv4CidrRoutingTable': False
    }

    pollers = []
    for k in pollers_enabled:
        pollers.append({
            'PollerType': k,
            'NetObject': 'N:' + nodeid,
            'NetObjectType': 'N',
            'NetObjectID': nodeid,
            'Enabled': pollers_enabled[k]
        })

    for poller in pollers:
        print("  Adding poller type: {} with status {}... ".format(
            poller['PollerType'], poller['Enabled']),
              end="")
        response = swis.create('Orion.Pollers', **poller)
        print("DONE!")
class SolarWinds:
    def __init__(self, npm_server, username, password, logger=None):

        self.logger = logger or logging.getLogger('__name__')

        # Create the SWIS client for use throughout the instance.
        self.swis = SwisClient(npm_server, username, password)

    def does_node_exist(self, node_name):
        """ Checks to see if a SolarWinds node exists with the given name.  Calls the get_node_id method of the class
            and uses the returned value to determine whether or not the node exists.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.

            Returns:
                True: The node exists.
                False: The node does not exist.

        """

        if self.get_node_id(node_name):
            return True
        else:
            return False

    def get_node_id(self, node_name):
        """ Returns the NodeID for the given NodeName.  Uses a SWIS query to the SolarWinds database to retrieve this
            information.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.

            Returns:
                node_id (string): The node ID that corresponds to the specified node name.

        """

        node_id = self.swis.query(
            "SELECT NodeID, Caption FROM Orion.Nodes WHERE Caption = @caption",
            caption=node_name)

        self.logger.info("get_node_id - node_id query results: %s.", node_id)

        if node_id['results']:
            return node_id['results'][0]['NodeID']
        else:
            return ""

    def get_node_uri(self, node_name):
        """ Returns the NodeURI for the given NodeName.  Uses a SWIS query to the SolarWinds database to retrieve this
            information.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.

            Returns:
                node_id (string): The node URI that corresponds to the specified node name.

        """

        node_uri = self.swis.query(
            "SELECT Caption, Uri FROM Orion.Nodes WHERE Caption = @caption",
            caption=node_name)

        self.logger.info("get_node_uri - node uri query results: %s.",
                         node_uri)
        if node_uri['results']:
            return node_uri['results'][0]['Uri']
        else:
            return ""

    def add_node_using_snmp_v3(self, node_name, ip_address, snmpv3_username,
                               snmpv3_priv_method, snmpv3_priv_pwd,
                               snmpv3_auth_method, snmpv3_auth_pwd):
        """ Creates a new node using the supplied name an IP address.  Configure with our standard SNMPv3 credentials.
            Once created, attached all of the standard Cisco pollers.

            Args:
                node_name(string): A node name to be used for the newly created node object.
                ip_address(string): The IP address that is associated with the supplied node name.
                snmpv3_username(string): The SNMPv3 username that will be associated with the node object.
                snmpv3_priv_method(string): The SNMPv3 privilege method that will be used.
                snmpv3_priv_pwd (string): The SNMPv3 privilege password that will be used.
                snmpv3_auth_method(string): The SNMPv3 authentication method that will be used.
                snmpv3_auth_pwd (string): The SNMPv3 authentication password that will be used.

            Returns:
                None.

        """

        if not self.does_node_exist(node_name):
            # set up property bag for the new node
            node_properties = {
                'IPAddress': ip_address,
                'EngineID': 1,
                'ObjectSubType': 'SNMP',
                'SNMPVersion': 3,
                'SNMPV3Username': snmpv3_username,
                'SNMPV3PrivMethod': snmpv3_priv_method,
                'SNMPV3PrivKeyIsPwd': True,
                'SNMPV3PrivKey': snmpv3_priv_pwd,
                'SNMPV3AuthMethod': snmpv3_auth_method,
                'SNMPV3AuthKeyIsPwd': True,
                'SNMPV3AuthKey': snmpv3_auth_pwd,
                'DNS': '',
                'SysName': '',
                'Caption': node_name
            }

            # Create base node object.
            results = self.swis.create('Orion.Nodes', **node_properties)
            self.logger.info("add_node - add node invoke results: %s", results)

            # Assign pollers to node.
            self.attach_poller_to_node(node_name, 'N.Status.ICMP.Native')
            self.attach_poller_to_node(node_name, 'N.Status.SNMP.Native',
                                       False)
            self.attach_poller_to_node(node_name, 'N.ResponseTime.ICMP.Native')
            self.attach_poller_to_node(node_name, 'N.ResponseTime.SNMP.Native',
                                       False)
            self.attach_poller_to_node(node_name, 'N.Details.SNMP.Generic')
            self.attach_poller_to_node(node_name, 'N.Uptime.SNMP.Generic')

    def is_poller_attached_to_node(self, node_name, poller_name):
        """ Checks to see if the specified poller is attached to the specified node.  Makes a SWIS query to see
            if there's a corresponding entry in the Orion.Pollers table.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.
                poller_name(string): The name of the poller as represented in the SolarWinds database.

            Returns:
                True: The poller is currently attached to the node.
                False: The poller is not currently attached to the node.

        """

        net_object_id = str(self.get_node_id(node_name))
        net_object = 'N:' + net_object_id

        results = self.swis.query(
            "SELECT PollerType FROM Orion.Pollers WHERE NetObject = @net_object AND PollerType "
            "= @poller_name",
            net_object=net_object,
            poller_name=poller_name)
        self.logger.info(
            "is_poller_attached_to_node - check for poller query results: %s",
            results)

        if results['results']:
            return True
        else:
            return False

    def attach_poller_to_node(self, node_name, poller_name, enabled=True):
        """ Checks to see if the specified poller is attached to the specified node.  If it is not, a SWIS create is
            executed against Orion.Pollers to attach the poller to the node.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.
                poller_name(string): The name of the poller as represented in the SolarWinds database.
                enabled(boolean): Whether or not to enable the attached poller.

            Returns:
                None.

        """

        if not self.is_poller_attached_to_node(node_name, poller_name):
            net_object_id = str(self.get_node_id(node_name))
            net_object = 'N:' + net_object_id

            poller_properties = {
                'PollerType': poller_name,
                'NetObject': net_object,
                'NetObjectType': 'N',
                'NetObjectID': net_object_id,
                'Enabled': enabled
            }

            results = self.swis.create('Orion.Pollers', **poller_properties)
            self.logger.info(
                "attach_poller_to_node - poller create results: %s", results)

    def enable_hardware_health_on_node(self, node_name):
        """ Enables the hardware health monitoring on the specified node.  Executes a SWIS invoke of the
            'EnableHardwareHealth' verb, passing it the node's net object ID.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.

            Returns:
                None.

        """

        net_object_id = str(self.get_node_id(node_name))
        net_object = 'N:' + net_object_id

        results = self.swis.invoke('Orion.HardwareHealth.HardwareInfo',
                                   'EnableHardwareHealth', net_object, 9)
        self.logger.info(
            "enable_hardware_health - enable hardware health invoke results: %s",
            results)

    def add_node_to_ncm(self, node_name):
        """ Adds the specified node to the SolarWinds NCM module.  Executes a SWIS invoke of the
            'AddNodetoNCM' verb, passing it the node's object ID.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.

            Returns:
                None.

        """

        results = self.swis.invoke('Cirrus.Nodes', 'AddNodeToNCM',
                                   self.get_node_id(node_name))
        self.logger.info(
            "add_node_to_ncm - add node to ncm invoke results: %s", results)

    def add_node_to_udt(self, node_name):
        udt_properties = {
            'NodeID': self.get_node_id(node_name),
            'Capability': '2',
            'Enabled': True
        }

        results = self.swis.create('Orion.UDT.NodeCapability',
                                   **udt_properties)
        self.logger.info(
            "add_node_to_udt - add node at l2 to udt create results: %s",
            results)

        udt_properties = {
            'NodeID': self.get_node_id(node_name),
            'Capability': '3',
            'Enabled': True
        }

        results = self.swis.create('Orion.UDT.NodeCapability',
                                   **udt_properties)
        self.logger.info(
            "add_node_to_udt - add node at l3 to udt create results: %s",
            results)

    def add_node_to_ip_vnqm(self, node_name):
        vnqm_node_properties = {
            'NodeID': self.get_node_id(node_name),
            'Name': node_name,
            'IsHub': False,
            'IsAutoConfigured': True
        }

        results = self.swis.create('Orion.IpSla.Sites', **vnqm_node_properties)
        self.logger.info(
            "add_node_to_vnqm - add node to vnqm create results: %s", results)

    def add_icmp_echo_ip_sla_operation_to_node(self, node_name,
                                               ip_sla_operation_number,
                                               ip_sla_name):
        ip_sla_properties = {
            'NodeID': self.get_node_id(node_name),
            'OperationTypeID': 5,
            'OperationType': "ICMP Echo",
            'IsAutoConfigured': False,
            'Frequency': 10,
            'IpSlaOperationNumber': ip_sla_operation_number,
            'OperationName': ip_sla_name
        }

        results = self.swis.create('Orion.IpSla.Operations',
                                   **ip_sla_properties)
        self.logger.info(
            "add_icmp_echo_ip_sla_operation_to_node - add IP SLA operation to node create results: %s",
            results)

    def set_custom_properties(self, node_name, custom_property_name,
                              custom_property_value):
        """ For a given node, sets the specified custom property to the specified value.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.
                custom_property_name(string): The custom property who's value we want to change.  The custom property
                    needs to have been previously created or nothing will be changed.
                custom_property_value(string): The desired value that the custom property will be set to.

            Returns:
                None.

        """

        node_uri = self.get_node_uri(node_name)

        custom_property = {custom_property_name: custom_property_value}

        self.swis.update(node_uri + '/CustomProperties', **custom_property)

    def get_custom_properties(self, node_name):
        """ For a given node, gets a list of the custom properties and values associated with it.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.

            Returns:
                custom_properties(list): A list of dictionaries.  Each dictionary is a single key/value pair that contains
                    the custom property name and value.

        """

        node_uri = self.get_node_uri(node_name)

        custom_properties = self.swis.read(node_uri + '/CustomProperties')
        self.logger.info(
            "set_custom_properties - custom_properties read results: %s",
            custom_properties)

        return custom_properties

    def get_list_of_custom_pollers_for_node(self, node_name):
        """ For a given node, gets a list of the currently assigned custom pollers.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.

            Returns:
                custom_pollers(dictionary): Returns a dictionary that represents all of the custom pollers attached to
                    the node.  Each key is the custom property name and the value is the associated custom property
                    value.

        """

        node_id = self.get_node_id(node_name)

        custom_pollers = self.swis.query(
            "SELECT CustomPollerName FROM Orion.NPM.CustomPollerAssignment WHERE NodeID "
            "= @node_id",
            node_id=node_id)
        self.logger.info(
            "get_list_of_custom_pollers_by_name - custom_pollers query results: %s",
            custom_pollers)

        return custom_pollers['results']

    def remove_custom_poller_by_name(self, node_name, poller_name):
        """ For a given node, detaches the specified custom poller.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.
                poller_name(string): The name of the custom poller that will be removed from the node.

            Returns:
                None.

        """

        node_id = self.get_node_id(node_name)

        custom_poller_id = self.swis.query(
            "SELECT CustomPollerID FROM Orion.NPM.CustomPollers WHERE UniqueName = "
            "@poller_name",
            poller_name=poller_name)
        self.logger.info(
            "remove_custom_poller_by_name - custom_poller_id query results: %s",
            custom_poller_id)

        custom_poller_uri = self.swis.query(
            "SELECT Uri FROM Orion.NPM.CustomPollerAssignmentOnNode WHERE "
            "NodeID=@node_id AND CustomPollerID=@custom_poller_id",
            node_id=node_id,
            custom_poller_id=custom_poller_id['results'][0]['CustomPollerID'])
        self.logger.info(
            "remove_custom_poller_by_name - custom_poller_uri query results: %s",
            custom_poller_uri)

        self.swis.delete(custom_poller_uri['results'][0]['Uri'])

    def add_custom_poller_by_name(self, node_name, poller_name):
        """ For a given node, attaches the specified custom poller.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.
                poller_name(string): The name of the custom poller which is to be attached to the specified node.

            Returns:
                None.

        """

        node_id = self.get_node_id(node_name)

        custom_poller_id = self.swis.query(
            "SELECT CustomPollerID FROM Orion.NPM.CustomPollers WHERE UniqueName = @poller_name",
            poller_name=poller_name)
        self.logger.info(
            "add_custom_poller_by_name - custom_poller_id query results: %s",
            custom_poller_id)

        poller_properties = {
            'NodeID': node_id,
            'customPollerID': custom_poller_id['results'][0]['CustomPollerID']
        }

        self.swis.create('Orion.NPM.CustomPollerAssignmentOnNode',
                         **poller_properties)

    def does_group_exist(self, group_name):
        """ Checks to see if a SolarWinds group exists with the given name.  Calls the get_group_id method of the class
            and uses the returned value to determine whether or not the group exists.

            Args:
                group_name(string): A group name which should equal the name used in SolarWinds for the container
                    object.

            Returns:
                True: The group exists.
                False: The group does not exist.

        """

        if self.get_group_id(group_name):
            return True
        else:
            return False

    def get_group_id(self, group_name):
        """ Returns the ContainerID for the given Group Name.  Uses a SWIS query to the SolarWinds database to retrieve
            this information.

            Args:
                group_name(string): A group name which should equal the name used in SolarWinds for the container
                    object.

            Returns:
                group_id (string): The group ID that corresponds to the specified group name.

        """

        group_id = self.swis.query(
            "SELECT ContainerID FROM Orion.Container WHERE Name = @group_name",
            group_name=group_name)
        self.logger.info("get_group_id - group_id query results: %s", group_id)

        if group_id['results']:
            return group_id['results'][0]['ContainerID']
        else:
            return ""

    def get_group_uri(self, group_name):
        """ Returns the ContainerUri for the given Group Name.  Uses a SWIS query to the SolarWinds database to retrieve this
            information.

            Args:
                group_name(string): A group name which should equal the name used in SolarWinds for the container object.

            Returns:
                group_uri (string): The group URI that corresponds to the specified group name.

        """

        group_uri = self.swis.query(
            "SELECT Uri FROM Orion.Container WHERE Name = @group_name",
            group_name=group_name)
        self.logger.info("get_group_uri - group_uri query results: %s",
                         group_uri)

        if group_uri['results']:
            return group_uri['results'][0]['Uri']
        else:
            return ""

    def add_group(self,
                  group_name,
                  owner='Core',
                  refresh_frequency=60,
                  status_rollup=0,
                  group_description='',
                  polling_enabled=True,
                  group_members=None):
        """ Creates a new empty group using the supplied name.  Sets all of the additional parameters to the default
            values.

            Args:
                group_name(string): A group name to be used for the newly created container.
                owner(string): Must be 'Core'.
                refresh_frequency(int): How often the group membership is updated.
                status_rollup(int): Status rollup mode.
                    # 0 = Mixed status shows warning
                    # 1 = Show worst status
                    # 2 = Show best status
                group_description(string):
                polling_enabled(boolean): Whether polling of the group is enabled or disabled.
                group_members(list): A list of group members and/or dynamic filters.

            Returns:
                None.

        """

        if group_members is None:
            group_members = []
        if not self.does_group_exist(group_name):
            results = self.swis.invoke('Orion.Container', 'CreateContainer',
                                       group_name, owner, refresh_frequency,
                                       status_rollup, group_description,
                                       polling_enabled, group_members)
            self.logger.info("add_group - add group invoke results: %s",
                             results)

    def is_node_in_group(self, node_name, group_name):
        """ Checks to see if a node is a member of a particular group.  Runs a SWIS query against the ContainerMembers
            table to see if there's a corresponding table entry.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.
                group_name(string): A group name which should equal the name used in SolarWinds for the container
                    object.

            Returns:
                True: The node is in the group.
                False: The node is not in the group.

        """

        results = self.swis.query(
            "SELECT Name FROM Orion.ContainerMembers WHERE ContainerID = @group_id and FullName "
            "= @node_name",
            group_id=self.get_group_id(group_name),
            node_name=node_name)
        self.logger.info(
            "is_node_in_group - is_node_in_group query results: %s", results)

        if results['results']:
            return True
        else:
            return False

    def add_node_to_group(self, node_name, group_name):
        """ If the specified node is not already in the specified group, a SWIS invoke of Orion.Container.AddDefinition
            is made to add the node to the group.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.
                group_name(string): A group name which should equal the name used in SolarWinds for the container object.

            Returns:
                None.

        """

        if not self.is_node_in_group(node_name, group_name):
            member_definition = {
                "Name": node_name,
                "Definition": self.get_node_uri(node_name)
            }
            self.swis.invoke('Orion.Container', 'AddDefinition',
                             int(self.get_group_id(group_name)),
                             member_definition)

    def delete_group_by_id(self, group_id):
        """ Delete a group that has the specified group id.

            Args:
                group_id(string): A group id which should equal the ContainerID used in SolarWinds for the container
                    object.

            Returns:
                None.

        """

        self.swis.invoke('Orion.Container', 'DeleteContainer', int(group_id))

    def delete_group_by_name(self, group_name):
        """ Delete a group that has the specified group name.

            Args:
                group_name(string): A group name which should equal the Name used in SolarWinds for the container
                    object.

            Returns:
                None.

        """

        group_id = self.get_group_id(group_name)

        self.delete_group_by_id(group_id)

    def does_dependency_exist(self, dependency_name):
        """ Checks to see if a SolarWinds dependency exists with the given name.  Calls the get_dependency_id method of
            the class and uses the returned value to determine whether or not the dependency exists.

            Args:
                dependency_name(string): A dependency name which should equal the name used in SolarWinds for the
                    dependency object.

            Returns:
                True: The dependency exists.
                False: The dependency does not exist.

        """

        if self.get_dependency_id(dependency_name):
            return True
        else:
            return False

    def get_dependency_id(self, dependency_name):
        """ Returns the DependencyID for the given Dependency Name.  Uses a SWIS query to the SolarWinds database to
            retrieve this information.

            Args:
                dependency_name(string): A dependency name which should equal the name used in SolarWinds for the
                    dependency object.

            Returns:
                dependency_id (string): The dependency ID that corresponds to the specified dependency name.

        """

        dependency_id = self.swis.query(
            "SELECT DependencyId FROM Orion.Dependencies WHERE Name = @dependency_name",
            dependency_name=dependency_name)
        self.logger.info("get_dependency_id - dependency_id query results: %s",
                         dependency_id)

        if dependency_id['results']:
            return dependency_id['results'][0]['DependencyId']
        else:
            return ""

    def add_dependency(self, dependency_name, parent_name, child_name):
        """ Creates a new dependency using the specified parent and child.  Does a SWIS create to the Orion.Dependencies
            table to create the dependency.

            Args:
                dependency_name(string): A dependency name to be used for the newly created dependency.
                parent_name(string): Name of the parent to be used in the dependency definition.
                child_name(string): Name of the child to be used in the dependency definition.

            Returns:
                True: The dependency was successfully created.
                False: The dependency was not created.

        """

        if not self.does_dependency_exist(dependency_name):
            if self.does_node_exist(parent_name):
                self.logger.info("add-dependency - The parent is a node.")
                parent_id = self.get_node_id(parent_name)
                parent_uri = self.get_node_uri(parent_name)
                parent_entity_type = 'Orion.Nodes'
            elif self.does_group_exist(parent_name):
                self.logger.info("add-dependency - The parent is a group.")
                parent_id = self.get_group_id(parent_name)
                parent_uri = self.get_group_uri(parent_name)
                parent_entity_type = 'Orion.Groups'
            else:
                return False

            if self.does_node_exist(child_name):
                self.logger.info("add-dependency - The child is a node.")
                child_id = self.get_node_id(child_name)
                child_uri = self.get_node_uri(child_name)
                child_entity_type = 'Orion.Nodes'
            elif self.does_group_exist(child_name):
                self.logger.info("add-dependency - The child is a group.")
                child_id = self.get_group_id(child_name)
                child_uri = self.get_group_uri(child_name)
                child_entity_type = 'Orion.Groups'
            else:
                return False

            dependency_properties = {
                'Name': dependency_name,
                'ParentUri': parent_uri,
                'ParentEntityType': parent_entity_type,
                'ParentNetObjectId': parent_id,
                'ChildUri': child_uri,
                'ChildEntityType': child_entity_type,
                'ChildNetObjectId': child_id
            }

            self.swis.create('Orion.Dependencies', **dependency_properties)

    def get_list_of_interfaces(self, node_name):
        """ Returns a dictionary of existing Interfaces on a given Node Name. Uses a SWIS query to the SolarWinds
            database to retrieve this information.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.
            Returns:
                list_interfaces_names(dictionary): Returns a dictionary that represents all of the interfaces, by name,
                attached to the node.
        """

        node_id = self.get_node_id(node_name)

        list_interfaces_names = self.swis.query(
            "SELECT Name FROM Orion.NPM.Interfaces WHERE NodeID "
            "= @node_id",
            node_id=node_id)

        self.logger.info(
            "get_list_of_interfaces_by_name - list_of_interface_names query results: %s",
            list_interfaces_names)

        if list_interfaces_names['results']:
            return list_interfaces_names['results']
        else:
            return ""

    def remove_interface(self, node_name, interface_name):
        """ For a given node, remove the given interface from the node using the interface name.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.
                interface_name(string): The name of the interface that will be removed from the node.
            Returns:
                True: Interface was successfully removed.
                False: Interface was not removed.

        """

        interface_uri = self.get_interface_uri(node_name, interface_name)

        if self.does_interface_exist(node_name, interface_name):
            self.logger.info(
                "remove_interface_by_name - interface_uri query results: %s",
                interface_uri)
            self.swis.delete(interface_uri)
        else:
            return False

    def get_interface_uri(self, node_name, interface_name):
        """ Returns the URI for a given interface belonging to a given node. Uses a SWIS query to the SolarWinds
            database to retrieve this information

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.
                interface_name(string): The name of the interface that you are getting the URI for

            Returns:
                interface_uri(string): The interface URI that corresponds to the specified interface name

        """

        node_id = self.get_node_id(node_name)

        interface_uri = self.swis.query(
            "SELECT Uri FROM Orion.NPM.Interfaces WHERE NodeID=@node_id AND "
            "InterfaceName=@interface_name",
            node_id=node_id,
            interface_name=interface_name)

        if interface_uri['results']:
            return interface_uri['results'][0]['Uri']
        else:
            return ""

    def get_interface_id(self, node_name, interface_name):
        """ Returns the InterfaceID for a given interface belonging to a given node. Uses a SWIS query to the SolarWinds
            database to retrieve this information

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.
                interface_name(string): The name of the interface that you are getting the ID of.

            Returns:
                interface_id(string): The interface ID that corresponds to the specified interface name

        """

        node_id = self.get_node_id(node_name)

        interface_id = self.swis.query(
            "SELECT InterfaceID FROM Orion.NPM.Interfaces WHERE NodeID=@node_id AND "
            "Name = @interface_name",
            node_id=node_id,
            interface_name=interface_name)

        if interface_id['results']:
            return interface_id['results'][0]['InterfaceID']
        else:
            return ""

    def does_interface_exist(self, node_name, interface_name):
        """ Checks to see if a SolarWinds interface, belonging to a given node, exists with the given name. Calls the
            get_interface_id method of the class and uses the returned value to determine whether or not the interface
            exists.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.
                interface_name(string): The name of the interface that you are getting the URI for

            Returns:
                True: The interface exists.
                False: THe interface does not exist.

        """

        if self.get_interface_id(node_name, interface_name):
            return True
        else:
            return False

    def get_discovered_interfaces(self, node_name):
        """ Returns a dictionary of Discovered Interfaces on a node given that node's name. Uses a SWIS invoke for
            DiscoverInterfacesOnNode.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.

            Returns:
                discovered_interfaces(Dictionary): The set of discovered interfaces on the node.
        """

        node_id = self.get_node_id(node_name)

        discovered_interfaces = self.swis.invoke('Orion.NPM.Interfaces',
                                                 'DiscoverInterfacesOnNode',
                                                 node_id)

        return discovered_interfaces['DiscoveredInterfaces']

    def add_interface(self, node_name, interface_name):
        """ For a given node, attach the given interface by that interface's name. The given interface must be a
            discovered interface to be attached to the node. Uses a SWIS invoke for AddInterfacesOnNode.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.
                interface_name(string): The name of the interface that will be added to the node.

            Returns:
                True: The interface was added to the node.
                False: The interface was not successfully added to the node.

        """

        node_id = self.get_node_id(node_name)

        discovered_interfaces = self.get_discovered_interfaces(node_name)
        discovered_interface = [
            x for x in discovered_interfaces
            if x['Caption'].startswith(interface_name)
        ]

        if discovered_interface:
            self.swis.invoke('Orion.NPM.Interfaces', 'AddInterfacesOnNode',
                             node_id, discovered_interface,
                             'AddDefaultPollers')

        else:
            return False

    def ncm_download_nodes_running_config(self, node_name):
        """ For a given node, download the node's running configuration. Uses a SWIS query to find the Cirrus node I.
            Uses a Swis invoke of DownloadConfig.

            Args:
                node_name(string): A node name which should equal the caption used in SolarWinds for the node object.

            Returns:
                None.

        """

        results = self.swis.query(
            'SELECT NodeID FROM Cirrus.Nodes WHERE NodeCaption = @node_name',
            node_name=node_name)['results']

        cirrus_node_id = results[0]['NodeID']

        self.swis.invoke('Cirrus.ConfigArchive', 'DownloadConfig',
                         [cirrus_node_id], 'Running')

    def ncm_run_compliance_report(self, report_name):
        """ For a given report name, run the Policy Report. Uses a SWIS query to get the policy report ID. Uses a
            SWIS invoke of StartCaching to run the policy report.

            Args:
                report_name(string): A report name which should equal the Name used in SolarWinds for a Policy
                    Report object

            Returns:
                None.

        """

        results = self.swis.query(
            'SELECT PolicyReportID FROM Cirrus.PolicyReports WHERE Name = @report_name',
            report_name=report_name)

        report_id = results['results'][0]['PolicyReportID']
        self.swis.invoke('Cirrus.PolicyReports', 'StartCaching', [report_id])
class SolarWindsInterface:
    """Defines SolarWinds API object"""
    disable_warnings(InsecureRequestWarning)

    def __init__(self, username, password, server):
        self.auth(username, password, server)
        self.data_path = Path('data/')
        self.results = None
        self.nodes = None
        self.uris = None
        self.custom_props = None

    def auth(self, username, password, server):
        print("Sending authorization request to SolarWinds")
        self.swis = SwisClient(server, username, password)
        print("Authorization successful")

        return 1

    def query(self, query_str, node=None):
        print("Sending query to SolarWinds.")
        if node is None:
            self.results = self.swis.query(query_str)
        else:
            self.results = self.swis.query(query_str % str(tuple(node)))
        print("Query received from SolarWinds.")

        return self.results

    def set_uris(self, uris):
        query_str = """SELECT TOP 10 NodeName, NodeID, Uri
                       FROM Orion.Nodes
                       WHERE Uri IN %s"""
        self.query(query_str, nodes=uris)
        self.collect_uris()

        return self.nodes

    def collect_uris(self):
        if self.results is None:
            print("Query never made to SolarWinds.")
            print("Use set_uris() if you're providing your own list of URIs")
            return
        self.nodes = {
            line['Uri']: line['NodeName']
            for line in self.results['results']
        }
        self.uris = [k for k, v in self.nodes.items()]
        return self.nodes

    def check_alerts(self):
        print("Requesting alert suppression states")
        invoke_results = self.swis.invoke('Orion.AlertSuppression',
                                          'GetAlertSuppressionState',
                                          self.uris)
        print("Received alert suppression states")

        states = {
            line['EntityUri']: line['SuppressionMode']
            for line in invoke_results
        }

        for uri, state in states.items():
            if state == 0:
                print("%s: NOT suppressed" % self.nodes[uri])
            elif state == 1:
                print("%s: suppressed" % self.nodes[uri])
            elif state == 2:
                print("%s: PARENT suppressed" % self.nodes[uri])
            elif state == 3:
                print("%s: suppression scheduled" % self.nodes[uri])
            elif state == 4:
                print("%s: PARENT suppression scheduled" % self.nodes[uri])

        return states

    def suppress_alerts(self, start, end):
        if self.nodes is None:
            self.collect_uris()
        try:
            start = parse(start)
            end = parse(end)
        except ValueError:
            print("Invalid start or end time")
            return
        print("Suppressing alerts FROM - UNTIL: ")
        print("%s - %s" % (str(start), str(end)))

        self.swis.invoke('Orion.AlertSuppression', 'SuppressAlerts', self.uris,
                         start, end)
        print("Finished suppressing alerts")
        states = self.check_alerts()

        return states

    def read_custom_properties(self, uri):
        properties = self.swis.read(uri + '/CustomProperties')
        self.custom_props = json.dumps(properties, indent=4)

        return self.custom_props

    def change_custom_properties(self, uri, updated_props):
        for k, v in updated_props.items():
            self.swis.update(uri + '/CustomProperties', **{k: v})
        print("Updating Custom Properties")

        return 1
Beispiel #16
0
def _custom_props(module):
    options = {
        'hostname': module.params['hostname'],
        'username': module.params['username'],
        'password': module.params['password']
    }

    swis = SwisClient(**options)
    node = _find_node(module)
    nodeid = "{0}".format(node['nodeId'])

    swis.update('swis://orion/Orion/Orion.Nodes/' + 'NodeID=' + nodeid +
                '/CustomProperties',
                Environment=module.params['env'])
    swis.update('swis://orion/Orion/Orion.Nodes/' + 'NodeID=' + nodeid +
                '/CustomProperties',
                FISSMA_System=module.params['fisma'])
    swis.update('swis://orion/Orion/Orion.Nodes/' + 'NodeID=' + nodeid +
                '/CustomProperties',
                Government_Contact_Information=module.params['project_lead'])
    swis.update('swis://orion/Orion/Orion.Nodes/' + 'NodeID=' + nodeid +
                '/CustomProperties',
                GSA_FISMA_System='GRACE')
    swis.update('swis://orion/Orion/Orion.Nodes/' + 'NodeID=' + nodeid +
                '/CustomProperties',
                Region='AWS - EAST')
    swis.update('swis://orion/Orion/Orion.Nodes/' + 'NodeID=' + nodeid +
                '/CustomProperties',
                Service_Group='GRACE')
    swis.update('swis://orion/Orion/Orion.Nodes/' + 'NodeID=' + nodeid +
                '/CustomProperties',
                SITE_ID='CAM - Amazon - Cloud Service Provider')
    swis.update('swis://orion/Orion/Orion.Nodes/' + 'NodeID=' + nodeid +
                '/CustomProperties',
                SME_Contact_Information=module.params['sme'])

    module.exit_json(changed=True)