def run_app(cloud_instance, host='0.0.0.0', port=8080): global _cloud, current_host, current_port _cloud = cloud_instance current_host = host current_port = port logger.info(f'Starting REST application on {host}:{port}') app.run(host=host, port=port, threaded=True)
def handler_container_die(self, event): cid = event['Actor']['ID'] if cid not in self.containers: return logger.info(f'Network disconnect event with container {cid[:12]}') self.remove_container(cid)
def listen(self): logger.info('Listening to Docker events...') for event in docker_client.events(decode=True): if not self.listening: break func = self._handlers.get((event['Type'], event['Action'])) if func: func(event)
def handler_network_disconnect(self, event): if event['Actor']['ID'] == self._network.id: cid = event['Actor']['Attributes']['container'] if cid not in self.containers: return logger.info(f'Network disconnect event with container {cid[:12]}') self.remove_container(cid)
def _stop_container(container): """ Force remove a container """ try: logger.info(f'Stopping container {container.id}') container.remove(force=True) except: pass finally: return True
def stop_service(self, name): """ Stop and deregister """ old_service = self.services.pop(name, None) if old_service: old_service.stop() self.used_ports.remove(old_service.port) logger.info(f"Removed service: {old_service.name}") return True logger.warning(f"Service {name} does not exist") return False
def handler_network_connect(self, event): if event['Actor']['ID'] == self._network.id: cid = event['Actor']['Attributes']['container'] if cid in self.containers: return container = docker_client.containers.get(cid) networks = container.attrs['NetworkSettings']['Networks'] ipaddr = networks[self._network.name]['IPAddress'] logger.info(f'Network connect event with container {cid[:12]}') self.add_container(container, ipaddr)
def parse_file(config_path): if not os.path.isfile(config_path): raise IOError with open(config_path, "r") as f: try: configs = json.load(f, encoding="utf-8") except ValueError: raise ValueError("Configuration file is not in JSON format") # config file must contain subnet range if "subnet" not in configs: raise KeyError("You need to specify the subnet range") logger.info(json.dumps(configs, indent=2, sort_keys=True)) return configs
def attach_to_existing_network(self, name): network_list = docker_client.networks.list(names=[name]) if len(network_list) > 0: logger.info('Existing Docker network found, attaching...') self._network = network_list[0] network_gateway = self._network.attrs['IPAM']['Config'][0].get('Gateway') if network_gateway: self._remove_ip(network_gateway) else: self.reservations['_'] = self._get_next_address() for cid, specs in self._network.attrs['Containers'].items(): addr = specs['IPv4Address'][:-3] self.add_container(cid, addr) return True else: return False
parsed = parser.parse_args() if parsed.config: kwargs = parse_file(parsed.config) else: kwargs = vars(parsed) my_cloud = None def sigterm_handler(_signo, _stack_frame): sys.exit(0) signal.signal(signal.SIGTERM, sigterm_handler) try: logger.info("Starting services...") my_cloud = cloud.MyCloud(**kwargs) logger.info("Everything is up") cloud_shell = CloudShell(my_cloud) def listener_loop(): my_cloud.network.listen() t = Thread(target=listener_loop, daemon=True) t.start() t_rest_api = Thread(target=restapi.run_app, args=(my_cloud, ), kwargs={'port': parsed.restapi_port},
def __init__(self, subnet=None, network_name=None, ovs=False, proxy_ip=None, gateway_ip=None, initial_services=None, entrypoint=None): self.running = True # declare variables for network stuff self.proxy_ip = proxy_ip self.gateway_ip = gateway_ip reservations = {'proxy': proxy_ip, 'gateway': gateway_ip} if not proxy_ip: reservations.pop('proxy') if not gateway_ip: reservations.pop('gateway') if ovs: self.network = OpenVSwitchNetwork(network_name, subnet, reservations) else: self.network = BridgeNetwork(network_name, subnet, reservations) self.registry_ip = self.network.reserve_ip('registry') logger.debug(f'registry ip requested: {self.registry_ip}') # create variables for important containers self.registry_name = "service-registry-%s" % network_name self.registrator_name = "service-registrator-%s" % network_name self.proxy_name = "proxy-%s" % network_name self.proxy_entrypoint = entrypoint self.registry = None self.registrator = None self.proxy = None self.services = {} self.used_ports = set() try: self.sfc_orchestrator = SfcOrchestrator(self.network) except SfcException: self.sfc_orchestrator = None try: self.create_registry() self.create_proxy() self.proxy.start() self.network.add_container(self.proxy, reservation='proxy') self.proxy.exec_run('/root/entry/custom-entrypoint.sh') logger.info("Proxy has been started") self.registry.start() self.network.add_container(self.registry, reservation='registry') logger.info("Service registry has been started") if self.network.ovs: self.network.registrator = Registrator(self.registry) else: self.create_registrator() if self.registrator: self.network.add_container(self.registrator) self.registrator.start() logger.info("Service registrator has been started") if initial_services: self.initialize_services(initial_services) except Exception as e: logger.error(''.join( traceback.format_exception(type(e), e, e.__traceback__))) self.cleanup() raise CloudException