-
Notifications
You must be signed in to change notification settings - Fork 49
/
get_device_list.py
222 lines (194 loc) · 8.62 KB
/
get_device_list.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#
# _author_ = Raajeev Kalyanaraman <[email protected]>
#
#
# Copyright (c) 2022 Dell EMC Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""
#### Synopsis
Script to get the list of devices managed by OM Enterprise
#### Description
This script uses the OME REST API to get a list of devices
currently being managed by that instance. For authentication X-Auth
is used over Basic Authentication
Note that the credentials entered are not stored to disk.
#### Python Example
`python get_device_list.py --ip <xx> --user <username> --password <pwd>`
"""
import argparse
import csv
import json
import os
import sys
from argparse import RawTextHelpFormatter
from getpass import getpass
import urllib3
class GetDeviceList:
auth_success = None
headers = None
""" Authenticate with OME and enumerate devices """
def __init__(self, session_input, output_details):
self.__session_input = session_input
self.__output_details = output_details
if not self.__validateargs():
return
self.__base_uri = 'https://%s' % self.__session_input["ip"]
try:
self.auth_success, self.headers = self.__authenticate_with_ome()
if not self.auth_success:
print("Unable to authenticate with OME .. Check IP/Username/Pwd")
return
except Exception as error:
print("Unable to connect to OME appliance %s. The error was %s" % (self.__session_input["ip"], error))
return
try:
if self.__get_device_list() is False:
print("Get device list failed.")
return
except Exception as get_ex:
print("Unable to get device list from OME appliance %s" % self.__session_input["ip"])
print(get_ex)
return
if self.__output_details["format"] == 'json':
self.__format_json()
elif self.__output_details["format"] == 'csv':
self.__format_csv()
def __request(self, url, payload=None, method='GET'):
""" Returns status and data """
request_obj = pool.urlopen(method, url, headers=self.headers, body=json.dumps(payload))
if request_obj.data and request_obj.status != 400:
data = json.loads(request_obj.data)
else:
data = request_obj.data
return request_obj.status, data
def __authenticate_with_ome(self):
""" Authenticate with OME and X-auth session creation """
auth_success = False
session_url = "https://%s/api/SessionService/Sessions" % self.__session_input["ip"]
user_details = {'UserName': self.__session_input["user"],
'Password': self.__session_input["password"],
'SessionType': 'API'}
headers = {'content-type': 'application/json'}
session_response = pool.urlopen('POST', session_url, headers=headers,
body=json.dumps(user_details))
if session_response.status == 201:
headers['X-Auth-Token'] = session_response.headers['X-Auth-Token']
auth_success = True
else:
error_msg = "Failed create of session with {0} - Status code = {1}"
print(error_msg.format(self.__session_input["ip"], session_response.status_code))
return auth_success, headers
def __get_device_from_uri(self, uri):
json_data = {}
status, device_response = self.__request(uri, method='GET')
if status == 200:
json_data = device_response
else:
print("Unable to retrieve device list from %s" % uri)
return json_data
def __get_device_list(self):
next_link_url = self.__base_uri + '/api/DeviceService/Devices'
self.json_data = None
while next_link_url is not None:
data = self.__get_device_from_uri(next_link_url)
next_link_url = None
if data['@odata.count'] <= 0:
print("No devices managed by %s" % self.__session_input["ip"])
return False
if '@odata.nextLink' in data:
next_link_url = self.__base_uri + data['@odata.nextLink']
if self.json_data is None:
self.json_data = data
else:
self.json_data['value'] += data['value']
return True
def __format_json(self):
# print to console in the absence of a specified file path
json_object = json.dumps(self.json_data, indent=4, sort_keys=True)
if self.__output_details["path"] == '':
print("*** Device List ***")
print(json_object)
return
# If file path is specified then write to file.
modified_filepath = self.__get_unique_filename()
with open(modified_filepath, "w") as json_file:
json_file.write(json_object)
def __format_csv(self):
exportable_props = ["Id", "Identifier", "DeviceServiceTag",
"ChassisServiceTag", "Model", "DeviceName"]
csv_file = None
if self.__output_details["path"] == '':
print("*** Device List ***")
writer = csv.writer(sys.stdout, lineterminator=os.linesep)
else:
modified_filepath = self.__get_unique_filename()
csv_file = open(modified_filepath, 'w', newline='')
writer = csv.writer(csv_file)
devices = self.json_data["value"]
writer.writerow(exportable_props)
for device in devices:
device_props = []
for prop in exportable_props:
device_props.append(device[prop])
writer.writerow(device_props)
if csv_file is not None:
csv_file.close()
def __get_unique_filename(self):
i = 1
new_filepath = self.__output_details["path"]
exists = os.path.isfile(new_filepath)
while os.path.isfile(new_filepath):
(root, ext) = os.path.splitext(self.__output_details["path"])
new_filepath = root + "({0})".format(i) + ext
i += 1
if exists:
print("Output file exists. Writing to {}".format(new_filepath))
return new_filepath
def __validateargs(self):
if self.__output_details["path"] != '' and \
os.path.splitext(self.__output_details["path"])[1] != '' and \
os.path.splitext(self.__output_details["path"])[1][1:] != self.__output_details["format"]:
print("Output filename must match requested file format")
return False
return True
if __name__ == '__main__':
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
parser = argparse.ArgumentParser(description=__doc__, formatter_class=RawTextHelpFormatter)
parser.add_argument("--ip", "-i", required=True, help="OME Appliance IP")
parser.add_argument("--user", "-u", required=False,
help="Username for OME Appliance", default="admin")
parser.add_argument("--password", "-p", required=False,
help="Password for OME Appliance")
parser.add_argument("--outformat", "-of", required=False, default="json",
choices=('json', 'csv'),
help="Output format type")
parser.add_argument("--outpath", "-op", required=False, default="",
help="Path to output file")
args = parser.parse_args()
if not args.password:
if not sys.stdin.isatty():
# notify user that they have a bad terminal
# perhaps if os.name == 'nt': , prompt them to use winpty?
print("Your terminal is not compatible with Python's getpass module. You will need to provide the"
" --password argument instead. See https://stackoverflow.com/a/58277159/4427375")
sys.exit(0)
else:
password = getpass()
else:
password = args.password
pool = urllib3.HTTPSConnectionPool(args.ip, port=443,
cert_reqs='CERT_NONE', assert_hostname=False)
GetDeviceList({"ip": args.ip, "user": args.user, "password": password},
{"format": args.outformat, "path": args.outpath})