hpcpack-mesos/restclient.py

161 строка
6.8 KiB
Python
Исходник Обычный вид История

2018-03-09 06:26:38 +03:00
import json
from collections import namedtuple
2018-03-13 12:24:55 +03:00
import requests
2018-07-20 05:44:04 +03:00
import urllib3
2018-06-12 09:02:57 +03:00
from requests.exceptions import HTTPError
from typing import Iterable
2018-03-13 12:24:55 +03:00
2018-03-09 07:31:51 +03:00
import logging_aux
2018-03-09 06:26:38 +03:00
2018-07-20 05:44:04 +03:00
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
2018-03-09 06:26:38 +03:00
GrowDecision = namedtuple("GrowDecision", "cores_to_grow nodes_to_grow sockets_to_grow")
IdleNode = namedtuple("IdleNode", "node_name timestamp server_name")
2018-03-09 06:26:38 +03:00
# TODO: change all method inputs to either all in json format or not
2018-03-13 12:24:55 +03:00
2018-06-19 10:33:03 +03:00
def _return_json_from_res(res):
jobj = json.loads(res.content)
return jobj
class HpcRestClient(object):
2018-06-19 10:33:03 +03:00
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"
2018-06-11 11:21:28 +03:00
# 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"
2018-06-26 09:46:31 +03:00
def __init__(self, pem, hostname="localhost"):
# type: (str) -> None
2018-03-09 06:26:38 +03:00
self.hostname = hostname
2018-03-09 07:31:51 +03:00
self.logger = logging_aux.init_logger_aux("hpcframework.restclient", 'hpcframework.restclient.log')
2018-06-26 09:46:31 +03:00
self._pem = pem
2018-03-09 06:26:38 +03:00
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.
2018-06-11 11:21:28 +03:00
def _get(self, function_name, function_route, params):
headers = {"Content-Type": "application/json"}
url = function_route.format(self.hostname)
2018-06-26 09:46:31 +03:00
res = requests.get(url, headers=headers, verify=False, params=params, cert=self._pem)
2018-06-12 09:02:57 +03:00
try:
res.raise_for_status()
2018-06-11 11:21:28 +03:00
self._log_info(function_name, res)
2018-06-12 09:02:57 +03:00
return res
2018-06-19 10:33:03 +03:00
except HTTPError:
2018-06-11 11:21:28 +03:00
self._log_error(function_name, res)
2018-06-12 09:02:57 +03:00
raise
2018-06-11 11:21:28 +03:00
def _post(self, function_name, function_route, data):
headers = {"Content-Type": "application/json"}
url = function_route.format(self.hostname)
2018-06-26 09:46:31 +03:00
res = requests.post(url, data=data, headers=headers, verify=False, cert=self._pem)
2018-06-12 09:02:57 +03:00
try:
res.raise_for_status()
self._log_info(function_name, res)
2018-06-12 09:02:57 +03:00
return res
2018-06-19 10:33:03 +03:00
except HTTPError:
self._log_error(function_name, res)
2018-06-12 09:02:57 +03:00
raise
# Starts auto-scale api
2018-06-19 10:33:03 +03:00
def get_grow_decision(self, node_group_name=""):
url = self.GROW_DECISION_API_ROUTE.format(self.hostname)
2018-06-26 09:46:31 +03:00
res = requests.post(url, verify=False, cert=self._pem, timeout=15)
2018-03-09 06:26:38 +03:00
if res.ok:
self.logger.info(res.content)
grow_decision_dict = {k.upper(): v for k, v in json.loads(res.content).items()}
2018-06-19 10:33:03 +03:00
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)
2018-03-09 06:26:38 +03:00
return GrowDecision(jobj['CoresToGrow'], jobj['NodesToGrow'], jobj['SocketsToGrow'])
else:
self.logger.error("status_code:{} content:{}".format(res.status_code, res.content))
2018-03-13 12:24:55 +03:00
2018-03-09 06:26:38 +03:00
def check_nodes_idle(self, nodes):
2018-06-26 09:46:31 +03:00
# type: (list[str]) -> list[IdleNode]
data = json.dumps(nodes)
2018-06-19 10:33:03 +03:00
res = self._post(self.check_nodes_idle.__name__, self.CHECK_NODES_IDLE_ROUTE, data)
2018-06-12 09:02:57 +03:00
jobjs = json.loads(res.content)
return [IdleNode(idle_info['NodeName'], idle_info['TimeStamp'], idle_info['ServerName']) for idle_info in jobjs]
2018-03-09 06:26:38 +03:00
# Starts node management api
def bring_nodes_online(self, nodes):
data = json.dumps(nodes)
2018-06-19 10:33:03 +03:00
res = self._post(self.bring_nodes_online.__name__, self.BRING_NODES_ONLINE_ROUTE, data)
return _return_json_from_res(res)
2018-03-13 12:24:55 +03:00
def take_nodes_offline(self, nodes):
data = json.dumps(nodes)
2018-06-19 10:33:03 +03:00
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})
2018-06-12 09:02:57 +03:00
res = self._post(self.assign_nodes_template.__name__, self.ASSIGN_NODES_TEMPLATE_ROUTE, params)
return _return_json_from_res(res)
2018-06-11 11:21:28 +03:00
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)
2018-06-11 11:21:28 +03:00
# Starts node group api
2018-06-19 10:33:03 +03:00
def list_node_groups(self, group_name=""):
2018-06-11 11:21:28 +03:00
params = {}
if group_name != "":
params['nodeGroupName'] = group_name
2018-06-19 10:33:03 +03:00
res = self._get(self.list_node_groups.__name__, self.LIST_NODE_GROUPS_ROUTE, params)
return _return_json_from_res(res)
2018-06-11 11:21:28 +03:00
def add_node_group(self, group_name, group_description=""):
params = json.dumps({"name": group_name, "description": group_description})
2018-06-12 09:02:57 +03:00
res = self._post(self.add_node_group.__name__, self.ADD_NEW_GROUP_ROUTE, params)
return _return_json_from_res(res)
2018-06-11 11:21:28 +03:00
def add_node_to_node_group(self, group_name, node_names):
2018-06-19 10:33:03 +03:00
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)