fabric commands examples ¶
Useof Connection, cd, run ¶
from fabric import Connection
## Define your remote server's hostname and your username
hostname = "load-testing"
username = "pvergain"
## Create a connection to the remote server
c = Connection(host=hostname, user=username)
## Run a shell command on the remote server
with c.cd("~/informatique/terraform/tf-debian-packer/environments/bioseal"):
result = c.run('uname -a')
result = c.run('ls -als')
Use of Connection, cd, put, run ¶
from fabric import Connection
c = Connection('web1')
c.put('myfiles.tgz', '/opt/mydata')
c.run('tar -C /opt/mydata -xzvf /opt/mydata/myfiles.tgz')
You could (but don’t have to) turn such blocks of code into functions, parameterized with a Connection object from the caller, to encourage reuse:
def upload_and_unpack(c):
c.put('myfiles.tgz', '/opt/mydata')
c.run('tar -C /opt/mydata -xzvf /opt/mydata/myfiles.tgz')
As you’ll see below, such functions can be handed to other API methods to enable more complex use cases as well.
Use of SerialGroup, run ¶
In [6]: from fabric import SerialGroup
In [7]: result = SerialGroup("load-testing").run('hostname')
load-testing
In [8]:
def disk_free(c):
uname = c.run('uname -s', hide=True)
if 'Linux' in uname.stdout:
command = "df -h / | tail -n1 | awk '{print $5}'"
return c.run(command, hide=True).stdout.strip()
err = "No idea how to get disk space on {}!".format(uname)
raise Exit(err)
print(disk_free(Connection('load-testing')))
3%
Use of the fab command + task, cd, run ¶
A fabfile.py example ¶
1 """fabfile.py
2
3 Calling examples
4 ===================
5
6 - fab --list
7 - fab -H machine uname
8 - fab -H machine update
9 """
10 from fabric import task
11
12
13 ## Define a task to upgrade the remote server's packages
14 @task
15 def uname(c):
16 c.run('uname -a')
17
18
19 ## Define a task to update the remote server's package index
20 @task
21 def update(c):
22 with c.cd('/tmp'):
23 c.run('sudo apt-get update')
24
25 ## Define a task to upgrade the remote server's packages
26 @task
27 def upgrade(c):
28 with c.cd('/tmp'):
29 c.run('sudo apt-get upgrade -y')
30
31 ## Define a task to install a package on the remote server
32 @task
33 def install_package(c, package_name):
34 with c.cd('/tmp'):
35 c.run(f'sudo apt-get install -y {package_name}')
Use of the fab command + task, cd, run + git + c.config.run.env (environment variables) + stderr ¶
1 """fabfile.py
2
3 Calling examples
4
5 - fab -H load-testing build-vm
6 - fab -H load-testing update-compose--infra
7 - fab -H load-testing build--api
8 - fab -H load-testing load-testing
9
10 """
11
12 import os
13
14 from fabric import task
15 from jinja2 import Environment
16 from jinja2 import FileSystemLoader
17
18
19 credentials_vsphere_password = os.getenv("SUT_CREDENTIALS_VSPHERE_PASSWORD")
20 vsphere_vm_cpu = os.getenv("SUT_VSPHERE_VM_CPU") # Example: 2, 4, 8, 10
21 vsphere_vm_memory = os.getenv("SUT_VSPHERE_VM_MEMORY") # Example : 4096
22 pool_size = int(os.getenv("SUT_POOL_SIZE"))
23 thead_count = int(os.getenv("SUT_THREAD_COUNT"))
24 xmx = int(vsphere_vm_memory) // 1024
25 xmx_g = f"{xmx}g"
26 memory_g = f"{xmx}g"
27
28
29 command_create_terraform = (
30 f"""terraform apply
31 -var credentials_vpshere_user=terraform
32 -var credentials_vsphere_password={credentials_vsphere_password}
33 -var vsphere_vm_cpu={vsphere_vm_cpu} -var vsphere_vm_memory={vsphere_vm_memory}
34 -auto-approve
35 """
36 ).replace("\n", " ")
37
38 command_destroy_terraform = (
39 f"""terraform destroy
40 -var credentials_vpshere_user=terraform
41 -var credentials_vsphere_password={credentials_vsphere_password}
42 -var vsphere_vm_cpu={vsphere_vm_cpu} -var vsphere_vm_memory={vsphere_vm_memory}
43 -auto-approve
44 """
45 ).replace("\n", " ")
46
47
48 @task
49 def build_debian(c):
50 """Step 1. Build debian 12 template once a month"""
51 try:
52 command_curl = 'curl --request POST --header "PRIVATE-TOKEN: glpat-4yrxr9NXi4Ghsfvd2TC1" "https://gitlab.xx/api/v4/projects/672/pipeline?ref=benchmark_pv"'
53 c.run(command_curl)
54 except Exception as error:
55 print(f"{error=}")
56
57
58 @task
59 def apply_vm(c):
60 """Step 2. Create the virtual machine -benchmark.xx
61 with the 2 parameters
62
63 - vsphere_vm_cpu
64 - vsphere_vm_memory
65
66 See: https://pv_biometrics.gitlab.xx/applis/tools/locust-ci-doc/installations/sut/2-creer--benchmark/2-creer--benchmark.html
67 """
68 try:
69 print(f"{vsphere_vm_cpu=} {vsphere_vm_memory=}")
70 with c.cd("~/informatique/terraform/tf-debian-packer/environments/bioseal"):
71 c.run("uname -a")
72 c.run("ls -als")
73 c.run(command_create_terraform)
74 except Exception as error:
75 print(f"{error=}")
76
77
78 @task
79 def destroy_vm(c):
80 try:
81 with c.cd("~/informatique/terraform/tf-debian-packer/environments/bioseal"):
82 c.run("uname -a")
83 c.run("ls -als")
84 c.run(command_destroy_terraform)
85 except Exception as error:
86 print(f"{error=}")
87
88
89 def build_docker_compose_file() -> None:
90 """Part of Step 3. Build a docker-compose.yml file with a jinja2 template file
91 and 5 variables:
92
93 - vsphere_vm_memory
94 - xmx
95 - memory
96 - pool_size
97 - thead_count
98 """
99 env = Environment(loader=FileSystemLoader("templates"))
100 compose_template = env.get_template("docker-compose.yml.jinja2")
101 print(f"{pool_size=} {thead_count=} {xmx_g=} {memory_g=}")
102 context = {
103 "vsphere_vm_memory": vsphere_vm_memory,
104 "xmx": xmx_g,
105 "memory": memory_g,
106 "pool_size": pool_size,
107 "thead_count": thead_count,
108 }
109 docker_compose_file = "docker-compose.yml"
110 with open(docker_compose_file, mode="w", encoding="utf-8") as compose:
111 compose.write(compose_template.render(context))
112 print(f"... wrote {docker_compose_file}")
113
114
115 @task
116 def update_compose_infra(c):
117 """Step 3.1 Update the Informatique/biosdeal-infra docker-compose.yml file
118
119 Calling update-compose-_infra task
120 ============================================
121
122 ::
123
124 fab -H load-testing update-compose--infra
125
126 See
127
128 - https://gitlab.xx/Informatique/-infra/-/blob/benchmark-pv/deployment/compose/docker-compose.yml?ref_type=heads
129 - https://gitlab.xx/Informatique/-infra/-/commits/benchmark-pv
130 """
131 try:
132 build_docker_compose_file()
133 with c.cd("~/informatique/-infra/deployment/compose"):
134 c.run("git switch benchmark-pv")
135 c.put(
136 "docker-compose.yml",
137 "/home/pvergain/informatique/-infra/deployment/compose/",
138 )
139 # c.run("cat docker-compose.yml")
140 c.run("git add .")
141 # see https://gitlab.xx/Informatique/-infra/-/commits/benchmark-pv
142 c.run(
143 f"git commit -m 'Update docker-compose {pool_size=} {thead_count=} {vsphere_vm_cpu=} {vsphere_vm_memory=} {xmx=}'"
144 )
145 c.run("git branch")
146 c.run("git push")
147 except Exception as error:
148 print(f"Exception: {error=}")
149
150
151 @task
152 def build_api(c):
153 """Step 3.2 install the -api on the -benchmark.xx. Apparemment pas nécessaire.
154
155 Calling build--api
156 ============================
157
158 ::
159
160 fab -H load-testing build--api
161
162 See
163
164 - https://gitlab.xx/Informatique/-infra/-/pipelines
165 """
166 try:
167 command_curl = 'curl --request POST --header "PRIVATE-TOKEN: XXXXXXXXXXXx" "https://gitlab.xx/api/v4/projects/207/pipeline?ref=benchmark-pv"'
168 c.run(command_curl)
169 except Exception as error:
170 print(f"{error=}")
171
172
173 @task
174 def load_testing(c):
175 """Step 4 the loading tests
176 ::
177
178 fab -H load-testing load-testing
179
180 See
181
182 - https://gitlab.xx/biometrics/applis/tools/benchmark/-/boards
183 """
184 try:
185 with c.cd("~/biometrics/applis/tools/locust-ci"):
186 c.config.run.env = {
187 "SUT_SERVER": os.getenv("SUT_SERVER"),
188 "SUT_API_KEY": os.getenv("SUT_API_KEY"),
189 "LOCUST_NB_USERS": os.getenv("LOCUST_NB_USERS"),
190 "LOCUST_RUN_TIME": os.getenv("LOCUST_RUN_TIME"),
191 "LOCUST_SPAWN_RATE": os.getenv("LOCUST_SPAWN_RATE"),
192 "LOCUST_TIMESCALE": os.getenv("LOCUST_TIMESCALE"),
193 "LOCUST_GRAFANA_URL": os.getenv("LOCUST_GRAFANA_URL"),
194 "PGHOST": os.getenv("PGHOST"),
195 "PGPORT": os.getenv("PGPORT"),
196 "PGUSER": os.getenv("PGUSER"),
197 "PGDATABASE": os.getenv("PGDATABASE"),
198 "PGPASSWORD": os.getenv("PGPASSWORD"),
199 }
200 result = c.run("source .venv/bin/activate; type locust; ./send_locust_commands.bash", hide=True)
201 print(f"{result=}")
202 for line in result.stderr.split('\n'):
203 if 'Report' in line:
204 s = line.split('Report:')
205 print(f"The report is here:{s[-1].strip()}")
206
207 except Exception as error:
208 print(f"{error=}")