def api_containers(container=None): if container: (_, v) = utils.find_item(swarm.instance.containers, container) if v: if flask.request.authorization.username == 'admin': return flask.jsonify(v) else: v = copy.copy(v) v.pop('env', None) return flask.jsonify(v) else: return flask.Response('container "%s" not found' % container, status=404) else: if flask.request.args.get('full'): if flask.request.authorization.username == 'admin': return flask.jsonify(swarm.instance.containers) else: results = dict() for k, v in swarm.instance.containers.items(): results[k] = copy.copy(v) results[k].pop('env', None) return flask.jsonify(results) else: results = { k: v['name'] for k, v in swarm.instance.containers.items() } return flask.jsonify(results)
def api_containers_stats(container, period): (k, _) = utils.find_item(swarm.instance.containers, container) if k: return get_stats(k, period) else: return flask.Response('container "%s" not found' % container, status=404)
def api_services_update(service): (k, _) = utils.find_item(swarm.instance.services, service) if k: swarm.instance.service_update(k) return flask.Response('service %s restarted' % service) else: return flask.Response('service "%s" not found' % service, status=404)
def api_services(service=None): if service: (_, v) = utils.find_item(swarm.instance.services, service) if v: if flask.request.authorization.username == 'admin': return flask.jsonify(v) else: v = copy.copy(v) v.pop('env', None) return flask.jsonify(v) else: return flask.Response('service "%s" not found' % service, status=404) else: if flask.request.args.get('full'): if flask.request.authorization.username == 'admin': return flask.jsonify(swarm.instance.services) else: results = dict() for k, v in swarm.instance.services.items(): results[k] = copy.copy(v) results[k].pop('env', None) return flask.jsonify(results) else: results = { k: v['name'] for k, v in swarm.instance.services.items() } return flask.jsonify(results)
def container_log(self, container, lines=10, timestamps=False): if lines == 'all': lines = 100 (k, v) = utils.find_item(self.containers, container) if not k: return None node = self.nodes[v['node']['id']] if 'url' in node: result = "" client = docker.APIClient(base_url=node['url'], version="auto", timeout=self.timeouts['docker']) try: log = client.logs(k, stdout=True, stderr=True, follow=False, timestamps=timestamps, tail=lines) if inspect.isgenerator(log): for row in log: # TODO work with generator result += row.decode('utf-8') else: result = log.decode('utf-8') except docker.errors.NotFound: self.logger.debug("Trying to get log from container '%s' that no longer exists." % container) result = "Countainer %s is no longer running." % container else: result = "Could not connect to docker host, no logs returned for %s." % container return result
def service_log(self, service, lines=10): (_, s) = utils.find_item(self.services, service) if not s: return None # TODO work with generator all_logs = [] for c in s['containers']: for line in self.container_log(c['id'], lines, True).split("\n"): pieces = line.split(maxsplit=1) if len(pieces) == 2: all_logs.append({'time': pieces[0], 'container': c['id'], 'log': pieces[1]}) sorted_logs = sorted(all_logs, key=lambda x: x['time']) if lines != 'all': sorted_logs = sorted_logs[-lines:] log = "" for line in sorted_logs: log += "%s | %s | %s\n" % (line['time'], line['container'], line['log']) # for line in sorted_logs: # pieces = line.split(maxsplit=1) # if len(pieces) == 2: # log += pieces[1] + "\n" return log
def service_remove(self, service): self.logger.info("remove service with name/id %s" % service) result = "successfully removed service " + service (k, v) = utils.find_item(self.services, service) removed = False if k: client = docker.APIClient(self.swarm_url, version='auto') try: removed = client.remove_service(k) except docker.errors.APIError: result = "failed to remove service" + service else: result = "failed to remove nonexistent service '%s'" % service if removed: # update in-memory storage. try: with self.lock: self.swarm['services'].remove(k) self.services.pop(k, None) for container_id in v.containers: self.containers.pop(container_id, None) for node_id in v.nodes: self.nodes.pop(node_id, None) except Exception as err: # it is fine to have exception here. self.logger.debug(err) return result
def html_services_logs(service): """ Return log viewer for a specific service. """ (k, v) = utils.find_item(swarm.instance.services, service) return flask.render_template('logs.html', service_id=k, service_name=v['name'], containers=v['containers'])
def api_services_restart(service): (k, v) = utils.find_item(swarm.instance.services, service) if k and v: replicas = v['replicas']['requested'] api_services_scale(k, 0) time.sleep(30) api_services_scale(k, replicas) return flask.Response('service %s restarted' % service) else: return flask.Response('service "%s" not found' % service, status=404)
def api_nodes(node): if node: (_, v) = utils.find_item(swarm.instance.nodes, node) if v: return flask.jsonify(v) else: return flask.Response('node "%s" not found' % node, status=404) else: if flask.request.args.get('full'): return flask.jsonify(swarm.instance.nodes) else: result = {k: v['name'] for k, v in swarm.instance.nodes.items()} return flask.jsonify(result)
def api_nodes_stats(node, period): (k, _) = utils.find_item(swarm.instance.nodes, node) if k: return get_stats(k, period) else: return flask.Response('node "%s" not found' % node, status=404)
def api_services_stats(service, period): (k, _) = utils.find_item(swarm.instance.services, service) if k: return get_stats(k, period) else: return flask.Response('service "%s" not found' % service, status=404)
def _service_update(self, service, force=False, **data): count = data.get("count", None) (k, v) = utils.find_item(self.services, service) if k: client = docker.APIClient(self.swarm_url, version='auto') s = client.inspect_service(k) if s and 'Spec' in s and 'TaskTemplate' in s['Spec']: spec = s['Spec'] task = spec['TaskTemplate'] config = task['ContainerSpec'] image = config['Image'] if force: image = re.sub(r'@sha256.*', '', image) container_spec = docker.types.ContainerSpec(image, command=config.get('Command', None), args=config.get('Args', None), hostname=config.get('Hostname', None), env=config.get('Env', None), workdir=config.get('Workdir', None), user=config.get('User', None), labels=config.get('Labels', None), mounts=config.get('Mounts', None), stop_grace_period=config.get('StopGracePeriod', None), secrets=config.get('Secrets', None)) if 'Resources' in task: if 'Limits' in task['Resources']: cpu_limit = task['Resources']['Limits'].get('NanoCPUs', None) mem_limit = task['Resources']['Limits'].get('MemoryBytes', None) else: cpu_limit = None mem_limit = None if 'Reservations' in task['Resources']: cpu_reservation = task['Resources']['Reservations'].get('NanoCPUs', None) mem_reservation = task['Resources']['Reservations'].get('MemoryBytes', None) else: cpu_reservation = None mem_reservation = None resources = docker.types.Resources(cpu_limit, mem_limit, cpu_reservation, mem_reservation) else: resources = None if 'RestartPolicy' in task: config = task['RestartPolicy'] restart_policy = docker.types.RestartPolicy(condition=config.get('Condition', 'none'), delay=config.get('Delay', 0), max_attempts=config.get('MaxAttempts', 0), window=config.get('Window', 0)) else: restart_policy = None if 'LogDriver' in task: config = task['LogDriver'] log_driver = docker.types.DriverConfig(config['Name'], options=config.get('Options', None)) else: log_driver = None force_update = task.get('ForceUpdate', 0) if force: force_update += 1 task_template = docker.types.TaskTemplate(container_spec, resources=resources, restart_policy=restart_policy, placement=task.get('Placement', None), log_driver=log_driver, force_update=force_update) if count is not None: mode = docker.types.ServiceMode("replicated", int(count)) # TODO bug in docker library, see https://github.com/docker/docker-py/issues/1572 if int(count) == 0: mode.get('replicated')['Replicas'] = 0 else: mode = docker.types.ServiceMode("replicated", utils.get_item(spec, 'Mode.Replicated.Replicas', 0)) if 'UpdateConfig' in spec: config = spec['EndpointSpec'] update_config = docker.types.UpdateConfig(config.get('Parallelism', 0), config.get('Delay', None), config.get('FailureAction', 'continue'), config.get('Monitor', None), config.get('MaxFailureRatio', None)) else: update_config = None if 'EndpointSpec' in spec: config = spec['EndpointSpec'] endpoint_spec = docker.types.EndpointSpec(config.get('Mode', None), config.get('Ports', None)) else: endpoint_spec = None labels = spec.get('Labels', {}) labels.update(data.get('labels', {})) if client.update_service(k, version=s['Version']['Index'], task_template=task_template, name=spec['Name'], labels=labels, mode=mode, update_config=update_config, networks=spec.get('Networks', None), endpoint_spec=endpoint_spec): if count is not None: v['replicas']['requested'] = int(count) return True, 'OK' else: return False, 'Could not update service %s.' % service else: return False, 'service "%s" not found' % service else: return False, 'service "%s" not found' % service