OrionBaseAction   A
last analyzed

Complexity

Total Complexity 35

Size/Duplication

Total Lines 219
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 219
rs 9
c 0
b 0
f 0
wmc 35

13 Methods

Rating   Name   Duplication   Size   Complexity  
A query() 0 5 1
A connect() 0 10 1
A update() 0 5 1
B get_snmp_cred_id() 0 24 2
B get_ncm_transfer_results() 0 38 5
A delete() 0 5 1
A get_snmp_community() 0 12 4
B get_engine_id() 0 24 3
A create() 0 5 1
A read() 0 5 1
C get_node() 0 57 10
A __init__() 0 11 4
A invoke() 0 5 1
1
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
2
# contributor license agreements.  See the NOTICE file distributed with
3
# this work for additional information regarding copyright ownership.
4
# The ASF licenses this file to You under the Apache License, Version 2.0
5
# (the "License"); you may not use this file except in compliance with
6
# the License.  You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
16
import time
17
18
from st2actions.runners.pythonrunner import Action
19
from orionsdk import SwisClient
20
21
from lib.node import OrionNode
22
from lib.utils import send_user_error, is_ip
23
24
25
class OrionBaseAction(Action):
26
    def __init__(self, config):
27
        super(OrionBaseAction, self).__init__(config)
28
29
        self.client = None
30
31
        if "orion_host" not in self.config:
32
            raise ValueError("Orion host details not in the config.yaml")
33
        elif "orion_user" not in self.config:
34
            raise ValueError("Orion user details not in the config.yaml")
35
        elif "orion_password" not in self.config:
36
            raise ValueError("Orion password details not in the config.yaml")
37
38
    def connect(self):
39
        """
40
        Connect to the Orion server listed in the config.
41
        """
42
43
        self.client = SwisClient(self.config['orion_host'],
44
                                 self.config['orion_user'],
45
                                 self.config['orion_password'])
46
47
        return self.config['orion_label']
48
49
    def get_node(self, node):
50
        """
51
        Get an OrionNode object
52
        """
53
54
        orion_node = OrionNode()
55
56
        if is_ip(node):
57
            query_for_where = "IPAddress"
58
        else:
59
            query_for_where = "Caption"
60
61
        swql = """SELECT NodeID, Uri, IPAddress, Caption
62
        FROM Orion.Nodes
63
        WHERE {}=@query_on""".format(query_for_where)
64
        kargs = {'query_on': node}
65
        data = self.query(swql, **kargs)
66
67
        if 'results' not in data:
68
            msg = "No results from Orion: {}".format(data)
69
            self.logger.info(msg)
70
            raise Exception(msg)
71
72
        if len(data['results']) == 1:
73
            try:
74
                orion_node.npm_id = data['results'][0]['NodeID']
75
                orion_node.uri = data['results'][0]['Uri']
76
                orion_node.ip_address = data['results'][0]['IPAddress']
77
                orion_node.caption = data['results'][0]['Caption']
78
            except IndexError:
79
                pass
80
        elif len(data['results']) >= 2:
81
            self.logger.debug(
82
                "Muliple Nodes match '{}' Caption: {}".format(
83
                    node, data))
84
            raise ValueError("Muliple Nodes match '{}' Caption".format(
85
                node))
86
87
        if orion_node.npm:
88
            swql = """SELECT NodeID
89
            FROM Cirrus.Nodes
90
            WHERE CoreNodeID=@CoreNodeID"""
91
            kargs = {'CoreNodeID': orion_node.npm_id}
92
            data = self.query(swql, **kargs)
93
94
            # Don't raise an exception if this fails.
95
            # The platform may not haev NCM installed.
96
            if 'results' not in data:
97
                msg = "No results from Orion NCM: {}".format(data)
98
                self.logger.info(msg)
99
            elif len(data['results']) == 1:
100
                try:
101
                    orion_node.ncm_id = data['results'][0]['NodeID']
102
                except IndexError:
103
                    pass
104
105
        return orion_node
106
107
    def query(self, swql, **kargs):
108
        """
109
        Run SWQL against the Orion Platform.
110
        """
111
        return self.client.query(swql, **kargs)
112
113
    def invoke(self, entity, verb, *args):
114
        """
115
        Run an Invoke against the Orion Platform.
116
        """
117
        return self.client.invoke(entity, verb, *args)
118
119
    def create(self, entity, **kargs):
120
        """
121
        Run an Create against the Orion Platform.
122
        """
123
        return self.client.create(entity, **kargs)
124
125
    def read(self, uri):
126
        """
127
        Run an Read against the Orion Platform.
128
        """
129
        return self.client.read(uri)
130
131
    def update(self, uri, **kargs):
132
        """
133
        Run an Update against the Orion Platform.
134
        """
135
        return self.client.update(uri, **kargs)
136
137
    def delete(self, uri):
138
        """
139
        Run an Delete of an URI against the Orion Platform.
140
        """
141
        return self.client.delete(uri)
142
143
    def get_snmp_community(self, community):
144
        """
145
        Return the correct SNMP comminity to use.
146
        """
147
        if community == "customer":
148
            return self.config['snmp_customer']
149
        elif community == "internal":
150
            return self.config['snmp_internal']
151
        elif community is None:
152
            return self.config['snmp_default']
153
        else:
154
            return community
155
156
    def get_snmp_cred_id(self, community):
157
        """
158
        Look up an SNMP community in the config and then look up
159
        the Orion ID for the Credential.
160
        """
161
162
        # Check if the community should be replaced.
163
        name = self.get_snmp_community(community)
164
165
        swql = """SELECT ID FROM Orion.Credential
166
        WHERE CredentialType=@CredentialType and Name=@name"""
167
168
        kargs = {'CredentialType':
169
                 'SolarWinds.Orion.Core.Models.Credentials.SnmpCredentialsV2',
170
                 'name': name}
171
        orion_data = self.query(swql, **kargs)
172
173
        if len(orion_data['results']) == 1:
174
            return orion_data['results'][0]['ID']
175
        else:
176
            msg = "Could not get ID for community in Orion.Credential: {}".format(
177
                community)
178
            send_user_error(msg)
179
            raise ValueError(msg)
180
181
    def get_engine_id(self, poller):
182
        """
183
        Takes a poller name (or primary) and returns the EngineID for
184
        the poller.
185
186
        Raises: ValueError on an invaild poller.
187
188
        Returns: The EngineID (int)
189
        """
190
191
        if poller == "primary":
192
            return 1
193
        else:
194
            swql = """SELECT EngineID, ServerName, IP, ServerType
195
            FROM Orion.Engines
196
            WHERE ServerName=@poller"""
197
            kargs = {'poller': poller}
198
            data = self.query(swql, **kargs)
199
200
            if len(data['results']) == 1:
201
                return data['results'][0]['EngineID']
202
            else:
203
                send_user_error("Invalid poller name")
204
                raise ValueError("Invalid poller name")
205
206
    def get_ncm_transfer_results(self, transfer_id, sleep_delay=10):
207
        """
208
        Gets the completed (waits until finished). NCM job transfer status
209
        from Orion.
210
211
        Retruns: The completed status.
212
        """
213
        ts = {}
214
        while True:
215
            swql = """SELECT TransferID, NodeID, Action, RequestedConfigType,
216
            RequestedScript, RequestedReboot, ConfigID, TransferProtocol,
217
            Status, ErrorMessage, DeviceOutput, DateTime, UserName
218
            FROM NCM.TransferResults
219
            WHERE TransferID=@transfer_id"""
220
            kargs = {'transfer_id': transfer_id}
221
222
            transfer_data = self.query(swql, **kargs)
223
            status = transfer_data['results'][0]['Status']
224
225
            if status == 1:
226
                time.sleep(sleep_delay)
227
            elif status == 2:
228
                ts['status'] = "Complete"
229
                break
230
            elif status == 3:
231
                ts['status'] = "Error"
232
                break
233
            else:
234
                ts['status'] = "Unknown"
235
                break
236
237
        ts['RequestedScript'] = transfer_data['results'][0]['RequestedScript']
238
        ts['RequestedReboot'] = transfer_data['results'][0]['RequestedReboot']
239
        ts['ErrorMessage'] = transfer_data['results'][0]['ErrorMessage']
240
        ts['DeviceOutput'] = transfer_data['results'][0]['DeviceOutput']
241
        ts['UserName'] = transfer_data['results'][0]['UserName']
242
243
        return ts
244