Skip to content

Router status & connections #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Empty file added router/__init__.py
Empty file.
59 changes: 59 additions & 0 deletions router/connections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import json
import requests

api_ver = "20190715"

def __format_bytes(size):
# 2**10 = 1024
power = 2**10
n = 0
power_labels = {0 : 'bytes', 1: 'kb', 2: 'mb', 3: 'gb', 4: 'tb'}
while size > power:
size /= power
n += 1
return "%d %s" % (size, power_labels[n])

def __router_call(route, router_ip, router_port, user, password):
url = "http://" + router_ip + ":" + str(router_port) + "/api/" + api_ver + route
try:
resp = requests.get(url,auth=(user, password))
except:
print("ERROR: Impossible to connect to the MySQL Router REST API")
return False
if resp.status_code == 200:
return resp
else:
print("ERROR: Got error %d when trying to connect to the MySQL Router REST API" % resp.status_code)
return False


def __cluster_routes(router_ip, router_port, user, password, route_to_find):
result = __router_call("/routes", router_ip, router_port, user, password)
if result:
result_json = json.loads(result.content)
fmt = "| {0:22s} | {1:15s} | {2:12s} | {3:>20s} | {4:>20s} | {5:27s} |"
header = fmt.format("Route", "Source", "Destination", "From Server", "To Server", "Connection Started")
bar = "+" + "-" * 24 + "+" + "-" * 17 + "+" + "-" * 14 + "+" + "-" * 22 + "+" + "-" * 22 + "+" + "-" * 29 + "+"
print (bar)
print (header)
print (bar)
for item in result_json['items']:
route_name = item['name']
if route_to_find in route_name:
result_item = __router_call("/routes/%s/connections" % route_name, router_ip, router_port, user, password)
result_item_json = json.loads(result_item.content)
if len(result_item_json['items']) > 0:
for entry in result_item_json['items']:
print (fmt.format(route_name, entry['sourceAddress'], entry['destinationAddress'],
str(__format_bytes(entry['bytesFromServer'])),
str(__format_bytes(entry['bytesToServer'])), entry['timeStarted']))
route_name=""
else:
print (fmt.format(route_name, " "," ", " ", " ", " "))

print (bar)


def connections(router_ip, router_port, user, password, route_to_find=""):
__cluster_routes(router_ip, router_port, user, password, route_to_find)

51 changes: 51 additions & 0 deletions router/init.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,53 @@
# init.py
# -------

from ext.mysqlsh_plugins_common import register_plugin
from ext.router import status as router_status
from ext.router import connections as router_connections
from ext.router.myrouter import MyRouter


router = shell.create_extension_object()


# Check if global object 'ext' has already been registered
if 'ext' in globals():
global_obj = ext
else:
# If not, register a new global object named 'ext' now
global_obj = shell.create_extension_object()
shell.register_global("ext", global_obj,
{
"brief": "MySQL Shell community plugins.",
"details": [
"The global object ext is the entry points for "
"MySQL Shell extensions."
]
})


def create(ip, port, user, password):
my_router = MyRouter(ip, port, user, password)
return {
'connections': lambda route_to_find="": my_router.connections(route_to_find),
'status': lambda: my_router.status(),
'api': my_router.api
}

shell.add_extension_object_member(router, 'create', lambda ip, port, user, password=False:create(ip, port, user, password),
{
'brief':'Create the MySQL Router Object', 'details':['It has MyRouter methods.'],
'parameters':[
{'name':'ip', 'type':'string', 'required':True, 'brief':'ip'},
{'name':'port', 'type':'integer', 'required':True, 'brief':'port'},
{'name':'user', 'type':'string', 'required':True, 'brief':'user'},
{'name':'password', 'type':'string', 'required':False, 'brief':'password'}
]
}
)

shell.add_extension_object_member(global_obj, 'router', router,
{
'brief':'MySQL Router Object',
'details':['MySQL Router Object.']
})
129 changes: 129 additions & 0 deletions router/myrouter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import json
import requests
import mysqlsh
shell = mysqlsh.globals.shell

class MyRouter:
def __init__(self, ip, port, user, password=False):
self.user = user
self.ip = ip
self.port = str(port)
self.user = user
if not password:
self.__password = shell.prompt('Password: ',{'type': 'password'})
else:
self.__password = password

def __format_bytes(self, size):
# 2**10 = 1024
power = 2**10
for unit in ('bytes', 'kb', 'mb', 'gb'):
if size <= power:
return "%d %s" % (size, unit)
size /= power

return "%d tb" % (size,)

def __router_call(self,route):

url = "http://" + self.ip + ":" + self.port + "/api/" + self.api + route
try:
resp = requests.get(url,auth=(self.user,self.__password))
except:
print("ERROR: Impossible to connect to the MySQL Router REST API")
return False
if resp.status_code == 200:
return resp
else:
print("ERROR: Got error %d when trying to connect to the MySQL Router REST API" % resp.status_code)
return False


def __cluster_routes(self, route_to_find):
result = self.__router_call("/routes")
if result:
result_json = json.loads(result.content)
fmt = "| {0:22s} | {1:18s} | {2:12s} | {3:>20s} | {4:>20s} | {5:27s} |"
header = fmt.format("Route", "Source", "Destination", "From Server", "To Server", "Connection Started")
bar = "+" + "-" * 24 + "+" + "-" * 20 + "+" + "-" * 14 + "+" + "-" * 22 + "+" + "-" * 22 + "+" + "-" * 29 + "+"
print (bar)
print (header)
print (bar)
for item in result_json['items']:
route_name = item['name']
if route_to_find in route_name:
result_item = self.__router_call("/routes/%s/connections" % route_name)
result_item_json = json.loads(result_item.content)
if len(result_item_json['items']) > 0:
for entry in result_item_json['items']:
print (fmt.format(route_name, entry['sourceAddress'], entry['destinationAddress'],
str(self.__format_bytes(entry['bytesFromServer'])),
str(self.__format_bytes(entry['bytesToServer'])), entry['timeStarted']))
route_name=""
else:
print (fmt.format(route_name, " "," ", " ", " ", " "))

print (bar)


def __cluster_metadata_status(self, cluster_name):
result = self.__router_call("/metadata/%s/status" % cluster_name)
if result:
result_json = json.loads(result.content)
print (" Refresh Succeeded: " + str(result_json['refreshSucceeded']))
print (" Refresh Failed: " + str(result_json['refreshFailed']))
print (" Last Refresh Hostname: " + result_json['lastRefreshHostname'] \
+ ":" + str(result_json['lastRefreshPort']))

def __cluster_all_routes(self):
result = self.__router_call("/routes")
if result:
print (" +--------+")
print (" | routes |")
print (" +--------+")
result_json = json.loads(result.content)
for item in result_json['items']:
route_name = item['name']
result_item = self.__router_call("/routes/%s/health" % route_name)
result_item_json = json.loads(result_item.content)
if result_item_json['isAlive']:
print(" * %s (alive) :" % route_name)
else:
print(" * %s (dead) :" % route_name)

result_status = self.__router_call("/routes/%s/status" % route_name)
result_status_json= json.loads(result_status.content)
print("\tTotal Connections: %d\tActive Connections: %d\tBlocked Hosts: %d"
% (result_status_json['totalConnections'], result_status_json['activeConnections'],
result_status_json['blockedHosts']))
result_routes = self.__router_call("/routes/%s/destinations" % route_name)
result_routes_json = json.loads(result_routes.content)
for destination in result_routes_json['items']:
print ("\t---> %s : %d" % (destination['address'], destination['port']))

def __cluster_name(self):
result = self.__router_call("/metadata")
if result:
result_json = json.loads(result.content)
cluster_name = result_json['items'][0]['name']
print ("+" + "-" * 16 + "-" * len(cluster_name) + "+")
print ("| Cluster name: %s |" % cluster_name)
print ("+" + "-" * 16 + "-" * len(cluster_name) + "+")
return cluster_name
return False


def status(self):
cluster_name = self.__cluster_name()
if cluster_name:
self.__cluster_metadata_status(cluster_name)
self.__cluster_all_routes()


def connections(self, route_to_find=""):
self.__cluster_routes(route_to_find)

api = "20190715"



65 changes: 65 additions & 0 deletions router/status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import json
import requests

api_ver = "20190715"

def __router_call(route, router_ip, router_port, user, password):
url = "http://" + router_ip + ":" + str(router_port) + "/api/" + api_ver + route
resp = requests.get(url,auth=(user, password))
if resp.status_code == 200:
return resp
else:
return False

def __cluster_name(router_ip, router_port, user, password):
result = __router_call("/metadata", router_ip, router_port, user, password)
if result:
result_json = json.loads(result.content)
cluster_name = result_json['items'][0]['name']
print ("+" + "-" * 16 + "-" * len(cluster_name) + "+")
print ("| Cluster name: %s |" % cluster_name)
print ("+" + "-" * 16 + "-" * len(cluster_name) + "+")
return cluster_name
return False

def __cluster_metadata_status(router_ip, router_port, user, password, cluster_name):
result = __router_call("/metadata/%s/status" % cluster_name, router_ip, router_port, user, password)
if result:
result_json = json.loads(result.content)
print (" Refresh Succeeded: " + str(result_json['refreshSucceeded']))
print (" Refresh Failed: " + str(result_json['refreshFailed']))
print (" Last Refresh Hostname: " + result_json['lastRefreshHostname'] \
+ ":" + str(result_json['lastRefreshPort']))

def __cluster_routes(router_ip, router_port, user, password):
result = __router_call("/routes", router_ip, router_port, user, password)
if result:
print (" +--------+")
print (" | routes |")
print (" +--------+")
result_json = json.loads(result.content)
for item in result_json['items']:
route_name = item['name']
result_item = __router_call("/routes/%s/health" % route_name, router_ip, router_port, user, password)
result_item_json = json.loads(result_item.content)
if result_item_json['isAlive']:
print(" * %s (alive) :" % route_name)
else:
print(" * %s (dead) :" % route_name)

result_status = __router_call("/routes/%s/status" % route_name, router_ip, router_port, user, password)
result_status_json= json.loads(result_status.content)
print("\tTotal Connections: %d\tActive Connections: %d\tBlocked Hosts: %d"
% (result_status_json['totalConnections'], result_status_json['activeConnections'],
result_status_json['blockedHosts']))
result_routes = __router_call("/routes/%s/destinations" % route_name, router_ip, router_port, user, password)
result_routes_json = json.loads(result_routes.content)
for destination in result_routes_json['items']:
print ("\t---> %s : %d" % (destination['address'], destination['port']))

def status(router_ip, router_port, user, password):
cluster_name = __cluster_name(router_ip, router_port, user, password)
if cluster_name:
__cluster_metadata_status(router_ip, router_port, user, password, cluster_name)
__cluster_routes(router_ip, router_port, user, password)