1#!/usr/local/bin/python3.8
2#
3# Authors: Sergey Satskiy
4#
5# $Id: ns_perf_probe.py 591938 2019-08-22 17:35:24Z satskyse $
6#
7
8"""
9Netschedule server throughput sampling script
10"""
11
12import sys
13from optparse import OptionParser
14from time import sleep
15from ncbi_grid_1_1.ncbi.grid import ns
16from datetime import datetime
17
18
19def parserError( parser_, message ):
20    " Prints the message and help on stderr "
21    sys.stdout = sys.stderr
22    print(message)
23    parser_.print_help()
24    return
25
26
27def accumulateCounters( counters, values ):
28    " Values came as a list of strings like 'Name: xxx' "
29    for value in values:
30        name, val = value.split( ':', 1 )
31        val = int( val )
32
33        if name in counters:
34            counters[ name ] += val
35        else:
36            counters[ name ] = val
37    return
38
39def formatTimestamp( ts ):
40    " As MS Excel likes it "
41    return ts.strftime( "%m/%d/%Y %H:%M:%S" )
42
43def main():
44    " main function for the netschedule multi test "
45
46    parser = OptionParser(
47    """
48    %prog <host>  <port>
49    %prog  <host:port>
50    Collects the number submitted jobs and the up time periodically and saves into a CSV file
51    """ )
52    parser.add_option( "-v", "--verbose",
53                       action="store_true", dest="verbose", default=False,
54                       help="be verbose (default: False)" )
55    parser.add_option( "--interval", dest="interval",
56                       default=60,
57                       help="Interval between probes, seconds. (Default: 60)" )
58
59    # parse the command line options
60    options, args = parser.parse_args()
61    if len( args ) not in [ 1, 2 ]:
62        parserError( parser, "Incorrect number of arguments" )
63        return 3
64
65    if len( args ) == 2:
66        host = args[ 0 ]
67        port = args[ 1 ]
68    else:
69        parts = args[0].split( ":" )
70        if len( parts ) != 2 :
71            parserError( parser, "Expected format host:port" )
72            return 3
73        host = parts[ 0 ]
74        port = parts[ 1 ]
75
76    try:
77        port = int( port )
78    except:
79        parserError( parser, "The port must be integer" )
80        return 3
81
82    interval = options.interval
83    try:
84        interval = int( interval )
85    except:
86        parserError( parser, "The interval must be an integer > 0" )
87        return 3
88    if interval <= 0:
89        parserError( parser, "The interval must be an integer > 0" )
90        return 3
91
92    # Get the server start time once
93    server = ns.NetScheduleServer( host + ":" + str( port ),
94            client_name = "performance_probe" )
95    server.allow_xsite_connections()
96    currentDate = datetime.now()
97    serverStatus = server.get_server_status()
98    if 'Started' not in serverStatus:
99        raise Exception( "Cannot get the server start timestamp" )
100    startDate = datetime.strptime( serverStatus[ 'Started' ],
101                                   "%m/%d/%Y %H:%M:%S" )
102
103    lastTotalSubmits = None
104    while True:
105        # Open a connection
106        server = ns.NetScheduleServer( host + ":" + str( port ),
107                client_name = "performance_probe" )
108        server.allow_xsite_connections()
109
110        # Interrogate
111        currentDate = datetime.now()
112        serverStatus = server.get_server_status()
113
114        counters = {}
115        for key in serverStatus:
116            if key.startswith( "queue " ):
117                accumulateCounters( counters, serverStatus[ key ] )
118        if 'submits' not in counters:
119            raise Exception( "Cannot get the total server submits" )
120        totalSubmits = counters[ 'submits' ]
121
122        # Print results
123        runtime = currentDate - startDate
124        runtime = str( runtime.total_seconds() ).split( '.' )[ 0 ]
125
126        if lastTotalSubmits is None:
127            print("Timestamp,seconds since server started,total submits")
128        print(formatTimestamp(currentDate) + "," + runtime + "," + str(totalSubmits))
129
130        if totalSubmits == lastTotalSubmits:
131            break
132        lastTotalSubmits = totalSubmits
133
134        # Sleep
135        sleep( interval )
136
137    return 0
138
139
140
141# The script execution entry point
142if __name__ == "__main__":
143    try:
144        returnValue = main()
145    except KeyboardInterrupt:
146        # Ctrl+C
147        print("Ctrl + C received", file=sys.stderr)
148        returnValue = 2
149
150    except Exception as excpt:
151        print(str(excpt), file=sys.stderr)
152        returnValue = 1
153
154    sys.exit( returnValue )
155