def prepare(self): report = StateReport() report.name = nexus.core.info.pdid report.osVersion = system_info.getOSVersion() # We can get the paradrop version from the installed python package. report.paradropVersion = system_info.getPackageVersion('paradrop') # TODO: Get pdinstall version - we will have to work with snappy or # devise some other mechanism, since it installs as a completely # separate snap. report.chutes = [] chuteStore = ChuteStorage() chutes = chuteStore.getChuteList() allocation = resource.computeResourceAllocation(chutes) for chute in chutes: container = ChuteContainer(chute.name) report.chutes.append({ 'name': chute.name, 'desired': chute.state, 'state': container.getStatus(), 'warning': chute.warning, 'version': getattr(chute, 'version', None), 'allocation': allocation.get(chute.name, None), 'environment': getattr(chute, 'environment', None), 'external': getattr(chute, 'external', None), 'resources': getattr(chute, 'resources', None) }) report.devices = devices.listSystemDevices() report.hostConfig = hostconfig.prepareHostConfig(write=False) client = SnapdClient() report.snaps = client.listSnaps() report.zerotierAddress = zerotier.getAddress() report.dmi = system_info.getDMI() # Add CPU, memory, disk, and network interface information. This gives # the controller useful debugging information such as high memory or # disk utilization and IP addresses. status_source = SystemStatus() report.status = status_source.getStatus(max_age=None) return report.__dict__
def get_chute(self, request, chute): """ Get information about an installed chute. **Example request**: .. sourcecode:: http GET /api/v1/chutes/hello-world **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "environment": {}, "name": "hello-world", "allocation": { "cpu_shares": 1024, "prioritize_traffic": false }, "state": "running", "version": "x1511808778", "resources": null } """ cors.config_cors(request) request.setHeader('Content-Type', 'application/json') try: chute_obj = ChuteStorage.chuteList[chute] service = chute_obj.get_default_service() container = ChuteContainer(service.get_container_name()) except KeyError: request.setResponseCode(404) return "{}" if not chute_access_allowed(request, chute_obj): return permission_denied(request) chuteStorage = ChuteStorage() allocation = resource.computeResourceAllocation( chuteStorage.getChuteList()) # TODO Return information about all of the chute's services. result = { 'name': chute, 'state': container.getStatus(), 'version': getattr(chute_obj, 'version', None), 'allocation': allocation.get(chute, None), 'environment': getattr(chute_obj, 'environment', None), 'resources': getattr(chute_obj, 'resources', None) } return json.dumps(result, cls=ChuteEncoder)
def get_chutes(self, request): """ List installed chutes. **Example request**: .. sourcecode:: http GET /api/v1/chutes/ **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json [ { "environment": {}, "name": "hello-world", "allocation": { "cpu_shares": 1024, "prioritize_traffic": false }, "state": "running", "version": "x1511808778", "resources": null } ] """ cors.config_cors(request) request.setHeader('Content-Type', 'application/json') chuteStorage = ChuteStorage() chutes = chuteStorage.getChuteList() allocation = resource.computeResourceAllocation(chutes) result = [] for chute in chutes: service = chute.get_default_service() container = ChuteContainer(service.get_container_name()) # TODO Return information about all of the chute's services. result.append({ 'name': chute.name, 'owner': chute.get_owner(), 'state': container.getStatus(), 'version': getattr(chute, 'version', None), 'allocation': allocation.get(chute.name, None), 'environment': getattr(chute, 'environment', None), 'resources': getattr(chute, 'resources', None) }) return json.dumps(result, cls=ChuteEncoder)
def prepare(self): chuteStore = ChuteStorage() chutes = chuteStore.getChuteList() # All network interfaces: we will divide these into chute-specific # interfaces and system-wide interfaces. network = SystemStatus.getNetworkInfo() system_interfaces = set(network.keys()) report = { 'chutes': [], 'network': [], 'system': SystemStatus.getSystemInfo(), 'time': time.time() } for chute in chutes: container = ChuteContainer(chute.name) chute_info = { 'name': chute.name, 'state': container.getStatus(), 'network': [] } try: pid = container.getPID() chute_info['process'] = SystemStatus.getProcessInfo(pid) except Exception as error: chute_info['process'] = None interfaces = chute.getCache('networkInterfaces') for iface in interfaces: ifname = iface['externalIntf'] if ifname in network: ifinfo = network[ifname] ifinfo['name'] = ifname ifinfo['type'] = iface.get('type', 'wifi') chute_info['network'].append(ifinfo) system_interfaces.remove(ifname) report['chutes'].append(chute_info) for ifname in system_interfaces: ifinfo = network[ifname] ifinfo['name'] = ifname ifinfo['type'] = None report['network'].append(ifinfo) return report
def get_chute(self, request, chute): """ Get information about an installed chute. **Example request**: .. sourcecode:: http GET /api/v1/chutes/hello-world **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "environment": {}, "name": "hello-world", "allocation": { "cpu_shares": 1024, "prioritize_traffic": false }, "state": "running", "version": "x1511808778", "resources": null } """ cors.config_cors(request) request.setHeader('Content-Type', 'application/json') chute_obj = ChuteStorage.chuteList[chute] container = ChuteContainer(chute) chuteStorage = ChuteStorage() allocation = resource.computeResourceAllocation( chuteStorage.getChuteList()) result = { 'name': chute, 'state': container.getStatus(), 'version': getattr(chute_obj, 'version', None), 'allocation': allocation.get(chute, None), 'environment': getattr(chute_obj, 'environment', None), 'resources': getattr(chute_obj, 'resources', None) } return json.dumps(result)
def prepare(self): chuteStore = ChuteStorage() chutes = chuteStore.getChuteList() # All network interfaces: we will divide these into chute-specific # interfaces and system-wide interfaces. network = SystemStatus.getNetworkInfo() system_interfaces = set(network.keys()) report = { 'chutes': [], 'network': [], 'system': SystemStatus.getSystemInfo(), 'time': time.time() } for chute in chutes: container = ChuteContainer(chute.name) chute_info = { 'name': chute.name, 'state': container.getStatus(), 'network': [] } try: pid = container.getPID() chute_info['process'] = SystemStatus.getProcessInfo(pid) except Exception: chute_info['process'] = None interfaces = chute.getCache('networkInterfaces') for iface in interfaces: ifname = iface['externalIntf'] if ifname in network: ifinfo = network[ifname] ifinfo['name'] = ifname ifinfo['type'] = iface.get('type', 'wifi') chute_info['network'].append(ifinfo) system_interfaces.remove(ifname) report['chutes'].append(chute_info) for ifname in system_interfaces: ifinfo = network[ifname] ifinfo['name'] = ifname ifinfo['type'] = None report['network'].append(ifinfo) return report
def generateConfigSections(): sections = [] sections.append({ "header": "global", "lines": [ "daemon", "maxconn 256", ] }) sections.append({ "header": "defaults", "lines": [ "mode http", "timeout connect 5000ms", "timeout client 50000ms", "timeout server 50000ms" ] }) sections.append({ "header": "backend portal", "lines": [ "server pd_portal 127.0.0.1:8080 maxconn 256" ] }) # Custom variables: # - req.querymarker: will be set to the literal "?" if the original request # contains a query string. We will use this to construct a redirect with a # query string only if needed. # - req.subpath: will be set to the remainder of the path, if anything, # after removing /chutes/<chutename>, e.g. "/chutes/hello-world/index.html" # becomes "/index.html". This does not include the query string. frontend = { "header": "frontend http-in", "lines": [ "bind *:80", "default_backend portal", "http-request set-var(req.querymarker) str(?) if { query -m found }", "http-request set-var(req.subpath) path,regsub(^/chutes/[^/]+,)" ] } sections.append(frontend) chuteStore = ChuteStorage() chutes = chuteStore.getChuteList() for chute in chutes: port, service = chute.get_web_port_and_service() if port is None or service is None: continue container = ChuteContainer(service.get_container_name()) if not container.isRunning(): continue # Generate a rule that matches HTTP host header to chute name. frontend['lines'].append("acl host_{} hdr(host) -i {}.chute.paradrop.org".format( chute.name, chute.name)) frontend['lines'].append("use_backend {} if host_{}".format( chute.name, chute.name)) # Generate rules that matches the beginning of the URL. # We need to be careful and either have an exact match # or make sure there is a slash or question mark after the chute name # to avoid mix-ups, e.g. "sticky-board" and "sticky-board-new". frontend['lines'].append("acl path_{} url /chutes/{}".format( chute.name, chute.name)) frontend['lines'].append("acl path_{} url_beg /chutes/{}/".format( chute.name, chute.name)) frontend['lines'].append("acl path_{} url_beg /chutes/{}?".format( chute.name, chute.name)) # Try to find a host binding for the web port to redirect: # http://<host addr>/chutes/<chute>/<path> -> # http://<host addr>:<chute port>/<path> # # We need to do a lookup because the host port might be dynamically # assigned by Docker. # # Use HTTP code 302 for the redirect, which will not be cached by the # web browser. The port portion of the URL can change whenever the # chute restarts, so we don't want web browsers to cache it. Browsers # will cache a 301 (Moved Permanently) response. portconf = container.getPortConfiguration(port, "tcp") if len(portconf) > 0: # TODO: Are there other elements in the list? binding = portconf[0] frontend['lines'].append("http-request replace-value Host (.*):(.*) \\1") frontend['lines'].append("http-request redirect location http://%[req.hdr(host)]:{}%[var(req.subpath)]%[var(req.querymarker)]%[query] code 302 if path_{}".format( binding['HostPort'], chute.name)) # Add a server at the chute's IP address. sections.append({ "header": "backend {}".format(chute.name), "lines": [ "server {} {}:{} maxconn 256".format(chute.name, container.getIP(), port) ] }) return sections
def generateConfigSections(): sections = [] sections.append({ "header": "global", "lines": [ "daemon", "maxconn 256", ] }) sections.append({ "header": "defaults", "lines": [ "mode http", "timeout connect 5000ms", "timeout client 50000ms", "timeout server 50000ms" ] }) sections.append({ "header": "backend portal", "lines": ["server pd_portal 127.0.0.1:8080 maxconn 256"] }) # Custom variables: # - req.querymarker: will be set to the literal "?" if the original request # contains a query string. We will use this to construct a redirect with a # query string only if needed. # - req.subpath: will be set to the remainder of the path, if anything, # after removing /chutes/<chutename>, e.g. "/chutes/hello-world/index.html" # becomes "/index.html". This does not include the query string. frontend = { "header": "frontend http-in", "lines": [ "bind *:80", "default_backend portal", "http-request set-var(req.querymarker) str(?) if { query -m found }", "http-request set-var(req.subpath) path,regsub(^/chutes/[^/]+,)" ] } sections.append(frontend) chuteStore = ChuteStorage() chutes = chuteStore.getChuteList() for chute in chutes: port, service = chute.get_web_port_and_service() if port is None or service is None: continue container = ChuteContainer(service.get_container_name()) if not container.isRunning(): continue # Generate a rule that matches HTTP host header to chute name. frontend['lines'].append( "acl host_{} hdr(host) -i {}.chute.paradrop.org".format( chute.name, chute.name)) frontend['lines'].append("use_backend {} if host_{}".format( chute.name, chute.name)) # Generate rules that matches the beginning of the URL. # We need to be careful and either have an exact match # or make sure there is a slash or question mark after the chute name # to avoid mix-ups, e.g. "sticky-board" and "sticky-board-new". frontend['lines'].append("acl path_{} url /chutes/{}".format( chute.name, chute.name)) frontend['lines'].append("acl path_{} url_beg /chutes/{}/".format( chute.name, chute.name)) frontend['lines'].append("acl path_{} url_beg /chutes/{}?".format( chute.name, chute.name)) # Try to find a host binding for the web port to redirect: # http://<host addr>/chutes/<chute>/<path> -> # http://<host addr>:<chute port>/<path> # # We need to do a lookup because the host port might be dynamically # assigned by Docker. # # Use HTTP code 302 for the redirect, which will not be cached by the # web browser. The port portion of the URL can change whenever the # chute restarts, so we don't want web browsers to cache it. Browsers # will cache a 301 (Moved Permanently) response. portconf = container.getPortConfiguration(port, "tcp") if len(portconf) > 0: # TODO: Are there other elements in the list? binding = portconf[0] frontend['lines'].append( "http-request redirect location http://%[req.hdr(host)]:{}%[var(req.subpath)]%[var(req.querymarker)]%[query] code 302 if path_{}" .format(binding['HostPort'], chute.name)) # Add a server at the chute's IP address. sections.append({ "header": "backend {}".format(chute.name), "lines": [ "server {} {}:{} maxconn 256".format(chute.name, container.getIP(), port) ] }) return sections
def prepare(self): report = StateReport() report.name = nexus.core.info.pdid report.osVersion = system_info.getOSVersion() # We can get the paradrop version from the installed python package. report.paradropVersion = system_info.getPackageVersion('paradrop') report.chutes = [] chuteStore = ChuteStorage() chutes = chuteStore.getChuteList() allocation = resource.computeResourceAllocation(chutes) for chute in chutes: service_info = {} for service in chute.get_services(): container_name = service.get_container_name() container = ChuteContainer(container_name) service_info[service.name] = { 'allocation': allocation.get(container_name, None), 'state': container.getStatus() } # Use the default service (e.g. "main") to report the chute's # current state. service = chute.get_default_service() container = ChuteContainer(service.get_container_name()) report.chutes.append({ 'name': chute.name, 'desired': chute.state, 'state': container.getStatus(), 'services': service_info, 'warning': None, 'version': getattr(chute, 'version', None), 'allocation': None, # deprecated 'environment': getattr(chute, 'environment', None), 'external': getattr(chute, 'external', None), 'resources': getattr(chute, 'resources', None) }) report.devices = devices.listSystemDevices() report.hostConfig = hostconfig.prepareHostConfig(write=False) if GovernorClient.isAvailable(): client = GovernorClient() report.snaps = client.listSnaps() report.zerotierAddress = zerotier.getAddress() report.dmi = system_info.getDMI() # Add CPU, memory, disk, and network interface information. This gives # the controller useful debugging information such as high memory or # disk utilization and IP addresses. status_source = SystemStatus() report.status = status_source.getStatus(max_age=None) return report.__dict__