-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUsageCaptureExample.py
More file actions
212 lines (162 loc) · 7.07 KB
/
UsageCaptureExample.py
File metadata and controls
212 lines (162 loc) · 7.07 KB
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
#
# UsageCaptureExample.py
#
# Solstice Usage Capture
#
# An OpenControl Protocol Example.
#
# This application monitors a Solstice Pod deployment for a given amount of time and
# saves connection count information for each Pod to a comma-separated datafile that can easilly be imported
# into Excel or another tool to visualize usage statistics over time.
#
# Usage: solsticeUsageCapture <Solstice Host File> <OutputFile (comma separated)> [-time] <time in seconds>
#
# The arguments are:
#
# <hostFile.txt>: A textfile that contains, on each line, a display name and it's corresponding IPAddress. This file
# contains the set of Solstice Hosts that will be monitored.
#
# <outputFile.txt>: The resulting output textfile. This file will be written throughout the monitoring process and closed
# when the program terminates. The format of this file is a CSV where each line contains the number of users connected
# at the sample for each host.
#
# <Time (in seconds!) to monitor the program>
#
# This application uses the OpenControl protocol to establish a connection and download utilization information.
#
# (c) Mersive Technologies, 2016
#
# Author: Christopher Jaynes
# CTO & Founder, Mersive
#
# --------------- LICENSE -MIT Open Source -----------------------------------------------
#Copyright (c) 2016 >Mersive
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies or substantial portions
# of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# -------------------------------------------------------------------------------
import argparse
import sys
import urllib.request, urllib.parse, urllib.error
import time
import os
import urllib.request, urllib.error, urllib.parse
# Solstice OpenControl is based on JSON records, you can parse by hand or use existing libraries (like I do here)
# Make sure you take a look at the OpenControl protocol documentation to see what other capabilties it provides.
# You can download from here:
# https://mersive.com/solstice-opencontrol-api/
#
#
import json
#
# I use the argparse library to quickly parse the command line for arguments and marshall them into each component
#
argumentParser = argparse.ArgumentParser(description='Solstice Usage Capture, Command Line Arguments.')
argumentParser.add_argument('HostFile', metavar='<hostfile.txt>', type=str, help='Solstice Host Text File: [Name] [IPAddr] [Port] per line')
argumentParser.add_argument('OutputFile', metavar='<outputFile.txt>', type=str, help='Output File for Usage Data')
argumentParser.add_argument('Time', metavar='<Time in Minutes>', type=int, help='Length of Capture in Minutes')
gHostConnectionInfo = []
gHostCount = 0
#
# This variable defines how often to poll user count for all hosts in the hostFile.txt file
gSampleIntervalInSeconds = 5
#
# OpenControl users several different URLs based on the type of information you are reading/writing (control, stats, config)
# This program will be reading statistics information (users connected), so we will be using the "stats" URL
#
gSolstice_Stats_URL = "/api/stats"
#
#
# DEFINE loadHostFile. A simple function to load a text file with hostname and IPAddr and load each line to the the
# gHostConnectionInfo array for processing later.
#
def loadHostFile(aHostFile):
whiteSpaceRegEx = "\\s"
#
# First test if the file exists, then open and read until no more data exists.
#
if (os.path.isfile(aHostFile)) :
with open(aHostFile, 'r') as file:
index = 0
for line in file:
gHostConnectionInfo.append(line.split())
index = index+1
return index
else:
print(aHostFile+" does not appear to exist or cannot be opened.")
exit()
#
#
# DEFINE getUserCountFromHost. Given an IPAddress, poll the number of users currently connected at that Solstice IPAddress.
# If there is a problem (i.e. there is no Solstice host at that IPAddress, or it cannot be reached, set to zero.
#
def getUserCountFromHost( aIPAddr ):
# This function users the url2lib for processing communicating to the socket and waiting on a response.
#
# NOTE: This example assumes that the admin password is not set for all the endpoints. If the admin password
# has been set. The OpenControl protocol will use https and not http as shown below. Additionally
# the urlStr would have to be appended with "?password=<your admin password>" so that the current admin password is
# transmitted as an argument to the Solstice Host as part of the URL get request.
urlStr = "http://"+aIPAddr+gSolstice_Stats_URL
try:
urlRequestResult = urllib.request.urlopen( urlStr , timeout=1 )
except urllib.error.URLError as e:
return(0)
hostValuesStr = urlRequestResult.read()
statsTopLevelRecord = json.loads( hostValuesStr );
##
## Parse out the Statistics SubRecord and Return User Count
##
if 'm_statistics' in statsTopLevelRecord:
displayInformation = statsTopLevelRecord[ 'm_statistics' ]
return( displayInformation['m_connectedUsers'] )
else:
return( 0 )
def main():
# Parse command line arguments
args = argumentParser.parse_args()
#Load Host file into the gConnectionInfo structure that holds hostname/IP/Port
gHostCount = loadHostFile( args.HostFile )
# Start the timer and begin collecting usage information from all hosts.
# At the end of each loop, append the result to the CSV output file.
#
timeStart = time.time()
timeEnd = timeStart + (args.Time)
#
# Open output file.
# and begin collecting data.
#
try:
lOutputFile = open(args.OutputFile, "w")
# Output HEADER Info
lOutputFile.write("Time, ")
for gHostNumber in range(0,gHostCount):
lOutputFile.write(gHostConnectionInfo[gHostNumber][0]+", ")
lOutputFile.write("Total\n")
while (time.time() < timeEnd):
accumulatedUserCount = 0
lOutputFile.write("%.0f" % (time.time() - timeStart))
# Get number of users Connected for each display.
for hostNumber in range(0,gHostCount):
lNumUsers = getUserCountFromHost( gHostConnectionInfo[hostNumber][1]);
accumulatedUserCount += lNumUsers
lOutputFile.write(", "+str( lNumUsers ) )
lOutputFile.write(", "+str(accumulatedUserCount)+"\n")
lOutputFile.flush()
time.sleep( gSampleIntervalInSeconds )
close(lOutputFile)
except IOError:
print(args.OutputFile+" could not be opened. Exiting.")
exit()
main()