def machine_actions(request): # TODO: We shouldn't return list_machines, just 200. Save the API! cloud_id = request.matchdict['cloud'] machine_id = request.matchdict['machine'] user = user_from_request(request) params = params_from_request(request) 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', 'undefine', 'suspend', 'resume'): if action == 'start': methods.start_machine(user, cloud_id, machine_id) elif action == 'stop': methods.stop_machine(user, cloud_id, machine_id) elif action == 'reboot': methods.reboot_machine(user, cloud_id, machine_id) elif action == 'destroy': methods.destroy_machine(user, cloud_id, machine_id) elif action == 'resize': methods.resize_machine(user, cloud_id, machine_id, plan_id) elif action == 'rename': methods.rename_machine(user, cloud_id, machine_id, name) elif action == 'undefine': methods.undefine_machine(user, cloud_id, machine_id) elif action == 'resume': methods.resume_machine(user, cloud_id, machine_id) elif action == 'suspend': methods.suspend_machine(user, cloud_id, machine_id) # return OK return methods.list_machines(user, cloud_id) raise BadRequestError()
def check_auth(request): """Check on the mist.core service if authenticated""" params = params_from_request(request) 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 associate_key(request): key_id = request.matchdict['key'] cloud_id = request.matchdict['cloud'] machine_id = request.matchdict['machine'] params = params_from_request(request) ssh_user = params.get('user', None) try: ssh_port = int(request.json_body.get('port', 22)) except: ssh_port = 22 try: host = request.json_body.get('host') except: host = None if not host: raise RequiredParameterMissingError('host') user = user_from_request(request) methods.associate_key(user, key_id, cloud_id, machine_id, host, username=ssh_user, port=ssh_port) return user.keypairs[key_id].machines
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 update_user_settings(request): """try free plan, by communicating to the mist.core service""" params = params_from_request(request) 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 update_monitoring(request): """Enable/disable monitoring for this machine using the hosted mist.io service. """ user = user_from_request(request) cloud_id = request.matchdict['cloud'] machine_id = request.matchdict['machine'] params = params_from_request(request) if not user.mist_api_token: log.info("trying to authenticate to service first") email = params.get('email') password = params.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('token', '') user.save() log.info("succesfully check_authed") elif ret.status_code in [400, 401]: with user.lock_n_load(): user.email = "" user.mist_api_token = "" user.save() raise UnauthorizedError("You need to authenticate to mist.io.") else: raise UnauthorizedError("You need to authenticate to mist.io.") action = params.get('action') or 'enable' name = params.get('name', '') public_ips = params.get('public_ips', []) dns_name = params.get('dns_name', '') no_ssh = bool(params.get('no_ssh', False)) dry = bool(params.get('dry', False)) if action == 'enable': ret_dict = methods.enable_monitoring( user, cloud_id, machine_id, name, dns_name, public_ips, no_ssh=no_ssh, dry=dry ) elif action == 'disable': methods.disable_monitoring(user, cloud_id, machine_id, no_ssh=no_ssh) ret_dict = {} else: raise BadRequestError() return ret_dict
def update_monitoring(request): """Enable/disable monitoring for this machine using the hosted mist.io service. """ user = user_from_request(request) cloud_id = request.matchdict['cloud'] machine_id = request.matchdict['machine'] params = params_from_request(request) if not user.mist_api_token: log.info("trying to authenticate to service first") email = params.get('email') password = params.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 = params.get('action') or 'enable' name = params.get('name', '') public_ips = params.get('public_ips', []) dns_name = params.get('dns_name', '') no_ssh = bool(params.get('no_ssh', False)) dry = bool(params.get('dry', False)) if action == 'enable': ret_dict = methods.enable_monitoring(user, cloud_id, machine_id, name, dns_name, public_ips, no_ssh=no_ssh, dry=dry) elif action == 'disable': methods.disable_monitoring(user, cloud_id, machine_id, no_ssh=no_ssh) ret_dict = {} else: raise BadRequestError() return ret_dict
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 edit_key(request): old_id = request.matchdict['key'] params = params_from_request(request) new_id = params.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 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 add_key(request): params = params_from_request(request) 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 associate_ip(request): cloud_id = request.matchdict['cloud'] network_id = request.matchdict['network'] params = params_from_request(request) ip = params.get('ip') machine = params.get('machine') assign = params.get('assign', True) user = user_from_request(request) ret = methods.associate_ip(user, cloud_id, network_id, ip, machine, assign) if ret: return OK else: return Response("Bad Request", 400)
def add_key(request): params = params_from_request(request) 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 probe(request): """Probes a machine using ping and ssh to collect metrics. .. note:: Used for getting uptime and a list of deployed keys. """ machine_id = request.matchdict['machine'] cloud_id = request.matchdict['cloud'] params = params_from_request(request) host = params.get('host', None) key_id = params.get('key', None) ssh_user = params.get('ssh_user', '') # FIXME: simply don't pass a key parameter if key_id == 'undefined': key_id = '' user = user_from_request(request) ret = methods.probe(user, cloud_id, machine_id, host, key_id, ssh_user) return ret
def toggle_cloud(request): cloud_id = request.matchdict['cloud'] params = params_from_request(request) new_state = params.get('new_state', '') if not new_state: raise RequiredParameterMissingError('new_state') if new_state != "1" and new_state != "0": raise BadRequestError('Invalid cloud state') user = user_from_request(request) if cloud_id not in user.clouds: raise CloudNotFoundError() with user.lock_n_load(): user.clouds[cloud_id].enabled = bool(int(new_state)) user.save() trigger_session_update(user.email, ['clouds']) return OK
def update_rule(request): """Creates or updates a rule. """ user = user_from_request(request) params = params_from_request(request) try: ret = requests.post(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: log.error("Error updating rule %d:%s", ret.status_code, ret.text) raise ServiceUnavailableError() trigger_session_update(user.email, ['monitoring']) return ret.json()
def update_rule(request): """Creates or updates a rule. """ user = user_from_request(request) params = params_from_request(request) try: ret = requests.post( 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: log.error("Error updating rule %d:%s", ret.status_code, ret.text) raise ServiceUnavailableError() trigger_session_update(user.email, ['monitoring']) return ret.json()
def update_user_settings(request): """try free plan, by communicating to the mist.core service""" params = params_from_request(request) 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 add_cloud(request): """Adds a new cloud.""" params = params_from_request(request) # remove spaces from start/end of string fields that are often included # when pasting keys, preventing thus succesfull connection with the # cloud for key in params.keys(): if type(params[key]) in [unicode, str]: params[key] = params[key].rstrip().lstrip() api_version = request.headers.get('Api-Version', 1) title = params.get('title', '') provider = params.get('provider', '') if not provider: raise RequiredParameterMissingError('provider') user = user_from_request(request) monitoring = None if int(api_version) == 2: ret = methods.add_cloud_v_2(user, title, provider, params) cloud_id = ret['cloud_id'] monitoring = ret.get('monitoring') else: apikey = params.get('apikey', '') apisecret = params.get('apisecret', '') apiurl = params.get('apiurl') or '' # fixes weird issue w/ 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 cloud_id = methods.add_cloud( 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, ) cloud = user.clouds[cloud_id] ret = { 'index': len(user.clouds) - 1, 'id': cloud_id, 'apikey': cloud.apikey, 'apiurl': cloud.apiurl, 'tenant_name': cloud.tenant_name, 'title': cloud.title, 'provider': cloud.provider, 'poll_interval': cloud.poll_interval, 'region': cloud.region, 'status': 'off', 'enabled': cloud.enabled, } if monitoring: ret['monitoring'] = monitoring return ret
def create_machine(request): """Creates a new virtual machine on the specified cloud.""" cloud_id = request.matchdict['cloud'] try: key_id = request.json_body.get('key') machine_name = request.json_body['name'] location_id = request.json_body.get('location', None) if request.json_body.get('provider') == 'libvirt': image_id = request.json_body.get('image') disk_size = int(request.json_body.get('libvirt_disk_size', 4)) disk_path = request.json_body.get('libvirt_disk_path', '') else: image_id = request.json_body['image'] disk_size = disk_path = None 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) script_id = request.json_body.get('script_id', '') script_params = params_from_request(request).get('script_params', '') post_script_id = request.json_body.get('post_script_id', '') post_script_params = params_from_request(request).get( 'post_script_params', '') async = request.json_body.get('async', False) quantity = request.json_body.get('quantity', 1) persist = request.json_body.get('persist', False) docker_port_bindings = request.json_body.get('docker_port_bindings', {}) docker_exposed_ports = request.json_body.get('docker_exposed_ports', {}) azure_port_bindings = request.json_body.get('azure_port_bindings', '') # hostname: if provided it will be attempted to assign a DNS name hostname = request.json_body.get('hostname', '') plugins = request.json_body.get('plugins') cloud_init = request.json_body.get('cloud_init', '') associate_floating_ip = request.json_body.get('associate_floating_ip', False) associate_floating_ip_subnet = request.json_body.get( 'attach_floating_ip_subnet', None) project_id = request.json_body.get('project', None) except Exception as e: raise RequiredParameterMissingError(e) user = user_from_request(request) import uuid job_id = uuid.uuid4().hex from mist.io import tasks args = (cloud_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) kwargs = { 'script_id': script_id, 'script_params': script_params, 'job_id': job_id, 'docker_port_bindings': docker_port_bindings, 'docker_exposed_ports': docker_exposed_ports, 'azure_port_bindings': azure_port_bindings, 'hostname': hostname, 'plugins': plugins, 'post_script_id': post_script_id, 'post_script_params': post_script_params, 'disk_size': disk_size, 'disk_path': disk_path, 'cloud_init': cloud_init, 'associate_floating_ip': associate_floating_ip, 'associate_floating_ip_subnet': associate_floating_ip_subnet, 'project_id': project_id } if not async: ret = methods.create_machine(user, *args, **kwargs) else: args = (user.email, ) + args kwargs.update({'quantity': quantity, 'persist': persist}) tasks.create_machine_async.apply_async(args, kwargs, countdown=2) ret = {'job_id': job_id} return ret
def create_machine(request): """Creates a new virtual machine on the specified cloud.""" cloud_id = request.matchdict['cloud'] try: key_id = request.json_body.get('key') machine_name = request.json_body['name'] location_id = request.json_body.get('location', None) if request.json_body.get('provider') == 'libvirt': image_id = request.json_body.get('image') disk_size = int(request.json_body.get('libvirt_disk_size', 4)) disk_path = request.json_body.get('libvirt_disk_path', '') create_from_existing = request.json_body.get('libvirt_existing_disk_path') else: image_id = request.json_body['image'] disk_size = disk_path = create_from_existing = None 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) script_id = request.json_body.get('script_id', '') script_params = params_from_request(request).get('script_params', '') post_script_id = request.json_body.get('post_script_id', '') post_script_params = params_from_request(request).get('post_script_params', '') async = request.json_body.get('async', False) quantity = request.json_body.get('quantity', 1) persist = request.json_body.get('persist', False) docker_port_bindings = request.json_body.get('docker_port_bindings', {}) docker_exposed_ports = request.json_body.get('docker_exposed_ports', {}) azure_port_bindings = request.json_body.get('azure_port_bindings', '') # hostname: if provided it will be attempted to assign a DNS name hostname = request.json_body.get('hostname', '') plugins = request.json_body.get('plugins') cloud_init = request.json_body.get('cloud_init', '') associate_floating_ip = request.json_body.get('associate_floating_ip', False) associate_floating_ip_subnet = request.json_body.get('attach_floating_ip_subnet', None) project_id = request.json_body.get('project', None) except Exception as e: raise RequiredParameterMissingError(e) user = user_from_request(request) import uuid job_id = uuid.uuid4().hex from mist.io import tasks args = (cloud_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) kwargs = {'script_id': script_id, 'script_params': script_params, 'job_id': job_id, 'docker_port_bindings': docker_port_bindings, 'docker_exposed_ports': docker_exposed_ports, 'azure_port_bindings': azure_port_bindings, 'hostname': hostname, 'plugins': plugins, 'post_script_id': post_script_id, 'post_script_params': post_script_params, 'disk_size': disk_size, 'disk_path': disk_path, 'create_from_existing': create_from_existing, 'cloud_init': cloud_init, 'associate_floating_ip': associate_floating_ip, 'associate_floating_ip_subnet': associate_floating_ip_subnet, 'project_id': project_id} if not async: ret = methods.create_machine(user, *args, **kwargs) else: args = (user.email, ) + args kwargs.update({'quantity': quantity, 'persist': persist}) tasks.create_machine_async.apply_async(args, kwargs, countdown=2) ret = {'job_id': job_id} return ret