-
Notifications
You must be signed in to change notification settings - Fork 6
/
restclient.py
160 lines (132 loc) · 6.81 KB
/
restclient.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import json
from collections import namedtuple
import requests
import urllib3
from requests.exceptions import HTTPError
from typing import Iterable
import logging_aux
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
GrowDecision = namedtuple("GrowDecision", "cores_to_grow nodes_to_grow sockets_to_grow")
IdleNode = namedtuple("IdleNode", "node_name timestamp server_name")
# TODO: change all method inputs to either all in json format or not
def _return_json_from_res(res):
jobj = json.loads(res.content)
return jobj
class HpcRestClient(object):
DEFAULT_NODEGROUP_TOKEN = "DEFAULT"
DEFAULT_COMPUTENODE_TEMPLATE = "Default ComputeNode Template"
# auto-scale api set
GROW_DECISION_API_ROUTE = "https://{}/HpcManager/api/auto-scale/grow-decision"
CHECK_NODES_IDLE_ROUTE = "https://{}/HpcManager/api/auto-scale/check-nodes-idle"
# node management api set
BRING_NODES_ONLINE_ROUTE = "https://{}/HpcManager/api/nodes/bringOnline"
TAKE_NODES_OFFLINE_ROUTE = "https://{}/HpcManager/api/nodes/takeOffline"
ASSIGN_NODES_TEMPLATE_ROUTE = "https://{}/HpcManager/api/nodes/assignTemplate"
REMOVE_NODES_ROUTE = "https://{}/HpcManager/api/nodes/remove"
NODE_STATUS_EXACT_ROUTE = "https://{}/HpcManager/api/nodes/status/getExact"
# node group api set
NODE_GROUPS_ROOT_ROUTE = "https://{}/HpcManager/api/node-groups"
LIST_NODE_GROUPS_ROUTE = NODE_GROUPS_ROOT_ROUTE
ADD_NEW_GROUP_ROUTE = NODE_GROUPS_ROOT_ROUTE
ADD_NODES_TO_NODE_GROUP_ROUTE = NODE_GROUPS_ROOT_ROUTE.format("{{}}") + "/{group_name}"
# constants in result
NODE_STATUS_NODE_NAME_KEY = "Name"
NODE_STATUS_NODE_STATE_KEY = "NodeState"
NODE_STATUS_NODE_STATE_ONLINE_VALUE = "Online"
NODE_STATUS_NODE_STATE_OFFLINE_VALUE = "Offline"
NODE_STATUS_NODE_HEALTH_KEY = "NodeHealth"
NODE_STATUS_NODE_HEALTH_UNAPPROVED_VALUE = "Unapproved"
NODE_STATUS_NODE_GROUP_KEY = "Groups"
def __init__(self, pem, hostname="localhost"):
# type: (str) -> None
self.hostname = hostname
self.logger = logging_aux.init_logger_aux("hpcframework.restclient", 'hpcframework.restclient.log')
self._pem = pem
def _log_error(self, function_name, res):
self.logger.error("{}: status_code:{} content:{}".format(function_name, res.status_code, res.content))
def _log_info(self, function_name, res):
self.logger.info(function_name + ":" + res.content)
# TODO: consolidate these ceremonies.
def _get(self, function_name, function_route, params):
headers = {"Content-Type": "application/json"}
url = function_route.format(self.hostname)
res = requests.get(url, headers=headers, verify=False, params=params, cert=self._pem)
try:
res.raise_for_status()
self._log_info(function_name, res)
return res
except HTTPError:
self._log_error(function_name, res)
raise
def _post(self, function_name, function_route, data):
headers = {"Content-Type": "application/json"}
url = function_route.format(self.hostname)
res = requests.post(url, data=data, headers=headers, verify=False, cert=self._pem)
try:
res.raise_for_status()
self._log_info(function_name, res)
return res
except HTTPError:
self._log_error(function_name, res)
raise
# Starts auto-scale api
def get_grow_decision(self, node_group_name=""):
url = self.GROW_DECISION_API_ROUTE.format(self.hostname)
res = requests.post(url, verify=False, cert=self._pem, timeout=15)
if res.ok:
self.logger.info(res.content)
grow_decision_dict = {k.upper(): v for k, v in json.loads(res.content).items()}
if node_group_name == "":
jobj = grow_decision_dict[self.DEFAULT_NODEGROUP_TOKEN]
elif node_group_name.upper() in grow_decision_dict:
jobj = grow_decision_dict[node_group_name.upper()]
else:
return GrowDecision(0, 0, 0)
return GrowDecision(jobj['CoresToGrow'], jobj['NodesToGrow'], jobj['SocketsToGrow'])
else:
self.logger.error("status_code:{} content:{}".format(res.status_code, res.content))
def check_nodes_idle(self, nodes):
# type: (list[str]) -> list[IdleNode]
data = json.dumps(nodes)
res = self._post(self.check_nodes_idle.__name__, self.CHECK_NODES_IDLE_ROUTE, data)
jobjs = json.loads(res.content)
return [IdleNode(idle_info['NodeName'], idle_info['TimeStamp'], idle_info['ServerName']) for idle_info in jobjs]
# Starts node management api
def bring_nodes_online(self, nodes):
data = json.dumps(nodes)
res = self._post(self.bring_nodes_online.__name__, self.BRING_NODES_ONLINE_ROUTE, data)
return _return_json_from_res(res)
def take_nodes_offline(self, nodes):
data = json.dumps(nodes)
res = self._post(self.take_nodes_offline.__name__, self.TAKE_NODES_OFFLINE_ROUTE, data)
return _return_json_from_res(res)
def assign_default_compute_node_template(self, nodename_arr):
return self.assign_nodes_template(nodename_arr, self.DEFAULT_COMPUTENODE_TEMPLATE)
def assign_nodes_template(self, nodename_arr, template_name):
params = json.dumps({"nodeNames": nodename_arr, "templateName": template_name})
res = self._post(self.assign_nodes_template.__name__, self.ASSIGN_NODES_TEMPLATE_ROUTE, params)
return _return_json_from_res(res)
def remove_nodes(self, nodes):
data = json.dumps(nodes)
res = self._post(self.remove_nodes.__name__, self.REMOVE_NODES_ROUTE, data)
return _return_json_from_res(res)
def get_node_status_exact(self, node_names):
# type: (Iterable[str]) -> list[dict[str, any]]
params = json.dumps({"nodeNames": node_names})
res = self._post(self.get_node_status_exact.__name__, self.NODE_STATUS_EXACT_ROUTE, params)
return _return_json_from_res(res)
# Starts node group api
def list_node_groups(self, group_name=""):
params = {}
if group_name != "":
params['nodeGroupName'] = group_name
res = self._get(self.list_node_groups.__name__, self.LIST_NODE_GROUPS_ROUTE, params)
return _return_json_from_res(res)
def add_node_group(self, group_name, group_description=""):
params = json.dumps({"name": group_name, "description": group_description})
res = self._post(self.add_node_group.__name__, self.ADD_NEW_GROUP_ROUTE, params)
return _return_json_from_res(res)
def add_node_to_node_group(self, group_name, node_names):
res = self._post(self.add_node_to_node_group.__name__, self.ADD_NODES_TO_NODE_GROUP_ROUTE.format(
group_name=group_name), json.dumps(node_names))
return _return_json_from_res(res)