Skip to content

Commit 68df770

Browse files
committed
Latest demo lab version
1 parent c870629 commit 68df770

File tree

11 files changed

+221
-233
lines changed

11 files changed

+221
-233
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
venv/
12
nutanix/
23

34
*.pyc

config.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
22

3+
34
class Config(object):
4-
SECRET_KEY = os.environ.get('SECRET_KEY') or 'some strong secret string'
5+
SECRET_KEY = os.environ.get("SECRET_KEY") or "some strong secret string"

lab/__init__.py

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,45 +3,45 @@
33
from flask import Flask
44
from flask_assets import Environment, Bundle
55

6-
from .util import apiclient
76
from config import Config
87

8+
99
def create_app(test_config=None):
1010
# create and configure the app
1111
app = Flask(__name__, instance_relative_config=True)
1212

1313
assets = Environment(app)
1414

1515
home_css = Bundle(
16-
'css/lib/reset.css',
17-
'css/lib/built-in.css',
18-
'css/lib/jquery-ui-custom.css',
19-
'css/lib/jq.gridster.css',
20-
'css/lib/jq.jqplot.css',
21-
'css/ntnx.css'
16+
"css/lib/reset.css",
17+
"css/lib/built-in.css",
18+
"css/lib/jquery-ui-custom.css",
19+
"css/lib/jq.gridster.css",
20+
"css/lib/jq.jqplot.css",
21+
"css/ntnx.css",
2222
)
2323
home_js = Bundle(
24-
'js/lib/jquery-2.1.3.min.js',
25-
'js/lib/classie.min.js',
26-
'js/lib/ntnx-bootstrap.min.js',
27-
'js/lib/modernizr.custom.min.js',
28-
'js/lib/jquery.jqplot.min.js',
29-
'js/lib/jqplot.logAxisRenderer.js',
30-
'js/lib/jqplot.categoryAxisRenderer.js',
31-
'js/lib/jqplot.canvasAxisLabelRenderer.js',
32-
'js/lib/jqplot.canvasTextRenderer.js',
33-
'js/lib/jquery.gridster.min.js',
34-
'js/ntnx.js'
24+
"js/lib/jquery-2.1.3.min.js",
25+
"js/lib/classie.min.js",
26+
"js/lib/ntnx-bootstrap.min.js",
27+
"js/lib/modernizr.custom.min.js",
28+
"js/lib/jquery.jqplot.min.js",
29+
"js/lib/jqplot.logAxisRenderer.js",
30+
"js/lib/jqplot.categoryAxisRenderer.js",
31+
"js/lib/jqplot.canvasAxisLabelRenderer.js",
32+
"js/lib/jqplot.canvasTextRenderer.js",
33+
"js/lib/jquery.gridster.min.js",
34+
"js/ntnx.js",
3535
)
3636

37-
assets.register('home_css',home_css)
38-
assets.register('home_js',home_js)
37+
assets.register("home_css", home_css)
38+
assets.register("home_js", home_js)
3939

4040
app.config.from_object(Config)
4141

4242
if test_config is None:
4343
# load the instance config, if it exists, when not testing
44-
app.config.from_pyfile('config.py', silent=True)
44+
app.config.from_pyfile("config.py", silent=True)
4545
else:
4646
# load the test config if passed in
4747
app.config.from_mapping(test_config)
@@ -53,9 +53,11 @@ def create_app(test_config=None):
5353
pass
5454

5555
from . import index
56+
5657
app.register_blueprint(index.bp)
5758

5859
from . import ajax
60+
5961
app.register_blueprint(ajax.bp)
6062

61-
return app
63+
return app

lab/ajax.py

Lines changed: 83 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
import os
22
import json
33
import base64
4-
import sys
54
from datetime import datetime
65
from datetime import timedelta
76
import time
87
import urllib3
98

109
from flask import (
11-
Blueprint, flash, g, redirect, render_template, request, session, url_for, jsonify
10+
Blueprint,
11+
request,
12+
jsonify,
1213
)
13-
from werkzeug.security import check_password_hash, generate_password_hash
1414

1515
from .util import apiclient
1616

17-
bp = Blueprint('ajax', __name__, url_prefix='/ajax')
17+
bp = Blueprint("ajax", __name__, url_prefix="/ajax")
1818

1919
"""
2020
disable insecure connection warnings
@@ -23,68 +23,68 @@
2323
"""
2424
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
2525

26+
2627
"""
2728
get the form POST data provided by the user
2829
"""
30+
31+
2932
def get_form():
3033
global form_data
3134
global cvmAddress
3235
global username
3336
global password
37+
global entity
3438
form_data = request.form
35-
cvmAddress = form_data['_cvmAddress']
36-
username = form_data['_username']
37-
password = form_data['_password']
39+
cvmAddress = form_data["_cvmAddress"]
40+
username = form_data["_username"]
41+
password = form_data["_password"]
42+
entity = form_data["_entity"]
43+
3844

3945
"""
4046
load the default layout at app startup
4147
"""
42-
@bp.route('/load-layout',methods=['POST'])
48+
49+
50+
@bp.route("/load-layout", methods=["POST"])
4351
def load_layout():
4452
site_root = os.path.realpath(os.path.dirname(__file__))
45-
layout_path = 'static/layouts'
46-
dashboard_file = 'dashboard.json'
47-
with open( f'{site_root}/{layout_path}/{dashboard_file}','r') as f:
53+
layout_path = "static/layouts"
54+
dashboard_file = "dashboard.json"
55+
with open(f"{site_root}/{layout_path}/{dashboard_file}", "r") as f:
4856
raw_json = json.loads(f.read())
49-
return base64.b64decode(raw_json['layout']).decode('utf-8')
57+
return base64.b64decode(raw_json["layout"]).decode("utf-8")
5058

51-
"""
52-
get some high level cluster info
53-
"""
54-
@bp.route('/cluster-info',methods=['POST'])
55-
def cluster_info():
56-
# get the request's POST data
57-
get_form()
58-
client = apiclient.ApiClient('post', cvmAddress,'clusters/list','{"kind":"cluster"}',username,password)
59-
results = client.get_info()
60-
return jsonify(results)
6159

6260
"""
63-
get the vm count
61+
connect to prism central and collect details about a specific type of entity
6462
"""
65-
@bp.route('/vm-info',methods=['GET','POST'])
66-
def vm_info():
67-
# get the request's POST data
68-
get_form()
69-
client = apiclient.ApiClient('get', cvmAddress,'vms','',username,password,'v2.0')
70-
results = client.get_info()
71-
return jsonify(results)
7263

73-
"""
74-
get the cluster's physical info e.g. # of hosts, host serial numbers
75-
"""
76-
@bp.route('/physical-info',methods=['POST'])
77-
def physical_info():
64+
65+
@bp.route("/pc-list-entities", methods=["POST"])
66+
def pc_list_entities():
7867
# get the request's POST data
7968
get_form()
80-
client = apiclient.ApiClient('get', cvmAddress,'hosts','',username,password,'v2.0')
69+
client = apiclient.ApiClient(
70+
method="post",
71+
cluster_ip=cvmAddress,
72+
request=f"{entity}s/list",
73+
entity=entity,
74+
body=f'{{"kind": "{entity}"}}',
75+
username=username,
76+
password=password,
77+
)
8178
results = client.get_info()
8279
return jsonify(results)
8380

81+
8482
"""
85-
get the cluster's storage performance
83+
get storage performance stats for the first storage container in a cluster
8684
"""
87-
@bp.route('/storage-performance',methods=['POST'])
85+
86+
87+
@bp.route("/storage-performance", methods=["POST"])
8888
def storage_performance():
8989
# get the request's POST data
9090
get_form()
@@ -97,17 +97,49 @@ def storage_performance():
9797
endTime = round(time.mktime(endTime.timetuple()) * 1000 * 1000)
9898
startTime = round(time.mktime(startTime.timetuple()) * 1000 * 1000)
9999

100-
client = apiclient.ApiClient('get',cvmAddress,f'cluster/stats/?metrics=controller_avg_io_latency_usecs&startTimeInUsecs={startTime}&endTimeInUsecs={endTime}&intervalInSecs=30','',username,password,'v1','PrismGateway/services/rest')
101-
results = client.get_info()
102-
return jsonify(results)
100+
# first, get the external IP address of the first cluster registered to this Prism Central instance
101+
entity = "cluster"
102+
client = apiclient.ApiClient(
103+
method="post",
104+
cluster_ip=cvmAddress,
105+
request=f"{entity}s/list",
106+
entity=entity,
107+
body=f'{{"kind": "{entity}"}}',
108+
username=username,
109+
password=password,
110+
)
111+
cluster_ip = client.get_info()["entities"][0]["status"]["resources"]["network"][
112+
"external_ip"
113+
]
103114

104-
"""
105-
get the container info e.g. # of containers
106-
"""
107-
@bp.route('/container-info',methods=['POST'])
108-
def containers():
109-
# get the request's POST data
110-
get_form()
111-
client = apiclient.ApiClient('get',cvmAddress,f'storage_containers','',username,password,'v2.0')
112-
results = client.get_info()
113-
return jsonify(results)
115+
# next, get the UUID of the first storage container in the cluster found in our previous request
116+
entity = "storage_containers"
117+
client = apiclient.ApiClient(
118+
method="get",
119+
cluster_ip=cluster_ip,
120+
request=entity,
121+
entity="",
122+
body="",
123+
username=username,
124+
password=password,
125+
version="v2.0",
126+
)
127+
storage_container_uuid = client.get_info()["entities"][0]["id"]
128+
129+
# finally, get the performance stats for the storage container found in our previous request
130+
entity = "storage_containers"
131+
full_request = f"storage_containers/{storage_container_uuid}/stats/?metrics=controller_avg_io_latency_usecs&start_time_in_usecs={startTime}&end_time_in_usecs={endTime}"
132+
client = apiclient.ApiClient(
133+
method="get",
134+
cluster_ip=cluster_ip,
135+
request=full_request,
136+
entity="",
137+
body="",
138+
username=username,
139+
password=password,
140+
version="v2.0",
141+
)
142+
stats = client.get_info()
143+
144+
# return the JSON array containing storage container performance info for the last 4 hours
145+
return jsonify(stats)

lab/forms.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
from flask_wtf import FlaskForm
2-
from wtforms import StringField, PasswordField, BooleanField, SubmitField
2+
from wtforms import StringField, PasswordField, SubmitField
33
from wtforms.validators import DataRequired
44

55
"""
66
The clusterForm class is used to identify the properties used when submitted cluster details
77
"""
8+
9+
810
class clusterForm(FlaskForm):
9-
cvmAddress = StringField('cvmAddress', validators=[DataRequired()])
10-
username = StringField('username', validators=[DataRequired()])
11-
password = PasswordField('password', validators=[DataRequired()])
12-
submit = SubmitField('Go!', id="goButton")
11+
cvmAddress = StringField("cvmAddress", validators=[DataRequired()])
12+
username = StringField("username", validators=[DataRequired()])
13+
password = PasswordField("password", validators=[DataRequired()])
14+
submit = SubmitField("Go!", id="goButton")

lab/index.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
from lab.forms import clusterForm
22

33
from flask import (
4-
Blueprint, flash, g, redirect, render_template, request, session, url_for
4+
Blueprint,
5+
render_template,
56
)
6-
from werkzeug.security import check_password_hash, generate_password_hash
77

8-
bp = Blueprint('index', __name__, url_prefix='/')
8+
bp = Blueprint("index", __name__, url_prefix="/")
99

10-
@bp.route('/')
10+
11+
@bp.route("/")
1112
def index():
1213
# make sure we are using the form that's been generated in forms.py
1314
form = clusterForm()
14-
return render_template('index.html', form=form)
15+
return render_template("index.html", form=form)

0 commit comments

Comments
 (0)