Created
October 10, 2018 15:38
-
-
Save nbeguier/47173566e9bfdba9fc5494460f67d5e6 to your computer and use it in GitHub Desktop.
check_scheduling.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
#-*- coding: utf-8 -*- | |
""" Check scheduling on nebula for a service """ | |
# Standard library imports | |
from __future__ import print_function | |
from sys import argv | |
# Third party library imports | |
from pyone import OneServer | |
def usage(): | |
""" | |
Display usage | |
""" | |
print('Usage: %s ENV VM_PREFIX' % argv[0]) | |
print('') | |
print('Ex: %s prd service_1' % argv[0]) | |
print('Ex: %s stg service_2' % argv[0]) | |
print('Ex: %s stg all # For all services' % argv[0]) | |
exit(1) | |
try: | |
ENV = argv[1] | |
VM_PREFIX = argv[2] | |
except IndexError: | |
usage() | |
if ENV == 'stg': | |
ONE = OneServer("http://lb-opennebula.domain.net:2633/RPC2", session="guest:guest") | |
else: | |
ONE = OneServer("http://lb-opennebula.staging.domain.net:2633/RPC2", session="guest:guest") | |
SERVICES_LIST = list() | |
def generate_services_list(): | |
""" | |
Generate a list of all VM name | |
""" | |
for one_vm in ONE.vmpool.info(-2, -1, -1, -1).VM: | |
if one_vm.NAME not in SERVICES_LIST: | |
SERVICES_LIST.append(one_vm.NAME) | |
class Checker(object): | |
""" | |
Main Checker class. | |
""" | |
def __init__(self, service_name): | |
""" | |
Init file. | |
""" | |
self.service_name = service_name | |
self.vmid_list = list() | |
self.clusterid_list = list() | |
self.hostid_list = list() | |
self.host_dict = dict() | |
self.full_host_list = list() | |
self.host_vm_list = list() | |
def generate_list(self): | |
""" | |
Generates a list a VM ID | |
""" | |
for one_vm in ONE.vmpool.info(-2, -1, -1, -1).VM: | |
if one_vm.NAME == self.service_name: | |
self.vmid_list.append(one_vm.ID) | |
def check_cluster_ha(self, verbose=True): | |
""" | |
Checks if there is HA with the cluster | |
""" | |
cluster_dict = dict() | |
for vmid in self.vmid_list: | |
try: | |
cluster_id = ONE.vm.info(vmid).TEMPLATE['NIC']['CLUSTER_ID'] | |
except TypeError: | |
cluster_id = ONE.vm.info(vmid).TEMPLATE['NIC'][0]['CLUSTER_ID'] | |
if cluster_id in cluster_dict: | |
cluster_dict[cluster_id] += 1 | |
else: | |
cluster_dict[cluster_id] = 1 | |
self.clusterid_list.append(int(cluster_id)) | |
cluster_ok = True | |
for cluster_id in cluster_dict: | |
if cluster_dict[cluster_id] != len(self.vmid_list) / len(cluster_dict): | |
cluster_ok = False | |
if cluster_ok: | |
cluster_status = 'OK' | |
else: | |
cluster_status = 'KO' | |
if verbose: | |
print("--------------------") | |
print("-- CLUSTER : %s --" % cluster_status) | |
print("--------------------") | |
print("Number of Cluster : %s" % len(cluster_dict)) | |
if not cluster_ok: | |
print("Cluster check : ERROR : %s" % cluster_dict) | |
return cluster_ok | |
def check_host_ha(self, verbose=True): | |
""" | |
Checks if there is HA with the hosts | |
""" | |
if verbose: | |
print("") | |
print("----------------") | |
print("-- HOSTS --") | |
print("----------------") | |
for vmid in self.vmid_list: | |
for cluster_id in self.clusterid_list: | |
for host_id in ONE.cluster.info(cluster_id).HOSTS.ID: | |
if vmid in ONE.host.info(host_id).VMS.ID: | |
self.host_vm_list.append((host_id, vmid)) | |
if host_id in self.host_dict: | |
self.host_dict[host_id] += 1 | |
else: | |
self.host_dict[host_id] = 1 | |
self.hostid_list.append(int(host_id)) | |
elif host_id not in self.host_dict: | |
self.host_dict[host_id] = 0 | |
# Detect free hosts | |
free_hosts = list() | |
for host_id in self.host_dict: | |
if self.host_dict[host_id] == 0: | |
free_hosts.append(host_id) | |
# Detect full hosts | |
nb_full_hosts = 0 | |
for host_id in self.host_dict: | |
if self.host_dict[host_id] > 1: | |
if verbose: | |
print("Host %s has %s VM of the same type !" % (host_id, self.host_dict[host_id])) | |
nb_full_hosts += 1 | |
self.full_host_list.append(host_id) | |
if nb_full_hosts > 0: | |
if verbose: | |
print("Host check : WARNING") | |
print("These hosts are free : %s" % free_hosts) | |
return False | |
if verbose: | |
print("Host check : OK") | |
return True | |
def migrating_host(self): | |
""" | |
This function allows to migrate host | |
""" | |
print("") | |
print("--------------------") | |
print("-- MIGRATION --") | |
print("--------------------") | |
old_host_id = int(input("Host to free %s: " % self.full_host_list)) | |
old_host_cluster_id = ONE.host.info(old_host_id).CLUSTER_ID | |
if self.host_dict[old_host_id] == 0: | |
print("Host ID %s have no VM %s." % (old_host_id, self.service_name)) | |
return False | |
elif self.host_dict[old_host_id] < 2: | |
print("Host ID %s have %s VMs %s." % (old_host_id, self.host_dict[old_host_id], self.service_name)) | |
return False | |
print("") | |
print("VMs on this host :") | |
vcpu = 0 | |
memory = 0 | |
disk = 0 | |
last_vm_id = '' | |
for host_id, vm_id in self.host_vm_list: | |
if host_id == old_host_id: | |
vcpu = int(ONE.vm.info(vm_id).TEMPLATE['VCPU']) | |
memory = int(ONE.vm.info(vm_id).TEMPLATE['MEMORY']) | |
try: | |
disk = int(ONE.vm.info(vm_id).TEMPLATE['DISK']['SIZE']) | |
except TypeError: | |
disk = 0 | |
for disk_content in ONE.vm.info(vm_id).TEMPLATE['DISK']: | |
disk += int(disk_content['SIZE']) | |
last_vm_id = vm_id | |
print('{vm_id: %s-%s, vcpu: %s, memory_MB: %s, disk_MB: %s}' % ( | |
self.service_name, | |
vm_id, | |
vcpu, | |
memory, | |
disk)) | |
# LIST AVAILABLE HOSTS | |
print("") | |
print("Candidate :") | |
at_least_one_host = False | |
for host_id in self.host_dict: | |
if self.host_dict[host_id] == 0 and old_host_cluster_id == ONE.host.info(host_id).CLUSTER_ID: | |
cpu_left = int((ONE.host.info(host_id).HOST_SHARE.MAX_CPU - ONE.host.info(host_id).HOST_SHARE.CPU_USAGE)/100) | |
memory_left = int((ONE.host.info(host_id).HOST_SHARE.MAX_MEM - ONE.host.info(host_id).HOST_SHARE.MEM_USAGE)/1024) | |
disk_left = int(ONE.host.info(host_id).HOST_SHARE.FREE_DISK) | |
if cpu_left >= vcpu and memory_left >= memory and disk_left >= disk: | |
at_least_one_host = True | |
print('{host_id: %s, free_cpu: %s, free_memory_MB: %s, free_disk_MB: %s}' % ( | |
host_id, | |
cpu_left, | |
memory_left, | |
disk_left)) | |
if not at_least_one_host: | |
print("No hosts are available on this cluster...") | |
return False | |
else: | |
print("") | |
new_host_id = int(input("New host ID for VM ID %s: " % last_vm_id)) | |
print("") | |
print('Migrating "%s-%s" service from host %s to host %s...' % ( | |
self.service_name, | |
last_vm_id, | |
old_host_id, | |
new_host_id)) | |
# TODO : Migration | |
# For now, it's just an output. | |
# We need to implement a login to permit the migration. | |
return True | |
if __name__ == '__main__': | |
if VM_PREFIX != 'all': | |
CHECK = Checker(VM_PREFIX) | |
CHECK.generate_list() | |
CHECK_CLUSTER = CHECK.check_cluster_ha() | |
CHECK_HOST = CHECK.check_host_ha() | |
if not CHECK_HOST: | |
CHECK.migrating_host() | |
if not CHECK_HOST or not CHECK_CLUSTER: | |
exit(1) | |
exit(0) | |
else: | |
generate_services_list() | |
for service in SERVICES_LIST: | |
CHECK = Checker(service) | |
CHECK.generate_list() | |
CHECK_CLUSTER = CHECK.check_cluster_ha(verbose=False) | |
CHECK_HOST = CHECK.check_host_ha(verbose=False) | |
if not CHECK_HOST or not CHECK_CLUSTER: | |
print("Service %s : ERROR" % service) | |
else: | |
print("Service %s : OK" % service) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment