def star_image(request): """Toggle image as starred.""" backend_id = request.matchdict['backend'] image_id = request.matchdict['image'] user = user_from_request(request) return methods.star_image(user, backend_id, image_id)
def get_loadavg(request, action=None): """Get the loadavg png displayed in the machines list view.""" params = request.params start = params.get('start', '') stop = params.get('stop', '') user = user_from_request(request) core_uri = config.CORE_URI payload = { 'start': start, 'stop': stop, } headers = { 'Authorization': get_auth_header(user), 'Content-type': 'image/png', 'Accept': '*/*' } try: ret = requests.get(config.CORE_URI + request.path, params=payload, headers=headers, verify=config.SSL_VERIFY) except requests.exceptions.SSLError as exc: log.error("%r", exc) raise SSLError() if ret.status_code != 200: log.error("Error getting loadavg %d:%s", ret.status_code, ret.text) raise ServiceUnavailableError() return Response(ret.content, content_type='image/png', request=request)
def update_user_settings(request): """try free plan, by communicating to the mist.core service""" params = request.json_body action = params.get('action', '').lower() plan = params.get('plan', '') name = params.get('name', '') company_name = params.get('company_name', '') country = params.get('country', '') number_of_servers = params.get('number_of_servers', '') number_of_people = params.get('number_of_people', '') user = user_from_request(request) payload = {'action': action, 'plan': plan, 'name': name, 'company_name': company_name, 'country': country, 'number_of_servers': number_of_servers, 'number_of_people': number_of_people} try: ret = requests.post(config.CORE_URI + '/account', params=payload, headers={'Authorization': get_auth_header(user)}, verify=config.SSL_VERIFY) except requests.exceptions.SSLError as exc: log.error("%r", exc) raise SSLError() if ret.status_code == 200: ret = json.loads(ret.content) return ret else: raise UnauthorizedError()
def get_stats(request): core_uri = config.CORE_URI user = user_from_request(request) params = request.params start = params.get('start') stop = params.get('stop') step = params.get('step') expression = params.get('expression') params = { 'start': start, 'stop': stop, 'step': step, 'expression': expression, } try: ret = requests.get(config.CORE_URI + request.path, params=params, headers={'Authorization': get_auth_header(user)}, verify=config.SSL_VERIFY) except requests.exceptions.SSLError as exc: log.error("%r", exc) raise SSLError() if ret.status_code == 200: return ret.json() else: log.error("Error getting stats %d:%s", ret.status_code, ret.text) raise ServiceUnavailableError()
def check_auth(request): """Check on the mist.core service if authenticated""" params = request.json_body email = params.get('email', '').lower() password = params.get('password', '') payload = {'email': email, 'password': password} try: ret = requests.post(config.CORE_URI + '/auth', params=payload, verify=config.SSL_VERIFY) except requests.exceptions.SSLError as exc: log.error("%r", exc) raise SSLError() if ret.status_code == 200: ret_dict = json.loads(ret.content) user = user_from_request(request) with user.lock_n_load(): user.email = email user.mist_api_token = ret_dict.pop('mist_api_token', '') user.save() log.info("succesfully check_authed") return ret_dict else: log.error("Couldn't check_auth to mist.io: %r", ret) raise UnauthorizedError()
def machine_actions(request): # TODO: We shouldn't return list_machines, just 200. Save the API! backend_id = request.matchdict['backend'] machine_id = request.matchdict['machine'] user = user_from_request(request) params = request.json_body action = params.get('action', '') plan_id = params.get('plan_id', '') # plan_id is the id of the plan to resize name = params.get('name', '') if action in ('start', 'stop', 'reboot', 'destroy', 'resize', 'rename'): if action == 'start': methods.start_machine(user, backend_id, machine_id) elif action == 'stop': methods.stop_machine(user, backend_id, machine_id) elif action == 'reboot': methods.reboot_machine(user, backend_id, machine_id) elif action == 'destroy': methods.destroy_machine(user, backend_id, machine_id) elif action == 'resize': methods.resize_machine(user, backend_id, machine_id, plan_id) elif action == 'rename': methods.rename_machine(user, backend_id, machine_id, name) # return OK return methods.list_machines(user, backend_id) raise BadRequestError()
def create_machine(request): """Creates a new virtual machine on the specified backend.""" backend_id = request.matchdict['backend'] try: key_id = request.json_body.get('key') machine_name = request.json_body['name'] location_id = request.json_body.get('location', None) image_id = request.json_body['image'] size_id = request.json_body['size'] #deploy_script received as unicode, but ScriptDeployment wants str script = str(request.json_body.get('script', '')) # these are required only for Linode/GCE, passing them anyway image_extra = request.json_body.get('image_extra', None) disk = request.json_body.get('disk', None) image_name = request.json_body.get('image_name', None) size_name = request.json_body.get('size_name', None) location_name = request.json_body.get('location_name', None) ips = request.json_body.get('ips', None) monitoring = request.json_body.get('monitoring', False) networks = request.json_body.get('networks', []) except Exception as e: raise RequiredParameterMissingError(e) user = user_from_request(request) ret = methods.create_machine(user, backend_id, key_id, machine_name, location_id, image_id, size_id, script, image_extra, disk, image_name, size_name, location_name, ips, monitoring, networks) return ret
def create_machine(request): """Creates a new virtual machine on the specified backend.""" backend_id = request.matchdict['backend'] try: key_id = request.json_body.get('key') machine_name = request.json_body['name'] location_id = request.json_body.get('location', None) image_id = request.json_body['image'] size_id = request.json_body['size'] #deploy_script received as unicode, but ScriptDeployment wants str script = str(request.json_body.get('script', '')) # these are required only for Linode/GCE, passing them anyway image_extra = request.json_body.get('image_extra', None) disk = request.json_body.get('disk', None) image_name = request.json_body.get('image_name', None) size_name = request.json_body.get('size_name', None) location_name = request.json_body.get('location_name', None) ips = request.json_body.get('ips', None) monitoring = request.json_body.get('monitoring', False) networks = request.json_body.get('networks', []) docker_env = request.json_body.get('docker_env', []) docker_command = request.json_body.get('docker_command', None) except Exception as e: raise RequiredParameterMissingError(e) user = user_from_request(request) ret = methods.create_machine(user, backend_id, key_id, machine_name, location_id, image_id, size_id, script, image_extra, disk, image_name, size_name, location_name, ips, monitoring, networks, docker_env, docker_command) return ret
def deploy_plugin(request): user = user_from_request(request) backend_id = request.matchdict['backend'] machine_id = request.matchdict['machine'] plugin_id = request.matchdict['plugin'] params = params_from_request(request) plugin_type = params.get('plugin_type') host = params.get('host') if plugin_type == 'python': ret = methods.deploy_python_plugin( user, backend_id, machine_id, plugin_id, value_type=params.get('value_type', 'gauge'), read_function=params.get('read_function'), host=host, ) methods.update_metric( user, metric_id=ret['metric_id'], name=params.get('name'), unit=params.get('unit'), backend_id=backend_id, machine_id=machine_id, ) return ret else: raise BadRequestError("Invalid plugin_type: '%s'" % plugin_type)
def check_monitoring(request): """Ask the mist.io service if monitoring is enabled for this machine. """ user = user_from_request(request) ret = methods.check_monitoring(user) return ret
def get_public_key(request): user = user_from_request(request) key_id = request.matchdict['key'] if not key_id: raise RequiredParameterMissingError("key_id") if not key_id in user.keypairs: raise KeypairNotFoundError(key_id) return user.keypairs[key_id].public
def __init__(self, *args, **kwargs): super(CustomNamespace, self).__init__(*args, **kwargs) self.user = user_from_request(self.request) self.session_id = uuid.uuid4().hex log.info("Initialized %s for user %s. Socket %s. Session %s", self.__class__.__name__, self.user.email, self.socket.sessid, self.session_id) self.init()
def get_public_key(request): user = user_from_request(request) key_id = request.matchdict['key'] if not key_id: raise RequiredParameterMissingError("key_id") if key_id not in user.keypairs: raise KeypairNotFoundError(key_id) return user.keypairs[key_id].public
def list_keys(request): """List keys. List all key pairs that are configured on this server. Only the public keys are returned. """ user = user_from_request(request) return methods.list_keys(user)
def shell_stream(request): """Execute command via SSH and stream output Streams output using the hidden iframe technique. """ def parse(lines): """Generator function that converts stdout_lines to html with js which it streams in a hidden iframe. """ # send some blank data to fill the initial buffer and get (webkit) # browsers to display right away what's sent #yield 1024*'\0' # start the html response yield "<html><body>\n" js = "<script type='text/javascript'>parent.appendShell('%s', '%s');</script>\n" for line in lines: # get commands output, line by line clear_line = line.replace('\'', '\\\'') clear_line = clear_line.replace('\n', '<br/>') clear_line = clear_line.replace('\r', '') #.replace('<','<').replace('>', '>') ret = js % (clear_line, cmd_id) yield ret js = "<script type='text/javascript'>" js += "parent.completeShell(%s, '%s');</script>\n" yield js % (1, cmd_id) # FIXME yield "</body></html>\n" log.info("got shell_stream request") backend_id = request.matchdict['backend'] machine_id = request.matchdict['machine'] cmd = request.params.get('command') cmd_id = request.params.get('command_id').encode('utf-8', 'ignore') host = request.params.get('host') try: if not cmd: raise RequiredParameterMissingError("command") if not host: raise RequiredParameterMissingError("host") user = user_from_request(request) shell = Shell(host) shell.autoconfigure(user, backend_id, machine_id) # stdout_lines is a generator that spits out lines of combined # stdout and stderr output. cmd is executed via the shell on the background # and the stdout_lines generator is immediately available. stdout_lines # will block if no line is in the buffer and will stop iterating once the # command is completed and the pipe is closed. stdout_lines = shell.command_stream(cmd) except Exception as e: message = ["Failed to execute command\n", "Error: %s \n" % e] return Response(status=500, app_iter=parse(message)) return Response(status=200, app_iter=parse(stdout_lines))
def list_backends(request): """Gets the available backends. .. note:: Currently, this is only used by the backend controller in js. """ user = user_from_request(request) return methods.list_backends(user)
def get_stats(request): return methods.get_stats( user_from_request(request), request.matchdict['backend'], request.matchdict['machine'], request.params.get('start'), request.params.get('stop'), request.params.get('step') )
def add_backend(request): """Adds a new backend.""" params = request.json_body #remove spaces from start/end of string fields that are often included #when pasting keys, preventing thus succesfull connection with the #backend for key in params.keys(): if type(params[key]) in [unicode, str]: params[key] = params[key].rstrip().lstrip() title = params.get('title', '') provider = params.get('provider', '') apikey = params.get('apikey', '') apisecret = params.get('apisecret', '') apiurl = params.get('apiurl') or '' # fixes weird issue with none value tenant_name = params.get('tenant_name', '') # following params are for baremetal machine_hostname = params.get('machine_ip', '') machine_key = params.get('machine_key', '') machine_user = params.get('machine_user', '') remove_on_error = params.get('remove_on_error', True) try: docker_port = int(params.get('docker_port', 4243)) except: docker_port = 4243 try: ssh_port = int(params.get('machine_port', 22)) except: ssh_port = 22 region = params.get('region', '') compute_endpoint = params.get('compute_endpoint', '') # TODO: check if all necessary information was provided in the request user = user_from_request(request) backend_id = methods.add_backend( user, title, provider, apikey, apisecret, apiurl, tenant_name=tenant_name, machine_hostname=machine_hostname, machine_key=machine_key, machine_user=machine_user, region=region, compute_endpoint=compute_endpoint, port=ssh_port, docker_port=docker_port, remove_on_error=remove_on_error, ) backend = user.backends[backend_id] return { 'index': len(user.backends) - 1, 'id': backend_id, 'apikey': backend.apikey, 'apiurl': backend.apiurl, 'tenant_name': backend.tenant_name, 'title': backend.title, 'provider': backend.provider, 'poll_interval': backend.poll_interval, 'region': backend.region, 'status': 'off', 'enabled': backend.enabled, }
def edit_key(request): old_id = request.matchdict['key'] new_id = request.json_body.get('new_id') if not new_id: raise RequiredParameterMissingError("new_id") user = user_from_request(request) methods.edit_key(user, new_id, old_id) return {'new_id': new_id}
def get_stats(request): data = methods.get_stats(user_from_request(request), request.matchdict['backend'], request.matchdict['machine'], request.params.get('start'), request.params.get('stop'), request.params.get('step'), request.params.get('metrics')) data['request_id'] = request.params.get('request_id') return data
def disassoc_metric(request): user = user_from_request(request) backend_id = request.matchdict['backend'] machine_id = request.matchdict['machine'] params = params_from_request(request) metric_id = params.get('metric_id') if not metric_id: raise RequiredParameterMissingError('metric_id') methods.disassoc_metric(user, backend_id, machine_id, metric_id) return {}
def add_backend(request): """Adds a new backend.""" params = request.json_body title = params.get('title', '') provider = params.get('provider', '') apikey = params.get('apikey', '') apisecret = params.get('apisecret', '') apiurl = params.get('apiurl') or '' # fixes weird issue with none value tenant_name = params.get('tenant_name', '') # following params are for baremetal machine_hostname = params.get('machine_ip', '') machine_key = params.get('machine_key', '') machine_user = params.get('machine_user', '') try: docker_port = int(params.get('docker_port', 4243)) except: docker_port = 4243 try: ssh_port = int(params.get('machine_port', 22)) except: ssh_port = 22 region = params.get('region', '') compute_endpoint = params.get('compute_endpoint', '') # TODO: check if all necessary information was provided in the request user = user_from_request(request) backend_id = methods.add_backend(user, title, provider, apikey, apisecret, apiurl, tenant_name=tenant_name, machine_hostname=machine_hostname, machine_key=machine_key, machine_user=machine_user, region=region, compute_endpoint=compute_endpoint, port=ssh_port, docker_port=docker_port) backend = user.backends[backend_id] return { 'index': len(user.backends) - 1, 'id': backend_id, 'apikey': backend.apikey, 'apiurl': backend.apiurl, 'tenant_name': backend.tenant_name, 'title': backend.title, 'provider': backend.provider, 'poll_interval': backend.poll_interval, 'region': backend.region, 'status': 'off', 'enabled': backend.enabled, }
def update_monitoring(request): """Enable/disable monitoring for this machine using the hosted mist.io service. """ user = user_from_request(request) backend_id = request.matchdict['backend'] machine_id = request.matchdict['machine'] if not user.mist_api_token: log.info("trying to authenticate to service first") email = request.json_body.get('email') password = request.json_body.get('password') if not email or not password: raise UnauthorizedError("You need to authenticate to mist.io.") payload = {'email': email, 'password': password} try: ret = requests.post(config.CORE_URI + '/auth', params=payload, verify=config.SSL_VERIFY) except requests.exceptions.SSLError as exc: log.error("%r", exc) raise SSLError() if ret.status_code == 200: ret_dict = json.loads(ret.content) with user.lock_n_load(): user.email = email user.mist_api_token = ret_dict.pop('mist_api_token', '') user.save() log.info("succesfully check_authed") else: raise UnauthorizedError("You need to authenticate to mist.io.") action = request.json_body['action'] or 'enable' name = request.json_body.get('name', '') public_ips = request.json_body.get('public_ips', []) dns_name = request.json_body.get('dns_name', '') no_ssh = bool(request.json_body.get('no_ssh', False)) dry = bool(request.json_body.get('dry', False)) if action == 'enable': ret_dict = methods.enable_monitoring(user, backend_id, machine_id, name, dns_name, public_ips, no_ssh=no_ssh, dry=dry) elif action == 'disable': methods.disable_monitoring(user, backend_id, machine_id, no_ssh=no_ssh) ret_dict = {} else: raise BadRequestError() return ret_dict
def delete_network(request): """ Deletes a network. Currently working only with OPENSTACK backend """ backend_id = request.matchdict['backend'] network_id = request.matchdict['network'] user = user_from_request(request) methods.delete_network(user, backend_id, network_id) return OK
def set_machine_metadata(request): """Sets metadata for a machine, given the backend and machine id.""" backend_id = request.matchdict['backend'] machine_id = request.matchdict['machine'] try: tag = request.json_body['tag'] except: raise RequiredParameterMissingError('tag') user = user_from_request(request) methods.set_machine_metadata(user, backend_id, machine_id, tag) return OK
def rename_backend(request): """Renames a backend.""" backend_id = request.matchdict['backend'] new_name = request.json_body.get('new_name', '') if not new_name: raise RequiredParameterMissingError('new_name') user = user_from_request(request) methods.rename_backend(user, backend_id, new_name) return OK
def disassociate_key(request): key_id = request.matchdict['key'] backend_id = request.matchdict['backend'] machine_id = request.matchdict['machine'] try: host = request.json_body.get('host') except: host = None user = user_from_request(request) methods.disassociate_key(user, key_id, backend_id, machine_id, host) return user.keypairs[key_id].machines
def delete_machine_tag(request): """Deletes tag for a machine, given the machine id and the tag to be deleted. """ backend_id = request.matchdict['backend'] machine_id = request.matchdict['machine'] tag = request.matchdict['tag'] user = user_from_request(request) methods.delete_machine_tag(user, backend_id, machine_id, tag) return OK
def list_keys(request): """List keys. List all key pairs that are configured on this server. Only the public keys are returned. """ user = user_from_request(request) return [{'id': key, 'machines': user.keypairs[key].machines, 'isDefault': user.keypairs[key].default} for key in user.keypairs]
def rename_cloud(request): """Renames a cloud.""" cloud_id = request.matchdict['cloud'] params = params_from_request(request) new_name = params.get('new_name', '') if not new_name: raise RequiredParameterMissingError('new_name') user = user_from_request(request) methods.rename_cloud(user, cloud_id, new_name) return OK
def delete_backend(request): """Deletes a backend. .. note:: It assumes the user may re-add it later so it does not remove any key associations. """ backend_id = request.matchdict['backend'] user = user_from_request(request) methods.delete_backend(user, backend_id) return OK
def get_stats(request): data = methods.get_stats( user_from_request(request), request.matchdict['backend'], request.matchdict['machine'], request.params.get('start'), request.params.get('stop'), request.params.get('step'), request.params.get('metrics') ) data['request_id'] = request.params.get('request_id') return data
def list_images(request): """List images from each backend. Furthermore if a search_term is provided, we loop through each backend and search for that term in the ids and the names of the community images""" backend_id = request.matchdict['backend'] try: term = request.json_body.get('search_term', '').lower() except: term = None user = user_from_request(request) return methods.list_images(user, backend_id, term)
def add_key(request): params = request.json_body key_id = params.get('id', '') private_key = params.get('priv', '') user = user_from_request(request) key_id = methods.add_key(user, key_id, private_key) keypair = user.keypairs[key_id] return {'id': key_id, 'machines': keypair.machines, 'isDefault': keypair.default}
def update_metric(request): user = user_from_request(request) metric_id = request.matchdict['metric'] params = params_from_request(request) methods.update_metric( user, metric_id, name=params.get('name'), unit=params.get('unit'), backend_id=params.get('backend_id'), machine_id=params.get('machine_id'), ) return {}
def undeploy_plugin(request): user = user_from_request(request) backend_id = request.matchdict['backend'] machine_id = request.matchdict['machine'] plugin_id = request.matchdict['plugin'] params = params_from_request(request) plugin_type = params.get('plugin_type') host = params.get('host') if plugin_type == 'python': ret = methods.undeploy_python_plugin(user, backend_id, machine_id, plugin_id, host) return ret else: raise BadRequestError("Invalid plugin_type: '%s'" % plugin_type)
def create_network(request): """ Creates a new network. Currently working only with OPENSTACK backend """ backend_id = request.matchdict['backend'] try: network = request.json_body.get('network') except Exception as e: raise RequiredParameterMissingError(e) subnet = request.json_body.get('subnet', None) user = user_from_request(request) return methods.create_network(user, backend_id, network, subnet)