1#!/usr/bin/env python
2import getopt
3import sys
4import os
5import time
6from threading import Thread
7from datetime import datetime
8import subprocess
9import platform
10
11sys.path = [".", "lib"] + sys.path
12from testconstants import WIN_COUCHBASE_BIN_PATH_RAW
13import TestInput
14
15
16def usage(error=None):
17    print """\
18Syntax: collect_server_info.py [options]
19
20Options
21 -l  Lower case of L. For local run on windows only.  No need ini file.
22 -i <file>        Path to .ini file containing cluster information.
23 -p <key=val,...> Comma-separated key=value info.
24
25Available keys:
26 path=<file_path> The destination path you want to put your zipped diag file
27
28Example:
29 collect_server_info.py -i cluster.ini -p path=/tmp/nosql
30"""
31    sys.exit(error)
32
33def time_stamp():
34    now = datetime.now()
35    day = now.day
36    month = now.month
37    year = now.year
38    hour = now.timetuple().tm_hour
39    min = now.timetuple().tm_min
40    date_time = "%s%02d%02d-%02d%02d" % (year, month, day, hour, min)
41    return date_time
42
43
44class couch_dbinfo_Runner(object):
45    def __init__(self, server, path, local=False):
46        self.server = server
47        self.path = path
48        self.local = local
49
50    def run(self):
51        file_name = "%s-%s-couch-dbinfo.txt" % (self.server.ip.replace('[', '').replace(']', '').replace(':', '.'),
52                                                time_stamp())
53        if not self.local:
54            from lib.remote.remote_util import RemoteMachineShellConnection
55            remote_client = RemoteMachineShellConnection(self.server)
56            print "Collecting dbinfo from %s\n" % self.server.ip
57            output, error = remote_client.execute_couch_dbinfo(file_name)
58            print "\n".join(output)
59            print "\n".join(error)
60
61            user_path = "/home/"
62            if remote_client.info.distribution_type.lower() == 'mac':
63                user_path = "/Users/"
64            else:
65                if self.server.ssh_username == "root":
66                    user_path = "/"
67
68            remote_path = "%s%s" % (user_path, self.server.ssh_username)
69            status = remote_client.file_exists(remote_path, file_name)
70            if not status:
71                raise Exception("%s doesn't exists on server" % file_name)
72            status = remote_client.get_file(remote_path, file_name,
73                                        "%s/%s" % (self.path, file_name))
74            if status:
75                print "Downloading dbinfo logs from %s" % self.server.ip
76            else:
77                raise Exception("Fail to download db logs from %s"
78                                                     % self.server.ip)
79            remote_client.execute_command("rm -f %s" % os.path.join(remote_path, file_name))
80            remote_client.disconnect()
81
82
83class cbcollectRunner(object):
84    def __init__(self, server, path, local=False):
85        self.server = server
86        self.path = path
87        self.local = local
88
89    def run(self):
90        file_name = "%s-%s-diag.zip" % (self.server.ip.replace('[', '').replace(']', '').replace(':', '.'),
91                                        time_stamp())
92        if not self.local:
93            from lib.remote.remote_util import RemoteMachineShellConnection
94            remote_client = RemoteMachineShellConnection(self.server)
95            print "Collecting logs from %s\n" % self.server.ip
96            output, error = remote_client.execute_cbcollect_info(file_name)
97            print "\n".join(error)
98
99            user_path = "/home/"
100            if remote_client.info.distribution_type.lower() == 'mac':
101                user_path = "/Users/"
102            else:
103                if self.server.ssh_username == "root":
104                    user_path = "/"
105
106            remote_path = "%s%s" % (user_path, self.server.ssh_username)
107            status = remote_client.file_exists(remote_path, file_name)
108            if not status:
109                raise Exception("%s doesn't exists on server" % file_name)
110            status = remote_client.get_file(remote_path, file_name,
111                                        "%s/%s" % (self.path, file_name))
112            if status:
113                print "Downloading zipped logs from %s" % self.server.ip
114            else:
115                raise Exception("Fail to download zipped logs from %s"
116                                                     % self.server.ip)
117            remote_client.execute_command("rm -f %s" % os.path.join(remote_path, file_name))
118            remote_client.disconnect()
119
120def main():
121    local = False
122    try:
123        (opts, args) = getopt.getopt(sys.argv[1:], 'hli:p', [])
124        for o, a in opts:
125            if o == "-h":
126                usage()
127            elif o == "-l":
128                if platform.system() == "Windows":
129                    print "*** windows os ***"
130                    local = True
131                else:
132                    print "This option '-l' only works for local windows."
133                    sys.exit()
134        if not local:
135            input = TestInput.TestInputParser.get_test_input(sys.argv)
136            if not input.servers:
137                usage("ERROR: no servers specified. Please use the -i parameter.")
138    except IndexError:
139        usage()
140    except getopt.GetoptError, error:
141        usage("ERROR: " + str(error))
142
143    if not local:
144        file_path = input.param("path", ".")
145        remotes = (cbcollectRunner(server, file_path, local) for server in input.servers)
146
147        remote_threads = [Thread(target=remote.run()) for remote in remotes]
148        for remote_thread in remote_threads:
149            remote_thread.daemon = True
150            remote_thread.start()
151            run_time = 0
152            while remote_thread.isAlive() and run_time < 1200:
153                time.sleep(15)
154                run_time += 15
155                print "Waiting for another 15 seconds (time-out after 20 min)"
156            if run_time == 1200:
157                print "cbcollect_info hung on this node. Jumping to next node"
158            print "collect info done"
159
160        for remote_thread in remote_threads:
161            remote_thread.join(120)
162            if remote_thread.isAlive():
163                raise Exception("cbcollect_info hung on remote node")
164    else:
165        file_name = "%s-%s-diag.zip" % ("local", time_stamp())
166        cbcollect_command = WIN_COUCHBASE_BIN_PATH_RAW + "cbcollect_info.exe"
167        result = subprocess.check_call([cbcollect_command, file_name])
168        if result == 0:
169            print "Log file name is \n %s" % file_name
170        else:
171            print "Failed to collect log"
172
173if __name__ == "__main__":
174    main()
175