コード例 #1
0
    def update_self(self, count=None, old_container=None, me_list=None, new_image=None):
        if count == 2:
            self.logger.debug('God im messy... cleaning myself up.')
            old_me_id = me_list[0].id if me_list[0].attrs['Created'] < me_list[1].attrs['Created'] else me_list[1].id
            old_me = self.client.containers.get(old_me_id)
            old_me_image_id = old_me.image.id

            old_me.stop()
            old_me.remove()

            self.client.images.remove(old_me_image_id)
            self.logger.debug('Ahhh. All better.')

            self.monitored = self.monitor_filter()
        elif count == 1:
            self.logger.debug('I need to update! Starting the ouroboros ;)')
            self_name = 'ouroboros-updated' if old_container.name == 'ouroboros' else 'ouroboros'
            new_config = set_properties(old=old_container, new=new_image, self_name=self_name)
            try:
                me_created = self.client.api.create_container(**new_config)
                new_me = self.client.containers.get(me_created.get("Id"))
                new_me.start()
                self.logger.debug('If you strike me down, I shall become '
                                  'more powerful than you could possibly imagine.')
                self.logger.debug('https://bit.ly/2VVY7GH')
                sleep(30)
            except APIError as e:
                self.logger.error("Self update failed.")
                self.logger.error(e)
コード例 #2
0
    def recreate(self, container, latest_image):
        new_config = set_properties(old=container, new=latest_image)

        self.stop(container)
        self.remove(container)

        created = self.client.api.create_container(**new_config)
        new_container = self.client.containers.get(created.get("Id"))

        # connect the new container to all networks of the old container
        for network_name, network_config in container.attrs['NetworkSettings'][
                'Networks'].items():
            network = self.client.networks.get(network_config['NetworkID'])
            try:
                network.disconnect(new_container.id, force=True)
            except APIError:
                pass
            new_network_config = {
                'container': new_container,
                'aliases': network_config['Aliases'],
                'links': network_config['Links']
            }
            if network_config['IPAMConfig']:
                new_network_config.update({
                    'ipv4_address':
                    network_config['IPAddress'],
                    'ipv6_address':
                    network_config['GlobalIPv6Address']
                })
            try:
                network.connect(**new_network_config)
            except APIError as e:
                if any(err in str(e) for err in
                       ['user configured subnets', 'user defined networks']):
                    if new_network_config.get('ipv4_address'):
                        del new_network_config['ipv4_address']
                    if new_network_config.get('ipv6_address'):
                        del new_network_config['ipv6_address']
                    network.connect(**new_network_config)
                else:
                    self.logger.error(
                        'Unable to attach updated container to network "%s". Error: %s',
                        network.name, e)

        new_container.start()
        return new_container
コード例 #3
0
ファイル: dockerclient.py プロジェクト: scobby/ouroboros
    def update_containers(self):
        updated_count = 0
        updated_container_tuples = []

        self.monitored = self.monitor_filter()

        if not self.monitored:
            self.logger.info('No containers are running or monitored on %s', self.socket)

        me_list = [c for c in self.client.api.containers() if 'ouroboros' in c['Names'][0].strip('/')]
        if len(me_list) > 1:
            self.update_self(count=2, me_list=me_list)

        for container in self.monitored:
            current_image = container.image

            shared_image = [uct for uct in updated_container_tuples if uct[1].id == current_image.id]
            if shared_image:
                latest_image = shared_image[0][2]
            else:
                try:
                    latest_image = self.pull(current_image)
                except ConnectionError:
                    continue

            # If current running container is running latest image
            if current_image.id != latest_image.id:
                if container.name in ['ouroboros', 'ouroboros-updated']:
                    self.update_self(old_container=container, new_image=latest_image, count=1)

                updated_container_tuples.append(
                    (container, current_image, latest_image)
                )
                self.logger.info('%s will be updated', container.name)

                # new container dict to create new container from
                new_config = set_properties(old=container, new=latest_image)

                self.logger.debug('Stopping container: %s', container.name)
                container.stop()

                self.logger.debug('Removing container: %s', container.name)
                try:
                    container.remove()
                except NotFound as e:
                    self.logger.error("Could not remove container. Error: %s", e)

                created = self.client.api.create_container(**new_config)
                new_container = self.client.containers.get(created.get("Id"))
                new_container.start()

                if self.config.cleanup:
                    try:
                        self.client.images.remove(current_image.id)
                    except APIError as e:
                        self.logger.error("Could not delete old image for %s, Error: %s", container.name, e)
                updated_count += 1

                self.logger.debug("Incrementing total container updated count")

                self.data_manager.total_updated[self.socket] += 1
                self.data_manager.add(label=container.name, socket=self.socket)
                self.data_manager.add(label='all', socket=self.socket)

        if updated_count > 0:
            self.notification_manager.send(container_tuples=updated_container_tuples, socket=self.socket,
                                           notification_type='data')

        self.notification_manager.send(notification_type='keep_alive')
コード例 #4
0
    def update_containers(self):
        updated_count = 0
        updated_container_tuples = []
        depends_on_list = []
        self.monitored = self.monitor_filter()

        if not self.monitored:
            self.logger.info('No containers are running or monitored on %s', self.socket)

        me_list = [c for c in self.client.api.containers() if 'ouroboros' in c['Names'][0].strip('/')]
        if len(me_list) > 1:
            self.update_self(count=2, me_list=me_list)

        for container in self.monitored:
            current_image = container.image

            shared_image = [uct for uct in updated_container_tuples if uct[1].id == current_image.id]
            if shared_image:
                latest_image = shared_image[0][2]
            else:
                try:
                    latest_image = self.pull(current_image)
                except ConnectionError:
                    continue

            if self.config.dry_run:
                # Ugly hack for repo digest
                repo_digest_id = current_image.attrs['RepoDigests'][0].split('@')[1]
                if repo_digest_id != latest_image.id:
                    self.logger.info('dry run : %s would be updated', container.name)
                continue

            # If current running container is running latest image
            if current_image.id != latest_image.id:
                updated_container_tuples.append(
                    (container, current_image, latest_image)
                )

                if container.name in ['ouroboros', 'ouroboros-updated']:
                    self.data_manager.total_updated[self.socket] += 1
                    self.data_manager.add(label=container.name, socket=self.socket)
                    self.data_manager.add(label='all', socket=self.socket)
                    self.notification_manager.send(container_tuples=updated_container_tuples,
                                                   socket=self.socket, kind='update')
                    self.update_self(old_container=container, new_image=latest_image, count=1)

                self.logger.info('%s will be updated', container.name)

                # Get container list to restart after update complete
                depends_on = container.labels.get('com.ouroboros.depends-on', False)
                if depends_on:
                    depends_on_list.extend([name.strip() for name in depends_on.split(',')])
                # new container dict to create new container from
                new_config = set_properties(old=container, new=latest_image)

                self.logger.debug('Stopping container: %s', container.name)
                stop_signal = container.labels.get('com.ouroboros.stop-signal', False)
                if stop_signal:
                    try:
                        container.kill(signal=stop_signal)
                    except APIError as e:
                        self.logger.error('Cannot kill container using signal %s. stopping normally. Error: %s',
                                          stop_signal, e)
                        container.stop()
                else:
                    container.stop()

                self.logger.debug('Removing container: %s', container.name)
                try:
                    container.remove()
                except NotFound as e:
                    self.logger.error("Could not remove container. Error: %s", e)

                created = self.client.api.create_container(**new_config)
                new_container = self.client.containers.get(created.get("Id"))
                new_container.start()

                if self.config.cleanup:
                    try:
                        self.client.images.remove(current_image.id)
                    except APIError as e:
                        self.logger.error("Could not delete old image for %s, Error: %s", container.name, e)
                updated_count += 1

                self.logger.debug("Incrementing total container updated count")

                self.data_manager.total_updated[self.socket] += 1
                self.data_manager.add(label=container.name, socket=self.socket)
                self.data_manager.add(label='all', socket=self.socket)

        if depends_on_list:
            depends_on_containers = []
            for name in list(set(depends_on_list)):
                try:
                    depends_on_containers.append(self.client.containers.get(name))
                except NotFound:
                    self.logger.error("Could not find dependant container %s on socket %s. Ignoring", name, self.socket)

            if depends_on_containers:
                for container in depends_on_containers:
                    self.logger.debug('Restarting dependant container %s', container.name)
                    container.restart()

        if updated_count > 0:
            self.notification_manager.send(container_tuples=updated_container_tuples, socket=self.socket, kind='update')