Skip to content

Commit 7d0767a

Browse files
committed
CBPS-1148: Prepare perfrunner for using Ubuntu 20 for on-prem servers
Change-Id: I75c19917d448a098aa5e574146fc68c1f3ded1a7 Reviewed-on: https://review.couchbase.org/c/perfrunner/+/190697 Tested-by: Build Bot <[email protected]> Reviewed-by: Salim Salim <[email protected]> Reviewed-by: Bo-Chun Wang <[email protected]>
1 parent 556c94e commit 7d0767a

File tree

23 files changed

+252
-251
lines changed

23 files changed

+252
-251
lines changed

cbagent/collectors/libstats/iostat.py

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,11 @@
1-
from typing import Dict, Union
1+
from typing import Dict, Optional, Tuple
22

33
from cbagent.collectors.libstats.remotestats import RemoteStats, parallel_task
44

55

66
class IOStat(RemoteStats):
77

8-
METRICS_Centos = (
9-
("rps", "r/s", 1),
10-
("wps", "w/s", 1),
11-
("rbps", "rkB/s", 1024), # kB -> B
12-
("wbps", "wkB/s", 1024), # kB -> B
13-
("avgqusz", "avgqu-sz", 1),
14-
("await", "await", 1),
15-
("util", "%util", 1),
16-
)
17-
18-
METRICS_Ubuntu = (
8+
METRICS = (
199
("rps", "r/s", 1),
2010
("wps", "w/s", 1),
2111
("rbps", "rkB/s", 1024), # kB -> B
@@ -24,7 +14,7 @@ class IOStat(RemoteStats):
2414
("util", "%util", 1),
2515
)
2616

27-
def get_device_name(self, path: str) -> [Union[None, str], bool]:
17+
def get_device_name(self, path: str) -> Tuple[Optional[str], bool]:
2818
stdout = self.run("df '{}' | head -2 | tail -1".format(path),
2919
quiet=True)
3020
if not stdout.return_code:
@@ -50,33 +40,21 @@ def get_iostat(self, device: str) -> Dict[str, str]:
5040

5141
@parallel_task(server_side=True)
5242
def get_server_samples(self, partitions: dict) -> dict:
53-
return self.get_samples_centos(partitions['server'])
43+
return self.get_samples(partitions['server'], self.METRICS)
5444

5545
@parallel_task(server_side=False)
5646
def get_client_samples(self, partitions: dict) -> dict:
57-
return self.get_samples_ubuntu(partitions['client'])
58-
59-
def get_samples_centos(self, partitions: Dict[str, str]) -> Dict[str, float]:
60-
samples = {}
61-
62-
for purpose, path in partitions.items():
63-
device, _ = self.get_device_name(path)
64-
if device is not None:
65-
stats = self.get_iostat(device)
66-
for metric, column, multiplier in self.METRICS_Centos:
67-
key = "{}_{}".format(purpose, metric)
68-
samples[key] = float(stats[column]) * multiplier
69-
70-
return samples
47+
return self.get_samples(partitions['client'], self.METRICS)
7148

72-
def get_samples_ubuntu(self, partitions: Dict[str, str]) -> Dict[str, float]:
49+
def get_samples(self, partitions: Dict[str, str],
50+
metrics: Tuple[Tuple[str, str, int]]) -> Dict[str, float]:
7351
samples = {}
7452

7553
for purpose, path in partitions.items():
7654
device, _ = self.get_device_name(path)
7755
if device is not None:
7856
stats = self.get_iostat(device)
79-
for metric, column, multiplier in self.METRICS_Ubuntu:
57+
for metric, column, multiplier in metrics:
8058
key = "{}_{}".format(purpose, metric)
8159
samples[key] = float(stats[column]) * multiplier
8260

cbagent/collectors/libstats/pcstat.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Tuple
2+
13
import numpy
24

35
from cbagent.collectors.libstats.remotestats import RemoteStats, parallel_task
@@ -17,7 +19,7 @@ def get_pcstat(self, partition: str) -> float:
1719
percents.append(float(percent))
1820
return numpy.average(percents)
1921

20-
def get_cachestat(self) -> [float, float]:
22+
def get_cachestat(self) -> Tuple[float, float]:
2123
stdout = self.run('cachestat')
2224
total_hits, hit_ratio = stdout.split()
2325
return float(total_hits), float(hit_ratio)

perfrunner/helpers/cbmonitor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ def add_collectors(self,
212212

213213
if not self.test.dynamic_infra:
214214
if not self.test.capella_infra:
215-
if self.test.remote.os != 'Cygwin':
215+
if self.test.remote.PLATFORM != 'cygwin':
216216
self.add_collector(PS)
217217
self.add_collector(Sysdig)
218218
if memory:

perfrunner/helpers/cluster.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,7 @@ def throttle_cpu(self):
913913
cluster['spec']['servers'] = updated_server_groups
914914
self.remote.update_cluster_config(cluster)
915915
else:
916-
if self.remote.os == 'Cygwin':
916+
if self.remote.PLATFORM == 'cygwin':
917917
return
918918

919919
if self.test_config.cluster.enable_cpu_cores:
@@ -1045,9 +1045,13 @@ def set_min_tls_version(self):
10451045
check_tls_version = self.rest.get_minimum_tls_version(self.master_node)
10461046
logger.info('new tls version: {}'.format(check_tls_version))
10471047

1048-
def get_debug_rpm_url(self):
1048+
def get_debug_package_url(self):
10491049
release, build_number = self.build.split('-')
1050-
if self.build_tuple > (7, 2, 0, 0):
1050+
if self.build_tuple > (8, 0, 0, 0):
1051+
release = 'morpheus'
1052+
elif self.build_tuple > (7, 6, 0, 0):
1053+
release = 'trinity'
1054+
elif (7, 2, 0, 0) < self.build_tuple <= (7, 2, 0, 2228) or self.build_tuple > (7, 5, 0, 0):
10511055
release = 'elixir'
10521056
elif self.build_tuple > (7, 1, 0, 0):
10531057
release = 'neo'
@@ -1057,16 +1061,21 @@ def get_debug_rpm_url(self):
10571061
release = 'mad-hatter'
10581062
elif self.build_tuple < (6, 5, 0, 0):
10591063
release = 'alice'
1060-
centos_version = self.remote.detect_centos_release()
10611064

1062-
rpm_url = 'http://latestbuilds.service.couchbase.com/builds/' \
1063-
'latestbuilds/couchbase-server/{}/{}/' \
1064-
'couchbase-server-enterprise-debuginfo-{}-centos{}.x86_64.rpm' \
1065-
''.format(release, build_number, self.build, centos_version)
1066-
return rpm_url
1065+
if self.remote.distro.upper() in ['UBUNTU', 'DEBIAN']:
1066+
package_name = 'couchbase-server-enterprise-dbg_{{}}-{{}}{{}}_amd64.deb'
1067+
else:
1068+
package_name = 'couchbase-server-enterprise-debuginfo-{{}}-{{}}{{}}.x86_64.rpm'
1069+
1070+
package_name = package_name.format(self.build, self.remote.distro,
1071+
self.remote.distro_version)
1072+
return (
1073+
'http://latestbuilds.service.couchbase.com/'
1074+
'builds/latestbuilds/couchbase-server/{}/{}/{}'
1075+
).format(release, build_number, package_name)
10671076

1068-
def install_cb_debug_rpm(self):
1069-
self.remote.install_cb_debug_rpm(url=self.get_debug_rpm_url())
1077+
def install_cb_debug_package(self):
1078+
self.remote.install_cb_debug_package(url=self.get_debug_package_url())
10701079

10711080
def enable_developer_preview(self):
10721081
if self.build_tuple > (7, 0, 0, 4698) or self.build_tuple < (1, 0, 0, 0):

perfrunner/helpers/local.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ def run_kvgen(hostname: str, num_docs: int, prefix: str):
551551

552552

553553
def build_ycsb(ycsb_client: str):
554-
cmd = 'pyenv local system && bin/ycsb build {}'.format(ycsb_client)
554+
cmd = 'pyenv local 2 && bin/ycsb build {}'.format(ycsb_client)
555555

556556
logger.info('Running: {}'.format(cmd))
557557
with lcd('YCSB'):
@@ -629,7 +629,7 @@ def run_ycsb(host: str,
629629
'-p couchbase.retryUpper={retry_upper} ' \
630630
'-p couchbase.retryFactor={retry_factor} '
631631

632-
cmd = 'pyenv local system && ' + cmd
632+
cmd = 'pyenv local 2 && ' + cmd
633633

634634
if durability is None:
635635
cmd += '-p couchbase.persistTo={persist_to} '

perfrunner/helpers/remote.py

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Tuple
2+
13
from fabric import state
24
from fabric.api import run, settings
35

@@ -14,7 +16,7 @@ def __new__(cls, cluster_spec: ClusterSpec, verbose: bool = False):
1416
if not cluster_spec.ssh_credentials:
1517
return None
1618
if cluster_spec.dynamic_infrastructure:
17-
return RemoteKubernetes(cluster_spec, 'kubernetes')
19+
return RemoteKubernetes(cluster_spec)
1820

1921
state.env.user, state.env.password = cluster_spec.ssh_credentials
2022
state.output.running = verbose
@@ -23,32 +25,33 @@ def __new__(cls, cluster_spec: ClusterSpec, verbose: bool = False):
2325
if cluster_spec.capella_infrastructure:
2426
state.env.use_ssh_config = True
2527

26-
if cluster_spec.cloud_infrastructure:
27-
if cluster_spec.infrastructure_settings.get('os_arch', 'x86_64') == 'arm':
28-
os = 'arm'
29-
elif cluster_spec.infrastructure_settings.get('os_arch', 'x86_64') == 'al2':
30-
os = 'al2'
31-
elif cluster_spec.capella_infrastructure:
32-
os = 'linux'
33-
else:
34-
os = cls.detect_server_os(cluster_spec.servers[0], cluster_spec)
35-
else:
36-
os = cls.detect_server_os(cluster_spec.servers[0], cluster_spec)
37-
if os == 'Cygwin':
38-
return RemoteWindows(cluster_spec, os)
39-
else:
40-
return RemoteLinux(cluster_spec, os)
28+
os_platform = cls.detect_os_platform(cluster_spec.servers[0], cluster_spec.ssh_credentials)
29+
30+
if os_platform.startswith('cygwin'):
31+
return RemoteWindows(cluster_spec)
32+
33+
return RemoteLinux(cluster_spec)
4134

4235
@staticmethod
43-
def detect_server_os(server: str, cluster_spec: ClusterSpec):
44-
state.env.user, state.env.password = cluster_spec.ssh_credentials
45-
logger.info('Detecting OS on server {}'.format(server))
46-
with settings(host_string=server):
47-
os = run('python -c "import platform; print platform.dist()[0]"')
48-
if os:
49-
return os
50-
else:
51-
return 'Cygwin'
36+
def detect_os_platform(host: str, credentials: Tuple[str, str]) -> str:
37+
state.env.user, state.env.password = credentials
38+
logger.info('Detecting OS platform on host {} using Python'.format(host))
39+
40+
with settings(host_string=host):
41+
platform = run('python3 -c "import platform; print(platform.system())"', warn_only=True)
42+
if platform.return_code != 0:
43+
platform = run('python -c "import platform; print platform.system()"',
44+
warn_only=True)
45+
46+
if not platform:
47+
logger.warn('Could not determine OS platform on host {}. Assuming "linux" by default.'
48+
.format(host))
49+
platform = 'linux'
50+
51+
platform = platform.lower()
52+
logger.info('Detected OS platform is {}'.format(platform))
53+
54+
return platform
5255

5356
@staticmethod
5457
def detect_client_os(server: str, cluster_spec: ClusterSpec):

perfrunner/remote/__init__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ class Remote:
1717

1818
CLIENT_PROCESSES = 'celery', 'cbc-pillowfight', 'memcached', 'cblite'
1919

20-
def __init__(self, cluster_spec, os):
21-
self.os = os
20+
def __init__(self, cluster_spec):
2221
self.cluster_spec = cluster_spec
2322

2423
@staticmethod
@@ -85,7 +84,7 @@ def clone_git_repo(self, repo: str, branch: str, worker_home: str, commit: str =
8584

8685
@all_clients
8786
def build_ycsb(self, worker_home: str, ycsb_client: str):
88-
cmd = 'pyenv local system && bin/ycsb build {}'.format(ycsb_client)
87+
cmd = 'pyenv local 2 && bin/ycsb build {}'.format(ycsb_client)
8988

9089
logger.info('Running: {}'.format(cmd))
9190
with cd(worker_home), cd('perfrunner'), cd('YCSB'):

perfrunner/remote/kubernetes.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616

1717
class RemoteKubernetes(Remote):
1818

19-
def __init__(self, cluster_spec: ClusterSpec, os):
20-
super().__init__(cluster_spec, os)
19+
PLATFORM = 'kubernetes'
20+
21+
def __init__(self, cluster_spec: ClusterSpec):
22+
super().__init__(cluster_spec)
2123
self.kube_config_path = "cloud/infrastructure/generated/kube_configs/k8s_cluster_1"
2224
self.base_path = 'cloud/operator'
2325
self.cluster_file = 'couchbase-cluster.yaml'
@@ -568,7 +570,7 @@ def build_ycsb(self, worker_home: str, ycsb_client: str):
568570
line = line.decode("utf-8")
569571
if "worker" in line:
570572
worker_name = line.split()[0]
571-
cmd = 'pyenv local system && bin/ycsb build {}'.format(ycsb_client)
573+
cmd = 'pyenv local 2 && bin/ycsb build {}'.format(ycsb_client)
572574

573575
logger.info('Running: {}'.format(cmd))
574576
self.kubectl_exec(worker_name, 'cd YCSB; {}'.format(cmd))

perfrunner/remote/linux.py

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
import time
33
from collections import defaultdict
4-
from typing import Dict, List, Optional
4+
from typing import Dict, List, Optional, Tuple
55
from urllib.parse import urlparse
66

77
from fabric.api import cd, get, put, quiet, run, settings
@@ -25,6 +25,8 @@
2525

2626
class RemoteLinux(Remote):
2727

28+
PLATFORM = 'linux'
29+
2830
CB_DIR = '/opt/couchbase'
2931

3032
PROCESSES = ('beam.smp', 'memcached', 'epmd', 'cbq-engine', 'indexer',
@@ -37,28 +39,27 @@ class RemoteLinux(Remote):
3739

3840
LINUX_PERF_DELAY = 30
3941

42+
def __init__(self, cluster_spec: ClusterSpec):
43+
super().__init__(cluster_spec)
44+
self.distro, self.distro_version = self.detect_distro()
45+
4046
@property
4147
def package(self):
42-
if self.os.upper() in ('UBUNTU', 'DEBIAN'):
48+
if self.distro.upper() in ('UBUNTU', 'DEBIAN'):
4349
return 'deb'
4450
else:
4551
return 'rpm'
4652

4753
@master_server
48-
def detect_centos_release(self) -> str:
49-
"""Detect CentOS release (e.g., 6 or 7).
50-
51-
Possible values:
52-
- CentOS release 6.x (Final)
53-
- CentOS Linux release 7.2.1511 (Core)
54-
"""
55-
return run('cat /etc/redhat-release').split()[-2][0]
56-
57-
@master_server
58-
def detect_ubuntu_release(self):
59-
return run('lsb_release -sr').strip()
60-
61-
def run_cbindex_command(self, options, worker_home='/tmp/perfrunner'):
54+
def detect_distro(self) -> Tuple[str, str]:
55+
logger.info('Detecting Linux distribution on master node')
56+
cmd = 'grep ^{}= /etc/os-release | cut -d= -f2 | tr -d \'"\''
57+
distro_id = run(cmd.format('ID'))
58+
distro_version = run(cmd.format('VERSION_ID'))
59+
logger.info('Detected Linux distribution: {} {}'.format(distro_id, distro_version))
60+
return distro_id, distro_version
61+
62+
def run_cbindex_command(self, options, worker_home='/tmp/perfrunner'):
6263
cmd = "/opt/couchbase/bin/cbindex {options}".format(options=options)
6364
logger.info('Running: {}'.format(cmd))
6465
run(cmd, shell_escape=False, pty=False)
@@ -341,7 +342,7 @@ def install_couchbase(self, url: str):
341342
logger.info('Installing Couchbase Server')
342343
if self.package == 'deb':
343344
run('yes | apt-get install gdebi')
344-
run('yes | apt install -y ./tmp/{}'.format(filename))
345+
run('yes | apt install -y /tmp/{}'.format(filename))
345346
else:
346347
run('yes | yum localinstall -y /tmp/{}'.format(filename))
347348

@@ -1030,9 +1031,14 @@ def cbbackupmgr_restore(self, master_node: str, cluster_spec: ClusterSpec, threa
10301031
run(cmd)
10311032

10321033
@all_servers
1033-
def install_cb_debug_rpm(self, url):
1034-
logger.info('Installing Couchbase Debug rpm on all servers')
1035-
run('rpm -iv {}'.format(url), quiet=True)
1034+
def install_cb_debug_package(self, url):
1035+
logger.info('Installing Couchbase Debug package on all servers')
1036+
if url.endswith('deb'):
1037+
cmd = 'dpkg -i {}'.format(url)
1038+
else:
1039+
cmd = 'rpm -iv {}'.format(url)
1040+
1041+
run(cmd, quiet=True)
10361042

10371043
@all_servers
10381044
def generate_linux_perf_script(self):

perfrunner/remote/windows.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
class RemoteWindows(Remote):
1313

14+
PLATFORM = 'cygwin'
15+
1416
CB_DIR = '/cygdrive/c/Program\\ Files/Couchbase/Server'
1517

1618
VERSION_FILE = '/cygdrive/c/Program Files/Couchbase/Server/VERSION.txt'

0 commit comments

Comments
 (0)