KB_5K0070: STAT5000 – Programming with the ISE Restful API via

advertisement
KB_5K0070: STAT5000 –
Programming with the ISE Restful
API via AutoIT.
Description:
This KB article summarizes the STAT5000
application and in the process will hopefully give you
pointers on how to modify the application for your
own purposes.
STAT5000 was designed and coded in one day as an
exercise to see how quickly a useful application
could be turned around using the Restful interface
into the ISE. The design goal of the program was
pretty simple. Basically, just jam as much
performance and status related information into a
single screen AND do this for multiple ISEs so that
we could monitor host performance across multiple
ISEs from the ISE perspective. It was a very, very,
long day (the author had only used AUTOIT for two
other programs previously).
Why use AutoIt? In late 2009, a quick ‘google’
search of the internet for ‘best automated windows
scripting language’ indicated that one method that
stood out was a tool called autoit. This tool has been
around in the industry for 10+ years now and has
quite a following, is relatively simple to use, and is
VERY feature rich. This, along with the desire to use
a language that was ‘free’ but also easy to pick up for
both programmers and non-programmers AND that
was capable of creating a final executable that had no
installation, dll, or registry dependencies all factored
into the decision to use it.
Interesting sidebar for those MAG Classic customers
out there. Almost 10 years ago AutoIt was used by
Xiotech Tech Marketing to create a program that ran
as a service on customers servers. The application
just sat there and monitored the servers volume
freespace and when freespace got too low the
application would use the RMC
easyscripting/autoscripting language (which this
author also designed) to tell the MAGNITUDE
storage array to expand its VDisk. VERY early
precursor to our existing XIP functionality.
THE PROGRAM:
STAT5000 was designed from the screen outwards
(i.e. literal napkin design). The final screen looked
like the following. Red-Green rules apply (better to
be handy than handsome):
The screen is organized as follows:
1) The upper left is the ISE selector/info/button
region. This is where you can:
a. type in a new IP address (in the box below
the list of IP addresses) and then press Add
(or just hit enter).
b. delete (remove) and ISE from the list by
selecting the IP address and pressing delete
(button or key).
c. Change the sampling interval by clicking the
Sample= button (it will cycle through 5 or so
different selections.) Rates aren’t necessarily
exact when you used the fastest sampling
due to variances in TCP traffic but it is pretty
fast.
d. Start and Stop captures. Use the Start
Captures button…it will change to Stop
Captures once captures are started up.
Capture interval is sampling interval AND
all ISE performance info will be captured to
a file that contains the IP address of the ISE
with a csv extension. The format can then be
fed straight into excel. Column headers are
named such that a left to right sort will pull
all qdepths together for example (lazy
method of quick plotting in excel).
e. Age captures…allows you to start a new
capture but first age out the existing
one…keeps 8 levels deep.
f. And in the legend area you can see what all
the colors/symbols/etc are for on the rest of
the screen.
2) The other 8 regions are each a separate ISE as
shown above. Each of these regions shows:
a. The ise/mrc/battery/powersupply/datapac
status and fw versions/etc where appropriate
b. The number of disks (i.e. each show as a disk
symbol) within each datapac PLUS the status
and activity in each disk. The status is shown
by the color of the top of the disk (green is
ok, yellow is reduced capacity, and red is
failed). The performance is reflected in the
color of the disk ‘body’ itself with colors
mixed via an algorithm that takes into
consideration IOPS, KBPS, QD, and
LATENCY. Lighter and brighter the busier
they are. Also, under each disk are up to
three horizontal lines, the length of which
indicates the relative qdepth+latency for the
top line, the iops for the middle line, and the
kbps for the bottom line. Finally, if the
mouse is dragged over any disk, a tooltip
will appear showing you much more detailed
info about that disk as shown in the full
screenshot above (mouse cursor symbol is
missing from capture). Left clicking while
this screen is up will save the information to
a text file and then pop that file up via
notepad (useful if you want to remember the
info and you have refresh set too fast…the
tooltip will continue to update dynamically
as you hold the mouse over a disk.)
c. The region under the disk symbols is a recent
addition (i.e. not in the first day of coding). It
can be an eyechart but it shows the
performance of each individual volume
(there can be up to 240 of them) or, if
selected by the user, this region can just
show the performance of each host hba.
These are tiny symbols, but, like the physical
disk info you can drag the mouse over these
little dots and a tooltip will tell you more
info about them (vdisk name, actual
performance numbers, host name, wwn, etc.)
d. Below this is the dashboard display (taken
somewhat literally when coded up.) On this
screen, total ISE is shown in pink, MRC1 is
brown, and MRC2 is an off green. Think of
the IOPS as a tachometer, the KBPS as a
speedometer, and the transfer size
(essentially kbps/iops) is the fuel gauge in
the middle. The things that look like eyes are
lights that get larger and brighter the higher
the qdepth and latency gets (so if you see big
red eyes it is really busy.) And of course the
actual readings are shown to the right of that.
Given that you know what you want to display, the
only other major task in this design was to determine
how to retrieve the data and analyze it. Retrieval is
discussed further down in this document, but it is
worth noting a few good starting points for accessing
restful information from the ISE. Before reading the
rest of this document, if you have an ISE available
right now do the following:
1) From a web browser, enter either one of your
ISEs IP addresses into the web browser address
bar followed by a /query (i.e. 10.10.20.30/query).
2) You will get something that looks like the
following:
<?xml version="1.0" encoding="ISO8859-1" ?>
- <array
self="http://10.20.54.32/storage/arr
ays/1BC10089">
<status value="0"
string="Operational" />
<globalid>1BC10089</globalid>
<id>20000014C367348C</id>
<name>ISE</name>
<serialnumber>1BC10089</serialnumber
>
<model>ISE1400</model>
<vendor>XIOTECH</vendor>
...and so on…
3) Cut and paste the http string into the browser and
press return. You will be requested for the
Adminstrator login and password. NOTE:
STAT5000 has the Administrator default
password hard coded into it.
4) Take other http:// lines that you see in the
resulting page and try looking at those
Now things will make more sense when you look at
what this code does (i.e. it is a big parsing, analysis,
and display engine for some of this data.)
Of note is that STAT5000 was actually written and
tested by the developer while working from Florida
and his mountain home in Georgia but while
monitoring ISEs simultaneously in both Minnesota
and Colorado to ensure that this would work fine
over normal home internet connections. Using a 5
year old laptop to boot. It was also necessary to slow
down the refresh rates from once a second to once
every two seconds as it got hard to pause or grab
information at the right moment when it was
changing so fast, so atomic speed of retrieval wasn’t
an issue for this type of application.
Screen resolution needs to be 1280 by 950 at least.
Some PCs exhibit no flicker at all, some see an
occasional catchup flicker. Learning curve on the
developers part who normally programs in C and
C++ (who also happens to be writing this KB article).
Before delving into the code itself, a few more points
on the code design. AutoIt is a powerful language but
it is single threaded from a programmer viewpoint. In
a sense this is good because multi-threading can be
somewhat of a headache for novice and expert
programmers alike...often times producing unwanted
results. Not something you want when programming
around your corporate storage. However, multithreading is useful for ‘speeding’ up things (i.e. say
you want instantaneous GUI response so that you can
tooltip around existing data but also need to wait for
xml data to be transferred from the ISEs).
The way you accomplish this functionality using
AutoIt is actually very easy. You simply:
1)
write one autoit program that gathers the data (in
this case it is called GET_XMLS.exe) and
2) write a main program (STAT5000.exe) that
spawns off the GET_XMLS.exe whenever it
needs data gathered,
a. thereby using the OS for multitasking/threading
b. and the filesystem as a ‘buffer’ mechanism as
follows
i. STAT5000 puts a list of ISE IP
addresses in an INI file
ii. then GET_XMLS
1. looks in that file for a list of
IP addresses to scan
2. grabs all the requested restful
xml data from each of these
ISEs
3. saves that information into
text files files,
iii. then STAT5000
1. sees that the data has
appeared,
2. reads the info in from the
files,
3. And then kicks off another
request after the desired
sample dwell has expired
Very simple and nothing steps on another process’s
toes.
A side benefit is that this means that future programs
can be written to use GET_XMLS.exe and
GET_XMLS.exe can be upgraded if necessary
without recompiling all the programs that use it. The
code for GET_XMLS.exe is only 300 lines or so of
autoit source code, BTW and will be shown below.
Also, STAT5000 is designed without any complex
schemas or data structures. You will see a pretty flat
structure when you look at the code and that was
done entirely to keep things readable and ‘safe’. No
pointers, strings are all essentially infinite length, no
complex conditional code that you have to reread a
number of times, etc. Also, this program is safe
because it is ONLY monitoring an ISE…there is no
configuration code active in this example at all (i.e.
no volume deletes). During the entire development
and subsequent testing of STAT5000 not a single
‘impact’ was ever seen on an ISE due to running this
program.
Now for the code. Sources for STAT5000 are
currently about 1300 lines of code. The code that is
provided with the SDK might vary a bit from this
documents contents but hopefully the gist will carry
forwards. The following section will go through the
code from top to bottom and after that section will be
one final section that summarizes Autoit.
When developing with AutoIt, you will want to
create an empty directory somewhere, put the source
for STAT5000.au3 and GET_XMLS.au3 in that
directory, build GET_XMLS to create
GET_XMLS.exe (or just copy in the existing
GET_XMLS.exe that is provided with the sdk) and
then you can modify and either build the
STAT5000.au3 or run it interactively. It doesn’t
seem to run any slower interactively so is very usable
either way. The Editor that comes with AutoIt has the
capability of doing full syntax and rules checking on
the code so is very handy as well.
The Code:
Each of the two executables (GET_XMLS.exe and
STAT5000.exe) are standalone executables (i.e. just
place them in a directory on a windows box and run
them). If run without each other, STAT5000 will
inform you that it needs to be able to see
GET_XMLS.exe in the same directory and
GET_XMLS.exe will just explain how to run it and
how to construct the ini file it uses in case you have
some standalone method you are testing (i.e. without
using STAT5000). Again, STAT5000 will normally
be all you run and it will call GET_XMLS.exe when
needed.
Sources for each executable are totally contained in
the files GET_XMLS.au3 and STAT5000.au3 which
are described in a bit more detail as follows.
GET_XMLS.AU3:
GET_XMLS.au3 was originally constructed as part
of a test program called rest5000 (which accessed
restful data and put it into a rudimentary report
format). With STAT5000 it was modularized to work
with both rest5000, STAT5000, and any other
applications that might be developed.
Quick comment on comments. Autoit has comments
(anything that starts with a ;) and also has comment
block capability (#cs/#ce):
;GET_XMLS for 5K - TRB 1/2010
#include <String.au3>
#include
#include
#include
#include
#include
#include
<Constants.au3>
<GuiEdit.au3>
<Date.au3>
<File.au3>
<Array.au3>
<Misc.au3>
The include files above are all included with AutoIt.
Interestingly they are just other source files so good
tutorials also.
$version = "1.0"
$iniLocation = "torun.ini"
global $ise_ips[64],$ip_cnt
AutoItSetOption("WinDetectHiddenText",1)
$ip_cnt = 0
I use a simple file blocking mechanism
(get_xmls.blk) to prevent recursion. Notice that the
onexit call ensure that the file is removed no matter
how the program is terminated…although there is a
slight hole if you were to power cycle your PC at just
the right time (then you just need to manually delete
the file).
if fileexists("get_xmls.blk") then exit
Opt("OnExitFunc","cleanup_on_exit")
filewrite("get_xmls.blk",$version)
Now just read the ini file to figure out what IP
addresses to process, get all the xmls from them, and
we are done so clean up
read_ini()
get_all_xmls()
filedelete("get_xmls.blk")
And that is the end of the program…somewhat like
perl it just kind of ends when it doesn’t have
anything but functions following it. Of course the
program is in the functions that follow.
Func read_ini()
If (FileExists($iniLocation)) Then
$ise_ips = _getISE_IPS()
if(UBound($ise_ips) > 1) Then
If (stringlen($ise_ips[1])>0) Then
$ip_cnt=UBound($ise_ips) -1
Endif
Endif
Endif
EndFunc
Func get_all_xmls()
for $i = 1 to UBound($ise_ips) - 1
;for each IP address
get_xmls($ise_ips[$i],$i)
Next
EndFunc
The above logic is pretty self explanatory, but the
bulk of the logic follows. The get_xmls routine is
where the commandline is processed. From this it
basically figures out what it has to grab in terms of
xml data from each ISE. NOTE: get_xmls CAN be
run standalone to just go out and grab data…if you
run it without any options it will tell you what you
need to do as shown in the MsgBox below…up to
how to create the INI file if you hadn’t used stat5000
to do that for you.
Aside from some convoluted logic that was placed in
the code to ‘skip’ queries if they had previously been
done during this session, the logic in get_xmls
basically just calls GetAndSave to actually do the
getting of the XML and then the saving of it to a file.
Func get_xmls($ipstr,$iv)
DIM $path_str[1]
Local $i
Local $todo=""
$can_skip_query=0
if($CmdLine[0]==0) Then
MsgBox(0,"get_xmls - Command Line
Usage","get_xmls all - gets every xml the
program knows about"&@CRLF&"get_xmls -f
perf - gets perf xml using old
query"&@CRLF&"get_xmls perf drives - gets
perf and drive xmls"&@CRLF&@CRLF&"Options:
perf cn ps vol bat host pool ise events dp
drives net"&@CRLF&@CRLF&"NOTE: torun.ini
file controls which MRCs are
queried"&@CRLF&@CRLF&"Example
torun.ini:"&@CRLF&"[IPS]"&@CRLF&"ISE_IPS=10
.64.50.118;10.64.50.115")
exit
elseIf($CmdLine[0]==1 AND
stringinstr($CmdLine[1],"all")>0) Then
$todo=",perf,cn,ps,vol,bat,host,pool,ise,ev
ents,dp,drives,net"
Else
For $i = 1 To $CmdLine[0]
if($CmdLine[$i]=="-f") Then
$can_skip_query=1
Else
$todo&=","&$CmdLine[$i]
EndIf
Next
Endif
if($can_skip_query == 1) Then
$can_skip_query=0
if(fileexists("query_"&$ipstr&".hdr"))
Then
$query_resp=fileread("query_"&$ipstr&".hdr"
)
if(StringInStr($query_resp," 200
OK")>0) Then
$query_resp=fileread("query_"&$ipstr&".xml"
)
if(stringlen($query_resp)>30)
Then $can_skip_query=1
endif
EndIf
endif
if(NOT ($can_skip_query == 1)) Then
$query_resp =
GetAndSave($ipstr,"","/query","query")
;figure out where things are
EndIf
if(StringInStr($query_resp," 200 OK")>0
OR $can_skip_query==1) Then ;did we get
good response
$path_str=_StringBetween($query_resp,$ipstr
,'"><Status')
;figure out path
if NOT @error Then
;grab xml info and analyze it
if(StringInStr($todo,",perf"))
Then
$data_resp =
GetAndSave($ipstr,$path_str[0],"/performanc
e","perf")
if(stringlen($data_resp)<25) then return
EndIf
if(StringInStr($todo,",cn"))
Then
$data_resp =
GetAndSave($ipstr,$path_str[0],"/controller
s","mrcs")
Endif
if(StringInStr($todo,",ps"))
Then
$data_resp =
GetAndSave($ipstr,$path_str[0],"/powersuppl
ies","ps")
Endif
if(StringInStr($todo,",vol"))
Then
$data_resp =
GetAndSave($ipstr,$path_str[0],"/volumes","
vols")
Endif
if(StringInStr($todo,",bat"))
Then
$data_resp =
GetAndSave($ipstr,$path_str[0],"/batteries"
,"bats")
Endif
if(StringInStr($todo,",host"))
Then
$data_resp =
GetAndSave($ipstr,$path_str[0],"/hosts","ho
sts")
Endif
if(StringInStr($todo,",pool"))
Then
$data_resp =
GetAndSave($ipstr,$path_str[0],"/pools","po
ols")
Endif
if(StringInStr($todo,",ise"))
Then
$data_resp =
GetAndSave($ipstr,$path_str[0],"?all=yes","
ise")
if(stringlen($data_resp)<25) then
sleep(2000)
$data_resp =
GetAndSave($ipstr,$path_str[0],"?all=yes","
ise")
if(stringlen($data_resp)<25) then
sleep(4000)
$data_resp =
GetAndSave($ipstr,$path_str[0],"?all=yes","
ise")
EndIf
EndIf
Endif
if(StringInStr($todo,",event")) Then
$data_resp =
GetAndSave($ipstr,$path_str[0],"/files/even
t","events")
Endif
if(StringInStr($todo,",dp"))
Then
$data_resp =
GetAndSave($ipstr,$path_str[0],"/datapacs",
"datapacs")
Endif
if(StringInStr($todo,",drive")) Then
$data_resp =
GetAndSave($ipstr,$path_str[0],"/drives","d
rives")
Endif
if(StringInStr($todo,",net"))
Then
$data_resp =
GetAndSave($ipstr,$path_str[0],"/network","
network")
Endif
EndIf
EndIf
EndFunc
;
; Grab the text found between the 'cnt'th
occurance of string 'from' and string 'to'
in string src
; …useful for xml (case insensitive
search):
$res=_TBetween($sub,"<SerialNumber>","</Ser
ialNumber>")
;
Func _TBetween($src,$from,$to,$cnt=1)
$x=StringInStr($src,$from,0,$cnt)
if($x=0) then return "-"
$x=$x+stringlen($from)
$y=StringInStr($src,$to,0,1,$x)
if($y=0 OR $y<$x) then return "-"
Return StringMid($src,$x,$y-$x)
EndFunc
Func
GetAndSave($ipstr,$pathstr,$substr,$fname)
$ret =
GetRestData($ipstr,$pathstr&$substr)
FileDelete($fname&"_"&$ipstr&".hdr")
$y=StringInStr($ret,"<?xml")
if($y>0) Then
FileWrite($fname&"_"&$ipstr&".hdr",stringle
ft($ret,$y-1))
Else
FileWrite($fname&"_"&$ipstr&".hdr",$ret)
EndIf
if($y>0) Then
FileDelete($fname&"_"&$ipstr&".xml")
filewrite($fname&"_"&$ipstr&".xml",stringri
ght($ret,stringlen($ret)-$y+1))
EndIf
return $ret
EndFunc
Func _getISE_IPs()
$iseipString = IniRead($iniLocation,
"IPS", "ISE_IPS", "NotFound")
$iseips = stringsplit($iseipString, ";")
if $iseips == "NotFound" Then
MsgBox(0, "Exception", "Could not find
IPS Key 'ISE_IPS' in the configuration
file")
exit
EndIf
return $iseips
EndFunc
Oddly enough the logic below could be replaced by a
single line in AutoIt but then we wouldn’t get the
error checking and retry logic that is provided by this
logic. The logic below takes things down to the
lowest level you can go (i.e. essentially just
TCPConnect, TCPSend, and TCPRecv logic.
Nothing rocket science.
Func GetRestData($host,$get_what,$port=80)
Local $data = ""
Opt("TCPTimeout",200)
;
Set TCP Timeout to 200 ms
TCPStartup()
;
Initialize TCP
$ip = TCPNameToIP($host)
;
convert host name to ip if necessary
$socket = TCPConnect($ip,$port)
;
connect
if($socket == -1) Then
$data="TCPConnect Err="&@error
else
; SEND HTTP GET
$sent = TCPSend($socket,'GET
'&$get_what&' HTTP/1.1'&@CRLF&'Host:
'&$host&@CRLF&'Authorization: Basic
YWRtaW5pc3RyYXRvcjphZG1pbmlzdHJhdG9y'&@CRLF
&'Accept: */*'&@CRLF&'Connection:
close'&@CRLF&@CRLF)
if($sent==0) Then
; should be #bytes sent to socket
$data="TCPSend
Err="&@error&@CRLF
else
$begin=TimerInit()
While 1
If TimerDiff($begin)>120000
Then
_FileWriteLog("GET_XMLS.LOG","120 second
timeout waiting for TCP data from "&$host)
if($data=="") Then
$data="TCPRecv Err=120 second program
timeout"&@CRLF
ExitLoop
Endif
$data &=
TCPRecv($socket,1024) ; Recieve data
If @error Then
; are we done yet?
if($data=="") Then
; not expected ending so log
sleep(100)
$data &=
TCPRecv($socket,1024)
if @error Then
if($data=="")
Then
$data="TCPRecv Err="&@error&@CRLF
EndIf
ExitLoop
EndIf
Else
ExitLoop
EndIf
EndIf
WEnd
EndIf
EndIf
TCPCloseSocket($socket)
TCPShutdown()
return $data
EndFunc
Func cleanup_on_exit()
;Remove our busy lock since we are dying
for whatever reason
If(FileExists("get_xmls.blk")) Then
FileDelete("get_xmls.blk")
EndFunc
STAT5000.AU3:
STAT5000 uses (to an extreme) windows controls
for its GUI logic. This has a side effect of not being
able to resize the windows, but that is good because
doing so would likely hide useful data (as tightly
packed all of the information is in this display.) It
also is best used in cases like this where you have
just a single screen so you don’t spend all your time
constructing and deconstruction controls.
;STAT5000 for 5K - TRB 2/2010
;based loosely on REST5000 - TRB 1/2009
;based loosely on VIEW5000 - TRB 12/2009
;which is based loosely on SHOW5000 11/2009
;which mimics capability of SHOWALL - later
half 2009
; Description:
;
Full logic writtin in autoit to:
;
1) gather restful info (xml data) from
MRCs. Migrated this logic to get_xmls.au3.
Standard now in get_xmls.au3.
;
2) analyze xml data and present the
results to the user in view5000 format, but
optimized to show stats and perf
;
3) also make the information available
in:
;
a) raw data (xml) retrieved files of
format [type]_[ip].xml (i.e.
drives_10.10.20.30.xml)
;
4) provide polling logic to retrieve
data on a timed basis
;
5) GUI (initially) will simply be
view5000 format. Intent is something neat
to watch (and to see performance).
;
6) add logic to change polling rate
(via button cycle)
;
7) add logic to capture all data into a
csv file for each sample interval
;
8) add logic to stop/start capture
;
9) add logic to age capture data and
then start capturing to an empty file
#include <String.au3>
#include <Constants.au3>
#include <GuiConstants.au3>
#include <GuiEdit.au3>
#include <Date.au3>
#include <Timers.au3>
#include <GUIListView.au3>
#include <WinAPI.au3>
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <GUIComboBox.au3>
#include <ListViewConstants.au3>
#include
#include
#include
#include
#include
#include
<WindowsConstants.au3>
<File.au3>
<Array.au3>
<Misc.au3>
<Math.au3>
<StaticConstants.au3>
You will note that the following line is NOT in the
get_xmls source…when get_xmls.exe runs you will
see it on your lower right screen icon tray…you can
actually pause it (or kill it) in that tray if you want to.
No need for that in a GUI since the GUI is on the
screen so this line allows you to hide it from the tray.
Opt("TrayIconHide", 1)
; don't put this app icon in the tray
Global $dll = DllOpen("user32.dll")
;
; define some 'constants'
;
$VERSION = "1.0"
$INILOCATION = "torun.ini"
Global $MWIDTH=414,$MHIGH=288,$MCNT=8
;
height, width, and number of 'ise' windows
Global $DO_HOSTS=1,$DO_VOLS=0
Global $INIT=1,$REFRESH=0
Global
$MAXIOPS=10000,$MAXKBPS=200000,$MAXQD=29,$M
AXIOSZ=1024
Global $MAX_ISES=17
;
actually this is maximum ises + 1
Global $MAX_VOLS=512
;
overkill since current is 240
Global $MAX_HOSTS=256
;
overkill, but unsure of max
Global $MAX_DISKS=40
; max
disks per ise
Global $MAX_EVENTS=512
; max
events gathered
;
; Window forms and buttons
;
Global $main_form,$listview
Global
$add_input,$sample_button,$delete_button,$a
dd_button,$agecaps_button,$stopstartcaps_bu
tton
Global $hListView,$lastdd=-1
Global $hEdit, $hDC, $hBrush, $Item = -1,
$SubItem = 0
Global $Style = BitOR($WS_CHILD,
$WS_VISIBLE, $ES_AUTOHSCROLL, $ES_LEFT)
Global $iLastItem = -1, $iLastsubitemNR = 1
Global $doing_get = 0
; reentrancy check for get_xmls call
Global $cwnd
;
current window handle (used by subs)
Global $passcnt=0
; tracks
frequency of slow data gathers
Global $capture_enabled=0
; used
to start and stop csv data capturing
Global $gather_timer
;
pointer to timer handle
Global $timestart = TimerInit()
; get
timer ticking and baseline
Global $begin
; tracks
timer differentials
Global $L_NUM_BAD,$L_NUM_WARN
; color
(green/yellow/red) trackers
Dim $host_or_vol[$MAX_ISES]
; tracks
what we are looking at (host hbas or
volumes)
;
; Following is what we directly use and
retrieve via restful calls
; NOTE: not everything in this Global list
is necessarily retrieved or used by this
APP
;
; for the ISE itself
Global $ise_ips[$MAX_ISES],$ip_cnt
Global
$ise_iops,$ise_kbps,$ise_qd,$ise_readpct,$i
se_readlat,$ise_writelat,$ise_xfersize
Global
$ise_sts,$ise_detail,$ise_sn,$ise_temp,$ise
_dhcp,$ise_wol
; for the mrcs
Global
$cn1_iops,$cn1_kbps,$cn1_qd,$cn1_readpct,$c
n1_readlat,$cn1_writelat,$cn1_xfersize
Global
$cn2_iops,$cn2_kbps,$cn2_qd,$cn2_readpct,$c
n2_readlat,$cn2_writelat,$cn2_xfersize
Global
$cn1_ip,$cn1_sts,$cn1_detail,$cn1_sn,$cn1_f
wver,$cn1_temp,$cn1_fcspeed,$cn1_lipcnt,$cn
1_noscnt
Global
$cn2_ip,$cn2_sts,$cn2_detail,$cn2_sn,$cn2_f
wver,$cn2_temp,$cn2_fcspeed,$cn2_lipcnt,$cn
2_noscnt
Global $cn1_conn,$cn2_conn
; for the power supplies
Global
$ps1_sts,$ps1_detail,$ps1_sn,$ps1_temp,$ps1
_bl1_sts,$ps1_bl2_sts
Global
$ps2_sts,$ps2_detail,$ps2_sn,$ps2_temp,$ps2
_bl1_sts,$ps2_bl2_sts
; for the batteries
Global
$bat1_sts,$bat1_detail,$bat1_sn,$bat1_temp,
$bat1_charge_sts,$bat1_charge_detail,$bat1_
charge_left
Global
$bat2_sts,$bat2_detail,$bat2_sn,$bat2_temp,
$bat2_charge_sts,$bat2_charge_detail,$bat2_
charge_left
; for the datapacs
Global
$dp1_sts,$dp1_detail,$dp1_sn,$dp1_temp,$dp1
_peaktemp,$dp1_poolnum,$dp1_health,$dp1_fwv
er,$dp1_model,$dp1_sparelevel,$dp1_capacity
Global
$dp2_sts,$dp2_detail,$dp2_sn,$dp2_temp,$dp2
_peaktemp,$dp2_poolnum,$dp2_health,$dp2_fwv
er,$dp2_model,$dp2_sparelevel,$dp2_capacity
Global $dp_type,$dp_cg
; for the pools
Global
$pool1_sts,$pool1_detail,$pool1_avail,$pool
1_used,$pool1_r0,$pool1_r1,$pool1_r5
Global
$pool2_sts,$pool2_detail,$pool2_avail,$pool
2_used,$pool2_r0,$pool2_r1,$pool2_r5
Global
$r5_cnt,$r1_cnt,$r0_cnt,$numdrives[$MAX_ISE
S]
Dim
$numevent,$event_date[$MAX_EVENTS],$event_t
ime[$MAX_EVENTS],$event_desc[$MAX_EVENTS],$
event_type[$MAX_EVENTS]
; for the volumes (luns) presented to
servers
Dim
$numvol[$MAX_ISES],$vol_sts[$MAX_ISES][$MAX
_VOLS],$vol_name[$MAX_ISES][$MAX_VOLS],$vol
_policy[$MAX_ISES][$MAX_VOLS]
Dim
$vol_size[$MAX_ISES][$MAX_VOLS],$vol_locali
d[$MAX_ISES][$MAX_VOLS],$vol_level[$MAX_ISE
S][$MAX_VOLS]
Dim
$vol_gid[$MAX_ISES][$MAX_VOLS],$vol_type[$M
AX_ISES][$MAX_VOLS],$vol_mirror[$MAX_ISES][
$MAX_VOLS],$v_h[$MAX_ISES][$MAX_VOLS]
Dim $v_ss[$MAX_ISES][$MAX_VOLS],$wb_cnt
Dim
$vol_iops[$MAX_ISES][$MAX_VOLS],$vol_kbps[$
MAX_ISES][$MAX_VOLS],$vol_riops[$MAX_ISES][
$MAX_VOLS]
Dim
$vol_wiops[$MAX_ISES][$MAX_VOLS],$vol_rkbps
[$MAX_ISES][$MAX_VOLS],$vol_wkbps[$MAX_ISES
][$MAX_VOLS]
Dim
$vol_readpct[$MAX_ISES][$MAX_VOLS],$vol_avg
xfrsize[$MAX_ISES][$MAX_VOLS],$vol_qd[$MAX_
ISES][$MAX_VOLS]
Dim
$vol_readlat[$MAX_ISES][$MAX_VOLS],$vol_wri
telat[$MAX_ISES][$MAX_VOLS]
Dim
$vol_qdmax[$MAX_ISES][$MAX_VOLS],$vol_rlatm
ax[$MAX_ISES][$MAX_VOLS],$vol_wlatmax[$MAX_
ISES][$MAX_VOLS]
; for the disks themselves
Dim
$numdrive,$d_iops[$MAX_ISES][$MAX_DISKS],$d
_kbps[$MAX_ISES][$MAX_DISKS],$d_qd[$MAX_ISE
S][$MAX_DISKS]
Dim
$d_readpct[$MAX_ISES][$MAX_DISKS],$d_readla
t[$MAX_ISES][$MAX_DISKS],$d_writelat[$MAX_I
SES][$MAX_DISKS]
Dim
$d_gotit[$MAX_ISES][$MAX_DISKS],$d_sn[$MAX_
ISES][$MAX_DISKS],$d_sts[$MAX_ISES][$MAX_DI
SKS],$d_detail[$MAX_ISES][$MAX_DISKS]
Dim
$d_capacity[$MAX_ISES][$MAX_DISKS],$d_fwver
[$MAX_ISES][$MAX_DISKS],$d_prodid[$MAX_ISES
][$MAX_DISKS]
Dim
$d_temp[$MAX_ISES][$MAX_DISKS],$d_id[$MAX_I
SES][$MAX_DISKS],$d_rc[$MAX_ISES][$MAX_DISK
S]
Dim
$d_5v[$MAX_ISES][$MAX_DISKS],$d_12v[$MAX_IS
ES][$MAX_DISKS],$d_dp[$MAX_ISES][$MAX_DISKS
],$d_position[$MAX_ISES][$MAX_DISKS]
; hosts
Global
$numhosts[$MAX_ISES],$host_id[$MAX_ISES][$M
AX_HOSTS],$host_wwn[$MAX_ISES][$MAX_HOSTS],
$host_name[$MAX_ISES][$MAX_HOSTS]
Dim
$host_type[$MAX_ISES][$MAX_HOSTS],$host_iop
s[$MAX_ISES][$MAX_HOSTS],$host_kbps[$MAX_IS
ES][$MAX_HOSTS]
Dim
$host_riops[$MAX_ISES][$MAX_HOSTS],$host_wi
ops[$MAX_ISES][$MAX_HOSTS],$host_rkbps[$MAX
_ISES][$MAX_HOSTS]
Dim
$host_wkbps[$MAX_ISES][$MAX_HOSTS],$host_re
adpct[$MAX_ISES][$MAX_HOSTS],$host_avgxfrsi
ze[$MAX_ISES][$MAX_HOSTS]
Dim
$host_qd[$MAX_ISES][$MAX_HOSTS],$host_readl
at[$MAX_ISES][$MAX_HOSTS],$host_writelat[$M
AX_ISES][$MAX_HOSTS]
Dim
$host_qdmax[$MAX_ISES][$MAX_HOSTS],$host_rl
atmax[$MAX_ISES][$MAX_HOSTS],$host_wlatmax[
$MAX_ISES][$MAX_HOSTS]
; following are control tags (used to
display/hide/etc a ControlClick
Dim
$G_TOP[$MAX_ISES],$G_CN1[$MAX_ISES],$G_CN2[
$MAX_ISES],$G_DP1[$MAX_ISES],$G_DP2[$MAX_IS
ES]
Dim
$G_IO_L[$MAX_ISES],$G_IO_I[$MAX_ISES],$G_IO
_1[$MAX_ISES],$G_IO_2[$MAX_ISES]
Dim
$G_KB_L[$MAX_ISES],$G_KB_I[$MAX_ISES],$G_KB
_1[$MAX_ISES],$G_KB_2[$MAX_ISES]
Dim
$G_QD_L[$MAX_ISES],$G_QD_I[$MAX_ISES],$G_QD
_1[$MAX_ISES],$G_QD_2[$MAX_ISES]
Dim
$G_MXLAT_L[$MAX_ISES],$G_MXLAT_I[$MAX_ISES]
,$G_MXLAT_1[$MAX_ISES],$G_MXLAT_2[$MAX_ISES
]
Dim
$G_RWPCT_L[$MAX_ISES],$G_RWPCT_I[$MAX_ISES]
,$G_RWPCT_1[$MAX_ISES],$G_RWPCT_2[$MAX_ISES
]
Dim $aa[$MAX_ISES]
;ise subwindow control
tag
;yes, this actually works but minimal
checking:
InetGet("http://10.64.50.118/query","toddte
st.xml")
The above variables are a bit overkill for this
application (currently) but are included to give you
an idea of some of the other things that you can
easily gather. The following few lines actually
comprise the entire ‘mainline’ of the code..basically
just a check to make sure you have a compiled
version of get_xmls.exe and then grab whatever ISE
IP addresses we might have, setup the windows GUI
stuff and jump into the main loop.
;*********START OF PROGRAM MAIN
CODE************
If NOT fileexists("get_xmls.exe") Then
MsgBox(0,"ERROR!","FILE: get_xmls.exe
missing. You need this for Cortex
Polling!")
exit
EndIf
; Gather up the MRC IP addresses
read_ini()
window_setup("Emprise 5000 Stat Watcher,
Version "&$VERSION)
draw_cheat_sheet()
draw_ise_windows($INIT)
main_loop()
gui_exit()
;**********END OF PROGRAM MAIN
CODE**************
; ----------------------------------------------------------------------------; FUNCTIONS
; ----------------------------------------------------------------------------;
; program stays in the following loop until
user closes app
; all processing is either a result of user
mouse movement, mouse clicks, keyboard
entry,
; or timer countdowns that kick off xml
data gathering and processing (which then
induce screen updates).
;
Func main_loop()
setup_listview()
$gather_timer=_Timer_SetTimer($main_form,20
00,"_get_xmls")
_get_xmls(0,0,0,0)
GUICtrlSetState($add_input, $GUI_FOCUS)
;so that when we type an IP and press
return we get 'Add'
While 1
$nMsg = GUIGetMsg()
$pos=GUIGetCursorInfo($main_form)
;NOTE: MouseGetPos is relative to entire
screen, this is 'local'
show_tool_tip($pos)
If _IsPressed("2E", $dll) Then
_GUICtrlListView_DeleteItemsSelected($hList
View)
GUICtrlSetData($listview, "#|IP
ADDRESSES
("&_GUICtrlListView_GetItemCount($listview)
&")")
save_ini()
EndIf
Switch $nMsg
Case $GUI_EVENT_CLOSE
save_ini()
gui_exit()
Exit
case $agecaps_button
do_age_captures()
GUICtrlSetState($add_input,
$GUI_FOCUS)
case $stopstartcaps_button
do_stopstart_captures()
if $capture_enabled Then
$nextbut="Stop Capture"
GUICtrlSetColor($stopstartcaps_button,0x801
080)
Else
$nextbut="Start Capture"
GUICtrlSetColor($stopstartcaps_button,0x000
000)
Endif
GUICtrlSetData($stopstartcaps_button,$nextb
ut)
GUICtrlSetState($add_input,
$GUI_FOCUS)
case $sample_button
$var=0
$curbut=GUICtrlRead($sample_button)
if $curbut<>"Sample=off"
Then
_Timer_KillTimer($main_form,$gather_timer)
if $curbut="Sample=1hr" Then
$nextbut="Sample=off"
GUICtrlSetData($sample_button,$nextbut)
elseif $curbut="Sample=off"
Then
$nextbut="Sample=2s"
$var=2000
elseif $curbut="Sample=2s"
Then
$nextbut="Sample=10s"
$var=10000
elseif $curbut="Sample=10s"
Then
$nextbut="Sample=1m"
$var=60000
elseif $curbut="Sample=1m"
Then
$nextbut="Sample=10m"
$var=600000
elseif $curbut="Sample=10m"
Then
$nextbut="Sample=1hr"
$var=3600000
endif
if($var>0) Then
$gather_timer=_Timer_SetTimer($main_form,$v
ar,"_get_xmls")
if @error OR
$gather_timer=0 Then ContinueLoop
_get_xmls(0,0,0,0)
GUICtrlSetData($sample_button,$nextbut)
GUICtrlSetState($add_input, $GUI_FOCUS)
EndIf
Case $delete_button
_GUICtrlListView_DeleteItemsSelected($hList
View)
GUICtrlSetData($listview,
"#|IP ADDRESSES
("&_GUICtrlListView_GetItemCount($listview)
&")")
save_ini()
Case $add_button
$iptest=GUICtrlRead($add_input)
If $iptest = "" OR
StringInstr($iptest,",")<>0 OR NOT
StringRegExp($iptest,"(\d\d?\d?).(\d\d?\d?)
.(\d\d?\d?).(\d{1,})$",0) Then
MsgBox(16,"Enter a Valid
IP address","Expected input is something
like 10.64.100.101")
Else
$addnum =
_GUICtrlListView_GetItemCount($listview)
_GUICtrlListView_AddItem($hListView,
$addnum+1, 0)
_GUICtrlListView_AddSubItem($hListView,
$addnum, GUICtrlRead($add_input), 1, 1)
_GUICtrlListView_EnsureVisible($hListView,
$addnum)
GUICtrlSetData($listview, "#|IP ADDRESS:
("&_GUICtrlListView_GetItemCount($listview)
&")")
GUICtrlSetData($add_input, "")
GUICtrlSetState($add_input, $GUI_FOCUS)
save_ini()
$passcnt=0
EndIf
EndSwitch
WEnd
_Timer_KillAllTimers($main_form)
EndFunc
;
; Get xml data via restful interface and
then process it.
; NOTE: the get process calls another
autoit program called get_xmls so that we
get multi-threading
;
without the normal pain of multithreading
;
Func
_get_xmls($hWnd,$Msg,$iIDTimer,$dwTime)
if($doing_get==1) THen Return
$doing_get=1
if($ip_cnt>0) Then
if(NOT fileexists("get_xmls.blk")) Then
sleep(100)
if(NOT fileexists("get_xmls.blk"))
Then
draw_ise_windows($REFRESH)
if(mod($passcnt,300)<>0) Then
Run(@ComSpec & " /c get_xmls.exe
-f perf",@ScriptDir,@SW_HIDE)
else
Run(@ComSpec & " /c get_xmls.exe
perf ise drive",@ScriptDir,@SW_HIDE)
endif
$passcnt=$passcnt+1
Endif
Endif
EndIf
$doing_get=0
EndFunc
Func process_xmls($ipstr,$wh)
local
$inp,$logise="",$logcn1="",$logcn2="",$logd
rives=""
$inp=FileRead("perf_"&$ipstr&".xml")
if(stringlen($inp)>100) Then
$sub=_TBetween($inp,"Element
self","</Element")
if(stringlen($sub)<20) Then
$sub=_TBetween($inp,"Array self","</Array")
$ise_iops=_TBetween($sub,"<TotalIOPS>","</T
otalIOPS>")
$ise_kbps=_TBetween($sub,"<TotalKBPS>","</T
otalKBPS>")
$ise_qd=_TBetween($sub,"<QueueDepth>","</Qu
eueDepth>")
$ise_readpct=_TBetween($sub,"<ReadPercent>"
,"</ReadPercent>")
$ise_readlat=_TBetween($sub,"<ReadLatency>"
,"</ReadLatency>")
$ise_writelat=_TBetween($sub,"<WriteLatency
>","</WriteLatency>")
$ise_xfersize=_TBetween($sub,"<AvgXfrSize>"
,"</AvgXfrSize>")
$sub=_TBetween($inp,"controllers/1","</cont
roller")
$cn1_iops=_TBetween($sub,"<TotalIOPS>","</T
otalIOPS>")
$cn1_kbps=_TBetween($sub,"<TotalKBPS>","</T
otalKBPS>")
$cn1_qd=_TBetween($sub,"<QueueDepth>","</Qu
eueDepth>")
$cn1_readpct=_TBetween($sub,"<ReadPercent>"
,"</ReadPercent>")
$cn1_readlat=_TBetween($sub,"<ReadLatency>"
,"</ReadLatency>")
$cn1_writelat=_TBetween($sub,"<WriteLatency
>","</WriteLatency>")
$cn1_xfersize=_TBetween($sub,"<AvgXfrSize>"
,"</AvgXfrSize>")
$sub=_TBetween($inp,"controllers/2","</cont
roller")
$cn2_iops=_TBetween($sub,"<TotalIOPS>","</T
otalIOPS>")
$cn2_kbps=_TBetween($sub,"<TotalKBPS>","</T
otalKBPS>")
$cn2_qd=_TBetween($sub,"<QueueDepth>","</Qu
eueDepth>")
$cn2_readpct=_TBetween($sub,"<ReadPercent>"
,"</ReadPercent>")
$cn2_readlat=_TBetween($sub,"<ReadLatency>"
,"</ReadLatency>")
$cn2_writelat=_TBetween($sub,"<WriteLatency
>","</WriteLatency>")
$cn2_xfersize=_TBetween($sub,"<AvgXfrSize>"
,"</AvgXfrSize>")
$numdrive=0
for $idx=1 to 40
$sub=_TBetween($inp,"drives/"&$idx,"</drive
")
if Stringlen($sub)>20 then
$numdrive=$numdrive+1
$d_gotit[$wh][$idx-1]=1
$d_iops[$wh][$idx1]=_TBetween($sub,"<TotalIOPS>","</TotalIOP
S>")
$d_kbps[$wh][$idx1]=_TBetween($sub,"<TotalKBPS>","</TotalKBP
S>")
$d_qd[$wh][$idx1]=_TBetween($sub,"<QueueDepth>","</QueueDe
pth>")
$d_readpct[$wh][$idx1]=_TBetween($sub,"<ReadPercent>","</ReadPe
rcent>")
$d_readlat[$wh][$idx1]=_TBetween($sub,"<ReadLatency>","</ReadLa
tency>")
$d_writelat[$wh][$idx1]=_TBetween($sub,"<WriteLatency>","</Write
Latency>")
$logdrives=$logdrives&","&$d_iops[$wh][$idx
-1]&","&$d_kbps[$wh][$idx1]&","&$d_qd[$wh][$idx1]&","&$d_readpct[$wh][$idx1]&","&$d_readlat[$wh][$idx1]&","&$d_writelat[$wh][$idx-1]
else
$d_gotit[$wh][$idx-1]=0
endif
Next
$sub2=_TBetween($inp,"<volumes","</volumes"
)
$idx=0
$sub=_Tbetween($sub2,"<volume","</volume",$
idx+1)
While $sub<>"-"
$idx=$idx+1
$vol_iops[$wh][$idx1]=_TBetween($sub,"<TotalIOPS>","</TotalIOP
S>")
$vol_kbps[$wh][$idx1]=_TBetween($sub,"<TotalKBPS>","</TotalKBP
S>")
$vol_riops[$wh][$idx1]=_TBetween($sub,"<ReadIOPS>","</ReadIOPS>
")
$vol_rkbps[$wh][$idx1]=_TBetween($sub,"<ReadKBPS>","</ReadKBPS>
")
$vol_wiops[$wh][$idx1]=_TBetween($sub,"<WriteIOPS>","</WriteIOP
S>")
$vol_wkbps[$wh][$idx1]=_TBetween($sub,"<WriteKBPS>","</WriteKBP
S>")
$vol_qd[$wh][$idx1]=_TBetween($sub,"<QueueDepth>","</QueueDe
pth>")
$vol_avgxfrsize[$wh][$idx1]=_TBetween($sub,"<avgxfrsize>","</avgxfrs
ize>")
$vol_readpct[$wh][$idx1]=_TBetween($sub,"<ReadPercent>","</ReadPe
rcent>")
$vol_readlat[$wh][$idx1]=_TBetween($sub,"<ReadLatency>","</ReadLa
tency>")
$vol_writelat[$wh][$idx1]=_TBetween($sub,"<WriteLatency>","</Write
Latency>")
$vol_rlatmax[$wh][$idx1]=_TBetween($sub,"<readlatencymax>","</rea
dlatencymax>")
$vol_wlatmax[$wh][$idx1]=_TBetween($sub,"<writelatencymax>","</wr
itelatencymax>")
$vol_qdmax[$wh][$idx1]=_TBetween($sub,"<QueueDepthmax>","</Queu
eDepthmax>")
$vol_name[$wh][$idx1]=_TBetween($sub,"<name>","</name")
$sub=_Tbetween($sub2,"<volume","</volume",$
idx+1)
WEnd
$numvol[$wh]=$idx
$sub2=_TBetween($inp,"<hosts","</hosts")
$idx=0
$sub3=_TBetween($sub2,"<host","</host",$idx
+1)
While $sub3<>"-"
$h_name=_TBetween($sub3,"<name>","</name")
$tcnt=1
$sub=_TBetween($sub3,"<endpoint
","</endpoint",$tcnt)
While $sub<>"-"
$tcnt=$tcnt+1
$idx=$idx+1
$host_name[$wh][$idx-1]=$h_name
$host_wwn[$wh][$idx1]=_TBetween($sub3,"<wwn>","</wwn")
if($host_wwn[$wh][$idx-1]="-")
Then
$host_wwn[$wh][$idx1]=_TBetween($sub3,"<globalid>","</globalid
")
EndIf
$host_iops[$wh][$idx1]=_TBetween($sub,"<TotalIOPS>","</TotalIOP
S>")
$host_kbps[$wh][$idx1]=_TBetween($sub,"<TotalKBPS>","</TotalKBP
S>")
$host_riops[$wh][$idx1]=_TBetween($sub,"<ReadIOPS>","</ReadIOPS>
")
$host_rkbps[$wh][$idx1]=_TBetween($sub,"<ReadKBPS>","</ReadKBPS>
")
$host_wiops[$wh][$idx1]=_TBetween($sub,"<WriteIOPS>","</WriteIOP
S>")
$host_wkbps[$wh][$idx1]=_TBetween($sub,"<WriteKBPS>","</WriteKBP
S>")
$host_qd[$wh][$idx1]=_TBetween($sub,"<QueueDepth>","</QueueDe
pth>")
$host_avgxfrsize[$wh][$idx1]=_TBetween($sub,"<avgxfrsize>","</avgxfrs
ize>")
$host_readpct[$wh][$idx1]=_TBetween($sub,"<ReadPercent>","</ReadPe
rcent>")
$host_readlat[$wh][$idx1]=_TBetween($sub,"<ReadLatency>","</ReadLa
tency>")
$host_writelat[$wh][$idx1]=_TBetween($sub,"<WriteLatency>","</Write
Latency>")
$host_rlatmax[$wh][$idx1]=_TBetween($sub,"<readlatencymax>","</rea
dlatencymax>")
$host_wlatmax[$wh][$idx1]=_TBetween($sub,"<writelatencymax>","</wr
itelatencymax>")
$host_qdmax[$wh][$idx1]=_TBetween($sub,"<QueueDepthmax>","</Queu
eDepthmax>")
$sub=_TBetween($sub3,"<endpoint
","</endpoint",$tcnt)
WEnd
$sub3=_TBetween($sub2,"<host","</host",$idx
+1)
Wend
$numhosts[$wh]=$idx
Else
return 0
EndIf
$inp=FileRead("ise_"&$ipstr&".xml")
if(stringlen($inp)>100) Then
$ise_sts=_TBetween($inp,'
string="','"><Details value')
$ise_detail=_TBetween($inp,"<detail>","</de
tail>")
$ise_sn=_TBetween($inp,"<SerialNumber>","</
SerialNumber>")
$cn1_ip=_TBetween($inp,"<IpAddress1>","</Ip
Address1>")
$cn2_ip=_TBetween($inp,"<IpAddress2>","</Ip
Address2>")
$ise_temp=_TBetween($inp,'<Temperature
value="','"')
$sub=_TBetween($inp,"/controllers/1","</con
troller>")
$cn1_sts=_TBetween($sub,'string="','"')
$sub=_TBetween($inp,"/controllers/2","</con
troller>")
$cn2_sts=_TBetween($sub,'string="','"')
$sub=_TBetween($inp,"/datapacs/1","</datapa
c>")
if($sub=="-") Then
$sub=_TBetween($inp,"/media/1","</media>")
$dp1_sts=_TBetween($sub,'string="','"')
$sub=_TBetween($inp,"/datapacs/2","</datapa
c>")
if($sub=="-") Then
$sub=_TBetween($inp,"/media/2","</media>")
$dp2_sts=_TBetween($sub,'string="','"')
$sub=_TBetween($inp,"/powersupplies/1","</p
owersupply>")
$ps1_sts=_TBetween($sub,'string="','"')
$sub=_TBetween($inp,"/powersupplies/2","</p
owersupply>")
$ps2_sts=_TBetween($sub,'string="','"')
$sub=_TBetween($inp,"/batteries/1","</batte
ry>")
$bat1_sts=_TBetween($sub,'string="','"')
$sub=_TBetween($inp,"/batteries/2","</batte
ry>")
$bat2_sts=_TBetween($sub,'string="','"')
$logise=","&$ise_sn&","&$ise_sts&","&int(($
ise_temp*9/5)+32)&","&$ise_iops&","&$ise_kb
ps&","&$ise_qd&","& _
$ise_readlat&","&$ise_writelat&","&$ise_rea
dpct&","&$ise_xfersize
$logcn1=","&$cn1_sts&","&$cn1_iops&","&$cn1
_kbps&","&$cn1_qd&","& _
$cn1_readlat&","&$cn1_writelat&","&$cn1_rea
dpct&","&$cn1_xfersize
$logcn2=","&$cn2_sts&","&$cn2_iops&","&$cn2
_kbps&","&$cn2_qd&","& _
$cn2_readlat&","&$cn2_writelat&","&$cn2_rea
dpct&","&$cn2_xfersize
Else
return 0
endif
$inp=FileRead("query_"&$ipstr&".xml")
if(stringlen($inp)>100) Then
$ise_wwn=_TBetween($inp,'
string="','"><Details value')
$ise_date=_TBetween($inp,'date="','" ')
$ise_time=_TBetween($inp,'time="','">')
$sub=_TBetween($inp,"controllers/1","/contr
oller")
if(stringlen($sub)>100) Then
$cn1_fwver=_TBetween($inp,"<FwVersion>","</
FwVersion>")
EndIf
$sub=_TBetween($inp,"controllers/2","/contr
oller")
if(stringlen($sub)>100) Then
$cn2_fwver=_TBetween($inp,"<FwVersion>","</
FwVersion>")
EndIf
Else
return 0
endif
$inp=FileRead("drives_"&$ipstr&".xml")
$numdrives[$wh]=0
if(stringlen($inp)>100) Then
do
$sub=_TBetween($inp,"<drive
","</drive>",($numdrives[$wh]+1))
if stringlen($sub)>100 Then
$d_sts[$wh][$numdrives[$wh]]=_TBetween($sub
,'Status string="','">')
$d_sn[$wh][$numdrives[$wh]]=_TBetween($sub,
"<SerialNumber>","</SerialNumber>")
$d_fwver[$wh][$numdrives[$wh]]=_TBetween($s
ub,"<FwVersion>","</FwVersion>")
$d_dp[$wh][$numdrives[$wh]]=_TBetween($sub,
"datapacs/",'"')
if($d_dp[$wh][$numdrives[$wh]]=="-") Then
$d_dp[$wh][$numdrives[$wh]]=_TBetween($sub,
"media/",'"')
endif
if($d_sts[$wh][$numdrives[$wh]]=="Operation
al" AND $d_dp[$wh][$numdrives[$wh]]==1)
Then
$dp1_fwver=$d_fwver[$wh][$numdrives[$wh]]
if($d_sts[$wh][$numdrives[$wh]]=="Operation
al" AND $d_dp[$wh][$numdrives[$wh]]==2)
Then
$dp2_fwver=$d_fwver[$wh][$numdrives[$wh]]
$d_capacity[$wh][$numdrives[$wh]]=_TBetween
($sub,"<Capacity>","</Capacity>")
$d_temp[$wh][$numdrives[$wh]]=_TBetween($su
b,'<Temperature value="','">')
$d_5v[$wh][$numdrives[$wh]]=_TBetween($sub,
"<Range5V>","</Range5V")
$d_12v[$wh][$numdrives[$wh]]=_TBetween($sub
,"<Range12V>","</Range12V")
$d_rc[$wh][$numdrives[$wh]]=_TBetween($sub,
"<ReducedCapacity>","</ReducedCapacity>")
$d_id[$wh][$numdrives[$wh]]=_TBetween($sub,
"<Position>","</Position>")
$d_prodid[$wh][$numdrives[$wh]]=_TBetween($
sub,"<ProductId>","</ProductId>")
$d_detail[$wh][$numdrives[$wh]]=_TBetween($
sub,"<Detail>","</Detail>")
$d_position[$wh][$numdrives[$wh]]=_TBetween
($sub,"<Position>","</Position>")
$numdrives[$wh]=$numdrives[$wh]+1
Else
ExitLoop
EndIf
until $numdrives[$wh]=40
EndIf
if $capture_enabled Then
if Not
fileexists("statperf_"&$ipstr&".csv") Then
$prline="date/time,ise sn,ise
status,ise temp,iops ise,kbps ise,qd
ise,read latency ise,write latency ise,read
percent ise,xfer size ise,"& _
"status cn1,iops cn1,kbps cn1,qd
cn1,read latency cn1,write latency cn1,read
percent cn1,xfer size cn1,"& _
"status cn2,iops cn2,kbps cn2,qd
cn2,read latency cn2,write latency cn2,read
percent cn2,xfer size cn2"
for $i=1 to $numdrives[$wh]
$prline=$prline&",iops
slot"&$i&",kbps slot"&$i&",qd
slot"&$i&",read percent slot"&$i&",read
latency slot"&$i&",write latency slot"
Next
FileWriteLine("statperf_"&$ipstr&".csv",$pr
line)
Endif
;and log one sample line
FileWriteLine("statperf_"&$ipstr&".csv",'"'
&@YEAR&"/"&@MON&"/"&@MDAY&""&@HOUR&":"&@MIN&":"&@SEC&'"'&$logise&$logc
n1&$logcn2&$logdrives)
EndIf
return 1
EndFunc
;
; logic toggles state of capture and ages
captures to a depth of 8
;
Func do_stopstart_captures()
$capture_enabled=1-$capture_enabled
EndFunc
Func do_age_captures()
local $i,$j
for $i = 1 to 8
if($i<UBound($ise_ips)) Then
; first age out old stuff
if
FileExists("statperf_"&$ise_ips[$i]&".csv")
Then
for $j=8 to 1 step -1
if
FileExists("statperf_bu_"&$j&"_"&$ise_ips[$
i]&".csv") Then
FileMove("statperf_bu_"&$j&"_"&$ise_ips[$i]
&".csv","statperf_bu_"&$j+1&"_"&$ise_ips[$i
]&".csv")
EndIf
Next
FileMove("statperf_"&$ise_ips[$i]&".csv","s
tatperf_bu_1_"&$ise_ips[$i]&".csv")
EndIf
EndIf
Next
EndFunc
;
; This logic just grabs the text found
between the 'cnt'th occurance of string
'from' and string 'to' in string src
; i.e. useful for xml (case insensitive
search):
$res=_TBetween($sub,"<SerialNumber>","</Ser
ialNumber>")
;
Func _TBetween($src,$from,$to,$cnt=1)
$x=StringInStr($src,$from,0,$cnt)
if($x=0) then return "-"
$x=$x+stringlen($from)
$y=StringInStr($src,$to,0,1,$x)
if($y=0 OR $y<$x) then return "-"
Return StringMid($src,$x,$y-$x)
EndFunc
;
; Following logic reads ip addresses from
the ini file and updates the ini file based
on list box contents
;
Func _getISE_IPs()
$iseipString = IniRead($INILOCATION,
"IPS", "ISE_IPS", "NotFound")
$iseips = stringsplit($iseipString, ";")
if $iseips == "NotFound" Then
MsgBox(0, "Exception", "Could not find
IPS Key 'ISE_IPS' in the configuration
file")
exit
EndIf
return $iseips
EndFunc
Func read_ini()
$ip_cnt=0
If (FileExists($INILOCATION)) Then
$ise_ips = _getISE_IPS()
if(UBound($ise_ips) > 1) Then
If (stringlen($ise_ips[1])>0) Then
$ip_cnt=UBound($ise_ips) -1
Endif
Endif
Endif
EndFunc
Func save_ini()
$ssdata=""
for $i =1 to
_GuiCtrlListView_GetItemCount($listview)
if(stringlen(_GuiCtrlListView_GetItemText($
hListView,$i-1,1)) > 7) Then
if(stringRegExp(_GuiCtrlListView_GetItemTex
t($hListView,$i1,1),"(\d\d?\d?).(\d\d?\d?).(\d\d?\d?).(\d{
1,})$",0)) Then
if $ssdata == "" then
$ssdata = "ISE_IPS=" &
$ssdata &
_GUICtrlListView_GetItemText($hListView,$i1,1)
else
$ssdata = $ssdata & ";"
&
_GUICtrlListView_GetItemText($hListView,$i1,1)
EndIf
Endif
Endif
Next
iniWriteSection($INILOCATION,"IPS",$ssdata)
read_ini()
EndFunc
;
; and the rest of this file is screen
drawing and handling
;
Tooltips are neat and pretty easy to implement. In the
main program loop this logic is called every time
there is ANY event (so lots). Not the most efficient
approach but it gives you a nice fast tooltip feel as
you slide the mouse around the display. The logic
below will either show the tooltip or clear it so it is
designed to disappear when the mouse leaves a
region. Having a 1 second compile and try cycle
using the interactive mode of AutoIt allows you to
create this kind of code without going insane waiting
for compiles to complete to find out you are off by
one pixel or two. Both coordinate systems for the
mouse are used in this logic (one to figure out where
you are on the GUI screen and one to figure out how
to tack the tooltip on the tail of the cursor.)
Func show_tool_tip($pos)
local
$dx,$dy,$gottip,$dx,$dy,$wx,$dd,$wh_dp,$lx,
$ly,$ux,$uy,$rx,$ry,$how_many_in_dp1,$wh
$tpos=MouseGetPos()
;first figure out which screen we are in
$dx=mod(int($pos[0]/$MWIDTH),3)
$dy=mod(int($pos[1]/$MHIGH),3)
$wh=$dx+$dy*3-1
if($wh>=0 AND WinActive($main_form))
Then
; check ise info
; check mrc info
; check bat info
; check ps info
; check dp info
; check dashboard and explain
; check volumes/hosts
if $pos[0]>2+$dx*$MWIDTH AND
$pos[0]<$dx*$MWIDTH+$MWIDTH-2 AND
$pos[1]<$dy*$MHIGH+$MHIGH-104 AND
$pos[1]>$dy*$MHIGH+$MHIGH-120 Then
if $host_or_vol[$wh]=$DO_HOSTS
Then
$idx=$numhosts[$wh]
Else
$idx=$numvol[$wh]
Endif
$wx=5
for $dd=0 to $idx-1
$ttx=$dx*$MWIDTH+((int($dd/3))*$wx)+10
$tty=$dy*$MHIGH+$MHIGH119+$wx*(mod($dd,3))
if $pos[0]>=$ttx AND
$pos[0]<$ttx+5 AND $pos[1]>=$tty AND
$pos[1]<$tty+5 Then
if($host_or_vol[$wh]=$DO_HOSTS) THen
$msg=" Host
"&$dd+1&" ("&$host_name[$wh][$dd]&") via
WWN: "&$host_wwn[$wh][$dd]&@CRLF& _
@CRLF&"
Performance is "&$host_iops[$wh][$dd]&"
IOPS at "&$host_kbps[$wh][$dd]&" KB/s
("&int($host_avgxfrsize[$wh][$dd]/1024)&"
KB/IO)"&@CRLF& _
" with Qdepth of
"&$host_qd[$wh][$dd]&" and read/write
latency of
"&$host_readlat[$wh][$dd]&"/"&$host_writela
t[$wh][$dd]&" ms."
$msg2="HOSTINFO_"
$msg3="Host HBAs"
$msg4="volumes"
Else
$msg=" Volume
"&$dd+1&" ("&$vol_name[$wh][$dd]&")"&@CRLF&
_
@CRLF&"
Performance is "&$vol_iops[$wh][$dd]&" IOPS
at "&$vol_kbps[$wh][$dd]&" KB/s
("&int($vol_avgxfrsize[$wh][$dd]/1024)&"
KB/IO)"&@CRLF& _
" with Qdepth of
"&$vol_qd[$wh][$dd]&" and read/write
latency of
"&$vol_readlat[$wh][$dd]&"/"&$vol_writelat[
$wh][$dd]&" ms."
$msg2="VOLINFO_"
$msg3="volumes"
$msg4="Host HBAs"
EndIf
If _IsPressed("02",$dll)
Then
$host_or_vol[$wh]=1$host_or_vol[$wh]
ToolTip("Refreshing
Data. Please
wait",$tpos[0]+10,$tpos[1]+20,"",0,4)
draw_ise_windows($REFRESH)
endif
If(_IsPressed("01",$dll)
AND (2000<TimerDiff($begin) OR
($dd+1)<>$lastdd)) Then
$begin=TimerInit()
$lastdd=$dd+1
if(fileexists($msg2&$ise_ips[$wh+1]&"_"&$dd
+1&".txt")) Then
FileDelete($msg2&$ise_ips[$wh+1]&"_"&$dd+1&
".txt")
Endif
FileWrite($msg2&$ise_ips[$wh+1]&"_"&$dd+1&"
.txt",$msg)
Run("notepad.exe
"&$msg2&$ise_ips[$wh+1]&"_"&$dd+1&".txt",@S
criptDir)
Else
$explain=@CRLF&@CRLF&"These little dots
represent "&$msg3&" with the
color"&@CRLF&"going from dark (idle) to
light (busy)"&@CRLF&@CRLF&"To see "&$msg4&"
press right button now"
ToolTip($msg&$explain,$tpos[0]+10,$tpos[1]+
20,default,0,4)
EndIf
return
EndIf
Next
EndIf
; check pdisks
$wx=20
$how_many_in_dp1=0
for $dd=0 to $numdrives[$wh]-1
if($d_dp[$wh][$dd]==2 AND
$how_many_in_dp1==0) Then
$how_many_in_dp1=$dd
$wh_dp=$d_dp[$wh][$dd]-1
$rx=mod($d_position[$wh][$dd]1,10)
$ry=int((($d_position[$wh][$dd]$how_many_in_dp1)-1)/10)
$lx=$dx*$MWIDTH+$wh_dp*($MWIDTH/2)+($rx*$wx
)+10
$ux=$lx+13
$uy=16+$dy*$MHIGH+110+39*$ry
$ly=$uy-38
if($pos[0]>$lx AND $pos[0]<$ux
AND $pos[1]>$ly AND $pos[1]<$uy) Then
if($d_rc[$wh][$dd]==0) Then
$rcmsg="(full
capacity.)"
Else
$rcmsg="(reduced
capacity.)"
Endif
if($d_iops[$wh][$dd]==0)
Then
$avgxfer=0
Else
$avgxfer=int($d_kbps[$wh][$dd]/$d_iops[$wh]
[$dd])
EndIf
if($d_detail[$wh][$dd]=="None") Then
$showdetail=""
Else
$showdetail="("&$d_detail[$wh][$dd]&")"
endif
$msg=" Spot "&$dd+1&" (SN
"&$d_sn[$wh][$dd]&") is
"&$d_sts[$wh][$dd]&$showdetail&@CRLF& _
@CRLF&" It is a
"&StringStripWS($d_prodid[$wh][$dd],3)&"
(rev "&$d_fwver[$wh][$dd]&"),
"&$d_capacity[$wh][$dd]&"GB Disk
"&$rcmsg&@CRLF& _
@CRLF&" Temperature is
"&int((($d_temp[$wh][$dd]*9)/5)+32)&" dF,
voltages are
"&StringFormat("%.2f",$d_5v[$wh][$dd]/1000)
&" and
"&StringFormat("%.2f",$d_12v[$wh][$dd]/1000
)&" V."&@CRLF& _
@CRLF&" Performance is
"&$d_iops[$wh][$dd]&" IOPS at
"&$d_kbps[$wh][$dd]&" KB/s
("&$avgxfer&"KB/IO)"&@CRLF& _
" with Qdepth of
"&$d_qd[$wh][$dd]&" and read/write latency
of
"&$d_readlat[$wh][$dd]&"/"&$d_writelat[$wh]
[$dd]&" ms."
; apologies for the
following If statement. 01=left button,
Timerdiff lets us debounce,
;
and lastdd lets us
catch different spot within debounce
interval
If(_IsPressed("01",$dll)
AND (2000<TimerDiff($begin) OR
($dd+1)<>$lastdd)) Then
$begin=TimerInit()
$lastdd=$dd+1
if(fileexists("PDINFO_"&$ise_ips[$wh+1]&"_"
&$dd+1&".txt")) Then
FileDelete("PDINFO_"&$ise_ips[$wh+1]&"_"&$d
d+1&".txt")
Endif
FileWrite("PDINFO_"&$ise_ips[$wh+1]&"_"&$dd
+1&".txt",$msg)
Run("notepad.exe
PDINFO_"&$ise_ips[$wh+1]&"_"&$dd+1&".txt",@
ScriptDir)
Else
ToolTip($msg,$tpos[0]+10,$tpos[1]+20,defaul
t,0,4)
Endif
return
EndIf
Next
Endif
ToolTip("")
EndFunc
Func draw_cheat_sheet()
; Draw Legend
$leg=GuiCtrlCreateGraphic(1,1,$MWIDTH,$MHIG
H)
set_context($leg)
GuiCtrlCreateLabel("LEGEND",275,15,120,18)
GUICtrlCreateLabel("OK",232,40,20,18)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0x000000,0xa0f0a0)
GUICtrlSetGraphic($cwnd, $GUI_GR_ELLIPSE,
215,43,13,8)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xa0a0a0,$GUI_GR_NOBKCOLOR)
GUICtrlCreateLabel("ReducedCap",274,40,85,1
8)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0x000000,0xf0f0a0)
GUICtrlSetGraphic($cwnd, $GUI_GR_ELLIPSE,
257,43,13,8)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xa0a0a0,$GUI_GR_NOBKCOLOR)
GUICtrlCreateLabel("BAD",379,40,30,18)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0x000000,0xf0a0a0)
GUICtrlSetGraphic($cwnd, $GUI_GR_ELLIPSE,
362,43,13,8)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xa0a0a0,$GUI_GR_NOBKCOLOR)
GUICtrlCreateLabel("Idle",232,80,30,18)
draw_disk(215,90,0xa0f0a0,0x7a7a7a) ;
idle = dark
GUICtrlCreateLabel("high
io",292,80,50,18)
draw_disk(275,90,0xa0f0a0,0x8080fa) ;
high IO = blue
GUICtrlCreateLabel("high
kb",358,80,55,18)
draw_disk(340,90,0xa0f0a0,0x80fa80) ;
high KBPS = green
GUICtrlCreateLabel("high
qd+latency",232,120,105,18)
draw_disk(215,130,0xa0f0a0,0xfa80fa) ;
high QD+RLAT+WLAT = red
GUICtrlCreateLabel("Busy!",358,120,40,18)
draw_disk(340,130,0xa0f0a0,0xffffff) ;
Real Busy = whitish
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0x000000,$GUI_GR_NOBKCOLOR)
draw_line(215,145,220,145)
draw_line(215,148,222,148)
draw_line(215,151,225,151)
GUICtrlCreateLabel("qd+lat over iops over
kbps",235,140,170,20)
GUICtrlCreateLabel("Mouse around for more
info",220,200,190,20)
GUICtrlCreateLabel("ISE",240,170,30,18)
GUICtrlCreateLabel("MRC1",300,170,40,18)
GUICtrlCreateLabel("MRC2",370,170,40,18)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xc060c0, 0xc060c0)
GUICtrlSetGraphic($cwnd, $GUI_GR_PIE,
235,182,20,180,-40)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xc0a050, 0xc0a050)
GUICtrlSetGraphic($cwnd, $GUI_GR_PIE,
295,182,20,180,-40)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xa0c060, 0xa0c060)
GUICtrlSetGraphic($cwnd, $GUI_GR_PIE,
365,182,20,180,-40)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xc060c0,$GUI_GR_NOBKCOLOR)
EndFunc
Func draw_line($sx,$sy,$tx,$ty)
GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE,
$sx, $sy)
; start point
GUICtrlSetGraphic($cwnd, $GUI_GR_LINE,
$tx, $ty)
EndFunc
Func draw_led($sts,$xx,$yy)
$retc=set_warning_color($sts)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0x000000,$retc)
GUICtrlSetGraphic($cwnd,
$GUI_GR_ELLIPSE, $xx, $yy,13,13)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xa0a0a0,$GUI_GR_NOBKCOLOR)
GuiCtrlSetDefColor(0x000000)
EndFunc
Func draw_filled($sx,$sy,$dx,$dy,$clr)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
$clr,$clr)
GUICtrlSetGraphic($cwnd, $GUI_GR_RECT,
$sx,$sy,$dx,$dy)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xa0a0a0,$GUI_GR_NOBKCOLOR)
GuiCtrlSetDefColor(0x000000)
EndFunc
This logic seems to be the favorite of the storage
geeks (along with pegging the IOPS and KBPS
meters). Keep in mind that busy is good as long as
busy doesn’t mean excessive latency at the server
level. Virtualized storage tends to run full tilt
whenever possible so that more bandwidth and lower
latency is available when it is needed (i.e. speed is
good.)
Func draw_drives($wh)
$wx=20
$how_many_in_dp1=0
for $dd=0 to $numdrives[$wh]-1
if($d_dp[$wh][$dd]==2 AND
$how_many_in_dp1==0) Then
$how_many_in_dp1=$dd
if($d_sts[$wh][$dd]=="Operational")
Then
$rc=0xa0f0a0
;green (OK)
if($d_rc[$wh][$dd]<>0) then
$rc=0xf0f0a0
;yellow (warning)
Else
$rc=0xf0a0a0
EndIf
$ti=$d_iops[$wh][$dd]
if($ti>500) then $ti=500
$ti=int($ti*128/500)
$tk=$d_kbps[$wh][$dd]
if($tk>30000) then $tk=30000
$tk=int($tk*128/30000)
$tq=$d_qd[$wh][$dd]+$d_readlat[$wh][$dd]/2+
$d_writelat[$wh][$dd]/2
if($tq>100) then $tq=100
$tq=int($tq*128/100)
$bc=0x7a7a7a+int($tq)*0x010000+int($tk)*0x0
100+int($ti)*0x01
$wh_dp=$d_dp[$wh][$dd]-1
$rx=mod($d_position[$wh][$dd]-1,10)
$ry=int((($d_position[$wh][$dd]$how_many_in_dp1)-1)/10)
draw_disk($wh_dp*($MWIDTH/2)+($rx*$wx)+10,1
10+39*$ry,$rc,$bc)
$tq=$tq*13/128
$ti=$ti*13/128
$tk=$tk*13/128
$ttx=$wh_dp*($MWIDTH/2)+($rx*$wx)+10
$tty=110+39*$ry+8
GUICtrlSetGraphic($cwnd,
$GUI_GR_COLOR, 0x000000,$GUI_GR_NOBKCOLOR)
draw_line($ttx,$tty,$ttx+int($tq),$tty)
draw_line($ttx,$tty+3,$ttx+int($ti),$tty+3)
draw_line($ttx,$tty+6,$ttx+int($tk),$tty+6)
next
EndFunc
The following is the late addition to the display.
Graphically it doesn’t feel right yet but it works and
gives you a wealth of info that you don’t normally
want to have to burrow down for in subwindows.
This will make more sense if you have one server
that is really busy.
Func draw_hosts_or_vols($wh)
$wx=5
$choice=$host_or_vol[$wh]
if($choice=$DO_HOSTS) Then
$idx=$numhosts[$wh]
Else
$idx=$numvol[$wh]
Endif
GUICtrlSetGraphic($aa[$wh],
$GUI_GR_COLOR, 0xf0f0f0, 0xf0f0f0)
GUICtrlSetGraphic($aa[$wh],
$GUI_GR_RECT, 3,$MHIGH-119,$MWIDTH-6,15)
for $dd=0 to $idx-1
If($choice=$DO_HOSTS) Then
$ti=$host_iops[$wh][$dd]
$tk=$host_kbps[$wh][$dd]
$tq=$host_qd[$wh][$dd]+$host_readlat[$wh][$
dd]/2+$host_writelat[$wh][$dd]/2
Else
$ti=$vol_iops[$wh][$dd]
$tk=$vol_kbps[$wh][$dd]
$tq=$vol_qd[$wh][$dd]+$vol_readlat[$wh][$dd
]/2+$vol_writelat[$wh][$dd]/2
Endif
if($ti>5000) then $ti=5000
$ti=int($ti*128/5000)
if($tk>30000) then $tk=30000
$tk=int($tk*128/30000)
if($tq>100) then $tq=100
$tq=int($tq*128/100)
$bc=0x7a7a7a+int($tq)*0x010000+int($tk)*0x0
100+int($ti)*0x01
$ttx=((int($dd/3))*$wx)+10
$tty=$MHIGH-119+$wx*(mod($dd,3))
GUICtrlSetGraphic($aa[$wh],
$GUI_GR_COLOR, $bc,$GUI_GR_NOBKCOLOR)
$tcw=$cwnd
$cwnd=$aa[$wh]
draw_line($ttx,$tty,$ttx+3,$tty)
draw_line($ttx,$tty+1,$ttx+3,$tty+1)
draw_line($ttx,$tty+2,$ttx+3,$tty+2)
draw_line($ttx,$tty+3,$ttx+3,$tty+3)
$cwnd=$tcw
GUICtrlSetGraphic($aa[$wh],
$GUI_GR_COLOR, 0x000000,$GUI_GR_NOBKCOLOR)
next
EndFunc
This is the dashboard logic. Basically brute force
coding, with some trips down memory lane
remembering how to intersect an arc with a
line…and then properly rotating the coordinate
system.
Func
drawcat($dx,$dy,$ise_iops,$cn1_iops,$cn2_io
ps,$ise_kbps,$cn1_kbps,$cn2_kbps,$cn1_qd,$c
n2_qd,$cn1_readlat,$cn2_readlat,$cn1_writel
at,$cn2_writelat)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0x505050,$GUI_GR_NOBKCOLOR)
GUICtrlSetGraphic($cwnd,
$GUI_GR_ELLIPSE, 8,$MHIGH-96,30,30)
GUICtrlSetGraphic($cwnd, $GUI_GR_PIE,
95,$MHIGH-23,70,90,90)
GUICtrlSetGraphic($cwnd, $GUI_GR_RECT,
100,$MHIGH-93,17,70)
GUICtrlSetGraphic($cwnd, $GUI_GR_PIE,
120,$MHIGH-23,70,0,90)
GUICtrlSetGraphic($cwnd,
$GUI_GR_ELLIPSE,180,$MHIGH-96,30,30)
; now calculate the eye size for
qdepths (full size eye for qdepth>=30)
$t=$cn2_qd
if($t>$MAXQD) then $t=$MAXQD
$t=int(($t*29/$MAXQD)+.5)
if($t>0) Then
$rc=0x909090
if($t>5) then $rc=0xa0a0b0
if($t>10) then $rc=0xe0e070
if($t>20) then $rc=0xe08080
GUICtrlSetGraphic($cwnd,
$GUI_GR_COLOR, $rc,$rc)
GUICtrlSetGraphic($cwnd,
$GUI_GR_ELLIPSE, 180+15-($t+1)/2,$MHIGH96+15-($t+1)/2,$t,$t)
EndIf
$t=$cn1_qd
if($t>$MAXQD) then $t=$MAXQD
$t=int(($t*29/$MAXQD)+.5)
if($t>0) Then
$rc=0x909090
if($t>5) then $rc=0xa0a0b0
if($t>10) then $rc=0xe0e080
if($t>20) then $rc=0xe08080
GUICtrlSetGraphic($cwnd,
$GUI_GR_COLOR, $rc,$rc)
GUICtrlSetGraphic($cwnd,
$GUI_GR_ELLIPSE, 8+15-($t+1)/2,$MHIGH96+15-($t+1)/2,$t,$t)
EndIf
; now for the tach (IOPS)
GUICtrlSetGraphic($cwnd,$GUI_GR_PENSIZE,2)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xc060c0,$GUI_GR_NOBKCOLOR)
$t=$ise_iops
if($t>$MAXIOPS) then $t=$MAXIOPS
$t=90-int($t*90/$MAXIOPS)
GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE,
95,$MHIGH-23)
GUICtrlSetGraphic($cwnd, $GUI_GR_LINE,
95(76*(sin((($t*3.14159265358979))/180))),$MH
IGH-23(75*(cos((($t*3.14159265358979)/180)))))
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xc0a050,$GUI_GR_NOBKCOLOR)
$t1=$cn1_iops
if($t1>$MAXIOPS) then $t1=$MAXIOPS
$t1=90-int($t1*90/$MAXIOPS)
GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE,
95,$MHIGH-23)
GUICtrlSetGraphic($cwnd, $GUI_GR_LINE,
95(74*(sin((($t1*3.14159265358979))/180))),$M
HIGH-23(75*(cos((($t1*3.14159265358979)/180)))))
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xa0c060,$GUI_GR_NOBKCOLOR)
$t2=$cn2_iops
if($t2>$MAXIOPS) then $t2=$MAXIOPS
$t2=90-int($t2*90/$MAXIOPS)
GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE,
95,$MHIGH-23)
GUICtrlSetGraphic($cwnd, $GUI_GR_LINE,
95(72*(sin((($t2*3.14159265358979))/180))),$M
HIGH-23(75*(cos((($t2*3.14159265358979)/180)))))
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xc060c0, 0xc060c0)
GUICtrlSetGraphic($cwnd, $GUI_GR_PIE,
95,$MHIGH-23,60,180,-(90-$t))
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xc0a050, 0xc0a050)
GUICtrlSetGraphic($cwnd, $GUI_GR_PIE,
95,$MHIGH-23,50,180,-(90-$t1))
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xa0c060, 0xa0c060)
GUICtrlSetGraphic($cwnd, $GUI_GR_PIE,
95,$MHIGH-23,40,180,-(90-$t2))
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xc060c0,$GUI_GR_NOBKCOLOR)
; now for the speed (KBPS)
$t=$ise_kbps
if($t>$MAXKBPS) then $t=$MAXKBPS
$t=90-int($t*90/$MAXKBPS)
GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE,
120,$MHIGH-23)
GUICtrlSetGraphic($cwnd, $GUI_GR_LINE,
120+(76*(sin((($t*3.14159265358979))/180)))
,$MHIGH-23(75*(cos((($t*3.14159265358979)/180)))))
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xc0a050,$GUI_GR_NOBKCOLOR)
$t1=$cn1_kbps
if($t1>$MAXKBPS) then $t1=$MAXKBPS
$t1=90-int($t1*90/$MAXKBPS)
GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE,
120,$MHIGH-23)
GUICtrlSetGraphic($cwnd, $GUI_GR_LINE,
120+(74*(sin((($t1*3.14159265358979))/180))
),$MHIGH-23(75*(cos((($t1*3.14159265358979)/180)))))
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xa0c060,$GUI_GR_NOBKCOLOR)
$t2=$cn2_kbps
if($t2>$MAXKBPS) then $t2=$MAXKBPS
$t2=90-int($t2*90/$MAXKBPS)
GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE,
120,$MHIGH-23)
GUICtrlSetGraphic($cwnd, $GUI_GR_LINE,
120+(72*(sin((($t2*3.14159265358979))/180))
),$MHIGH-23(75*(cos((($t2*3.14159265358979)/180)))))
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xc060c0, 0xc060c0)
GUICtrlSetGraphic($cwnd, $GUI_GR_PIE,
120,$MHIGH-23,60,0,(90-$t))
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xc0a050, 0xc0a050)
GUICtrlSetGraphic($cwnd, $GUI_GR_PIE,
120,$MHIGH-23,50,0,(90-$t1))
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xa0c060, 0xa0c060)
GUICtrlSetGraphic($cwnd, $GUI_GR_PIE,
120,$MHIGH-23,40,0,(90-$t2))
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xc060c0,$GUI_GR_NOBKCOLOR)
; now for the gear (io size)
if($ise_iops==0) Then
$t=0
Else
$t=$ise_kbps/$ise_iops
EndIf
if($t>$MAXIOSZ) then $t=$MAXIOSZ
$t=70-int($t*70/$MAXIOSZ)
GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE,
97, $MHIGH-93+$t)
GUICtrlSetGraphic($cwnd, $GUI_GR_LINE,
118, $MHIGH-93+$t)
GUICtrlSetGraphic($cwnd,$GUI_GR_PENSIZE,1)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xc060c0,0xc060c0)
GUICtrlSetGraphic($cwnd, $GUI_GR_RECT,
101,$MHIGH-93+$t,15,70-$t)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xa0a0a0,$GUI_GR_NOBKCOLOR)
EndFunc
Func set_context($wnd)
$cwnd=$wnd
EndFunc
Func draw_disk($x,$y,$topc,$bodyc)
; normalize the rgb values down by 3
bits per color...this reduces the number of
GDI Objects
; used by the system by a factor of
8x8x8. NOTE: drawing EVERY color will
eventually use up all memory
$redc=int($bodyc/0x10000)
$greenc=mod(int($bodyc/0x100),0x100)
$bluec=mod($bodyc,0x100)
$redc=int($redc/8)*8
$greenc=int($greenc/8)*8
$bluec=int($bluec/8)*8
$bodyc=$bluec+($greenc*0x100)+($redc*0x1000
0)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
$bodyc,$bodyc)
GUICtrlSetGraphic($cwnd,
$GUI_GR_ELLIPSE, $x,$y-2,13,8)
GUICtrlSetGraphic($cwnd, $GUI_GR_RECT,
$x,$y-16,13,18)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0x000000,$topc)
GUICtrlSetGraphic($cwnd,
$GUI_GR_ELLIPSE, $x,$y-18,13,8)
GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR,
0xa0a0a0,$GUI_GR_NOBKCOLOR)
Endfunc
And this is the paint logic for all the ISE sub
windows. Just brute force logic that works off of data
variables in memory at the time.
Func draw_ise_windows($how)
$dy=0
$dx=1
;beep(500,150)
GUISetState(@SW_LOCK,$main_form)
for $i = 0 to 7
$L_NUM_BAD=0
$L_NUM_WARN=0
$need_erase=0
if($how=$REFRESH) Then
GuiCtrlDelete($aa[$i])
Else
GUICtrlCreateLabel("MRC1",
20+$MWIDTH*$dx, 32+$MHIGH*$dy, 50,16)
GUICtrlCreateLabel("MRC2",
20+$MWIDTH/2+$MWIDTH*$dx, 32+$MHIGH*$dy,
50,16)
GUICtrlCreateLabel("DP1",
20+$MWIDTH*$dx, 68+$MHIGH*$dy, 50,16)
GUICtrlCreateLabel("DP2",
20+$MWIDTH/2+$MWIDTH*$dx, 68+$MHIGH*$dy,
50,16)
GUICtrlCreateLabel("BAT1",
20+$MWIDTH*$dx, 50+$MHIGH*$dy, 50,16)
GUICtrlCreateLabel("BAT2",
120+$MWIDTH*$dx, 50+$MHIGH*$dy, 50,16)
GUICtrlCreateLabel("PS1",
20+$MWIDTH/2+$MWIDTH*$dx, 50+$MHIGH*$dy,
50,16)
GUICtrlCreateLabel("PS2",
120+$MWIDTH/2+$MWIDTH*$dx, 50+$MHIGH*$dy,
50,16)
GUICtrlCreateLabel("Q1",
5+$MWIDTH*$dx, $MHIGH-21+$MHIGH*$dy, 50,16)
GUICtrlCreateLabel("IOPS",45+$MWIDTH*$dx,
$MHIGH-21+$MHIGH*$dy, 50,16)
GUICtrlCreateLabel("SZ",
100+$MWIDTH*$dx, $MHIGH-21+$MHIGH*$dy,
50,16)
GUICtrlCreateLabel("KBPS",140+$MWIDTH*$dx,
$MHIGH-21+$MHIGH*$dy, 50,16)
GUICtrlCreateLabel("Q2",190+$MWIDTH*$dx,
$MHIGH-21+$MHIGH*$dy, 30,16)
EndIf
$aa[$i]=GuiCtrlCreateGraphic($MWIDTH*$dx,$M
HIGH*$dy,$MWIDTH,$MHIGH)
set_context($aa[$i])
if($i<UBound($ise_ips)-1) Then
if(process_xmls($ise_ips[$i+1],$i)=1) Then
GUICtrlSetDefColor(0x000000)
GUICtrlSetBkColor($aa[$i],
$GUI_BKCOLOR_TRANSPARENT)
draw_line(16+$MWIDTH/2,$MHIGH104,16+$MWIDTH/2,$MHIGH-4)
draw_line(2,$MHIGH-120,$MWIDTH2,$MHIGH-120)
draw_line(16+$MWIDTH/2,$MHIGH84,$MWIDTH-3,$MHIGH-84)
draw_line(16+$MWIDTH/2,$MHIGH64,$MWIDTH-3,$MHIGH-64)
draw_line(16+$MWIDTH/2,$MHIGH44,$MWIDTH-3,$MHIGH-44)
draw_line(16+$MWIDTH/2,$MHIGH24,$MWIDTH-3,$MHIGH-24)
If($how==$INIT) Then
$G_QD_L[$i]=
GuiCtrlCreateLabel("QD",20+$MWIDTH/2+$MWIDT
H*$dx,$MHIGH-101+$MHIGH*$dy,40,16)
$G_IO_L[$i]=
GuiCtrlCreateLabel("IO/s",20+$MWIDTH/2+$MWI
DTH*$dx,$MHIGH-81+$MHIGH*$dy,40,16)
$G_KB_L[$i]=
GuiCtrlCreateLabel("KB/s",20+$MWIDTH/2+$MWI
DTH*$dx,$MHIGH-61+$MHIGH*$dy,40,16)
$G_RWPCT_L[$i]=
GuiCtrlCreateLabel("RD%",20+$MWIDTH/2+$MWID
TH*$dx,$MHIGH-41+$MHIGH*$dy,40,16)
$G_MXLAT_L[$i]=
GuiCtrlCreateLabel("MaxL",20+$MWIDTH/2+$MWI
DTH*$dx,$MHIGH-21+$MHIGH*$dy,40,16)
GUICtrlSetDefColor(0x801080)
$G_QD_I[$i]=
GuiCtrlCreateLabel($ise_qd,40+20+$MWIDTH/2+
$MWIDTH*$dx,$MHIGH-101+$MHIGH*$dy,48,16)
$G_IO_I[$i]=
GuiCtrlCreateLabel($ise_iops,40+20+$MWIDTH/
2+$MWIDTH*$dx,$MHIGH-81+$MHIGH*$dy,48,16)
$G_KB_I[$i]=
GuiCtrlCreateLabel($ise_kbps,40+20+$MWIDTH/
2+$MWIDTH*$dx,$MHIGH-61+$MHIGH*$dy,48,16)
$G_RWPCT_I[$i]=
GuiCtrlCreateLabel($ise_readpct,40+20+$MWID
TH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,48,16)
$G_MXLAT_I[$i]=
GuiCtrlCreateLabel(_Max(Number($ise_readlat
),Number($ise_writelat)),40+20+$MWIDTH/2+$M
WIDTH*$dx,$MHIGH-21+$MHIGH*$dy,48,16)
GUICtrlSetDefColor(0x807010)
$G_QD_1[$i]=
GuiCtrlCreateLabel($cn1_qd,88+20+$MWIDTH/2+
$MWIDTH*$dx,$MHIGH-101+$MHIGH*$dy,47,16)
$G_IO_1[$i]=
GuiCtrlCreateLabel($cn1_iops,88+20+$MWIDTH/
2+$MWIDTH*$dx,$MHIGH-81+$MHIGH*$dy,47,16)
$G_KB_1[$i]=
GuiCtrlCreateLabel($cn1_kbps,88+20+$MWIDTH/
2+$MWIDTH*$dx,$MHIGH-61+$MHIGH*$dy,47,16)
$G_RWPCT_1[$i]=
GuiCtrlCreateLabel($cn1_readpct,88+20+$MWID
TH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,47,16)
$G_MXLAT_1[$i]=
GuiCtrlCreateLabel(_Max(Number($cn1_readlat
),Number($cn1_writelat)),88+20+$MWIDTH/2+$M
WIDTH*$dx,$MHIGH-21+$MHIGH*$dy,47,16)
GUICtrlSetDefColor(0x507010)
$G_QD_2[$i]=
GuiCtrlCreateLabel($cn2_qd,135+20+$MWIDTH/2
+$MWIDTH*$dx,$MHIGH-101+$MHIGH*$dy,45,16)
$G_IO_2[$i]=
GuiCtrlCreateLabel($cn2_iops,135+20+$MWIDTH
/2+$MWIDTH*$dx,$MHIGH-81+$MHIGH*$dy,45,16)
$G_KB_2[$i]=
GuiCtrlCreateLabel($cn2_kbps,135+20+$MWIDTH
/2+$MWIDTH*$dx,$MHIGH-61+$MHIGH*$dy,45,16)
$G_RWPCT_2[$i]=
GuiCtrlCreateLabel($cn2_readpct,135+20+$MWI
DTH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,45,16)
$G_MXLAT_2[$i]=
GuiCtrlCreateLabel(_Max(Number($cn2_readlat
),Number($cn2_writelat)),135+20+$MWIDTH/2+$
MWIDTH*$dx,$MHIGH-21+$MHIGH*$dy,43,16)
GUICtrlSetDefColor(0x000000)
$G_TOP[$i]=GUICtrlCreateLabel("ISE
(SN="&$ise_sn&")
IP(s)="&$cn1_ip&"/"&$cn2_ip,
20+$MWIDTH*$dx, 8+$MHIGH*$dy, $MWIDTH-70,
16)
$G_CN1[$i]=GUICtrlCreateLabel("(FW="&$cn1_f
wver&")", 60+$MWIDTH*$dx, 32+$MHIGH*$dy,
$MWIDTH/2-100,16)
$G_CN2[$i]=GUICtrlCreateLabel("(FW="&$cn2_f
wver&")", 60+$MWIDTH/2+$MWIDTH*$dx,
32+$MHIGH*$dy, $MWIDTH/2-100,16)
$G_DP1[$i]=GUICtrlCreateLabel("(FW="&$dp1_f
wver&")", 60+$MWIDTH*$dx, 68+$MHIGH*$dy,
$MWIDTH/2-80,16)
$G_DP2[$i]=GUICtrlCreateLabel("(FW="&$dp2_f
wver&")", 60+$MWIDTH/2+$MWIDTH*$dx,
68+$MHIGH*$dy, $MWIDTH/2-80,16)
Else
GuiCtrlSetData($G_QD_L[$i],"QD")
GUICtrlSetData($G_IO_L[$i],
"IO/s")
GUICtrlSetData($G_KB_L[$i],
"KB/s")
GUICtrlSetData($G_RWPCT_L[$i],
"RD%")
GUICtrlSetData($G_MXLAT_L[$i],
"MaxL")
GUICtrlSetDefColor(0x801080)
GuiCtrlSetData($G_QD_I[$i],
$ise_qd)
GUICtrlSetData($G_IO_I[$i],
$ise_iops)
GUICtrlSetData($G_KB_I[$i],
$ise_kbps)
GUICtrlSetData($G_RWPCT_I[$i],
$ise_readpct)
GUICtrlSetData($G_MXLAT_I[$i],
_Max(Number($ise_readlat),Number($ise_write
lat)))
GUICtrlSetDefColor(0x807010)
GUICtrlSetData($G_QD_1[$i],
$cn1_qd)
GUICtrlSetData($G_IO_1[$i],
$cn1_iops)
GUICtrlSetData($G_KB_1[$i],
$cn1_kbps)
GUICtrlSetData($G_RWPCT_1[$i],
$cn1_readpct)
GUICtrlSetData($G_MXLAT_1[$i],
_Max(Number($cn1_readlat),Number($cn1_write
lat)))
GUICtrlSetDefColor(0x507010)
GUICtrlSetData($G_QD_2[$i],
$cn2_qd)
GUICtrlSetData($G_IO_2[$i],
$cn2_iops)
GUICtrlSetData($G_KB_2[$i],
$cn2_kbps)
GUICtrlSetData($G_RWPCT_2[$i],
$cn2_readpct)
GUICtrlSetData($G_MXLAT_2[$i],
_Max(Number($cn2_readlat),Number($cn2_write
lat)))
GUICtrlSetDefColor(0x000000)
GUICtrlSetData($G_TOP[$i],"ISE
(SN="&$ise_sn&")
IP(s)="&$cn1_ip&"/"&$cn2_ip)
GUICtrlSetData($G_CN1[$i],"(FW="&$cn1_fwver
&")")
GUICtrlSetData($G_CN2[$i],"(FW="&$cn2_fwver
&")")
GUICtrlSetData($G_DP1[$i],"(FW="&$dp1_fwver
&")")
GUICtrlSetData($G_DP2[$i],"(FW="&$dp2_fwver
&")")
EndIf
draw_led($ise_sts,3,10)
draw_led($cn1_sts, 3,33)
draw_led($cn2_sts,
$MWIDTH/2+3,33)
draw_led($dp1_sts, 3,69)
draw_led($dp2_sts,
$MWIDTH/2+3,69)
draw_led($bat1_sts, 3,52)
draw_led($ps1_sts,
$MWIDTH/2+3,52)
draw_led($bat2_sts,
$MWIDTH/4+3,52)
draw_led($ps2_sts,
$MWIDTH/2+$MWIDTH/4+3,52)
draw_drives($i)
draw_hosts_or_vols($i)
drawcat($dx,$dy,$ise_iops,$cn1_iops,$cn2_io
ps,$ise_kbps,$cn1_kbps,$cn2_kbps,$cn1_qd,$c
n2_qd,$cn1_readlat,$cn2_readlat,$cn1_writel
at,$cn2_writelat)
GUICtrlSetDefColor(0x000000)
else
If($how==$INIT) Then
$G_TOP[$i]=GUICtrlCreateLabel("Requesting
data from IP: "&$ise_ips[$i+1],
20+$MWIDTH*$dx, 8+$MHIGH*$dy, $MWIDTH-70,
16)
Else
GUICtrlSetData($G_TOP[$i],"Requesting data
from IP: "&$ise_ips[$i+1])
EndIf
$need_erase=1
$L_NUM_WARN=1
endif
Else
If($how==$INIT) Then
$G_TOP[$i]=GUICtrlCreateLabel("
", 20+$MWIDTH*$dx, 8+$MHIGH*$dy, $MWIDTH70, 16)
Else
GUICtrlSetData($G_TOP[$i]," ")
EndIf
$need_erase=1
EndIf
if($need_erase==1) Then
If($how==$INIT) Then
$G_CN1[$i]=GUICtrlCreateLabel("
", 60+$MWIDTH*$dx, 32+$MHIGH*$dy,
$MWIDTH/2-85,16)
$G_CN2[$i]=GUICtrlCreateLabel("
", 70+$MWIDTH/2+$MWIDTH*$dx, 32+$MHIGH*$dy,
$MWIDTH/2-85,16)
$G_DP1[$i]=GUICtrlCreateLabel("
", 60+$MWIDTH*$dx, 68+$MHIGH*$dy,
$MWIDTH/2-85,16)
$G_DP2[$i]=GUICtrlCreateLabel("
", 70+$MWIDTH/2+$MWIDTH*$dx, 68+$MHIGH*$dy,
$MWIDTH/2-85,16)
$G_QD_L[$i]=
GuiCtrlCreateLabel("
",20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH101+$MHIGH*$dy,40,16)
$G_IO_L[$i]=
GuiCtrlCreateLabel("
",20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH81+$MHIGH*$dy,40,16)
$G_KB_L[$i]=
GuiCtrlCreateLabel("
",20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH61+$MHIGH*$dy,40,16)
$G_RWPCT_L[$i]=
GuiCtrlCreateLabel("
",20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,40,16)
$G_MXLAT_L[$i]=
GuiCtrlCreateLabel("
",20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH21+$MHIGH*$dy,40,16)
GUICtrlSetDefColor(0x801080)
$G_QD_I[$i]=
GuiCtrlCreateLabel("
",40+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH101+$MHIGH*$dy,48,16)
$G_IO_I[$i]=
GuiCtrlCreateLabel("
",40+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH81+$MHIGH*$dy,48,16)
$G_KB_I[$i]=
GuiCtrlCreateLabel("
",40+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH61+$MHIGH*$dy,48,16)
$G_RWPCT_I[$i]=
GuiCtrlCreateLabel("
",40+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,48,16)
$G_MXLAT_I[$i]=
GuiCtrlCreateLabel("
",40+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH21+$MHIGH*$dy,48,16)
GUICtrlSetDefColor(0x807010)
$G_QD_1[$i]=
GuiCtrlCreateLabel("
",88+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH101+$MHIGH*$dy,47,16)
$G_IO_1[$i]=
GuiCtrlCreateLabel("
",88+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH81+$MHIGH*$dy,47,16)
$G_KB_1[$i]=
GuiCtrlCreateLabel("
",88+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH61+$MHIGH*$dy,47,16)
$G_RWPCT_1[$i]=
GuiCtrlCreateLabel("
",88+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,47,16)
$G_MXLAT_1[$i]=
GuiCtrlCreateLabel("
",88+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH21+$MHIGH*$dy,47,16)
GUICtrlSetDefColor(0x507010)
$G_QD_2[$i]=
GuiCtrlCreateLabel("
",135+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH101+$MHIGH*$dy,45,16)
$G_IO_2[$i]=
GuiCtrlCreateLabel("
",135+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH81+$MHIGH*$dy,45,16)
$G_KB_2[$i]=
GuiCtrlCreateLabel("
",135+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH61+$MHIGH*$dy,45,16)
$G_RWPCT_2[$i]=
GuiCtrlCreateLabel("
",135+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,45,16)
$G_MXLAT_2[$i]=
GuiCtrlCreateLabel("
",135+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH21+$MHIGH*$dy,43,16)
GUICtrlSetDefColor(0x000000)
Else
GUICtrlSetData($G_CN1[$i]," ")
GUICtrlSetData($G_CN2[$i]," ")
GUICtrlSetData($G_DP1[$i]," ")
GUICtrlSetData($G_DP2[$i]," ")
GUICtrlSetData($G_QD_L[$i], " ")
GUICtrlSetData($G_QD_I[$i], " ")
GUICtrlSetData($G_QD_1[$i], " ")
GUICtrlSetData($G_QD_2[$i], " ")
GUICtrlSetData($G_IO_L[$i], " ")
GUICtrlSetData($G_IO_I[$i], " ")
GUICtrlSetData($G_IO_1[$i], " ")
GUICtrlSetData($G_IO_2[$i], " ")
GUICtrlSetData($G_KB_L[$i], " ")
GUICtrlSetData($G_KB_I[$i], " ")
GUICtrlSetData($G_KB_1[$i], " ")
GUICtrlSetData($G_KB_2[$i], " ")
GUICtrlSetData($G_RWPCT_L[$i], "
")
GUICtrlSetData($G_RWPCT_I[$i], "
")
GUICtrlSetData($G_RWPCT_1[$i], "
")
GUICtrlSetData($G_RWPCT_2[$i], "
")
GUICtrlSetData($G_MXLAT_L[$i], "
")
GUICtrlSetData($G_MXLAT_I[$i], "
")
GUICtrlSetData($G_MXLAT_1[$i], "
")
GUICtrlSetData($G_MXLAT_2[$i], "
")
EndIf
draw_line(16+$MWIDTH/2,$MHIGH104,16+$MWIDTH/2,$MHIGH-4)
draw_line(2,$MHIGH-120,$MWIDTH2,$MHIGH-120)
draw_line(16+$MWIDTH/2,$MHIGH84,$MWIDTH-3,$MHIGH-84)
draw_line(16+$MWIDTH/2,$MHIGH64,$MWIDTH-3,$MHIGH-64)
draw_line(16+$MWIDTH/2,$MHIGH44,$MWIDTH-3,$MHIGH-44)
draw_line(16+$MWIDTH/2,$MHIGH24,$MWIDTH-3,$MHIGH-24)
endif
GUICtrlSetBkColor($aa[$i],
$GUI_BKCOLOR_TRANSPARENT)
if($L_NUM_BAD > 0) then
GUICtrlSetGraphic($aa[$i],
$GUI_GR_COLOR, 0xff0000)
elseif ($L_NUM_WARN >0) Then
GUICtrlSetGraphic($aa[$i],$GUI_GR_COLOR,0xc
0c000)
else
GUICtrlSetGraphic($aa[$i],
$GUI_GR_COLOR, 0x00ff00)
endif
GUICtrlSetGraphic($aa[$i],$GUI_GR_RECT,
0,0,$MWIDTH,$MHIGH)
;box around
everything
GUICtrlSetGraphic($aa[$i],$GUI_GR_RECT,
1,1,$MWIDTH-2,$MHIGH-2) ;thicken (could
use pen=2)
GUICtrlSetGraphic($aa[$i],
$GUI_GR_COLOR, 0)
;go
back to black text
GUICtrlSetGraphic($aa[$i],$GUI_GR_RECT,
2,2,$MWIDTH-4,$MHIGH-4) ;and draw inner
box lines
draw_line(2,30,$MWIDTH-2,30)
draw_line(2,49,$MWIDTH-2,49)
draw_line(2,67,$MWIDTH-2,67)
draw_line($MWIDTH/2+$MWIDTH/4,49,$MWIDTH/2+
$MWIDTH/4,67)
draw_line($MWIDTH/4,49,$MWIDTH/4,67)
draw_line(2,85,$MWIDTH-2,85)
draw_line($MWIDTH/2,$MHIGH120,$MWIDTH/2,30)
draw_line(2,$MHIGH-104,$MWIDTH-2,$MHIGH104)
if($dx==2) then
$dx=0
$dy=$dy+1
Else
$dx=$dx+1
endif
next
GUISetState(@SW_UNLOCK,$main_form)
GUISetState(@SW_SHOW)
EndFunc
;
; GUI window setup followed by exit
(cleanup) routine
;
Func window_setup($verstr)
If WinExists($verstr) <> 0 Then
WinActivate($verstr)
Exit
EndIf
$main_form = GUICreate($verstr,
$MWIDTH*3, $MHIGH*3, -1, -1)
$listview = GUICtrlCreateListView("#|IP
ADDRESSES", 8, 8, 200, $MHIGH-35,
$LVS_REPORT)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH,
0, 30)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH,
1, 390)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH,
2, 144)
$add_input = GUICtrlCreateInput("", 8,
$MHIGH-25, 180, 21)
$add_button = GUICtrlCreateButton("Add",
210, $MHIGH-25, 46, 25,
BitOR($BS_DEFPUSHBUTTON,$WS_GROUP))
$sample_button =
GUICtrlCreateButton("Sample=2s", 326,
$MHIGH-25, 85, 25, $WS_GROUP)
$delete_button =
GUICtrlCreateButton("Delete", 260, $MHIGH25, 59, 25, $WS_GROUP)
$agecaps_button =
GUICtrlCreateButton("Age captures", 210,
$MHIGH-55, 95, 25, $WS_GROUP)
$stopstartcaps_button =
GUICtrlCreateButton("Start captures", 311,
$MHIGH-55, 100, 25, $WS_GROUP)
EndFunc
Func gui_exit()
_GUICtrlListView_UnRegisterSortCallBack($li
stview)
DllClose($dll)
GUIDelete()
EndFunc
;
; following logic just takes a status
string and figures out a warning color
based on text in the String
;
Func set_warning_color($msg)
if((StringInStr($msg,"Crit",0)>0) OR
(StringInStr($msg,"Bad",0)>0) OR
(StringInStr($msg,"FAIL",0)>0) OR
(StringInstr($msg,"[F",0)>0) OR
(StringInStr($msg,"Non",0)>0)) Then
$retcolor=0xa00000
elseif((StringInStr($msg,"[W",0) >0) OR
(StringInStr($msg,"degrad",0)>0) OR
(StringInStr($msg,"risk",0)>0) OR
(StringInStr($msg,"Warning",0)>0)) Then
$retcolor=0xb0b000
Else
$retcolor=0x00a000
EndIf
GuiCtrlSetDefColor($retcolor)
return $retcolor
EndFunc
;
; following logic configures and handles
the listview box (used to select IP
addresses)
;
Func setup_listview()
$hListView = GUICtrlGetHandle($listview)
GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUIRegisterMsg($WM_COMMAND,
"WM_COMMAND")
GUISetState()
GUICtrlSetData($listview, "#|IP
ADDRESSES ("&$ip_cnt&")")
If $ip_cnt > 0 Then
For $i=1 To $ip_cnt
GUICtrlCreateListViewItem($i &
"|" & $ise_ips[$i], $listview)
Next
_GUICtrlListView_EnsureVisible($hListView,
$ip_cnt)
EndIf
_WinAPI_RedrawWindow($hListView)
_GUICtrlListView_RegisterSortCallBack($hLis
tView)
_GUICtrlListView_SortItems($hListView,
1)
EndFunc
Func WM_NOTIFY($hWnd, $iMsg, $iwParam,
$ilParam)
#forceref $hWnd, $iMsg, $iwParam
Local $hWndFrom, $iIDFrom, $iCode,
$tNMHDR, $hWndListView, $tInfo
$hWndListView = $hListView
If Not IsHWnd($hListView) Then
$hWndListView =
GUICtrlGetHandle($hListView)
$tNMHDR = DllStructCreate($tagNMHDR,
$ilParam)
$hWndFrom =
HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
$iIDFrom = DllStructGetData($tNMHDR,
"IDFrom")
$iCode = DllStructGetData($tNMHDR,
"Code")
Switch $hWndFrom
Case $hWndListView
Switch $iCode
Case $LVN_COLUMNCLICK ; A
column was clicked
$tInfo =
DllStructCreate($tagNMLISTVIEW, $ilParam)
_GUICtrlListView_SortItems($hWndFrom,
DllStructGetData($tInfo, "SubItem"))
Case $NM_DBLCLK ; Sent by a
list-view control when the user doubleclicks an item with the left mouse button
Local $aRect
Local $aHit =
_GUICtrlListView_SubItemHitTest($hListView)
If ($aHit[0] <> -1) And
($aHit[1] = 0) Then
$Item = $aHit[0]
$SubItem = 0
$aRect =
_GUICtrlListView_GetItemRect($hListView,
$Item)
ElseIf ($aHit[0] <> -1)
And ($aHit[1] > 0) Then
$Item = $aHit[0]
$SubItem = $aHit[1]
$aRect =
_GUICtrlListView_GetSubItemRect($hListView,
$Item, $SubItem)
Else
Return
$GUI_RUNDEFMSG
EndIf
Local $iItemText =
_GUICtrlListView_GetItemText($hListView,
$Item, $SubItem)
If $SubItem = 1 Then
Local $iLen = 377
Else
Local $iLen = 131
EndIf
Local $aPos =
ControlGetPos($main_form, "", $hListView)
Local $iX = $aPos[0] +
$aRect[0] + 5
Local $iY = $aPos[1] +
$aRect[1] + 2
Global $hEdit =
_GUICtrlEdit_Create($main_form, $iItemText,
$iX, $iY, $iLen + 10, 17, $Style)
_GUICtrlEdit_SetSel($hEdit, 0, -1)
_WinAPI_SetFocus($hEdit)
$hDC =
_WinAPI_GetWindowDC($hEdit)
$hBrush =
_WinAPI_CreateSolidBrush(0x000000)
FrameRect($hDC, 0, 0,
$iLen + 10, 17, $hBrush)
Case $NM_RCLICK
Case $LVN_HOTTRACK ;future
tooltip implementation
EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc
;==>WM_NOTIFY
Func RGB2BGR($iColor)
Return
BitAND(BitShift(String(Binary($iColor)),
8), 0xFFFFFF)
EndFunc
;==>RGB2BGR
Func FrameRect($hDC, $nLeft, $nTop,
$nRight, $nBottom, $hBrush)
Local $stRect =
DllStructCreate("int;int;int;int")
DllStructSetData($stRect, 1, $nLeft)
DllStructSetData($stRect, 2, $nTop)
DllStructSetData($stRect, 3, $nRight)
DllStructSetData($stRect, 4, $nBottom)
DllCall("user32.dll", "int",
"FrameRect", "hwnd", $hDC, "ptr",
DllStructGetPtr($stRect), "hwnd", $hBrush)
EndFunc
;==>FrameRect
Func WM_COMMAND($hWnd, $Msg, $wParam,
$lParam)
#forceref $hWnd, $Msg
Local $hWndFrom, $iIDFrom, $hWndEdit,
$iCode
; Local $iCode = BitShift($wParam, 16)
If Not IsHWnd($hEdit) Then $hWndEdit =
GUICtrlGetHandle($hEdit)
$hWndFrom = $lParam
$iIDFrom = _WinAPI_LoWord($wParam)
$iCode = _WinAPI_HiWord($wParam)
If _IsPressed("0D", $dll) Then
GUICtrlSetState($add_input,
$GUI_FOCUS)
EndIf
Switch $lParam
Case $hEdit, $hWndEdit
Switch $iCode
Case $EN_KILLFOCUS
Local $iText =
_GUICtrlEdit_GetText($hEdit)
_GUICtrlListView_SetItemText($hListView,
$Item, $iText, $SubItem)
_WinAPI_DeleteObject($hBrush)
_WinAPI_ReleaseDC($hEdit, $hDC)
_WinAPI_DestroyWindow($hEdit)
$Item = -1
$SubItem = 0
EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc
;==>WM_COMMAND
And that is it. When first coded up there was a fear
by the developer that this might be a bit frail, so extra
logic was put in to ensure that it wasn’t impacted if
capitalization of XML tags changed (they did) or
path logic changed (it did a bit). Actually pretty
much all search logic is set to default to case
insensitive, which allows you to get a little sloppy
with the coding as well with no impact. At the time
of this writing the current logic works with the
earliest Restful alpha code that I had access to as well
as the most recent code. No promises that something
down the line won’t break it but should be easy to
fix.
AUTOIT:
NOTE: while stat5000.exe is compiled using AutoIt,
it is not necessary to install the autoit compiler on
your workstation to actually use stat5000 unless you
intend to modify the code in some form or another. If
you do want to modify the code then autoit is a free
download that takes just minutes to install and is
trivial to use. As the following sections mention, it is
a ‘basic-like’ language, but in actuality it is also a ‘C’
like language and even in some cases a C++ like
language. After programming in them all they tend to
blend together anyway.
The following is right from the autoit home page
(http://www.autoitscript.com/autoit3/):
AutoIt v3 is a freeware BASIC-like scripting language
designed for automating the Windows GUI and general
scripting. It uses a combination of simulated keystrokes,
mouse movement and window/control manipulation in
order to automate tasks in a way not possible or reliable
with other languages (e.g. VBScript and SendKeys).
AutoIt is also very small, self-contained and will run on all
versions of Windows out-of-the-box with no annoying
"runtimes" required!
AutoIt was initially designed for PC "roll out" situations to
reliably automate and configure thousands of PCs. Over
time it has become a powerful language that supports
complex expressions, user functions, loops and everything
else that veteran scripters would expect.
Features:















Easy to learn BASIC-like syntax
Simulate keystrokes and mouse movements
Manipulate windows and processes
Interact with all standard windows controls
Scripts can be compiled into standalone
executables
Create Graphical User Interfaces (GUIs)
COM support
Regular expressions
Directly call external DLL and Windows API
functions
Scriptable RunAs functions
Detailed helpfile and large community-based
support forums
Compatible with Windows 95 / 98 / ME / NT4 /
2000 / XP / 2003 / Vista / 2008
Unicode and x64 support
Digitally signed for peace of mind
Works with Windows Vista's User Account Control
(UAC)
AutoIt has been designed to be as small as possible and
stand-alone with no external .dll files or registry entries
required making it safe to use on Servers. Scripts can be
compiled into stand-alone executables with Aut2Exe.
Also supplied is a combined COM and DLL version of
AutoIt called AutoItX that allows you to add the unique
features of AutoIt to your own favourite scripting or
programming languages!
Also, AutoIt comes with an extremely powerful text
editor called SciTE4AutoIt3. The following info
comes from the autoit web page as well:
Quote Neil Hodgson:"SciTE is a SCIntilla based Text
Editor. Originally built to demonstrate Scintilla, it has
grown to be a generally useful editor with facilities for
building and running programs."
SciTE4AutoIt3 contains SciTE, wrapped into a single
installer with all needed configuration settings and lots of
utility programs like Tidy, Obfuscator, AU3Check,
ScriptWriter, AutoIt3Wrapper etc to enhanced SciTE for
use with AutoIt3.
It has a customized Lexer for AutoIt3 which
handles the
Syntax Highlighting and Code folding:
CodeFolding:
Autocomplete:
Intellisense:
This customized version of SciTE has
the following functionality:
















Customized Syntax highlighting.
AutoComplete AutoIt3 commands
automatically (suggest the option in a
dropdownbox while typing), just hit
ENTER or TAB to Autocomplete.)
AutoComplete anything already in the
script, like variable and Func names,
with Ctrl+Enter.
Intellisense (Show a ToolTip with the
parameter expected in the selected
function).
Code folding for easy code viewing.
Auto indentation while typing.
F1 - open Helpfile on the keyword were
the cursor is located.
Shift+F1 will bring up a Popup screen
showing all AutoIt3 functions. Just
Double-Click or Enter on the function
you need and it will be pasted back into
your script. It Also has a dynamic Help
facility!
Ctrl+F1 - open this Helpfile.
F5 - Run Tylo's Au3Check and when no
errors/warnings found run AutoIt3.exe.
Ctrl+F5 - Run Tylo's SyntaxCheck With
latest Production definitions, showing
all Syntax errors and possible issues
with variable declarations.
Ctrl+Alt+F5 - Run Tylo's SyntaxCheck
With latest Beta definitions, showing all
Syntax errors and possible issues with
variable declarations.
Alt+F6 - Run Larry's ScriptWriter to
record clicks and keystrokes and write
this into your Autoit Script.
Ctrl+F6 - Run Larry's AU3_Spy program
to detect the Text and Names of
controls on the program windows.
F7 - Build (compile) your script.
Alt+F7 - Run VoSs2o0o's
AutoItMacroGenerator ...Another recorder
for script.






Ctrl+F7 - AutoIt3Wrapper: Build
(compile) your script with Options to
change Compiler version, ICON,
Passphrase or compression, Update
Resource info of the target program like
Program version etc. Optional run Tylo's
AU3Check before compiling the source
and running other programs Before or
After compilation.
Ctrl+T will run Tidy.exe (included in this
install) to auto indent and Tidy your
AutoIt3 source file.
Alt+M will run CodeWizard.exe written by
Peppe which assists you in creating
MsgBox or InputBox() statements.
Alt+G will run GuiWizard.exe written
by CyberSlug which assists you in
creating GUI Layouts.
Ctrl+Alt+s will Run the Snippet holder .
Several LUA scripts to enhance SciTE
editing.
o Insert a copy of the Bookmarked
line(s) - Ctrl+Alt+B
This functions will insert all
Bookmarked lines at the beginning
for the current line.
Lines can be Bookmarked by
pressing Ctrl+F2.
o Jump to the "Func ???" definition of
the functionname under the Cursor
- Ctrl+J. It will also Bookmark the
original line to enable you to jump
back to the original line with F2.
o List dropdownbox Ctrl+L with all
available Func's in the current script
and jumps to selected script. It will
also Bookmark the original line to
enable you to jump back to the
original line with F2.
o Ctrl+Shift+D - Add Debug msgbox
This function will add a MSGBOX
below the current line that contains
the Var the cursor is at
$a = $b + 1 (Put the cursor on $b
and press Ctrl+Shift+D the
following line will be added)
MsgBox(4096,'debug:' & $b,$b)
;### Debug MSGBOX
o Alt+D - Add Debug ConsoleWrite
message
This function will add a
ConsoleWrite line below the current
line that contains the Var the cursor
o
o
o
o
is at
$a = $b + 1 (Put the cursor on $b
and press Alt+D the following line
will be added)
ConsoleWrite('Line:~4 debug ==>
$b: ' & $b & @lf) ;### Debug
Console
Alt+Shift+D - Comment ALL
DEBUG MsgBox and ConsoleWrite
lines.
Ctrl+Alt+D - UnComment ALL
Debug MsgBoxes and ConsoleWrite
lines.
Add TRACE ConsoleWrites to all
lines to easily trace your
program:Available under
Tools/Debug: Add Trace lines
Remove ALL Debug MsgBoxes and
ConsoleWrite lines: Available under
Tools/Debug: Remove ALL lines
And, here is a VERY useful set of commonly used
example functions, keywords, and macros that autoit
supports (this is NOT the complete set by any
means):
Functions












Abs - Calculates the absolute value of a
number
ACos - Calculates the arcCosine of a
number
AdlibDisable - Disables the adlib
functionality
AdlibEnable - Enables Adlib functionality
Asc - Returns the ASCII code of a
character
ASin - Calculates the arcsine of a
number
ATan - Calculates the arctangent of a
number
AutoItSetOption - Changes the behavior
of several AutoIt functi...
AutoItWinGetTitle - Retrieves the title of
the AutoIt window
AutoItWinSetTitle - Changes the title of
the AutoIt window
BitAND - Performs a bitwise AND
operation
BitNOT - Performs a bitwise NOT
operation






























BitOR - Performs a bitwise OR operation
BitShift - Performs a bit shifting
operation
BitXOR - Performs a bitwise exclusive OR
(XOR) operati...
BlockInput - Disable/enable the mouse
and keyboard
Break - Enables or disables the users'
ability to exi...
Call - Calls a user-defined function
contained in a ...
CDTray - Opens or closes the CD tray
Chr - Returns a character corresponding
to an ASCII...
ClipGet - Retrieves text from the
clipboard
ClipPut - Writes text to the clipboard
ControlClick - Sends a mouse click
command to a given contro...
ControlCommand - Sends a command to
a control
ControlDisable - Sends a command to a
control
ControlEnable - Enables a disabled
control
ControlFocus - Sets input focus to a
given control on a wind...
ControlGetFocus - Returns the control
reference number of the c...
ControlGetHandle - Gets the internal
handle of a control
ControlGetPos - Retrieves the position
and size of a control ...
ControlGetText - Retrieves text from a
control
ControlHide - Hides a control
ControlListView - Sends a command to a
ListView control
ControlMove - Moves a control within a
window
ControlSend - Sends a string of
characters to a control
ControlSetText - Sets text of a control
ControlShow - Shows a control that was
hidden
Cos - Calculates the cosine of a number
Dec - Returns a numeric representation
of a hexadec...
DirCopy - Copies a directory and all subdirectories an...
DirCreate - Creates a directory
DirGetSize - Returns the size of a
specified directory in ...






























DirMove - Moves a directory and all subdirectories and...
DirRemove - Deletes a directory
DllCall - Dynamically calls a function in a
DLL
DllClose - Closes a previously opened
DLL
DllOpen - Opens a dll file for use in
DllCall
DriveGetDrive - Returns an array
containing the enumerated dr...
DriveGetFileSystem - Returns File
System Type of a drive
DriveGetLabel - Returns Volume Label of
a drive, if it has on...
DriveGetSerial - Returns Serial Number
of a drive
DriveGetType - Returns drive type
DriveMapAdd - Maps a network drive
DriveMapDel - Disconnects a network
drive
DriveMapGet - Retreives the details of a
mapped drive
DriveSetLabel - Sets the Volume Label of
a drive
DriveSpaceFree - Returns the free disk
space of a path in Mega...
DriveSpaceTotal - Returns the total disk
space of a path in Meg...
DriveStatus - Returns the status of the
drive as a string
EnvGet - Retrieves an environment
variable
EnvSet - Writes an environment variable
EnvUpdate - Refreshes the OS
environment
Eval - Return the value of the variable
whose name i...
Exp - Calculates e to the power of a
number
FileChangeDir - Changes the current
working directory
FileClose - Closes a text file
FileCopy - Copies one or more files
FileCreateShortcut - Creates a shortcut
to a file
FileDelete - Delete one or more files
FileExists - Checks if a file or directory
exists
FileFindFirstFile - Returns a filename
according to search string
FileFindNextFile - Returns a filename
according to search string



























FileGetAttrib - Returns a code string
representing a file's a...
FileGetLongName - Returns the long path
and filename of the pat...
FileGetShortcut - Retrieves details about
a shortcut
FileGetShortName - Returns the 8.3
(short) path and filename of ...
FileGetSize - Returns the size of a file in
bytes
FileGetTime - Returns the time and date
information for a f...
FileGetVersion - Returns the "File"
version information
FileInstall - Include and install a file with
the compiled ...
FileMove - Moves one or more files
FileOpen - Opens a text file for reading
or writing
FileOpenDialog - Initiates a Open File
Dialog
FileRead - Read in a number of
characters from a previou...
FileReadLine - Read in a line of text from
a previously open...
FileRecycle - Sends a file or directory to
the recycle bin,...
FileRecycleEmpty - Empties the recycle
bin
FileSaveDialog - Initiates a Save File
Dialog
FileSelectFolder - Initiates a Browse For
Folder GUI
FileSetAttrib - Sets the attributes of one
or more files
FileSetTime - Sets the timestamp of one
of more files
FileWrite - Append a line of text to the
end of a previou...
FileWriteLine - Append a line of text to
the end of a previou...
FtpSetProxy - Sets the internet proxy to
use for ftp access
GUICreate - Creates a GUI window
GUICtrlCreateAVI - Creates an AVI video
control for the GUI
GUICtrlCreateButton - Creates a Button
control for the GUI
GUICtrlCreateCheckbox - Creates a
Checkbox control for the GUI
GUICtrlCreateCombo - Creates a
ComboBox control for the GUI



























GUICtrlCreateContextMenu - Creates a
context menu for a control or entir...
GUICtrlCreateDate - Creates a date
control for the GUI
GUICtrlCreateDummy - Creates a
Dummy control for the GUI
GUICtrlCreateEdit - Creates an Edit
control for the GUI
GUICtrlCreateGroup - Creates a Group
control for the GUI
GUICtrlCreateIcon - Creates an Icon
control for the GUI
GUICtrlCreateInput - Creates an Input
control for the GUI
GUICtrlCreateLabel - Creates a static
Label control for the GUI
GUICtrlCreateList - Creates a List control
for the GUI
GUICtrlCreateListView - Creates a
ListView control for the GUI
GUICtrlCreateListViewItem - Creates a
ListView item
GUICtrlCreateMenu - Creates a Menu
control for the GUI
GUICtrlCreateMenuitem - Creates a
MenuItem control for the GUI
GUICtrlCreatePic - Creates a Picture
control for the GUI
GUICtrlCreateProgress - Creates a
Progress control for the GUI
GUICtrlCreateRadio - Creates a Radio
button control for the GUI
GUICtrlCreateSlider - Creates a Slider
control for the GUI
GUICtrlCreateTab - Creates a Tab control
for the GUI
GUICtrlCreateTabItem - Creates a
TabItem control for the GUI
GUICtrlCreateTreeView - Creates a
TreeView control for the GUI
GUICtrlCreateTreeViewItem - Creates a
TreeViewItem control for the GUI
GUICtrlCreateUpdown - Creates an
UpDown control for the GUI
GUICtrlDelete - Deletes a control
GUICtrlGetState - Gets the current state
of a control
GUICtrlRead - Read state or data of a
control
GUICtrlRecvMsg - Send a message to a
control and retrieve info...
GUICtrlSendMsg - Send a message to a
control


























GUICtrlSendToDummy - Sends a
message to a Dummy control
GUICtrlSetBkColor - Sets the background
color of a control
GUICtrlSetColor - Sets the text color of a
control
GUICtrlSetCursor - Sets mouse cursor
icon for a particular contr...
GUICtrlSetData - Modifies the data for a
control
GUICtrlSetFont - Sets the font for a
control
GUICtrlSetImage - Sets the bitmap or
icon image to use for a co...
GUICtrlSetLimit - Limits the number of
characters/pixels for a ...
GUICtrlSetOnEvent - Defines a userdefined function to be called ...
GUICtrlSetPos - Changes the position of
a control within the ...
GUICtrlSetResizing - Defines the resizing
method used by a control
GUICtrlSetState - Changes the state of a
control
GUICtrlSetStyle - Changes the style of a
control
GUICtrlSetTipf - Sets the tip text
associated with a control
GUIDelete - Deletes a GUI window and
all controls that it...
GUIGetCursorInfo ([]) - Gets the mouse
cursor position relative to GU...
GUIGetMsg - Polls the GUI to see if any
events have ocurr...
GUISetBkColor - Sets the background
color of the GUI window
GUISetCoord - Sets absolute coordinates
for next control
GUISetCursor - Sets the mouse cursor
icon for a GUI window
GUISetFont - Sets the default font for a
GUI window
GUISetHelp - Sets an executable file that
will be run when...
GUISetIcon - Sets the icon used in a GUI
window
GUISetOnEvent - Defines a user function
to be called when a c...
GUISetState - Changes the state of a
GUI window
GUIStartGroup - Defines that any
subsequent controls that are...



























GUISwitch - Switches the current window
used for GUI func...
Hex - Returns a string representation of
an integer...
HotKeySet - Sets a hotkey that calls a
user function
HttpSetProxy - Sets the internet proxy to
use for http acces...
InetGet - Downloads a file from the
internet using the ...
InetGetSize - Returns the size of a file
located on the Int...
IniDelete - Deletes a value from a
standard format .ini f...
IniRead - Reads a value from a standard
format .ini fil...
IniReadSection - Reads all key/value
pairs from a section in a...
IniReadSectionNames - Reads all
sections in a standard format .ini ...
IniWrite - Writes a value to a standard
format .ini file
InputBox - Displays an input box to ask
the user to ente...
Int - Returns the integer representation
of an expr...
IsAdmin - Checks if the current user has
administrator ...
IsArray - Checks if a variable is an array
type
IsDeclared - Check if a variable has been
declared
IsFloat - Checks if a variable or
expression is a float...
IsInt - Checks if a variable or expression
is an inte...
IsNumber - Checks if a variable's base
type is numeric
IsString - Checks if a variable is a string
type
Log - Calculates the natural logarithm of
a number
MemGetStats - Retrieves memory
related information
Mod - Performs the modulus operation
MouseClick - Perform a mouse click
operation
MouseClickDrag - Perform a mouse click
and drag operation
MouseDown - Perform a mouse down
event at the current mou...
MouseGetCursor - Returns a cursor ID
Number of the current Mou...




























MouseGetPos - Retrieves the current
position of the mouse c...
MouseMove - Moves the mouse pointer
MouseUp - Perform a mouse up event at
the current mouse...
MouseWheel - Moves the mouse wheel
up or down
MsgBox - Displays a simple message box
with optional t...
Number - Returns the numeric
representation of an expr...
Ping - Pings a host and returns the
roundtrip-time
PixelChecksum - Generates a checksum
for a region of pixels
PixelGetColor - Returns a pixel color
according to x,y pixel ...
PixelSearch - Searches a rectangle of
pixels for the pixel ...
ProcessClose - Terminates a named
process
ProcessExists - Checks to see if a
specified process exists
ProcessList - Returns an array listing the
currently runnin...
ProcessSetPriority - Changes the priority
of a process
ProcessWait - Pauses script execution
until a given process...
ProcessWaitClose - Pauses script
execution until a given process...
ProgressOff - Turns Progress window off
ProgressOn - Creates a customizable
progress bar window
ProgressSet - Sets the position and/or
text of a previously...
Random - Generates a pseudo-random
float-type number
RegDelete - Deletes a key or value from
the registry
RegEnumKey - Reads the name of a
subkey according to it's ...
RegEnumVal - Reads the name of a
value according to it's i...
RegRead - Reads a value from the
registry
RegWrite - Writes a value to the registry
Round - Returns a number rounded to a
specified numbe...
Run - Runs an external program
RunAsSet - Initialise a set of user
credentials to use d...




























RunWait - Runs an external program and
pauses script ex...
Send - Sends simulated keystrokes to
the active wind...
SetError - Manually set the value of the
@error macro
SetExtended - Manually set the value of
the @extended macro
Shutdown - Shuts down the system
Sin - Calculates the sine of a number
Sleep - Pause script execution
SoundPlay - Play a sound file
SoundSetWaveVolume - Sets the system
wave volume by percent
SplashImageOn - Creates a customizable
image popup window
SplashOff - Turns SplashText or
SplashImage off
SplashTextOn - Creates a customizable
text popup window
Sqrt - Calculates the square-root of a
number
StatusbarGetText - Retrieves the text
from a standard status bar...
String - Returns the string representation
of an expre...
StringAddCR - Takes a string and
prefixes all linefeed char...
StringFormat - Returns a formatted
string (similar to the C ...
StringInStr - Checks if a string contains a
given substring...
StringIsAlNum - Checks if a string
contains only alphanumeric...
StringIsAlpha - Checks if a string
contains only alphabetic c...
StringIsASCII - Checks if a string
contains only ASCII charac...
StringIsDigit - Checks if a string contains
only digit (0-9) ...
StringIsFloat - Checks if a string is a
floating point number
StringIsInt - Checks if a string is an
integer
StringIsLower - Checks if a string
contains only lowercase ch...
StringIsSpace - Checks if a string
contains only whitespace c...
StringIsUpper - Checks if a string
contains only uppercase ch...
StringIsXDigit - Checks if a string
contains only hexadecimal ...



























StringLeft - Returns a number of
characters from the left-...
StringLen - Returns the number of
characters in a string
StringLower - Converts a string to
lowercase
StringMid - Extracts a number of
characters from a string
StringReplace - Replaces substrings in a
string
StringRight - Returns a number of
characters from the right...
StringSplit - Splits up a string into
substrings depending ...
StringStripCR - Removes all carriage
return values from a str...
StringStripWS - Strips the white space in
a string
StringTrimLeft - Trims a number of
characters from the left ha...
StringTrimRight - Trims a number of
characters from the right h...
StringUpper - Converts a string to
uppercase
Tan - Calculates the tangent of a
number
TimerDiff - Returns a difference in time
from a previous ...
TimerInit - Returns a time stamp in
milliseconds with acc...
ToolTip - Creates a tooltip anywhere on
the screen
TrayTip - Displays a balloon tip from the
AutoIt Icon
UBound - Returns the size of array
dimensions
WinActivate - Sets focus to a window
WinActive - Checks to see if a specified
window exists an...
WinClose - Closes a window
WinExists - Checks to see if a specified
window exists
WinGetCaretPos - Returns the
coordinates of the caret in the f...
WinGetClassList - Retrieves the classes
from a window
WinGetClientSize - Retrieves the size of a
given window's client...
WinGetHandle - Retrieves the internal
handle of a window
WinGetPos - Retrieves the position and
size of a given wi...


















WinGetProcess - Retrieves the Process
ID (PID) associated wit...
WinGetState - Retrieves the state of a
given window
WinGetText - Retrieves the text from a
window
WinGetTitle - Retrieves the full title from
a window
WinKill - Forces a window to close
WinList - Retrieves a list of windows
WinMenuSelectItem - Invokes a menu
item of a window
WinMinimizeAll - Minimizes all windows
WinMinimizeAllUndo - Undoes a previous
WinMinimizeAll function
WinMove - Moves and/or resizes a
window
WinSetOnTop - Change a window's
"Always On Top" attribute
WinSetState - Shows, hides, minimizes,
maximizes, or restor...
WinSetTitle - Changes the title of a
window
WinSetTrans - Sets the transparency of a
window
WinWait - Pauses execution of the script
until the requ...
WinWaitActive - Pauses execution of the
script until the requ...
WinWaitClose - Pauses execution of the
script until the requ...
WinWaitNotActive - Pauses execution of
the script until the requ...
Keywords








#ce - Identifies the end of comment lines
not to be...
#comments-end - Identifies the end of
comment lines not to be...
#comments-start - Identifies the start of
comment lines not to ...
#cs - Identifies the start of comment
lines not to ...
#include - Includes the contents of
another script in th...
#include-once - Keeps a script from
being included in another...
#NoTrayIcon - Indicates that the AutoIt
tray icon will not ...
Case - Specifies a condition to evaluate
in a Select...























ContinueLoop - Instructs script to
continue a loop statement
Dim - Declare a variable or create an
array
Do - Loop based on an expression
Else - Identifies the statement to process
if the co...
ElseIf - Identifies an additional
expression to be han...
EndFunc - Identifies the end of the code
for a user def...
EndIf - Marks the end of a If/Else
statement
EndSelect - Marks the end of a
conditional Select stateme...
Exit - Terminates the script
ExitLoop - Terminate a While/Do/For
loop
For - Loop based on an expression
Func - Defines a user-defined function
that takes ze...
Global - Creates a variable in the Global
scope
If - Conditionally run a statement
Local - Creates a variable in the
Local/Function scop...
Next - Marks the end of a For loop
ReDim - Resize an existing array
Return - Exits a function
Select - Conditionally run statements
Then - Identifies statement to run if
conditional If...
Until - Loop based on an expression
WEnd - Marks the end of a While loop
While - Loop based on an expression
Macros








@AppDataCommonDir - Path to
Application Data folder
@AppDataDir - Path to current user's
Application Data
@AutoItVersion - Version number of
AutoIt
@CommonFilesDir - Path to Common
Files folder
@Compiled - Identifies if script is running
as a complied...
@ComputerName - Computer's network
name
@ComSpec - Path and file name of
command interpreter
@CR - Carriage return































@CRLF - Carriage return and line feed
@DesktopCommonDir - Path to Desktop
@DesktopDepth - Depth of the desktop
screen in bits per pixel
@DesktopDir - Path to current user's
Desktop
@DesktopHeight - Height of screen in
pixels
@DesktopWidth - Width of screen in
pixels
@DocumentsCommonDir - Path to
Documents
@Error - Status of the error flag
@FavoritesCommonDir - Path to
Favorites
@FavoritesDir - Path to current user's
Favorites
@HomeDrive - Drive letter of drive
containing current user...
@HomePath - Directory part of current
user's home directo...
@HomeShare - Server and share name
containing current user...
@Hour - Hours value of clock in 24-hour
format
@IPAddress1 - IP address of first
network adapter
@IPAddress2 - IP address of second
network adapter
@IPAddress3 - IP address of thrid
network adapter
@IPAddress4 - IP address of fourth
network adapter
@LF - Line feed
@LogonDNSDomain - Logon DNS
Domain
@LogonDomain - Logon Domain
@LogonServer - Logon server
@MDay - Current day of month
@Min - Minutes value of clock
@Mon - Current month
@MyDocumentsDir - Path to My
Documents target
@OSBuild - Returns the OS build
number
@OSLang - Returns code denoting OS
Language
@OSServicePack - Service pack info
@OSType - Identifies NT or later
versions of Windows
@OSVersion - Version of Windows as
text string






























@ProgramFilesDir - Path to Program Files
folder
@ProgramsCommonDir - Path to Start
Menu's Programs folder
@ProgramsDir - Path to current user's
Programs (folder on St...
@ScriptDir - Directory containing the
running script.
@ScriptFullPath - Full path and name of
current script
@ScriptName - Long filename of the
running script
@Sec - Seconds value of clock
@StartMenuCommonDir - Path to Start
Menu folder
@StartMenuDir - Path to current user's
Start Menu
@StartupCommonDir - Path to Startup
folder
@StartupDir - Current user's Startup
folder
@SW_Hide - Hide window
@SW_Maximize - Maximize window
@SW_Minimize - Minimize window
@SW_Restore - Undoes a window
minimization or maximization
@SW_Show - Shows a previously hidden
window
@SW_ShowDefault - Sets the show state
based on the SW_ value sp...
@SW_ShowMaximized - Activates the
window and displays it as a max...
@SW_ShowMinimized - Activates the
window and displays it as a min...
@SW_ShowMinNoActive - Displays the
window as a minimized window.
@SW_ShowNA - Displays the window in
its current size and p...
@SW_ShowNoActivate - Displays a
window in its most recent size and...
@SW_ShowNormal - Activates and
displays a window
@SystemDir - Path to the Windows
System (or System32) fold...
@Tab - Tab character
@TempDir - Path to the temporary files
folder
@UserName - ID of the currently logged
on user
@UserProfileDir - Path to current user's
Profile folder
@WDay - Numeric day of week
@WindowsDir - Path to Windows folder



<>
@WorkingDir - Current/active working
directory
@YDay - Current day of year
@Year - Current four-digit year
Download