def add_server(self, host_ips): """ Add server to swarm_servers If the server consist in the self.swarm_servers it won't be add Args: host_ips(list or str) Returns: Append to self.swarm_servers the host_ips """ logger = Logger(filename="orchastrator", logger_name="ContainerManagement add_server") if isinstance(host_ips, str): if host_ips not in self.swarm_servers: self.swarm_servers.append(host_ips) update_config("orchastrator.json", "swarm_servers", host_ips, state='add') else: # print("The host ip is already in the list") logger.info( "The host ip {} is already in the list".format(host_ips)) logger.clear_handler() elif isinstance(host_ips, list): self.swarm_servers = list(set(self.swarm_servers + host_ips)) update_config("orchastrator.json", "swarm_servers", host_ips, state='add') else: logger.error("Server should be list or string") logger.clear_handler() raise TypeError("Server should be list or string")
def stop_container(self, name, host_ip): """ Stopping container """ logger = Logger(filename="orchastrator", logger_name="ContainerManagement stop_container") client = self.get_docker_api(host_ip) container_names = self.get_container_names() container_names[name].stop(timeout=30) # print("Exiting from orchestration func because we stop a container") # print("=== Pruned stopped containers ===") logger.info( "Exiting from orchestration func because we stop a container") logger.info("=== Pruned stopped containers ===") logger.clear_handler() client.containers.prune(filters=None)
def parse_config(json_file): """ Parse json_file and load it to a dictionary Returns: js_data(dict) """ try: with open(json_file) as json_data: js_data = json.load(json_data) except IOError: logger = Logger(filename="orchastrator", logger_name="parse_config") logger.error( "File => {} couldn't be opened for read!".format(json_file)) logger.clear_handler() raise ("File => {} couldn't be opened for read!".format(json_file)) return js_data
def remove_swarm_server(self, host_ip): """ Remove server ip from self.swarm_servers Args: host_ip(str) """ if host_ip in self.swarm_servers: self.swarm_servers.remove(host_ip) update_config("orchastrator.json", "swarm_servers", host_ip, state='remove') else: logger = Logger(filename="orchastrator", logger_name="SwarmManagment remove_swarm_server") logger.error( "Node {} can't be removed from swarm_servers (It is not in swarm_servers)" .format(host_ip)) logger.clear_handler()
def leave_server_swarm(self, host_ip): """ Leave server from the swarm Args: host_ip(str) """ #####First way # if host_ip in parse_config("orchastrator.json")["master_nodes"]: # print("Demoting the node from manager") # self.demote_manager(host_ip) # self.ssh_client.connect(host_ip, username=self.user, password=self.password) # _, stdout, _ = self.ssh_client.exec_command('docker swarm leave') # stdout = '\n'.join(map(lambda x: x.rstrip(), stdout.readlines())) # print("STDOUT => {}".format(stdout)) # stdout = "Node left the swarm" # hostname = self.get_hostname(host_ip) # if re.search(r'Node left the swarm', stdout, re.I|re.S): # print("YEEEEE") # self.ssh_client.connect(self.__master, username=self.user, password=self.password) # _, leave_stdout, _ = self.ssh_client.exec_command('docker node rm -f {}'.format(hostname)) # leave_stdout = '\n'.join(map(lambda x: x.rstrip(), leave_stdout.readlines())) # self.add_server(host_ip) # self.remove_swarm_server(host_ip) # else: # return "Node {} can't left the swarm for some reason".format(host_ip) #####Second way logger = Logger(filename="orchastrator", logger_name="SwarmManagment leave_server_swarm") docker_api = self.get_docker_api(host_ip) response = docker_api.swarm.leave(force=True) if response: self.add_server(host_ip) self.remove_swarm_server(host_ip) else: logger.error( "Node {} can't left the swarm for some reason".format(host_ip)) logger.clear_handler() return "Node {} can't left the swarm for some reason".format( host_ip)
def run_container(self, host_ip, application): """ Run container Args: host_ip(str) """ logger = Logger(filename="orchastrator", logger_name="ContainerManagement run_container") docker_api = self.get_docker_api(host_ip) oc_containers = self.get_container_names() # print("Aplication {} will be runned on server => {}".format(application, host_ip)) logger.info("Aplication {} will be runned on server => {}".format( application, host_ip)) for role_config in self.roles_config[application].keys(): if not role_config in oc_containers: # print("This name is not runned as container => {} with this ip => {}".format \ # (role_config, self.roles_config[application][role_config])) logger.info("This name is not runned as container => {} with this ip => {}".format \ (role_config, self.roles_config[application][role_config])) ### Two ways:: 1st => run the contaienr and then connect it ### to the network ### 2nd => create the container, then connect it to the ### network and then start it # runned_container = docker_api.containers. \ # run(image = "g2.pslab.opencode.com:5000/{}1:v2". \ # format(application), \ # hostname = role_config, name = role_config, \ # privileged = True, detach=True) runned_container = docker_api.containers. \ create(image = "g2.pslab.opencode.com:5000/{}1:v2". \ format(application), \ hostname = role_config, name = role_config, \ privileged = True, detach=True) docker_api.networks.get(parse_config('orchastrator.json')['network_name']). \ connect(runned_container, \ ipv4_address=self.roles_config[application][role_config]) runned_container.start() break logger.clear_handler()
def add_swarm_server(self, host_ip): """ Add server to swarm_servers If the server consist in the list it won't be add Args: host_ips(str) Returns: Append to self.swarm_servers the host_ip """ logger = Logger(filename="orchastrator", logger_name="SwarmManagment add_swarm_server") if isinstance(host_ip, str): if host_ip not in self.swarm_servers: self.swarm_servers.append(host_ip) update_config("orchastrator.json", "swarm_servers", host_ip, state='add') else: # print("The host ip is already in the list") logger.info("The host ip is already in the list") logger.clear_handler()
def demote_manager(self, host_ip): """ Demote the server from manager in the swarm Args: host_ip(str) """ logger = Logger(filename="orchastrator", logger_name="SwarmManagment demote_manager") hostname = self.get_hostname(host_ip) self.ssh_client.connect(self.__master, username=self.user, password=self.password) _, demoted_stdout, _ = self.ssh_client.exec_command( 'docker node demote {}'.format(hostname)) demoted_stdout = '\n'.join( map(lambda x: x.rstrip(), demoted_stdout.readlines())) if re.search(r'demoted in the swarm', demoted_stdout, re.I | re.S): self.remove_master_node(host_ip) else: logger.error( "Node {} can't be demoted from manager".format(host_ip)) logger.clear_handler() return "Node {} can't be demoted from manager".format(host_ip)
def join_server_swarm(self, host_ip): """ Join server to the swarm Args: host_ip(str) """ #####First way # self.ssh_client.connect(host_ip, username=self.user, password=self.password) # _, stdout, _ = self.ssh_client.exec_command('docker swarm join --token {} {}:2377'. \ # format(self.__token, self.__master)) # stdout = '\n'.join(map(lambda x: x.rstrip(), stdout.readlines())) # if re.search(r'This node joined a swarm as a worker', stdout, re.I|re.S): # self.remove_available_server(host_ip) # self.add_swarm_server(host_ip) # else: # return "Node {} can't be joined to the swarm".format(host_ip) #####Second way logger = Logger(filename="orchastrator", logger_name="SwarmManagment join_server_swarm") docker_api = self.get_docker_api(host_ip) response = False try: response = docker_api.swarm.join(remote_addrs= \ [parse_config("orchastrator.json")["master"]], \ join_token = parse_config("orchastrator.json")["token"]) except docker.errors.APIError as e: logger.info( "Exception handling swarm joining but config will be updated and corrected" ) logger.clear_handler() self.remove_available_server(host_ip) self.add_swarm_server(host_ip) if response == True: logger.info( "Node {} was successfully joined to the swarm".format(host_ip)) logger.clear_handler() self.remove_available_server(host_ip) self.add_swarm_server(host_ip) else: logger.error( "Node {} can't be joined to the swarm".format(host_ip)) logger.clear_handler() return "Node {} can't be joined to the swarm".format(host_ip)
def making_host_decision(self, application, decision, release_node=False): """ Make decision on which host to run container Args: application(str) decision(str) Returns: host(str) """ logger = Logger(filename="orchastrator", logger_name="DecisionMaker making_host_decision") swarm_manager = SwarmManagment() app_per_node = "{}_per_node".format(application) app_by_hosts = self.counting_app_by_host(application) if release_node: del (app_by_hosts[release_node]) host_number = len(app_by_hosts.keys()) if decision is 'up': application_number = 0 for host in app_by_hosts.keys(): if app_by_hosts[host][application] == 0: return host else: application_number += app_by_hosts[host][application] average_app_number = application_number / host_number # print("Average => {}".format(average_app_number)) # print("Appp => {}".format(parse_config('orchastrator.json')[app_per_node])) logger.info("Aplication {} ||| Average => {}\tApp_per_node => {}". \ format(application, average_app_number, parse_config('orchastrator.json')[app_per_node])) logger.clear_handler() ###logic for adding node to the swarm if average_app_number >= parse_config( 'orchastrator.json')[app_per_node]: if len(parse_config('orchastrator.json') ['available_servers']) != 0: new_server = parse_config( 'orchastrator.json')['available_servers'][0] swarm_manager.join_server_swarm(host_ip=parse_config( 'orchastrator.json')['available_servers'][0]) return new_server else: logger.critical("There are not any available servers should" \ "look at host stat to run on the lowest" \ "loaded host a container") logger.clear_handler() # print("There are not any available servers should \ # look at host stat to run on the lowest \ # loaded host a container") ###logic for adding node to the swarm for host in app_by_hosts.keys(): if app_by_hosts[host][application] < average_app_number and \ app_by_hosts[host][application] < parse_config('orchastrator.json')[app_per_node]: return host for host in app_by_hosts.keys(): return host elif decision is 'down': application_number = 0 for host in app_by_hosts.keys(): application_number += app_by_hosts[host][application] min_app = "{}_min".format(application) # print("Min_app => {}\t app_num {}".format(parse_config('orchastrator.json')[min_app], application_number)) logger.warning("Application => {} ||| min_apps on platform=> {}\tcurrent app_num {}". \ format(application, parse_config('orchastrator.json')[min_app], application_number)) logger.clear_handler() if application_number == parse_config( 'orchastrator.json')[min_app]: return None average_app_number = application_number / host_number for host in app_by_hosts.keys(): if app_by_hosts[host][application] > average_app_number and \ app_by_hosts[host][application] < parse_config('orchastrator.json')[app_per_node]: return host for host in app_by_hosts.keys(): return host