Skip to content

Commit d40c363

Browse files
djmailhotandrewsg
authored andcommitted
Fix managed instances demo web server to correctly start/stop CPU loading (GoogleCloudPlatform#2310)
* Update minfra demo to correctly terminate worker process * Create CpuBurner object for minfra demo to simulate CPU load * Fix linting error in minfra demo webserver for CpuBurner
1 parent 543542d commit d40c363

File tree

2 files changed

+47
-26
lines changed

2 files changed

+47
-26
lines changed

compute/managed-instances/demo/app.py

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,38 @@
1919
Attached health checks should query the '/health' path.
2020
"""
2121

22+
from ctypes import c_bool
2223
from flask import Flask, make_response, render_template
24+
from multiprocessing import Process, Value
2325
from random import random
2426
from re import sub
2527
from requests import get
2628
from socket import gethostname
27-
from multiprocessing import Process
29+
from time import sleep
2830

2931
PORT_NUMBER = 80
3032

3133
app = Flask(__name__)
3234
_is_healthy = True
33-
_worker = None
35+
_cpu_burner = None
36+
37+
38+
@app.before_first_request
39+
def init():
40+
global _cpu_burner
41+
_cpu_burner = CpuBurner()
3442

3543

3644
@app.route('/')
3745
def index():
3846
"""Returns the demo UI."""
39-
global _is_healthy
47+
global _cpu_burner, _is_healthy
4048
return render_template('index.html',
4149
hostname=gethostname(),
4250
zone=_get_zone(),
4351
template=_get_template(),
4452
healthy=_is_healthy,
45-
working=_is_working())
53+
working=_cpu_burner.is_running())
4654

4755

4856
@app.route('/health')
@@ -60,15 +68,15 @@ def health():
6068
@app.route('/makeHealthy')
6169
def make_healthy():
6270
"""Sets the server to simulate a 'healthy' status."""
63-
global _is_healthy
71+
global _cpu_burner, _is_healthy
6472
_is_healthy = True
6573

6674
template = render_template('index.html',
6775
hostname=gethostname(),
6876
zone=_get_zone(),
6977
template=_get_template(),
7078
healthy=True,
71-
working=_is_working())
79+
working=_cpu_burner.is_running())
7280
response = make_response(template, 302)
7381
response.headers['Location'] = '/'
7482
return response
@@ -77,15 +85,15 @@ def make_healthy():
7785
@app.route('/makeUnhealthy')
7886
def make_unhealthy():
7987
"""Sets the server to simulate an 'unhealthy' status."""
80-
global _is_healthy
88+
global _cpu_burner, _is_healthy
8189
_is_healthy = False
8290

8391
template = render_template('index.html',
8492
hostname=gethostname(),
8593
zone=_get_zone(),
8694
template=_get_template(),
8795
healthy=False,
88-
working=_is_working())
96+
working=_cpu_burner.is_running())
8997
response = make_response(template, 302)
9098
response.headers['Location'] = '/'
9199
return response
@@ -94,10 +102,8 @@ def make_unhealthy():
94102
@app.route('/startLoad')
95103
def start_load():
96104
"""Sets the server to simulate high CPU load."""
97-
global _worker, _is_healthy
98-
if not _is_working():
99-
_worker = Process(target=_burn_cpu)
100-
_worker.start()
105+
global _cpu_burner, _is_healthy
106+
_cpu_burner.start()
101107

102108
template = render_template('index.html',
103109
hostname=gethostname(),
@@ -113,10 +119,8 @@ def start_load():
113119
@app.route('/stopLoad')
114120
def stop_load():
115121
"""Sets the server to stop simulating CPU load."""
116-
global _worker, _is_healthy
117-
if _is_working():
118-
_worker.terminate()
119-
_worker = None
122+
global _cpu_burner, _is_healthy
123+
_cpu_burner.stop()
120124

121125
template = render_template('index.html',
122126
hostname=gethostname(),
@@ -162,16 +166,32 @@ def _get_template():
162166
return ''
163167

164168

165-
def _is_working():
166-
"""Returns TRUE if the server is currently simulating CPU load."""
167-
global _worker
168-
return _worker is not None and _worker.is_alive()
169-
170-
171-
def _burn_cpu():
172-
"""Burn CPU cycles to simulate high CPU load."""
173-
while True:
174-
random()*random()
169+
class CpuBurner:
170+
"""
171+
Object to asynchronously burn CPU cycles to simulate high CPU load.
172+
Burns CPU in a separate process and can be toggled on and off.
173+
"""
174+
def __init__(self):
175+
self._toggle = Value(c_bool, False, lock=True)
176+
self._process = Process(target=self._burn_cpu)
177+
self._process.start()
178+
179+
def start(self):
180+
"""Start burning CPU."""
181+
self._toggle.value = True
182+
183+
def stop(self):
184+
"""Stop burning CPU."""
185+
self._toggle.value = False
186+
187+
def is_running(self):
188+
"""Returns true if currently burning CPU."""
189+
return self._toggle.value
190+
191+
def _burn_cpu(self):
192+
"""Burn CPU cycles if work is toggled, otherwise sleep."""
193+
while True:
194+
random()*random() if self._toggle.value else sleep(1)
175195

176196

177197
if __name__ == "__main__":
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
flask==1.0
2+
requests

0 commit comments

Comments
 (0)