Exemplo n.º 1
0
    def __init__(self, network_name, subnet, reserved_ips=None):
        self.name = network_name
        self.ovs = True
        self.subnet = ipaddress.ip_network(subnet)
        self.address_pool = SortedSet(self.subnet.hosts())
        self.containers = dict()
        self.registrator = None
        self.listening = False
        self.dpid = None

        self.reservations = reserved_ips

        # reserve 1 IP address for the default gateway
        self.reservations['_'] = self._get_next_address()
        for _, ip in self.reservations.items():
            self._remove_ip(ip)

        if not self.check_bridge_exists():
            self.create_network(network_name)
        else:
            logger.debug('Bridge already exists, using it instead')

        self.get_ovs_dpid()

        self._handlers = {
            ('container', 'die'): self.handler_container_die,
            ('container', 'start'): self.handler_container_start
        }
Exemplo n.º 2
0
    def __init__(self, consul_container):
        consul_container.reload()
        consul_ip = consul_container.attrs['NetworkSettings']['Networks'][
            'bridge']['IPAddress']

        logger.debug(f'Connecting to Consul at address {consul_ip}')
        self.consul = consul.Consul(host=consul_ip)
Exemplo n.º 3
0
    def add_container(self, container, addr=None, reservation=None, register=False):
        reserved_ip = self.reservations.get(reservation)

        if reserved_ip:
            ipaddr = ipaddress.ip_address(reserved_ip)
        elif addr:
            ipaddr = self._remove_ip(addr)
        else:
            ipaddr = self._get_next_address()
        mac = _generate_random_MAC()

        logger.debug(f'Connect container {container.id[:12]} to network')

        if register:
            self.registrator.register(container, str(ipaddr))

        # connect to ovs bridge
        command = f'ovs-docker add-port {self.name} eth1 {container.id[:12]} '
        command += f'--ipaddress={str(ipaddr)}/{self.subnet.prefixlen} '
        command += f'--macaddress="{mac}"'
        run = subprocess.Popen(command, shell=True,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
        out, err = run.communicate()

        if run.returncode != 0:
            logger.error(f'Error while connecting container {container.id[:12]} to network')
            return OvsException('Failed while connecting container to network')
        else:
            self.containers[container.id] = Interface(ipaddr, mac)
Exemplo n.º 4
0
    def _get_next_address(self):
        if self.address_pool:
            next_addr = self.address_pool[0]
            self.address_pool.pop(0)

            logger.debug(f'Lending IP address {str(next_addr)}')
            return str(next_addr)
        else:
            logger.debug(f'No available IP address in the address pool')
            return None
Exemplo n.º 5
0
    def _remove_ip(self, ip):
        addr = ipaddress.ip_address(ip)

        if addr not in self.subnet:
            raise ValueError

        try:
            self.address_pool.remove(addr)
            logger.debug(f'Address {ip} is now in use')
            return addr
        except KeyError:
            return None
Exemplo n.º 6
0
    def remove_container(self, cid):
        logger.debug(f'Disconnect container {cid[:12]} from network')

        try:
            docker_api_client.disconnect_container_from_network(
                cid, self._network.id, force=True
            )
        except docker.errors.APIError:
            pass

        ipaddr = self.containers.pop(cid, None)
        if ipaddr:
            self._add_ip(ipaddr)
Exemplo n.º 7
0
    def add_container(self, container, addr=None, reservation=None, register=None):
        reserved_ip = self.reservations.get(reservation)

        if reserved_ip:
            ipaddr = ipaddress.ip_address(reserved_ip)
        elif addr:
            ipaddr = self._remove_ip(addr)
        else:
            ipaddr = self._get_next_address()

        logger.debug(f'Connect container {container.id[:12]} to network')

        # docker network connect
        docker_api_client.connect_container_to_network(
            container.id, self._network.id, ipv4_address=str(ipaddr)
        )

        self.containers[container.id] = ipaddr
Exemplo n.º 8
0
    def remove_container(self, cid):
        logger.debug(f'Disconnect container {cid[:12]} from network')

        if self.listening:
            self.registrator.deregister(cid)

        command = f'ovs-docker del-port {self.name} eth1 {cid[:12]}'
        run = subprocess.Popen(command, shell=True,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
        run.communicate()

        if run.returncode != 0:
            logger.error(f'Error while removing container {cid[:12]} from network')
            raise OvsException('Failed while removing container from network')

        interface = self.containers.pop(cid, None)
        if interface.ip:
            self._add_ip(interface.ip)
Exemplo n.º 9
0
    def register(self, container, ip):
        container.reload()

        config = container.attrs['Config']
        env_vars = config['Env']
        ports = list(config['ExposedPorts'].keys())
        port = int(ports[0].split('/')[0])

        service = dict()
        for var in env_vars:
            key, val = var.split('=')
            if key.startswith('SERVICE'):
                _, attr = key.lower().split('_')
                service[attr] = val

        if 'name' in service:
            logger.debug(f'Registering container {container.id} with {ip}')
            self.consul.agent.service.register(service['name'],
                                               service_id=container.id,
                                               port=port,
                                               address=ip)
Exemplo n.º 10
0
    def cleanup(self):
        """
        Stop the cloud manager and all components
        """
        logger.debug("Cleaning up everything")
        self.network.stop_listening()
        for container in (self.registry, self.registrator, self.proxy):
            try:
                self.network.remove_container(container.id)
                _stop_container(container)
            except:
                continue
        for service in self.services.values():
            service.stop()
        if self.sfc_orchestrator:
            self.sfc_orchestrator.stop()
        try:
            self.network.remove()
        except:
            pass

        self.running = False
        logger.debug("Removed running services and docker network")
Exemplo n.º 11
0
 def deregister(self, cid):
     logger.debug(f'De-registering container {cid}')
     self.consul.agent.service.deregister(cid)
Exemplo n.º 12
0
    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
Exemplo n.º 13
0
 def _add_ip(self, ip):
     addr = ipaddress.ip_address(ip)
     self.address_pool.add(addr)
     logger.debug(f'Address {ip} is now available in the address pool')
     return addr