def update_user_settings(request): """ Tags: users --- User related actions Edit name, Update password """ # SEC raise exception if not user user = user_from_request(request) auth_context = auth_context_from_request(request) params = params_from_request(request) action = params.get('action') actions = ['update_details', 'update_password'] if action not in actions: log.error("Update_user_settings bad action='%s'", action) raise BadRequestError('action') if action == 'update_details': avatar = params.get('avatar') if avatar: try: Avatar.objects.get(id=avatar) user.avatar = avatar except DoesNotExist: raise BadRequestError('Avatar does not exist') if params.get('first_name') or params.get('last_name'): user.first_name = params.get('first_name') user.last_name = params.get('last_name') elif params.get('name'): name_array = params.get('name').split(' ') if len(name_array) > 1: user.last_name = name_array[-1] user.first_name = ' '.join(name_array[:-1]) user.save() trigger_session_update(auth_context.owner, ['user']) return {} if action == 'update_password': current_password = params.get('current_password', '') password = params.get('password', '') # check if current_password provided if not current_password and (user.password and user.password != ''): raise RequiredParameterMissingError("Current password") # check if new password provided if not password: raise RequiredParameterMissingError("New password") # SEC check if current_password valid if not user.check_password(current_password): raise UnauthorizedError("Invalid current password") # set new password user.set_password(password) return {}
def _create_volume__prepare_args(self, kwargs): for param in ( 'name', 'size', ): if not kwargs.get(param): raise RequiredParameterMissingError(param) if not kwargs['dynamic']: if not kwargs.get('volume_params'): msg = """Parameter volume_params must be a populated dictionary/object with the coresponding parameter/value pairs depending on volume type. If you are not sure please enable dynamic creation.""" raise RequiredParameterMissingError(msg) else: kwargs['ex_volume_params'] = kwargs.pop('volume_params') if not kwargs.get('volume_type'): msg = """A volume_type must be specified from the supported volume types by kubernetes. If you are not sure enable dynamic volume creation.""" raise RequiredParameterMissingError(msg) else: for param in ('location', 'storage_class_name'): if not kwargs.get(param): raise RequiredParameterMissingError(param) kwargs['ex_storage_class_name'] = kwargs.pop('storage_class_name') if 'volume_type' in kwargs: kwargs['ex_volume_type'] = kwargs.pop('volume_type') if 'volume_mode' in kwargs: if kwargs['volume_mode'] not in {'Filesystem', 'Block'}: raise ValueError("volume_mode can be either " "Filesysystem or Block.") kwargs['ex_volume_mode'] = kwargs.pop('volume_mode') if 'access_mode' in kwargs: kwargs['ex_access_mode'] = kwargs.pop('access_mode') if 'reclaim_policy' in kwargs: kwargs['ex_reclaim_policy'] = kwargs.pop('reclaim_policy') kwargs['ex_dynamic'] = kwargs.pop('dynamic') # FIXME circular imports from mist.api.clouds.models import CloudLocation if not kwargs.get('location'): raise RequiredParameterMissingError('location') try: location = CloudLocation.objects.get(id=kwargs['location'], missing_since=None) kwargs['location'] = location except CloudLocation.DoesNotExist: raise NotFoundError("Location with id '%s'." % kwargs['location'])
def suppressed_emails(request): params = dict(params_from_request(request).copy()) try: mac_verify(params) except Exception as exc: raise BadRequestError(str(exc)) try: decrypted_str = decrypt(params['token']) decrypted_json = json.loads(decrypted_str) except Exception as exc: log.exception(repr(exc)) raise BadRequestError() if decrypted_json.get('key') != Portal.get_singleton().external_api_key: raise NotFoundError() action = decrypted_json.get('action') if not action: raise RequiredParameterMissingError('action') if action == 'delete': Notification.objects(suppressed=True).delete() elif action == 'unsuppress': Notification.objects.update(suppressed=False) else: raise BadRequestError('Action "%s" not supported' % action) return Response("OK", 200)
def delete_schedule(request): """ Tags: schedules --- Deletes a schedule entry of a user. REMOVE permission required on schedule --- schedule_id: type: string required: true """ schedule_id = request.matchdict['schedule_id'] auth_context = auth_context_from_request(request) if not schedule_id: raise RequiredParameterMissingError('No schedule id provided') # Check if entry exists try: schedule = Schedule.objects.get(id=schedule_id, deleted=None) except me.DoesNotExist: raise ScheduleTaskNotFound() # SEC auth_context.check_perm('schedule', 'remove', schedule_id) # NOTE: Do not perform an atomic operation when marking a schedule as # deleted, since we do not wish to bypass pre-save validation/cleaning. schedule.deleted = datetime.utcnow() schedule.save() trigger_session_update(auth_context.owner, ['schedules']) return OK
def su(request): """ Impersonate another user. This allows an admin to take the identity of any other user. It is meant to be used strictly for debugging. You can return to your regular user simply by logging out. This won't affect the last login time of the actual user. An email should be immediately sent out to the team, notifying of the 'su' action for security reasons. """ # SEC raise exception if user not admin user = user_from_request(request, admin=True) session = request.environ['session'] if isinstance(session, ApiToken): raise ForbiddenError('Cannot do su when authenticated with api token') real_email = user.email params = params_from_request(request) email = params.get('email') if not email: raise RequiredParameterMissingError('email') try: user = User.objects.get(email=email) except (UserNotFoundError, User.DoesNotExist): raise UserUnauthorizedError() reissue_cookie_session(request, real_email, su=user.id) # alert admins subject = "Some admin used su" body = "Admin: %s\nUser: %s\nServer: %s" % (real_email, user.email, config.CORE_URI) send_email(subject, body, config.NOTIFICATION_EMAIL['ops']) return HTTPFound('/')
def transfer_ownership_to_user(request): """ Tags: ownership --- Transfer ownership of a resource If a resource isn't owned by the requesting user, then an UnauthorizedError error will be thrown, unless the requesting user is a member of the Owners team. """ auth_context = auth_context_from_request(request) params = params_from_request(request) if not params.get('user_id'): raise RequiredParameterMissingError('user_id') try: new_owner = User.objects.get(id=params['user_id']) except User.DoesNotExist: raise NotFoundError('User with id %s' % params['user_id']) for rtype, rids in params.get('resources', {}).iteritems(): Model = get_resource_model(rtype) for rid in rids: try: resource = Model.objects.get(owner=auth_context.owner, id=rid) resource.transfer_ownership(auth_context, new_owner) except Model.DoesNotExist: raise NotFoundError('%s with id %s' % (rtype, rid)) trigger_session_update(auth_context.owner) return Response('OK', 200)
def get_private_key(request): """ Gets private key from key name. It is used in single key view when the user clicks the display private key button. READ_PRIVATE permission required on key. --- key: description: The key id in: path required: true type: string """ key_id = request.matchdict['key'] if not key_id: raise RequiredParameterMissingError("key_id") auth_context = auth_context_from_request(request) try: key = SSHKey.objects.get(owner=auth_context.owner, id=key_id, deleted=None) except me.DoesNotExist: raise NotFoundError('Key id does not exist') auth_context.check_perm('key', 'read_private', key.id) return key.private
def add(cls, owner, cloud, id='', **kwargs): """Add Zone This is a class method, meaning that it is meant to be called on the class itself and not on an instance of the class. You're not meant to be calling this directly, but on a cloud subclass instead like this: zone = Zone.add(owner=org, domain='domain.com.') Params: - owner and domain are common and required params - only provide a custom zone id if you're migrating something - kwargs will be passed to appropriate controller, in most cases these should match the extra fields of the particular zone type. """ if not kwargs['domain']: raise RequiredParameterMissingError('domain') if not cloud or not isinstance(cloud, Cloud): raise BadRequestError('cloud') if not owner or not isinstance(owner, Organization): raise BadRequestError('owner') zone = cls(owner=owner, cloud=cloud, domain=kwargs['domain']) if id: zone.id = id return zone.ctl.create_zone(**kwargs)
def get_public_key(request): """ Get public key Gets public key from key name. READ permission required on key. --- key: description: The key id in: path required: true type: string """ key_id = request.matchdict['key'] if not key_id: raise RequiredParameterMissingError("key_id") auth_context = auth_context_from_request(request) try: key = SSHKey.objects.get(owner=auth_context.owner, id=key_id, deleted=None) except me.DoesNotExist: raise NotFoundError('Key id does not exist') auth_context.check_perm('key', 'read', key.id) return key.public
def revoke_session(request): """ Tags: sessions --- Revoke an active session --- id: description: Session ID """ auth_context = auth_context_from_request(request) params = params_from_request(request) auth_token_id = params.get("id") if not auth_token_id: raise RequiredParameterMissingError("No token id parameter provided") try: if auth_context.is_owner(): auth_token = AuthToken.objects.get(org=auth_context.org, id=auth_token_id) else: auth_token = AuthToken.objects.get( user_id=auth_context.user.get_id(), id=auth_token_id) if auth_token.is_valid(): auth_token.invalidate() auth_token.save() except me.DoesNotExist: raise NotFoundError('Session not found') return OK
def rename_cloud(request): """ Rename a cloud Renames cloud with given cloud_id. EDIT permission required on cloud. --- cloud: in: path required: true type: string new_name: description: ' New name for the key (will also serve as the key''s id)' type: string """ auth_context = auth_context_from_request(request) cloud_id = request.matchdict['cloud'] try: Cloud.objects.get(owner=auth_context.owner, id=cloud_id, deleted=None) except Cloud.DoesNotExist: raise NotFoundError('Cloud does not exist') params = params_from_request(request) new_name = params.get('new_name', '') if not new_name: raise RequiredParameterMissingError('new_name') auth_context.check_perm('cloud', 'edit', cloud_id) m_rename_cloud(auth_context.owner, cloud_id, new_name) return OK
def disassociate_metric(request): """ Tags: monitoring --- Disassociate a metric from a machine. READ permission required on cloud. EDIT_GRAPHS permission required on machine --- machine: in: path type: string required: true metric_id: type: string required: true """ auth_context = auth_context_from_request(request) machine = _machine_from_matchdict(request) # SEC require permission EDIT_GRAPHS on machine auth_context.check_perm("machine", "edit_graphs", machine.id) params = params_from_request(request) metric_id = params.get('metric_id') if not metric_id: raise RequiredParameterMissingError('metric_id') mist.api.monitoring.methods.disassociate_metric(machine, metric_id) return {}
def show_schedule_entry(request): """ Tags: schedules --- Show details of schedule. READ permission required on schedule --- schedule_id: type: string required: true """ schedule_id = request.matchdict['schedule_id'] auth_context = auth_context_from_request(request) if not schedule_id: raise RequiredParameterMissingError('No schedule id provided') try: schedule = Schedule.objects.get(id=schedule_id, deleted=None, owner=auth_context.owner) except me.DoesNotExist: raise ScheduleTaskNotFound() # SEC require READ permission on schedule auth_context.check_perm('schedule', 'read', schedule_id) return schedule.as_dict()
def __init__(self, host, username=None, key=None, password=None, cert_file=None, port=22): """Initialize a Shell instance Initializes a Shell instance for host. If username is provided, then it tries to actually initiate the connection, by calling connect(). Check out the docstring of connect(). """ if not host: raise RequiredParameterMissingError('host not given') self.host = host self.sudo = False self.ssh = paramiko.SSHClient() self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # if username provided, try to connect if username: self.connect(username, key, password, cert_file, port)
def delete_script(request): """ Delete script REMOVE permission required on script. --- script_id: in: path required: true type: string """ script_id = request.matchdict['script_id'] auth_context = auth_context_from_request(request) if not script_id: raise RequiredParameterMissingError('No script id provided') try: script = Script.objects.get(owner=auth_context.owner, id=script_id, deleted=None) except me.DoesNotExist: raise NotFoundError('Script id not found') # SEC require REMOVE permission on script auth_context.check_perm('script', 'remove', script_id) script.ctl.delete() return OK
def add(cls, owner, title, id='', **kwargs): """Add cloud This is a class method, meaning that it is meant to be called on the class itself and not on an instance of the class. You're not meant to be calling this directly, but on a cloud subclass instead like this: cloud = AmazonCloud.add(owner=org, title='EC2', apikey=apikey, apisecret=apisecret) Params: - owner and title are common and required params - only provide a custom cloud id if you're migrating something - kwargs will be passed to appropriate controller, in most cases these should match the extra fields of the particular cloud type. """ if not title: raise RequiredParameterMissingError('title') if not owner or not isinstance(owner, Organization): raise BadRequestError('owner') if Cloud.objects(owner=owner, title=title, deleted=None): raise CloudExistsError() cloud = cls(owner=owner, title=title) if id: cloud.id = id cloud.ctl.add(**kwargs) return cloud
def download_script(request): """ Download script file or archive. READ permission required on script. --- script_id: type: string required: true in: path """ script_id = request.matchdict['script_id'] auth_context = auth_context_from_request(request) if not script_id: raise RequiredParameterMissingError('No script id provided') try: script = Script.objects.get(owner=auth_context.owner, id=script_id, deleted=None) except me.DoesNotExist: raise NotFoundError('Script id not found') # SEC require READ permission on SCRIPT auth_context.check_perm('script', 'read', script_id) try: return script.ctl.get_file() except BadRequestError(): return Response("Unable to find: {}".format(request.path_info))
def show_script(request): """ Show script details and job history. READ permission required on script. --- script_id: type: string required: true in: path """ script_id = request.matchdict['script_id'] auth_context = auth_context_from_request(request) if not script_id: raise RequiredParameterMissingError('No script id provided') try: script = Script.objects.get(owner=auth_context.owner, id=script_id, deleted=None) except me.DoesNotExist: raise NotFoundError('Script id not found') # SEC require READ permission on SCRIPT auth_context.check_perm('script', 'read', script_id) ret_dict = script.as_dict() jobs = get_stories('job', auth_context.owner.id, script_id=script_id) ret_dict['jobs'] = [job['job_id'] for job in jobs] return ret_dict
def add(cls, network, cidr, name='', description='', id='', **kwargs): """Add a Subnet. This is a class method, meaning that it is meant to be called on the class itself and not on an instance of the class. You're not meant to be calling this directly, but on a network subclass instead like this: subnet = AmazonSubnet.add(network=network, name='Ec2Subnet', cidr='172.31.10.0/24') :param network: the Network nn which the subnet is going to be created. :param cidr: the CIDR to be assigned to the new subnet. :param name: the name to be assigned to the new subnet. :param description: an optional description. :param id: a custom object id, passed in case of a migration. :param kwargs: the kwargs to be passed to the corresponding controller. """ assert isinstance(network, Network) if not cidr: raise RequiredParameterMissingError('cidr') subnet = cls(network=network, cidr=cidr, name=name, description=description) if id: subnet.id = id subnet.ctl.create(**kwargs) return subnet
def connect(self, username, key=None, password=None, cert_file=None, port=22): """Initialize an SSH connection. Tries to connect and configure self. If only password is provided, it will be used for authentication. If key is provided, it is treated as and OpenSSH private RSA key and used for authentication. If both key and password are provided, password is used as a passphrase to unlock the private key. Raises MachineUnauthorizedError if it fails to connect. """ if not key and not password: raise RequiredParameterMissingError("neither key nor password " "provided.") if key: private = key.private if isinstance(key, SignedSSHKey) and cert_file: # signed ssh key, use RSACert rsa_key = paramiko.RSACert(privkey_file_obj=StringIO(private), cert_file_obj=StringIO(cert_file)) else: rsa_key = paramiko.RSAKey.from_private_key(StringIO(private)) else: rsa_key = None attempts = 3 while attempts: attempts -= 1 try: self.ssh.connect( self.host, port=port, username=username, password=password, pkey=rsa_key, allow_agent=False, look_for_keys=False, timeout=10 ) break except paramiko.AuthenticationException as exc: log.error("ssh exception %r", exc) raise MachineUnauthorizedError("Couldn't connect to " "%s@%s:%s. %s" % (username, self.host, port, exc)) except socket.error as exc: log.error("Got ssh error: %r", exc) if not attempts: raise ServiceUnavailableError("SSH timed-out repeatedly.") except Exception as exc: log.error("ssh exception %r", exc) # don't fail if SSHException or other paramiko exception, # eg related to network, but keep until all attempts are made if not attempts: raise ServiceUnavailableError(repr(exc))
def edit_key(request): """ Edit a key Edits a given key's name to new_name EDIT permission required on key. --- new_name: description: The new key name type: string key_id: description: The key id in: path required: true type: string """ key_id = request.matchdict['key'] params = params_from_request(request) new_name = params.get('new_name') if not new_name: raise RequiredParameterMissingError("new_name") auth_context = auth_context_from_request(request) try: key = Key.objects.get(owner=auth_context.owner, id=key_id, deleted=None) except me.DoesNotExist: raise NotFoundError('Key with that id does not exist') auth_context.check_perm('key', 'edit', key.id) key.ctl.rename(new_name) return {'new_name': new_name}
def delete_portforward(request): """ Tags: networks --- Delete the portforward of a GigG8 network READ permission required on network EDIT permission required on network --- network: in: path required: true type: string public_port: required: true type: string protocol: required: true type: string """ network_id = request.matchdict['network'] auth_context = auth_context_from_request(request) params = params_from_request(request) if not params.get('public_port'): raise RequiredParameterMissingError('public_port') if not params.get('protocol'): raise RequiredParameterMissingError('protocol') # SEC auth_context.check_perm('network', 'read', network_id) auth_context.check_perm('network', 'edit', network_id) try: network = Network.objects.get(owner=auth_context.owner, id=network_id) except Network.DoesNotExist: raise NetworkNotFoundError() try: network.cloud.ctl.network.delete_portforward(network, **params) except NotImplementedError: raise MistNotImplementedError return OK
def create_network(request): """ Create network on a cloud Creates a new network. If subnet dict is specified, after creating the network it will use the new network's id to create a subnet. CREATE_RESOURCES permission required on cloud. --- cloud_id: in: path required: true description: The Cloud ID type: string network: required: true type: dict subnet: type: dict """ cloud_id = request.matchdict['cloud'] params = params_from_request(request) network_params = params.get('network') subnet_params = params.get('subnet') auth_context = auth_context_from_request(request) if not network_params: raise RequiredParameterMissingError('network') # TODO if not auth_context.is_owner(): raise PolicyUnauthorizedError() try: cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id) except me.DoesNotExist: raise CloudNotFoundError network = methods.create_network(auth_context.owner, cloud, network_params) network_dict = network.as_dict() # Bundling Subnet creation in this call because it is required # for backwards compatibility with the current UI if subnet_params: try: subnet = create_subnet(auth_context.owner, cloud, network, subnet_params) except Exception as exc: # Cleaning up the network object in case subnet creation # fails for any reason network.ctl.delete() raise exc network_dict['subnet'] = subnet.as_dict() return network.as_dict()
def _create_volume__prepare_args(self, kwargs): # FIXME Imported here due to circular dependency issues. from mist.api.clouds.models import CloudLocation if not kwargs.get('location'): raise RequiredParameterMissingError('location') try: location = CloudLocation.objects.get(id=kwargs['location']) except CloudLocation.DoesNotExist: raise NotFoundError("Location with id '%s'." % kwargs['location']) kwargs['location'] = location.name
def update_monitoring(request): """ Tags: monitoring --- Enable or disable monitoring for a machine --- machine: in: path type: string required: true action: enum: - enable - disable type: string required: true no_ssh: type: boolean default: false dry: type: boolean default: false """ auth_context = auth_context_from_request(request) params = params_from_request(request) no_ssh = bool(params.get('no_ssh')) dry = bool(params.get('dry')) action = params.get('action') if not action: raise RequiredParameterMissingError('action') if action == 'enable': machine = _machine_from_matchdict(request) elif action == 'disable': machine = _machine_from_matchdict(request, deleted=True) else: raise BadRequestError('Action must be one of (enable, disable)') # SEC require permission EDIT on machine auth_context.check_perm("machine", "edit", machine.id) if action == 'enable': return mist.api.monitoring.methods.enable_monitoring( owner=auth_context.owner, cloud_id=machine.cloud.id, machine_id=machine.machine_id, no_ssh=no_ssh, dry=dry) elif action == 'disable': return mist.api.monitoring.methods.disable_monitoring( owner=auth_context.owner, cloud_id=machine.cloud.id, machine_id=machine.machine_id, no_ssh=no_ssh)
def add_key(request): """ Tags: keys --- Adds key. ADD permission required on key. --- name: description: The key's name required: true type: string priv: description: The private key required: true type: string certificate: description: The signed public key, when using signed ssh keys type: string """ params = params_from_request(request) key_name = params.pop('name', None) private_key = params.get('priv', None) certificate = params.get('certificate', None) auth_context = auth_context_from_request(request) key_tags = auth_context.check_perm("key", "add", None) if not key_name: raise BadRequestError("Key name is not provided") if not private_key: raise RequiredParameterMissingError("Private key is not provided") if certificate: key = SignedSSHKey.add(auth_context.owner, key_name, **params) else: key = SSHKey.add(auth_context.owner, key_name, **params) # Set ownership. key.assign_to(auth_context.user) if key_tags: add_tags_to_resource(auth_context.owner, key, key_tags.items()) # since its a new key machines fields should be an empty list clouds = Cloud.objects(owner=auth_context.owner, deleted=None) machines = Machine.objects(cloud__in=clouds, key_associations__keypair__exact=key) assoc_machines = transform_key_machine_associations(machines, key) return { 'id': key.id, 'name': key.name, 'machines': assoc_machines, 'isDefault': key.default }
def delete_keys(request): """ Tags: keys --- Deletes multiple keys. Provide a list of key ids to be deleted. The method will try to delete all of them and then return a json that describes for each key id whether or not it was deleted or not_found if the key id could not be located. If no key id was found then a 404(Not Found) response will be returned. REMOVE permission required on each key. --- key_ids: required: true type: array items: type: string """ auth_context = auth_context_from_request(request) params = params_from_request(request) key_ids = params.get('key_ids', []) if type(key_ids) != list or len(key_ids) == 0: raise RequiredParameterMissingError('No key ids provided') # remove duplicate ids if there are any key_ids = set(key_ids) report = {} for key_id in key_ids: try: key = Key.objects.get(owner=auth_context.owner, id=key_id, deleted=None) except me.DoesNotExist: report[key_id] = 'not_found' continue try: auth_context.check_perm('key', 'remove', key.id) except PolicyUnauthorizedError: report[key_id] = 'unauthorized' else: delete_key(auth_context.owner, key_id) report[key_id] = 'deleted' # if no key id was valid raise exception if len(filter(lambda key_id: report[key_id] == 'not_found', report)) == len(key_ids): raise NotFoundError('No valid key id provided') # if user was unauthorized for all keys if len(filter(lambda key_id: report[key_id] == 'unauthorized', report)) == len(key_ids): raise NotFoundError('Unauthorized to modify any of the keys') return report
def _create_volume__prepare_args(self, kwargs): if not kwargs.get('resource_group'): raise RequiredParameterMissingError('resource_group') if not kwargs.get('location'): raise RequiredParameterMissingError('location') # FIXME Imported here due to circular dependency issues. from mist.api.clouds.models import CloudLocation try: location = CloudLocation.objects.get(id=kwargs['location']) except CloudLocation.DoesNotExist: raise NotFoundError("Location with id '%s'." % kwargs['location']) node_location = NodeLocation(id=location.external_id, name=location.name, country=location.country, driver=None) kwargs['location'] = node_location resource_group = kwargs.pop('resource_group') conn = self.cloud.ctl.compute.connection resource_groups = conn.ex_list_resource_groups() ex_resource_group = None for lib_resource_group in resource_groups: if lib_resource_group.id == resource_group: ex_resource_group = lib_resource_group.name break # if not found, create it if ex_resource_group is None: try: conn.ex_create_resource_group(resource_group, node_location) ex_resource_group = resource_group # add delay cause sometimes the group is not yet ready time.sleep(5) except Exception as exc: raise LibcloudError("Couldn't create resource group. \ %s" % exc) kwargs['ex_resource_group'] = ex_resource_group account_type = kwargs.pop('storage_account_type', 'Standard_LRS') kwargs['ex_storage_account_type'] = account_type
def toggle_cloud(request): """ Tags: clouds --- Toggles cloud with given cloud id. EDIT permission required on cloud. --- cloud_id: in: path required: true type: string new_state: enum: - '0' - '1' required: true type: string """ auth_context = auth_context_from_request(request) cloud_id = request.matchdict['cloud'] try: cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id, deleted=None) except Cloud.DoesNotExist: raise NotFoundError('Cloud does not exist') auth_context.check_perm('cloud', 'edit', cloud_id) new_state = params_from_request(request).get('new_state', None) dns_enabled = params_from_request(request).get('dns_enabled', None) if new_state == '1': cloud.ctl.enable() elif new_state == '0': cloud.ctl.disable() elif new_state: raise BadRequestError('Invalid cloud state') if dns_enabled == 1: cloud.ctl.dns_enable() elif dns_enabled == 0: cloud.ctl.dns_disable() elif dns_enabled: raise BadRequestError('Invalid DNS state') if new_state is None and dns_enabled is None: raise RequiredParameterMissingError('new_state or dns_enabled') trigger_session_update(auth_context.owner, ['clouds']) return OK
def add_cloud_v_2(owner, title, provider, params): """Add cloud to owner""" # FIXME: Some of these should be explicit arguments, others shouldn't exist fail_on_error = params.pop('fail_on_error', params.pop('remove_on_error', True)) monitoring = params.pop('monitoring', False) params.pop('title', None) params.pop('provider', None) # Find proper Cloud subclass. if not provider: raise RequiredParameterMissingError("provider") log.info("Adding new cloud in provider '%s'", provider) if provider not in cloud_models.CLOUDS: raise BadRequestError("Invalid provider '%s'." % provider) cloud_cls = cloud_models.CLOUDS[provider] # Class of Cloud model. # Add the cloud. cloud = cloud_cls.add(owner, title, fail_on_error=fail_on_error, fail_on_invalid_params=False, **params) ret = {'cloud_id': cloud.id} if provider == 'bare_metal' and monitoring: # Let's overload this a bit more by also combining monitoring. machine = Machine.objects.get(cloud=cloud) ret['monitoring'] = enable_monitoring( owner, cloud.id, machine.machine_id, no_ssh=not (machine.os_type == 'unix' and machine.key_associations)) # SEC owner.mapper.update(cloud) log.info("Cloud with id '%s' added succesfully.", cloud.id) trigger_session_update(owner, ['clouds']) c_count = Cloud.objects(owner=owner, deleted=None).count() if owner.clouds_count != c_count: owner.clouds_count = c_count owner.save() cloud.polling_interval = 1800 # 30 min * 60 sec/min cloud.save() ListMachinesPollingSchedule.add(cloud=cloud) return ret