1c7ecad54SAndrei Baranouskiimport logger
2c891e06fSAndrei Baranouskiimport unittest
3c7ecad54SAndrei Baranouskifrom TestInput import TestInputSingleton
4c891e06fSAndrei Baranouskifrom remote.remote_util import RemoteMachineShellConnection, RemoteMachineHelper
55edf749cSLi Yangimport re
60d4c20d3SAndrei Baranouskiimport time
7fd844442SAndrei Baranouski
80a6fcc9cSAndrei Baranouskitry:
90a6fcc9cSAndrei Baranouski    import requests
100a6fcc9cSAndrei Baranouski    from requests.exceptions import ConnectionError
110a6fcc9cSAndrei Baranouskiexcept ImportError as e:
120a6fcc9cSAndrei Baranouski    print 'please install required modules:', e
130a6fcc9cSAndrei Baranouski    raise
14c7ecad54SAndrei Baranouski
15c7ecad54SAndrei Baranouski
16c891e06fSAndrei Baranouskiclass GatewayBaseTest(unittest.TestCase):
17c7ecad54SAndrei Baranouski    BUILDS = {
18d461f429SLi Yang        'http://latestbuilds.hq.couchbase.com/couchbase-sync-gateway': (
19b742a21aSAndrei Baranouski            'release/1.1.0/{0}/couchbase-sync-gateway-community_{0}_{1}.{2}',
2044244426SAndrei Baranouski            'release/1.1.1/{0}/couchbase-sync-gateway-community_{0}_{1}.{2}',
21b742a21aSAndrei Baranouski            '1.1.0/{0}/couchbase-sync-gateway-community_{0}_{1}.{2}',
22b742a21aSAndrei Baranouski            '0.0.0/{0}/couchbase-sync-gateway-community_{0}_{1}.{2}',
23b742a21aSAndrei Baranouski            '0.0.1/{0}/couchbase-sync-gateway-community_{0}_{1}.{2}'
24c7ecad54SAndrei Baranouski        ),
25c7ecad54SAndrei Baranouski    }
26c7ecad54SAndrei Baranouski
27c7ecad54SAndrei Baranouski    def setUp(self):
286f4184d7SAndrei Baranouski        super(GatewayBaseTest, self).setUp()
29c7ecad54SAndrei Baranouski        self.log = logger.Logger.get_logger()
30c7ecad54SAndrei Baranouski        self.input = TestInputSingleton.input
31e0c00442SAndrei Baranouski        self.case_number = self.input.param("case_number", 0)
3279f502ffSAndrei Baranouski        self.version = self.input.param("version_sg", "0.0.0-358")
33e0c00442SAndrei Baranouski        self.extra_param = self.input.param("extra_param", "")
34e0c00442SAndrei Baranouski        if isinstance(self.extra_param, str):
35fd844442SAndrei Baranouski            self.extra_param = self.extra_param.replace("$", "=")  # '=' is a delimiter in conf file
36b742a21aSAndrei Baranouski        self.logsdir = self.input.param("logsdir", "/tmp/sync_gateway/logs")
37b742a21aSAndrei Baranouski        self.datadir = self.input.param("datadir", "/tmp/sync_gateway")
38b742a21aSAndrei Baranouski        self.configdir = self.input.param("configdir", "/tmp/sync_gateway")
395edf749cSLi Yang        self.configfile = self.input.param("configfile", "sync_gateway.json")
4035a7f636SAndrei Baranouski        self.expected_error = self.input.param("expected_error", "")
41c7ecad54SAndrei Baranouski        self.servers = self.input.servers
42c7ecad54SAndrei Baranouski        self.master = self.servers[0]
432d9c217bSAndrei Baranouski        self.folder_prefix = ""
442d9c217bSAndrei Baranouski        self.installed_folder = '/opt/couchbase-sync-gateway/bin'
4549406394SAndrei Baranouski        shell = RemoteMachineShellConnection(self.master)
46ded76c1cSAndrei Baranouski        type = shell.extract_remote_info().distribution_type
4749406394SAndrei Baranouski        shell.disconnect()
48b742a21aSAndrei Baranouski        if type.lower() == 'windows':
49b742a21aSAndrei Baranouski            self.folder_prefix = "/cygdrive/c"
502d9c217bSAndrei Baranouski            self.installed_folder = '/cygdrive/c/Program\ Files\ \(x86\)/Couchbase'
51b742a21aSAndrei Baranouski            self.logsdir = self.folder_prefix + self.configdir
52b742a21aSAndrei Baranouski            self.datadir = self.folder_prefix + self.configdir
53b742a21aSAndrei Baranouski            self.configdir = self.folder_prefix + self.configdir
54b742a21aSAndrei Baranouski
556a1508bdSLi Yang    def find_package(self, shell):
566a1508bdSLi Yang        for filename, url in self.get_expected_locations(shell):
57c7ecad54SAndrei Baranouski            try:
586a1508bdSLi Yang                self.log.info('Trying to get "{0}"'.format(url))
59c7ecad54SAndrei Baranouski                status_code = requests.head(url).status_code
60c7ecad54SAndrei Baranouski            except ConnectionError:
61c7ecad54SAndrei Baranouski                pass
62c7ecad54SAndrei Baranouski            else:
63c7ecad54SAndrei Baranouski                if status_code == 200:
646a1508bdSLi Yang                    self.log.info('Found "{0}"'.format(url))
65c7ecad54SAndrei Baranouski                    return filename, url
66dbd61406SAndrei Baranouski        self.log.fatal('Target build not found')
67c7ecad54SAndrei Baranouski
686a1508bdSLi Yang    def get_expected_locations(self, shell):
696a1508bdSLi Yang        self.info = shell.extract_remote_info()
705edf749cSLi Yang        distribution_type = self.info.distribution_type.lower()
715edf749cSLi Yang        if self.info.type.lower() == 'linux':
725edf749cSLi Yang            if distribution_type == 'centos':
735edf749cSLi Yang                file_ext = 'rpm'
745edf749cSLi Yang            elif distribution_type == 'ubuntu':
755edf749cSLi Yang                file_ext = 'deb'
765edf749cSLi Yang            elif distribution_type == 'mac':
775edf749cSLi Yang                file_ext = 'tar.gz'
78b742a21aSAndrei Baranouski        elif self.info.type.lower() == 'windows':
79b742a21aSAndrei Baranouski            file_ext = 'exe'
805edf749cSLi Yang
81c7ecad54SAndrei Baranouski        for location, patterns in self.BUILDS.items():
82c7ecad54SAndrei Baranouski            for pattern in patterns:
836f4184d7SAndrei Baranouski                url = '{0}/{1}'.format(location, pattern.format(self.version, self.info.architecture_type, file_ext))
84c7ecad54SAndrei Baranouski                filename = url.split('/')[-1]
85c7ecad54SAndrei Baranouski                yield filename, url
86c7ecad54SAndrei Baranouski
876a1508bdSLi Yang    def install(self, shell):
886a1508bdSLi Yang        self.kill_processes_gateway(shell)
896a1508bdSLi Yang        self.uninstall_gateway(shell)
906a1508bdSLi Yang        self.install_gateway(shell)
916a1508bdSLi Yang        self.start_sync_gateways(shell)
92c7ecad54SAndrei Baranouski
936a1508bdSLi Yang    def kill_processes_gateway(self, shell):
946a1508bdSLi Yang        self.log.info('=== Killing Sync Gateway')
95b742a21aSAndrei Baranouski        shell.terminate_process(process_name='sync_gateway')
96ded76c1cSAndrei Baranouski        shell.execute_command('killall sync_gateway')
97fd844442SAndrei Baranouski        shell.execute_command('pkill sync_gateway')  # centos 7
98c7ecad54SAndrei Baranouski
99c7ecad54SAndrei Baranouski    def uninstall_gateway(self, shell):
1006a1508bdSLi Yang        self.info = shell.extract_remote_info()
1015edf749cSLi Yang        type = self.info.type.lower()
1025edf749cSLi Yang        distribution_type = self.info.distribution_type.lower()
1035edf749cSLi Yang        if self.info.type.lower() == 'linux':
1045edf749cSLi Yang            if distribution_type == 'centos':
1056a1508bdSLi Yang                cmd = 'yes | yum remove couchbase-sync-gateway'
1065edf749cSLi Yang            elif distribution_type == 'ubuntu':
1076a1508bdSLi Yang                cmd = 'dpkg -r couchbase-sync-gateway'
1085edf749cSLi Yang            elif distribution_type == 'mac':
1095edf749cSLi Yang                cmd = 'sudo launchctl unload /Library/LaunchDaemons/com.couchbase.mobile.sync_gateway.plist'
1105edf749cSLi Yang            else:
1115edf749cSLi Yang                self.log.info('uninstall_gateway is not supported on {0}, {1}'.format(type, distribution_type))
112b742a21aSAndrei Baranouski            self.log.info('=== Un-installing Sync Gateway package on {0} - cmd: {1}'.format(self.master, cmd))
113b742a21aSAndrei Baranouski            output, error = shell.execute_command(cmd)
114b742a21aSAndrei Baranouski            shell.log_command_output(output, error)
115b742a21aSAndrei Baranouski        elif self.info.type.lower() == 'windows':
116b742a21aSAndrei Baranouski            cmd = "wmic product where name='Couchbase Sync Gateway' uninstall"
117b742a21aSAndrei Baranouski            self.log.info('=== Un-installing Sync Gateway package on {0} - cmd: {1}'.format(self.master, cmd))
118b742a21aSAndrei Baranouski            output, error = shell.execute_batch_command(cmd)
119b742a21aSAndrei Baranouski            shell.log_command_output(output, error)
120c7ecad54SAndrei Baranouski
121c7ecad54SAndrei Baranouski    def install_gateway(self, shell):
1226a1508bdSLi Yang        filename, url = self.find_package(shell)
1232d9c217bSAndrei Baranouski        type = shell.extract_remote_info().type.lower()
1245edf749cSLi Yang        distribution_type = self.info.distribution_type.lower()
1252d9c217bSAndrei Baranouski        if type == 'linux':
126ded76c1cSAndrei Baranouski            wget_str = 'wget'
1275edf749cSLi Yang            if distribution_type == 'centos':
1286a1508bdSLi Yang                cmd = 'yes | rpm -i /tmp/{0}'.format(filename)
1295edf749cSLi Yang            elif distribution_type == 'ubuntu':
1306a1508bdSLi Yang                cmd = 'yes | dpkg -i /tmp/{0}'.format(filename)
1315edf749cSLi Yang            elif distribution_type == 'mac':
1326f4184d7SAndrei Baranouski                filename_tar = re.sub('\.gz$', '', filename)
133fd844442SAndrei Baranouski                cmd = 'cd /tmp; gunzip {0}; tar xopf {1}; cp -r couchbase-sync-gateway /opt' \
1345edf749cSLi Yang                    .format(filename, filename_tar, filename_tar)
1355edf749cSLi Yang                wget_str = '/usr/local/bin/wget'
136b742a21aSAndrei Baranouski            else:
137b742a21aSAndrei Baranouski                self.log.info('install_gateway is not supported on {0}, {1}'.format(type, distribution_type))
138fd844442SAndrei Baranouski            output, error = shell.execute_command_raw(
139fd844442SAndrei Baranouski                'cd /tmp; {0} -q -O {1} {2};ls -lh'.format(wget_str, filename, url))
140b742a21aSAndrei Baranouski
1412d9c217bSAndrei Baranouski        elif type == 'windows':
142fd844442SAndrei Baranouski            cmd = "cd /cygdrive/c/tmp;cmd /c 'couchbase-sync-gateway.exe /S /v/qn'"  # couchbase-sync-gateway.exe /v"/l*v C:\install.log /qb
143b742a21aSAndrei Baranouski            output, error = shell.execute_command(
144fd844442SAndrei Baranouski                "cd /cygdrive/c/tmp;cmd /c 'c:\\automation\\wget.exe --no-check-certificate -q"
145fd844442SAndrei Baranouski                " {0} -O {1}.exe';ls -lh;".format(url, "couchbase-sync-gateway"))
146c7ecad54SAndrei Baranouski        shell.log_command_output(output, error)
1476a1508bdSLi Yang        output, error = shell.execute_command_raw(cmd)
148c7ecad54SAndrei Baranouski        shell.log_command_output(output, error)
1492d9c217bSAndrei Baranouski        if type == 'windows':
150b742a21aSAndrei Baranouski            exist = shell.file_exists('/cygdrive/c/Program Files (x86)/Couchbase', 'sync_gateway.exe')
151b742a21aSAndrei Baranouski        else:
152fd844442SAndrei Baranouski            exist = shell.file_exists(self.installed_folder.replace("\\", ""), 'sync_gateway')
1536a1508bdSLi Yang        if exist:
1546a1508bdSLi Yang            return True
1556a1508bdSLi Yang        else:
1562d9c217bSAndrei Baranouski            self.log.error('Installed file not found - {0}/sync_gateway'.format(self.installed_folder))
1576a1508bdSLi Yang            return False
158c7ecad54SAndrei Baranouski
159c7ecad54SAndrei Baranouski    def start_sync_gateways(self, shell):
1602d9c217bSAndrei Baranouski        type = shell.extract_remote_info().type.lower()
1616a1508bdSLi Yang        self.log.info('=== Starting Sync Gateway instances')
162b742a21aSAndrei Baranouski        shell.copy_files_local_to_remote('pytests/sg/resources', self.folder_prefix + '/tmp')
1632d9c217bSAndrei Baranouski        if type == 'windows':
16467241ba6SAndrei Baranouski            output, error = shell.execute_command_raw('{0}/sync_gateway.exe'
165fd844442SAndrei Baranouski                                                      ' c:/tmp/gateway_config.json > {1}/tmp/gateway.log 2>&1 &'.
1662d9c217bSAndrei Baranouski                                                      format(self.installed_folder, self.folder_prefix))
1672d9c217bSAndrei Baranouski        else:
168213da98aSAndrei Baranouski            output, error = shell.execute_command_raw('nohup {0}/sync_gateway'
169fd844442SAndrei Baranouski                                                      ' /tmp/gateway_config.json >/tmp/gateway.log 2>&1 &'.
1702d9c217bSAndrei Baranouski                                                      format(self.installed_folder))
1716a1508bdSLi Yang        shell.log_command_output(output, error)
172c7ecad54SAndrei Baranouski
173e0c00442SAndrei Baranouski    def start_simpleServe(self, shell):
174e0c00442SAndrei Baranouski        self.log.info('=== Starting SimpleServe instances')
175fd844442SAndrei Baranouski        shell.copy_file_local_to_remote("pytests/sg/simpleServe.go",
176fd844442SAndrei Baranouski                                        "{0}/tmp/simpleServe.go".format(self.folder_prefix))
17767241ba6SAndrei Baranouski        type = shell.extract_remote_info().type.lower()
17867241ba6SAndrei Baranouski        if type == 'windows':
17967241ba6SAndrei Baranouski            shell.terminate_process(process_name='simpleServe.exe')
18067241ba6SAndrei Baranouski            output, error = shell.execute_command_raw('c:/Go/bin/go.exe run c:/tmp/simpleServe.go 8081'
181fd844442SAndrei Baranouski                                                      ' >{0}/tmp/simpleServe.txt 2>&1 &'.format(self.folder_prefix))
18267241ba6SAndrei Baranouski        else:
18304e89234SAndrei Baranouski            shell.terminate_process(process_name='simpleServe')
18467241ba6SAndrei Baranouski            shell.execute_command("kill $(ps aux | grep '8081' | awk '{print $2}')")
18567241ba6SAndrei Baranouski            output, error = shell.execute_command_raw('go run {0}/tmp/simpleServe.go 8081'
186fd844442SAndrei Baranouski                                                      '  >{0}/tmp/simpleServe.txt 2>&1 &'.format(self.folder_prefix))
187e0c00442SAndrei Baranouski        shell.log_command_output(output, error)
188e0c00442SAndrei Baranouski
1895edf749cSLi Yang    def add_user(self, shell, user_name):
1905edf749cSLi Yang        self.log.info('=== Add user {0}'.format(user_name))
1916a1508bdSLi Yang        self.info = shell.extract_remote_info()
1925edf749cSLi Yang        distribution_type = self.info.distribution_type.lower()
1935edf749cSLi Yang        if self.info.type.lower() == 'linux':
1945edf749cSLi Yang            if distribution_type == 'centos' or distribution_type == 'ubuntu':
1956f4184d7SAndrei Baranouski                if not self.check_user(shell, user_name):
1965edf749cSLi Yang                    output, error = shell.execute_command_raw('useradd -m {0}'.format(user_name))
197ded76c1cSAndrei Baranouski                    shell.log_command_output(output, error)
1986f4184d7SAndrei Baranouski                return self.check_user(shell, user_name)
1996a1508bdSLi Yang            else:
20067241ba6SAndrei Baranouski                self.log.info('add_user is not supported on Mac/Wind')
2015edf749cSLi Yang                return False
2025edf749cSLi Yang        else:
203ded76c1cSAndrei Baranouski            type = self.info.type.lower()
2045edf749cSLi Yang            self.log.info('add_user is not supported on {0}, {1}'.format(type, distribution_type))
2056a1508bdSLi Yang            return False
2065edf749cSLi Yang
2075edf749cSLi Yang    def remove_user(self, shell, user_name):
2085edf749cSLi Yang        self.log.info('=== Remove user {0}'.format(user_name))
2095edf749cSLi Yang        self.info = shell.extract_remote_info()
2105edf749cSLi Yang        type = self.info.type.lower()
2115edf749cSLi Yang        distribution_type = self.info.distribution_type.lower()
2125edf749cSLi Yang        if type == 'linux':
2135edf749cSLi Yang            if distribution_type == 'centos' or distribution_type == 'ubuntu':
2146f4184d7SAndrei Baranouski                if self.check_user(shell, user_name):
2155edf749cSLi Yang                    output, error = shell.execute_command_raw('userdel {0}'.format(user_name))
216ded76c1cSAndrei Baranouski                    shell.log_command_output(output, error)
2176f4184d7SAndrei Baranouski                return not self.check_user(shell, user_name)
2185edf749cSLi Yang            else:
2195edf749cSLi Yang                self.log.info('remove_user is only supported on centos and ubuntu')
2205edf749cSLi Yang                return False
2215edf749cSLi Yang        else:
2225edf749cSLi Yang            self.log.info('remove_user is not supported on {0}, {1}'.format(type, distribution_type))
2235edf749cSLi Yang            return False
2245edf749cSLi Yang
2255edf749cSLi Yang    def check_user(self, shell, user_name):
2265edf749cSLi Yang        self.log.info('=== Check user {0} exists'.format(user_name))
2275edf749cSLi Yang        self.info = shell.extract_remote_info()
2285edf749cSLi Yang        distribution_type = self.info.distribution_type.lower()
2295edf749cSLi Yang        if self.info.type.lower() == 'linux':
2305edf749cSLi Yang            if distribution_type == 'centos' or distribution_type == 'ubuntu':
2315edf749cSLi Yang                output, error = shell.execute_command_raw('cat /etc/passwd | grep {0} '.format(user_name))
2325edf749cSLi Yang                shell.log_command_output(output, error)
2335edf749cSLi Yang                if output and output[0].startswith('{0}:'.format(user_name)):
2345edf749cSLi Yang                    self.log.info('User {0} exists'.format(user_name))
2355edf749cSLi Yang                    return True
2365edf749cSLi Yang                else:
2375edf749cSLi Yang                    self.log.info('User {0} does not exists'.format(user_name))
2385edf749cSLi Yang                    return False
2395edf749cSLi Yang            else:
2405edf749cSLi Yang                self.log.info('check_user is only supported on centos and ubuntu')
2415edf749cSLi Yang                return False
2425edf749cSLi Yang        else:
243ded76c1cSAndrei Baranouski            type = self.info.type.lower()
2445edf749cSLi Yang            self.log.info('check_user is not supported on {0}, {1}', type, distribution_type)
2455edf749cSLi Yang            return False
2465edf749cSLi Yang
2475edf749cSLi Yang    def is_sync_gateway_service_running(self, shell):
2485edf749cSLi Yang        self.info = shell.extract_remote_info()
2495edf749cSLi Yang        type = self.info.type.lower()
2505edf749cSLi Yang        distribution_type = self.info.distribution_type.lower()
2515edf749cSLi Yang        distribution_version = self.info.distribution_version
2525edf749cSLi Yang        if self.info.type.lower() == 'linux':
2535edf749cSLi Yang            if distribution_type == 'centos' and distribution_version == 'CentOS 7':
254fd844442SAndrei Baranouski                cmd = 'systemctl | grep sync_gateway'
255fd844442SAndrei Baranouski                service_str = 'sync_gateway.service                                                       ' \
256fd844442SAndrei Baranouski                              '               loaded active running'
2575edf749cSLi Yang            elif distribution_type == 'ubuntu' or \
2585edf749cSLi Yang                    (distribution_type == 'centos' and distribution_version != 'CentOS 7'):
2595edf749cSLi Yang                cmd = 'initctl list | grep sync_gateway'
2605edf749cSLi Yang                service_str = 'sync_gateway start/running, process '
2615edf749cSLi Yang            elif distribution_type == 'mac':
2625edf749cSLi Yang                cmd = 'launchctl  list | grep sync_gateway'
2635edf749cSLi Yang                service_str = ''
2645edf749cSLi Yang            else:
2655edf749cSLi Yang                self.log.info('is_sync_gateway_service_running is not supported on {0}, {1}'
2665edf749cSLi Yang                              .format(type, distribution_type))
2675edf749cSLi Yang                return False
2685edf749cSLi Yang        else:
269fd844442SAndrei Baranouski            self.log.info(
270fd844442SAndrei Baranouski                'is_sync_gateway_service_running is not supported on {0}, {1}'.format(type, distribution_type))
2716a1508bdSLi Yang            return False
2726a1508bdSLi Yang
2736a1508bdSLi Yang        self.log.info('=== Check whether Sync Gateway service is running on {0} - cmd: {1}'.format(self.master, cmd))
2746a1508bdSLi Yang        output, error = shell.execute_command_raw(cmd)
2756a1508bdSLi Yang        shell.log_command_output(output, error)
2765edf749cSLi Yang        if output and output[0].startswith(service_str):
2776a1508bdSLi Yang            self.log.info('Sync Gateway service is running')
2786a1508bdSLi Yang            return True
2796a1508bdSLi Yang        else:
2806a1508bdSLi Yang            self.log.info('Sync Gateway service is NOT running')
2816a1508bdSLi Yang            return False
2826a1508bdSLi Yang
2835edf749cSLi Yang    def start_gateway_service(self, shell):
2845edf749cSLi Yang        self.info = shell.extract_remote_info()
2855edf749cSLi Yang        type = self.info.type.lower()
2865edf749cSLi Yang        distribution_type = self.info.distribution_type.lower()
2875edf749cSLi Yang        distribution_version = self.info.distribution_version
2885edf749cSLi Yang        if self.info.type.lower() == 'linux':
2895edf749cSLi Yang            if distribution_type == 'centos':
290ded76c1cSAndrei Baranouski                if distribution_version == 'CentOS 7':
2915edf749cSLi Yang                    cmd = 'systemctl start sync_gateway'
2925edf749cSLi Yang                else:
2935edf749cSLi Yang                    cmd = 'start sync_gateway'
2945edf749cSLi Yang            elif distribution_type == 'ubuntu':
2955edf749cSLi Yang                cmd = 'service sync_gateway start'
2965edf749cSLi Yang            elif distribution_type == 'mac':
2975edf749cSLi Yang                cmd = 'launchctl start com.couchbase.mobile.sync_gateway'
2985edf749cSLi Yang            else:
2995edf749cSLi Yang                self.log.info('start_gateway_service is not supported on {0}, {1}'.format(type, distribution_type))
3005edf749cSLi Yang                return False
3015edf749cSLi Yang        else:
3025edf749cSLi Yang            self.log.info('start_gateway_service is not supported on {0}, {1}'.format(type, distribution_type))
3035edf749cSLi Yang            return False
3045edf749cSLi Yang
3055edf749cSLi Yang        self.log.info('=== Starting gateway service')
3065edf749cSLi Yang        output, error = shell.execute_command_raw(cmd)
3075edf749cSLi Yang        return output, error
3085edf749cSLi Yang
3095edf749cSLi Yang    def stop_gateway_service(self, shell):
3105edf749cSLi Yang        self.info = shell.extract_remote_info()
3115edf749cSLi Yang        distribution_type = self.info.distribution_type.lower()
3125edf749cSLi Yang        distribution_version = self.info.distribution_version
3135edf749cSLi Yang        if self.info.type.lower() == 'linux':
3145edf749cSLi Yang            if distribution_type == 'centos':
3155edf749cSLi Yang                if (distribution_version == 'CentOS 7'):
3165edf749cSLi Yang                    cmd = 'systemctl stop sync_gateway'
3175edf749cSLi Yang                else:
3185edf749cSLi Yang                    cmd = 'stop sync_gateway'
3195edf749cSLi Yang            elif distribution_type == 'mac':
3205edf749cSLi Yang                cmd = 'launchctl stop com.couchbase.mobile.sync_gateway'
3215edf749cSLi Yang            else:
3225edf749cSLi Yang                cmd = 'service sync_gateway stop'
3235edf749cSLi Yang
3245edf749cSLi Yang        self.log.info('=== Stopping gateway service')
3255edf749cSLi Yang        output, error = shell.execute_command_raw(cmd)
3265edf749cSLi Yang        return output, error
3275edf749cSLi Yang
3286a1508bdSLi Yang    def is_sync_gateway_process_running(self, shell):
3295edf749cSLi Yang        self.log.info('=== Check whether Sync Gateway process is running on {0}'.format(self.master))
3305edf749cSLi Yang        obj = RemoteMachineHelper(shell).is_process_running('sync_gateway')
3316a1508bdSLi Yang        if obj and obj.pid:
3326a1508bdSLi Yang            self.log.info('Sync Gateway is running with pid of {0}'.format(obj.pid))
3336a1508bdSLi Yang            return True
3346a1508bdSLi Yang        else:
3356a1508bdSLi Yang            self.log.info('Sync Gateway is NOT running')
3366a1508bdSLi Yang            return False
3376a1508bdSLi Yang
3386a1508bdSLi Yang    def service_clean(self, shell):
3396a1508bdSLi Yang        self.log.info('=== Cleaning Sync Gateway service and remove files')
340c7ecad54SAndrei Baranouski        self.uninstall_gateway(shell)
341ded76c1cSAndrei Baranouski        shell.execute_command_raw(
342b742a21aSAndrei Baranouski            'rm -rf /tmp/*.log /tmp/*.json /tmp/logs /tmp/data /tmp/sync_gateway/* '
3435edf749cSLi Yang            '/dirNotExist /opt/couchbase-sync-gateway* /tmp/couchbase-sync-gateway '
3445edf749cSLi Yang            '/tmp/couchbase-sync-gateway*tar')
3456a1508bdSLi Yang        # return true only if the service is not running
3466a1508bdSLi Yang        if self.is_sync_gateway_service_running(shell):
3475edf749cSLi Yang            self.log.error('Fail to clean Sync Gateway service.   The service is still running')
3486a1508bdSLi Yang            return False
3496a1508bdSLi Yang        else:
3506a1508bdSLi Yang            return True
3516a1508bdSLi Yang
3526a1508bdSLi Yang    def service_install(self, shell):
353c7ecad54SAndrei Baranouski        self.install_gateway(shell)
3546a1508bdSLi Yang        self.run_sync_gateway_service_install(shell)
355c7ecad54SAndrei Baranouski
3565edf749cSLi Yang    def run_sync_gateway_service_install(self, shell, options=''):
3575edf749cSLi Yang        self.info = shell.extract_remote_info()
3585edf749cSLi Yang        if self.servers[0].ssh_username == 'root':
3595edf749cSLi Yang            cmd = 'cd /opt/couchbase-sync-gateway/service; . ./sync_gateway_service_install.sh '
3605edf749cSLi Yang        else:
361fd844442SAndrei Baranouski            cmd = 'cd /opt/couchbase-sync-gateway/service;  echo {0} | sudo . ./sync_gateway_service_install.sh ' \
3625edf749cSLi Yang                .format(self.servers[0].ssh_password)
3636f4184d7SAndrei Baranouski        output, error = shell.execute_command(cmd + options)
364c7ecad54SAndrei Baranouski        shell.log_command_output(output, error)
365c7ecad54SAndrei Baranouski        return output, error
366c7ecad54SAndrei Baranouski
3675edf749cSLi Yang    def check_normal_error_output(self, shell, output, error):
3685edf749cSLi Yang        self.info = shell.extract_remote_info()
3695edf749cSLi Yang        type = self.info.type.lower()
3705edf749cSLi Yang        distribution_type = self.info.distribution_type.lower()
3715edf749cSLi Yang        distribution_version = self.info.distribution_version.lower()
3725edf749cSLi Yang        if type == 'linux':
3735edf749cSLi Yang            if distribution_type == 'centos' and distribution_version == 'centos 7':
3745edf749cSLi Yang                if error[0].startswith('ln -s ') and 'sync_gateway.service' in error[0]:
3755edf749cSLi Yang                    if output == []:
3765edf749cSLi Yang                        return True
3775edf749cSLi Yang                    else:
3785edf749cSLi Yang                        self.log.error('check_normal_error_output: On CentOS 7, expect output to be null, but got {0}'
379fd844442SAndrei Baranouski                                       .format(output[0]))
3805edf749cSLi Yang                        return False
3815edf749cSLi Yang                else:
3825edf749cSLi Yang                    self.log.error('check_normal_error_output: On CentOS 7, expect error: '
3835edf749cSLi Yang                                   'ln -s \'/usr/lib/systemd/system/sync_gateway.service\'..., but got {0}'
3845edf749cSLi Yang                                   .format(error[0]))
3855edf749cSLi Yang                    return False
3865edf749cSLi Yang            elif distribution_type == 'ubuntu' or \
3875edf749cSLi Yang                    (distribution_type == 'centos' and distribution_version != 'centos 7'):
3885edf749cSLi Yang                if error == []:
3895edf749cSLi Yang                    if 'sync_gateway start/running' in output[0]:
3905edf749cSLi Yang                        return True
3915edf749cSLi Yang                    else:
3925edf749cSLi Yang                        self.log.error('check_normal_error_output: On linux, expect output to be: '
3935edf749cSLi Yang                                       '\'sync_gateway start/running\', but got {0}'.format(output[0]))
3945edf749cSLi Yang                        return False
3955edf749cSLi Yang                else:
3965edf749cSLi Yang                    self.log.error('check_normal_error_output: On linux, expect error to be null, but got {0}'
3975edf749cSLi Yang                                   .format(error[0]))
3985edf749cSLi Yang                    return False
3995edf749cSLi Yang            elif distribution_type == 'mac':
4005edf749cSLi Yang                if error == []:
4015edf749cSLi Yang                    expect_output = 'launchctl load /Library/LaunchDaemons/com.couchbase.mobile.sync_gateway.plist'
4025edf749cSLi Yang                    if output[0] == expect_output:
4035edf749cSLi Yang                        return True
4045edf749cSLi Yang                    else:
4055edf749cSLi Yang                        self.log.error('Expect output to be "{0}", but got {1}'.format(expect_output, output[0]))
4065edf749cSLi Yang                        return False
4075edf749cSLi Yang                else:
4085edf749cSLi Yang                    self.log.error('Expect error to be null, but got {0}'.format(error[0]))
4095edf749cSLi Yang                    return False
4105edf749cSLi Yang            else:
4115edf749cSLi Yang                self.log.info('check_normal_error_output is not supported on {0}, {1}'.format(type, distribution_type))
4125edf749cSLi Yang                return False
4135edf749cSLi Yang        else:
4145edf749cSLi Yang            self.log.info('check_normal_error_output is not supported on {0}, {1}'.format(type, distribution_type))
4155edf749cSLi Yang            return False
4165edf749cSLi Yang
4175edf749cSLi Yang    def check_job_already_running(self, shell, output, error):
4185edf749cSLi Yang        self.info = shell.extract_remote_info()
4195edf749cSLi Yang        type = self.info.type.lower()
4205edf749cSLi Yang        distribution_type = self.info.distribution_type.lower()
4215edf749cSLi Yang        distribution_version = self.info.distribution_version.lower()
4225edf749cSLi Yang        if type == 'linux':
4235edf749cSLi Yang            if (distribution_type == 'centos') and (distribution_version == 'centos 7'):
4245edf749cSLi Yang                if error == []:
4255edf749cSLi Yang                    if output == []:
4265edf749cSLi Yang                        return True
4275edf749cSLi Yang                    else:
4285edf749cSLi Yang                        self.log.error('check_job_already_running: On CentOS 7, expect output to be null, but got {0}'
429fd844442SAndrei Baranouski                                       .format(output[0]))
4305edf749cSLi Yang                        return False
4315edf749cSLi Yang                else:
4325edf749cSLi Yang                    self.log.error('check_job_already_running: On CentOS 7, expect error to be null, but got {0}'
4335edf749cSLi Yang                                   .format(error[0]))
4345edf749cSLi Yang                    return False
4355edf749cSLi Yang            elif distribution_type == 'ubuntu' or distribution_type == 'mac' or \
4365edf749cSLi Yang                    (distribution_type == 'centos' and distribution_version != 'centos 7'):
4375edf749cSLi Yang                if 'is already running' in error[0]:
4385edf749cSLi Yang                    if output == []:
4395edf749cSLi Yang                        return True
4405edf749cSLi Yang                    else:
4415edf749cSLi Yang                        self.log.error('check_job_already_running: On linux, expect output to be null, but got {0}'
442fd844442SAndrei Baranouski                                       .format(output[0]))
4435edf749cSLi Yang                        return False
4445edf749cSLi Yang                else:
445fd844442SAndrei Baranouski                    self.log.error(
446fd844442SAndrei Baranouski                        'check_job_already_running: On linux, expect error to contain: \'is already running\' '
447fd844442SAndrei Baranouski                        ' but get {0}'.format(error[0]))
4485edf749cSLi Yang                    return False
4495edf749cSLi Yang            else:
4505edf749cSLi Yang                self.log.info('check_job_already_running is not supported on {0}, {1}'.format(type, distribution_type))
4515edf749cSLi Yang                return False
4525edf749cSLi Yang        else:
4535edf749cSLi Yang            self.log.info('check_job_already_running is not supported on {0}, {1}'.format(type, distribution_type))
4546f4184d7SAndrei Baranouski            return False
4550d4c20d3SAndrei Baranouski
4560d4c20d3SAndrei Baranouski    def check_status_in_gateway_log(self, shell):
457fd844442SAndrei Baranouski        logs = shell.read_remote_file('{0}/tmp/'.format(self.folder_prefix), 'gateway.log')[-5:]  # last 5 lines
45867241ba6SAndrei Baranouski        self.log.info(logs)
45967241ba6SAndrei Baranouski        status = re.search(".* got status (\w+)", logs[4])
4600d4c20d3SAndrei Baranouski        if not status:
46167241ba6SAndrei Baranouski            self.log.info('check_status_in_gateway_log failed, sync_gateway log has: {0}'.format(logs[4]))
4620d4c20d3SAndrei Baranouski            return ''
4630d4c20d3SAndrei Baranouski        else:
4640d4c20d3SAndrei Baranouski            return status.group(1)
4650d4c20d3SAndrei Baranouski
4660d4c20d3SAndrei Baranouski    def check_message_in_gatewaylog(self, shell, expected_str):
4670d4c20d3SAndrei Baranouski        if not expected_str:
4680d4c20d3SAndrei Baranouski            return True
4690d4c20d3SAndrei Baranouski        for i in range(3):
470fd844442SAndrei Baranouski            output, error = shell.execute_command_raw(
471fd844442SAndrei Baranouski                'grep \'{0}\' {1}/tmp/gateway.log'.format(expected_str, self.folder_prefix))
4720d4c20d3SAndrei Baranouski            shell.log_command_output(output, error)
4730d4c20d3SAndrei Baranouski            if not output or not output[0]:
4740d4c20d3SAndrei Baranouski                if i < 2:
4750d4c20d3SAndrei Baranouski                    time.sleep(1)
4760d4c20d3SAndrei Baranouski                    continue
4770d4c20d3SAndrei Baranouski                else:
4780d4c20d3SAndrei Baranouski                    self.log.info('check_message_in_gatewaylog did not find expected error - {0}'.format(expected_str))
479b7ea7bb9SAndrei Baranouski                    output, error = shell.execute_command_raw('cat {0}/tmp/gateway.log'.format(self.folder_prefix))
4800d4c20d3SAndrei Baranouski                    shell.log_command_output(output, error)
4810d4c20d3SAndrei Baranouski                    return False
4820d4c20d3SAndrei Baranouski            else:
483fd844442SAndrei Baranouski                return True
484