def run(job=None, *args, **kwargs):
    # Disable SSL errors
    verify = False
    if not verify:
        requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

    # Get SolarWinds ConnectionInfo
    solarwinds = ConnectionInfo.objects.get(name='SolarWinds')
    swis = SwisClient(solarwinds.ip, solarwinds.username, solarwinds.password)
    if not solarwinds:
        return "FAILURE", "", "Missing required SolarWinds connection info. (Admin -> Connection Info -> New Connection Info)"

    # Get Server Info
    server = job.server_set.first()

    # Find the Uri you want to delete based on a SWQL query
    results = swis.query("select ipaddress, caption, uri from orion.nodes where ipaddress = '{}'".format(server.ip))

    # Use as needed
    if len(results['results']) > 1:
        print('Refine your search. Found more than one node matching that criteria.')
    elif len(results['results']) == 1:
        print("Deleting {}".format(results['results'][0]['ipaddress']))
        response = swis.delete(results['results'][0]['uri'])
        print("Done")
    else:
        print("Nothing to delete from SolarWinds")

    return "","",""
Пример #2
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
Пример #3
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
Пример #4
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
Пример #5
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'])
Пример #6
0
# duplicated-nodes.sh tarafindan paramatre olarak verilen en kucuk nodeID'ye ait node'u siler
import os
import re
import sys
import requests
import datetime 

from orionsdk import SwisClient
from requests.packages.urllib3.exceptions import InsecureRequestWarning

print ("Initialize duplicated-nodes.py for NodeID = ", str(sys.argv[1]))

# setup swis params
npm_server = '192.168.x.x'        # Change this to your solarwinds IP or hostname
username = ''	                 # Change this to your username
password = ''			# Change this to your password

# disable SSL warnings
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

# Setup the swis connection
swis = SwisClient(npm_server, username, password)

# Find the Uri you want to delete based on a SWQL query
results = swis.query("SELECT Uri FROM Orion.Nodes WHERE NodeID = @node_id", node_id = str(sys.argv[1]))

print("Deleting {}".format(results['results'][0]['Uri']))
response = swis.delete(results['results'][0]['Uri'])
print ("Deleted NodeID = ", str(sys.argv[1]))
Пример #7
0
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])