예제 #1
0
def revoke_ownership(group_name):
    """

    Revoke group ownership from an existing group user.

    :param group_name: Group's name.
    :queryparam user_name: User's username.

    """
    u = identity.current.user
    group = _get_group_by_name(group_name, lockmode='update')
    if not group.can_modify_ownership(identity.current.user):
        raise Forbidden403('Cannot edit ownership of group %s' % group_name)
    if 'user_name' not in request.args:
        raise MethodNotAllowed405
    user = _get_user_by_username(request.args['user_name'])
    if user not in group.users:
        raise BadRequest400('User is not a member of group %s' % group_name)
    if group.has_owner(user):
        if len(group.owners()) == 1 and not u.is_admin():
            raise Forbidden403('Cannot remove the only owner')
        group.revoke_ownership(user, agent=identity.current.user)
    else:
        raise Conflict409('User %s is not an owner of group %s' %
                          (user.user_name, group_name))
    return '', 204
예제 #2
0
def delete_keystone_trust(username):
    """
    Deletes the Keystone trust for a user account.

    :param username: The user's username.
    """
    user = _get_user(username)

    if not user.can_edit(identity.current.user):
        raise Forbidden403('Cannot edit Keystone trust of user %s' % username)
    if not user.openstack_trust_id:
        raise BadRequest400('No Keystone trust created by user %s' % username)
    try:
        manager = dynamic_virt.VirtManager(user)
        manager.delete_keystone_trust()
    except ValueError as e:
        # If we can't create a VirtManager we presume that the trust has been
        # invalidated by different means.
        log.debug(e.message)
    except RuntimeError as e:
        # Sanity check failed. Because OpenStack is not configured.
        log.debug(e.message)
    old_trust_id = user.openstack_trust_id
    user.openstack_trust_id = None
    user.record_activity(user=identity.current.user,
                         service=u'HTTP',
                         field=u'OpenStack Trust ID',
                         action=u'Deleted',
                         old=old_trust_id)
    return '', 204
예제 #3
0
파일: pools.py 프로젝트: xhernandez/beaker
def remove_system_from_pool(pool_name):
    """
    Remove a system from a system pool

    :param pool_name: System pool's name.
    :queryparam fqdn: System's fully-qualified domain name

    """
    if 'fqdn' not in request.args:
        raise MethodNotAllowed405
    fqdn = request.args['fqdn']
    system = _get_system_by_FQDN(fqdn)
    u = identity.current.user
    pool = _get_pool_by_name(pool_name, lockmode='update')
    if pool in system.pools:
        if pool.can_edit(u) or system.can_edit(u):
            if system.active_access_policy == pool.access_policy:
                system.active_access_policy = system.custom_access_policy
                system.record_activity(user=u, service=u'HTTP',
                                       field=u'Active Access Policy',
                                       action=u'Changed',
                                       old = pool.access_policy,
                                       new = system.custom_access_policy)
            system.pools.remove(pool)
            system.record_activity(user=u, service=u'HTTP',
                                   action=u'Removed', field=u'Pool', old=unicode(pool), new=None)
            system.date_modified = datetime.datetime.utcnow()
            pool.record_activity(user=u, service=u'HTTP',
                       action=u'Removed', field=u'System', old=unicode(system), new=None)
        else:
            raise Forbidden403('You do not have permission to modify system %s'
                               'or remove systems from pool %s' % (system.fqdn, pool.name))
    else:
        raise BadRequest400('System %s is not in pool %s' % (system.fqdn, pool.name))
    return '', 204
예제 #4
0
def exclude_user(group_name):
    """
    Exclude a user from an inverted group. Then the user will not have the group
    membership.

    :param group_name: Group's name.
    :jsonparam string user_name: User's username.

    """
    u = identity.current.user
    data = read_json_request(request)
    group = _get_group_by_name(group_name, lockmode='update')
    if not group.can_modify_membership(identity.current.user):
        raise Forbidden403('Cannot edit membership of group %s' % group_name)
    if group.membership_type == GroupMembershipType.normal:
        raise NotFound404('Normal group %s do not have excluded users' %
                          group_name)
    if 'user_name' not in data:
        raise BadRequest400('User not specified')
    user = _get_user_by_username(data['user_name'])
    if user in group.users:
        if not group.can_exclude_member(u, user.id):
            raise Forbidden403('Cannot exclude user %s from group %s' %
                               (user, group_name))
        with convert_internal_errors():
            group.exclude_user(user, agent=identity.current.user)
    else:
        raise Conflict409('User %s is already excluded from group %s' %
                          (user.user_name, group_name))
    return '', 204
예제 #5
0
파일: group.py 프로젝트: qhsong/beaker
def add_group_membership(group_name):
    """
    Add a user to a group.

    :param group_name: Group's name.
    :jsonparam string user_name: User's username.
    :jsonparam boolean is_owner: If true, the given user will become one of the
      group owners.

    """
    u = identity.current.user
    data = read_json_request(request)
    group = _get_group_by_name(group_name, lockmode='update')
    if not group.can_modify_membership(identity.current.user):
        raise Forbidden403('Cannot edit membership of group %s' % group_name)
    if 'user_name' not in data:
        raise BadRequest400('User not specified')
    user = _get_user_by_username(data['user_name'])
    is_owner = data.get('is_owner', False)
    if user not in group.users:
        group.add_member(user, is_owner=is_owner, agent=identity.current.user)
        mail.group_membership_notify(user, group, agent=u, action='Added')
    else:
        raise Conflict409('User %s is already a member of group %s' % (user.user_name, group_name))
    return '', 204
예제 #6
0
def delete_powertype(id):
    """
    Deletes a power type by the given id.

    :param id: The id of the power type to be deleted.
    :status 204: Power type successfully deleted.
    :status 400: Power type is referenced by systems.
    :status 404: Power type can not be found.
    """
    try:
        powertype = PowerType.by_id(id)
    except NoResultFound:
        raise NotFound404('Power type: %s does not exist' % id)

    systems_referenced = System.query.join(
        System.power).filter(Power.power_type == powertype).count()
    if systems_referenced:
        raise BadRequest400('Power type %s still referenced by %i systems' %
                            (powertype.name, systems_referenced))

    session.delete(powertype)

    activity = Activity(identity.current.user, u'HTTP', u'Deleted',
                        u'PowerType', powertype.name)
    session.add(activity)

    return '', 204
예제 #7
0
def save_system_access_policy(fqdn):
    system = _get_system_by_FQDN(fqdn)
    if not system.can_edit_policy(identity.current.user):
        raise Forbidden403('Cannot edit system policy')
    if system.custom_access_policy:
        policy = system.custom_access_policy
    else:
        policy = system.custom_access_policy = SystemAccessPolicy()
    data = read_json_request(request)
    # Figure out what is added, what is removed.
    # Rules are immutable, so if it has an id it is unchanged,
    # if it has no id it is new.
    kept_rule_ids = frozenset(r['id'] for r in data['rules'] if 'id' in r)
    removed = []
    for old_rule in policy.rules:
        if old_rule.id not in kept_rule_ids:
            removed.append(old_rule)
    for old_rule in removed:
        system.record_activity(user=identity.current.user,
                               service=u'HTTP',
                               field=u'Access Policy Rule',
                               action=u'Removed',
                               old=repr(old_rule))
        policy.rules.remove(old_rule)
    for rule in data['rules']:
        if 'id' not in rule:
            if rule['user']:
                user = User.by_user_name(rule['user'])
                if user is None:
                    raise BadRequest400('No such user %r' % rule['user'])
            else:
                user = None
            try:
                group = Group.by_name(rule['group']) if rule['group'] else None
            except NoResultFound:
                raise BadRequest400('No such group %r' % rule['group'])
            permission = SystemPermission.from_string(rule['permission'])
            new_rule = policy.add_rule(user=user,
                                       group=group,
                                       everybody=rule['everybody'],
                                       permission=permission)
            system.record_activity(user=identity.current.user,
                                   service=u'HTTP',
                                   field=u'Access Policy Rule',
                                   action=u'Added',
                                   new=repr(new_rule))
    return jsonify(policy.__json__())
예제 #8
0
def doit():
    distro_trees = []
    for id in request.form.getlist('distro_tree_id'):
        try:
            distro_trees.append(DistroTree.by_id(id))
        except NoResultFound:
            raise BadRequest400('Distro tree %r does not exist' % id)
    job_details = {}
    job_details['pick'] = request.form.get('pick') or 'auto'
    system_choice = 'any system'
    if job_details['pick'] == 'fqdn':
        try:
            job_details['system'] = System.by_fqdn(request.form.get('system'),
                                                   identity.current.user)
            system_choice = 'a specific system'
        except DatabaseLookupError:
            raise BadRequest400('System %s not found' %
                                request.form.get('system'))
    elif job_details['pick'] == 'lab':
        try:
            job_details['lab'] = LabController.by_name(request.form.get('lab'))
            system_choice = 'any lab system'
        except NoResultFound:
            raise BadRequest400('Lab controller %s not found' %
                                request.form.get('lab'))
    reservetime = int(
        request.form.get('reserve_duration') or DEFAULT_RESERVE_SECONDS)
    if reservetime > MAX_SECONDS_PROVISION:
        raise BadRequest400(
            'Reservation time exceeds maximum time of %s hours' %
            MAX_HOURS_PROVISION)
    job_details['reservetime'] = reservetime
    job_details['whiteboard'] = request.form.get('whiteboard')
    if not job_details['whiteboard']:
        job_details['whiteboard'] = (
            "Reserve Workflow provision of distro %s on %s for %d seconds" %
            (request.form.get('distro'), system_choice,
             job_details['reservetime']))

    job_details['ks_meta'] = request.form.get('ks_meta')
    job_details['koptions'] = request.form.get('koptions')
    job_details['koptions_post'] = request.form.get('koptions_post')
    with convert_internal_errors():
        job = Job.provision_system_job(distro_trees, **job_details)
    return 'Created %s' % job.t_id, 201, [('Location',
                                           absolute_url('/jobs/%s' % job.id))]
예제 #9
0
def _extend_watchdog(recipe_id, data):
    recipe = _get_recipe_by_id(recipe_id)
    kill_time = data.get('kill_time')
    if not kill_time:
        raise BadRequest400('Time not specified')
    with convert_internal_errors():
        seconds = recipe.extend(kill_time)
    return jsonify({'seconds': seconds})
예제 #10
0
파일: group.py 프로젝트: qhsong/beaker
def update_group(group_name):
    """
    Updates attributes of an existing group. The request body must be a JSON
    object containing one or more of the following keys.

    :jsonparam string group_name: New name for the group.
    :jsonparam string display_name: Display name of the group.
    :jsonparam string description: Description of the group.
    :jsonparam string root_password: Optional password. Can be an empty string.
      If empty, group jobs will use the root password preferences of the job submitter.
    :jsonparam string membership_type: New membership type for the group.
      See `POST /groups/` for more information.

    :status 200: Group was updated.
    :status 400: Invalid data was given.
    """
    group = _get_group_by_name(group_name)
    if not group.can_edit(identity.current.user):
        raise Forbidden403('Cannot edit group')
    data = read_json_request(request)
    with convert_internal_errors():
        user = identity.current.user
        renamed = False
        if 'group_name' in data:
            new_name = data['group_name']
            if new_name != group.group_name:
                if Group.query.filter(Group.group_name == new_name).count():
                    raise Conflict409('Group %s already exists' % new_name)
                group.set_name(user, u'HTTP', new_name)
                renamed = True
        if 'display_name' in data:
            new_display_name = data['display_name']
            if new_display_name != group.display_name:
                group.set_display_name(user, u'HTTP', new_display_name)
        if 'description' in data:
            new_description = data['description']
            if new_description != group.description:
                group.set_description(user, u'HTTP', new_description)
        if 'root_password' in data:
            new_root_password = data['root_password']
            if new_root_password != group.root_password:
                group.set_root_password(user, u'HTTP', new_root_password)
        # for backwards compatibility
        if data.pop('ldap', False):
            data['membership_type'] = 'ldap'
        if 'membership_type' in data:
            new_type = GroupMembershipType.from_string(
                    data['membership_type'])
            if (new_type == GroupMembershipType.ldap and not
                group.can_edit_ldap(user)):
                raise BadRequest400('Cannot edit LDAP group %s' % group)
            if new_type != group.membership_type:
                group.membership_type = new_type
    response = jsonify(group.to_json())
    if renamed:
        response.headers.add('Location', absolute_url(group.href))
    return response
예제 #11
0
def update_reservation_request(id):
    """
    Updates the reservation request of a recipe. The request must be 
    :mimetype:`application/json`.

    :param id: Recipe's id.
    :jsonparam boolean reserve: Whether the system will be reserved at the end
      of the recipe. If true, the system will be reserved. If false, the system
      will not be reserved.
    :jsonparam int duration: Number of seconds to rerserve the system.
    """

    recipe = _get_recipe_by_id(id)
    if not recipe.can_update_reservation_request(identity.current.user):
        raise Forbidden403('Cannot update the reservation request of recipe %s'
                % recipe.id)
    data = read_json_request(request)
    if 'reserve' not in data:
        raise BadRequest400('No reserve specified')
    with convert_internal_errors():
        if data['reserve']:
            if 'duration' not in data:
                raise BadRequest400('No duration specified')
            duration = data['duration']
            if duration > MAX_SECONDS_PROVISION:
                raise BadRequest400('Reservation time exceeds maximum time of %s hours' % MAX_HOURS_PROVISION)
            if recipe.reservation_request:
                old_duration = recipe.reservation_request.duration
                recipe.reservation_request.duration = data['duration']
                _record_activity(recipe, u'Reservation Request', old_duration,
                        data['duration'])
            else:
                reservation_request = RecipeReservationRequest(data['duration'])
                recipe.reservation_request = reservation_request
                _record_activity(recipe, u'Reservation Request', None,
                        reservation_request.duration, 'Changed')
            return jsonify(recipe.reservation_request.__json__())
        else:
            if recipe.reservation_request:
                session.delete(recipe.reservation_request)
                _record_activity(recipe, u'Reservation Request',
                        recipe.reservation_request.duration, None)
            return jsonify(RecipeReservationRequest.empty_json())
예제 #12
0
파일: pools.py 프로젝트: ShaolongHu/beaker
def add_access_policy_rule(pool_name):
    """
    Adds a new rule to the access policy for a system pool. Each rule in the policy
    grants a permission to a single user, a group of users, or to everybody.

    See :ref:`system-access-policies-api` for a description of the expected JSON parameters.

    :param pool_name: System pool's name.
    """
    pool = _get_pool_by_name(pool_name)
    if not pool.can_edit_policy(identity.current.user):
        raise Forbidden403('Cannot edit system pool policy')
    policy = pool.access_policy
    rule = read_json_request(request)
    if rule.get('user', None):
        user = User.by_user_name(rule['user'])
        if not user:
            raise BadRequest400("User '%s' does not exist" % rule['user'])
    else:
        user = None

    if rule.get('group', None):
        try:
            group = Group.by_name(rule['group'])
        except NoResultFound:
            raise BadRequest400("Group '%s' does not exist" % rule['group'])
    else:
        group = None

    try:
        permission = SystemPermission.from_string(rule['permission'])
    except ValueError:
        raise BadRequest400('Invalid permission')
    new_rule = policy.add_rule(user=user,
                               group=group,
                               everybody=rule['everybody'],
                               permission=permission)
    pool.record_activity(user=identity.current.user,
                         service=u'HTTP',
                         field=u'Access Policy Rule',
                         action=u'Added',
                         new=repr(new_rule))
    return '', 204
예제 #13
0
파일: pools.py 프로젝트: clrkwllms/beaker
def _get_owner(data):
    if data is None:
        data = {}
    user_name = data.get('user_name')
    group_name = data.get('group_name')
    if user_name and group_name:
        raise Forbidden403('System pool can have either an user or a group as owner')
    if user_name:
        owner = User.by_user_name(user_name)
        if owner is None:
            raise BadRequest400('No such user %s' % user_name)
        owner_type = 'user'
    if group_name:
        try:
            owner = Group.by_name(group_name)
        except NoResultFound:
            raise BadRequest400('No such group %r' % group_name)
        owner_type = 'group'
    return owner, owner_type
예제 #14
0
파일: pools.py 프로젝트: ShaolongHu/beaker
def add_system_to_pool(pool_name):
    """
    Add a system to a system pool

    :param pool_name: System pool's name.
    :jsonparam fqdn: System's fully-qualified domain name.

    """
    u = identity.current.user
    data = read_json_request(request)
    pool = _get_pool_by_name(pool_name, lockmode='update')
    if 'fqdn' not in data:
        raise BadRequest400('System FQDN not specified')
    try:
        system = System.by_fqdn(data['fqdn'], u)
    except NoResultFound:
        raise BadRequest400("System '%s' does not exist" % data['fqdn'])
    if not pool in system.pools:
        if pool.can_edit(u) and system.can_edit(u):
            system.record_activity(user=u,
                                   service=u'HTTP',
                                   action=u'Added',
                                   field=u'Pool',
                                   old=None,
                                   new=unicode(pool))
            system.pools.append(pool)
            system.date_modified = datetime.datetime.utcnow()
            pool.record_activity(user=u,
                                 service=u'HTTP',
                                 action=u'Added',
                                 field=u'System',
                                 old=None,
                                 new=unicode(system))
        else:
            if not pool.can_edit(u):
                raise Forbidden403('You do not have permission to '
                                   'add systems to pool %s' % pool.name)
            if not system.can_edit(u):
                raise Forbidden403('You do not have permission to '
                                   'modify system %s' % system.fqdn)

    return '', 204
예제 #15
0
def delete_keystone_trust(username):
    """
    Deletes the Keystone trust for a user account.

    :param username: The user's username.
    """
    user = _get_user(username)
    if not config.get('openstack.identity_api_url'):
        raise BadRequest400("OpenStack Integration is not enabled")
    if not user.can_edit_keystone_trust(identity.current.user):
        raise Forbidden403('Cannot edit Keystone trust of user %s' % username)
    if not user.openstack_trust_id:
        raise BadRequest400('No Keystone trust created by %s' % user)
    manager = dynamic_virt.VirtManager(user)
    manager.delete_keystone_trust()
    old_trust_id = user.openstack_trust_id
    user.openstack_trust_id = None
    user.record_activity(user=identity.current.user, service=u'HTTP',
            field=u'OpenStack Trust ID', action=u'Deleted',
            old=old_trust_id)
    return '', 204
예제 #16
0
def _create_keystone_trust(user):
    if not config.get('openstack.identity_api_url'):
        raise BadRequest400("OpenStack Integration is not enabled")
    if not user.can_edit_keystone_trust(identity.current.user):
        raise Forbidden403('Cannot edit Keystone trust of user %s' % user.username)
    data = read_json_request(request)
    if 'openstack_username' not in data:
        raise BadRequest400('No OpenStack username specified')
    if 'openstack_password' not in data:
        raise BadRequest400('No OpenStack password specified')
    if 'openstack_project_name' not in data:
        raise BadRequest400('No OpenStack project name specified')
    try:
        trust_id = dynamic_virt.create_keystone_trust(data['openstack_username'],
                data['openstack_password'], data['openstack_project_name'])
    except ValueError as err:
        raise BadRequest400(u'Could not authenticate with OpenStack using your credentials: %s' % unicode(err))
    user.openstack_trust_id = trust_id
    user.record_activity(user=identity.current.user, service=u'HTTP',
            field=u'OpenStack Trust ID', action=u'Changed')
    return jsonify({'openstack_trust_id': trust_id})
예제 #17
0
def system_command(fqdn):
    system = _get_system_by_FQDN(fqdn)
    if not system.lab_controller:
        raise BadRequest400('System is not attached to a lab controller')
    if not system.can_power(identity.current.user):
        raise Forbidden403('You do not have permission to control this system')
    # We accept JSON or form-encoded for convenience
    if request.json:
        if 'action' not in request.json:
            raise BadRequest400('Missing action key')
        action = request.json['action']
    elif request.form:
        if 'action' not in request.form:
            raise BadRequest400('Missing action parameter')
        action = request.form['action']
    else:
        raise UnsupportedMediaType415
    if action == 'reboot':
        raise BadRequest400('"reboot" is not a valid power command, '
                            'send "off" followed by "on" instead')
    elif action in ['on', 'off', 'interrupt']:
        if not system.power:
            raise BadRequest400('System is not configured for power support')
        command = system.action_power(service=u'HTTP', action=action)
    elif action == 'clear_netboot':
        command = system.clear_netboot(service=u'HTTP')
    else:
        raise BadRequest400('Unknown action %r' % action)
    session.flush()  # for created attribute
    return jsonify(command.__json__())
예제 #18
0
def add_system_access_policy_rule(fqdn):
    system = _get_system_by_FQDN(fqdn)
    if not system.can_edit_policy(identity.current.user):
        raise Forbidden403('Cannot edit system policy')
    if system.custom_access_policy:
        policy = system.custom_access_policy
    else:
        policy = system.custom_access_policy = SystemAccessPolicy()
    rule = read_json_request(request)

    if rule['user']:
        user = User.by_user_name(rule['user'])
        if not user:
            raise BadRequest400("User '%s' does not exist" % rule['user'])
    else:
        user = None

    if rule['group']:
        try:
            group = Group.by_name(rule['group'])
        except NoResultFound:
            raise BadRequest400("Group '%s' does not exist" % rule['group'])
    else:
        group = None

    try:
        permission = SystemPermission.from_string(rule['permission'])
    except ValueError:
        raise BadRequest400
    new_rule = policy.add_rule(user=user,
                               group=group,
                               everybody=rule['everybody'],
                               permission=permission)
    system.record_activity(user=identity.current.user,
                           service=u'HTTP',
                           field=u'Access Policy Rule',
                           action=u'Added',
                           new=repr(new_rule))
    return '', 204
예제 #19
0
def add_submission_delegate(username):
    """
    Adds a submission delegate for a user account. Submission delegates are 
    other users who are allowed to submit jobs on behalf of this user.

    :param username: The user's username.
    :jsonparam string user_name: The submission delegate's username.
    """
    user = _get_user(username)
    if not user.can_edit(identity.current.user):
        raise Forbidden403('Cannot edit user %s' % user)
    data = read_json_request(request)
    if 'user_name' not in data:
        raise BadRequest400('Missing "user_name" key to specify submission delegate')
    submission_delegate = User.by_user_name(data['user_name'])
    if submission_delegate is None:
        raise BadRequest400('Submission delegate %s does not exist' % data['user_name'])
    try:
        user.add_submission_delegate(submission_delegate, service=u'HTTP')
    except NoChangeException as e:
        raise Conflict409(unicode(e))
    return 'Added', 201
예제 #20
0
def update_user(user, display_name=None, email_address=None, password=''):
    if user.lab_controller:
        raise BadRequest400(
            'User %s is already associated with lab controller %s' %
            (user, user.lab_controller))
    user.display_name = display_name
    user.email_address = email_address
    if password:
        user.password = password

    group = Group.by_name(u'lab_controller')
    if group not in user.groups:
        group.add_member(user, agent=identity.current.user)
    return user
예제 #21
0
def get_system_access_policy(fqdn):
    # XXX need to consolidate this with SystemAccessPolicy.__json__
    # (maybe get rid of filtering here and implement it client side instead)
    system = _get_system_by_FQDN(fqdn)

    policy = system.custom_access_policy
    # For now, we don't distinguish between an empty policy and an absent one.
    if not policy:
        return jsonify(SystemAccessPolicy.empty_json())

    # filtering, if any
    if len(request.args.keys()) > 1:
        raise BadRequest400('Only one filtering criteria allowd')

    query = SystemAccessPolicyRule.query.\
        filter(SystemAccessPolicyRule.policy == policy)

    if request.args.get('mine'):
        if not identity.current.user:
            raise Unauthorised401(
                "The 'mine' access policy filter requires authentication")
        query = query.join(SystemAccessPolicyRule.user)\
            .filter(User.user_name.in_([identity.current.user.user_name]))
    elif request.args.get('user', None):
        query = query.join(SystemAccessPolicyRule.user)\
            .filter(User.user_name.in_(request.args.getlist('user')))
    elif request.args.get('group', None):
        query = query.join(SystemAccessPolicyRule.group)\
            .filter(Group.group_name.in_(request.args.getlist('group')))

    return jsonify({
        'id':
        policy.id,
        'rules': [{
            'id': rule.id,
            'user': rule.user.user_name if rule.user else None,
            'group': rule.group.group_name if rule.group else None,
            'everybody': rule.everybody,
            'permission': unicode(rule.permission)
        } for rule in query],
        'possible_permissions': [{
            'value': unicode(permission),
            'label': unicode(permission.label)
        } for permission in SystemPermission],
    })
예제 #22
0
def post_recipeset_comment(id):
    """
    Adds a new comment to a recipe set. The request must be :mimetype:`application/json`.

    :param id: ID of the recipe set.
    :jsonparam string comment: Comment text.
    """
    recipeset = _get_rs_by_id(id)
    if not recipeset.can_comment(identity.current.user):
        raise Forbidden403('Cannot post recipe set comment')
    data = read_json_request(request)
    if 'comment' not in data:
        raise BadRequest400('Missing "comment" key')
    with convert_internal_errors():
        comment = RecipeSetComment(user=identity.current.user,
                                   comment=data['comment'])
        recipeset.comments.append(comment)
    session.flush()  # to populate the id
    return jsonify(comment.__json__())
예제 #23
0
파일: group.py 프로젝트: qhsong/beaker
def add_permission(group_name):
    """
    Add a permission to a group.

    :param group_name: Group's name.
    :jsonparam permission_name: Permission's name.

    """
    u = identity.current.user
    data = read_json_request(request)
    group = _get_group_by_name(group_name, lockmode='update')
    if 'permission_name' not in data:
        raise BadRequest400('Permission name not specified')
    permission = _get_permission_by_name(data['permission_name'])
    if permission not in group.permissions:
        group.permissions.append(permission)
        group.record_activity(user=u, service=u'HTTP',
                             action=u'Added', field=u'Permission', old=None,
                             new=unicode(permission))
    return '', 204
예제 #24
0
def extend_watchdog_by_taskspec(taskspec):
    """
    Extend the watchdog for a recipe identified by a taskspec. The valid type
    of a taskspec is either R(recipe) or T(recipe-task).
    See :ref:`Specifying tasks <taskspec>` in :manpage:`bkr(1)`.

    :param taskspec: A taskspec argument that identifies a recipe or recipe task.
    :jsonparam string kill_time: Time in seconds to extend the watchdog by.
    """
    if not taskspec.startswith(('R', 'T')):
        raise BadRequest400('Taskspec type must be one of [R, T]')

    try:
        obj = TaskBase.get_by_t_id(taskspec)
    except BeakerException as exc:
        raise NotFound404(unicode(exc))

    if isinstance(obj, Recipe):
        recipe = obj
    else:
        recipe = obj.recipe
    data = read_json_request(request)
    return _extend_watchdog(recipe.id, data)
예제 #25
0
파일: group.py 프로젝트: qhsong/beaker
def grant_ownership(group_name):
    """
    Grant group ownership to a user. The user can either be the group member or
    not. If the user is not the group member, it will be added first.

    :param group_name: Group's name.
    :jsonparam string user_name: User's username.

    """
    u = identity.current.user
    data = read_json_request(request)
    group = _get_group_by_name(group_name, lockmode='update')
    if not group.can_modify_ownership(identity.current.user):
        raise Forbidden403('Cannot edit ownership of group %s' % group_name)
    if 'user_name' not in data:
        raise BadRequest400('User not specified')
    user_name = data['user_name']
    user = _get_user_by_username(user_name)
    if not group.has_owner(user):
        group.grant_ownership(user, agent=identity.current.user)
    else:
        raise Conflict409('User %s is already an owner of group %s' % (user.user_name, group_name))
    return '', 204
예제 #26
0
파일: group.py 프로젝트: joyxu/beaker
def _get_permission_by_name(permission_name):
    try:
        return Permission.by_name(permission_name)
    except NoResultFound:
        # Needs to return 400 as the resource exists but the given parameter is bad.
        raise BadRequest400("Permission '%s' does not exist" % permission_name)
예제 #27
0
def create_group():
    """
    Creates a new user group in Beaker. The request must be 
    :mimetype:`application/json`.

    :jsonparam string group_name: Symbolic name for the group.
    :jsonparam string display_name: Human-friendly display name for the group.
    :jsonparam string description: Description of the group.
    :jsonparam string root_password: Optional root password for group jobs.
      If this is not set, group jobs will use the root password preferences of 
      the job submitter.
    :jsonparam string membership_type: Specifies how group membership is populated.
      Possible values are:

      * normal: Group is initially empty, members are explicitly added and removed by
        group owner.
      * ldap: Membership is populated from the LDAP group with the same group name.
      * inverted: Group contains all Beaker users *except* users who have been explicitly
        excluded by the group owner.

    :status 201: The group was successfully created.
    """
    user = identity.current.user
    data = read_json_request(request)
    if 'group_name' not in data:
        raise BadRequest400('Missing group_name key')
    if 'display_name' not in data:
        raise BadRequest400('Missing display_name key')
    # for backwards compatibility
    if data.pop('ldap', False):
        data['membership_type'] = 'ldap'
    if data.get('membership_type') == 'ldap':
        if not config.get("identity.ldap.enabled", False):
            raise BadRequest400('LDAP is not enabled')
        if not identity.current.user.is_admin():
            raise BadRequest400('Only admins can create LDAP groups')
    try:
        Group.by_name(data['group_name'])
    except NoResultFound:
        pass
    else:
        raise Conflict409("Group already exists: %s" % data['group_name'])
    with convert_internal_errors():
        group = Group.lazy_create(group_name=data['group_name'])
        group.display_name = data['display_name']
        group.description = data.get('description')
        group.root_password = data.get('root_password')
        session.add(group)
        group.record_activity(user=user,
                              service=u'HTTP',
                              field=u'Group',
                              action=u'Created')
        if data.get('membership_type'):
            group.membership_type = GroupMembershipType.from_string(
                data['membership_type'])
        if group.membership_type == GroupMembershipType.ldap:
            group.refresh_ldap_members()
        else:  # LDAP groups don't have any owners
            group.add_member(user, is_owner=True, agent=identity.current.user)
    response = jsonify(group.__json__())
    response.status_code = 201
    response.headers.add('Location', absolute_url(group.href))
    return response
예제 #28
0
def update_labcontroller(fqdn):
    """
    Updates attributes of the lab controller identified by it's FQDN. The
    request body must be a json object or only the FQDN if
    that is the only value to be updated.

    :param string fqdn: Lab controller's new fully-qualified domain name.
    :jsonparam string user_name: User name associated with the lab controller.
    :jsonparam string email_address: Email of the user account associated with the lab controller.
    :jsonparam string password: Optional password for the user account used to login.
    :jsonparam string removed: If True, detaches all systems, cancels all
        running recipes and removes associated distro trees. If False, restores
        the lab controller.
    :jsonparam bool disabled: Whether the lab controller should be disabled. New
        recipes are not scheduled on a lab controller while it is disabled.
    :status 200: LabController updated.
    :status 400: Invalid data was given.
    """
    labcontroller = find_labcontroller_or_raise404(fqdn)
    if not labcontroller.can_edit(identity.current.user):
        raise Forbidden403('Cannot edit lab controller')
    data = read_json_request(request)
    with convert_internal_errors():
        # should the lab controller be removed?
        if data.get('removed', False) and not labcontroller.removed:
            remove_labcontroller(labcontroller)

        # should the controller be restored?
        if data.get('removed') is False and labcontroller.removed:
            restore_labcontroller(labcontroller)
        fqdn_changed = False
        new_fqdn = data.get('fqdn', fqdn)
        if labcontroller.fqdn != new_fqdn:
            lc = None
            try:
                lc = LabController.by_name(new_fqdn)
            except NoResultFound:
                pass
            if lc is not None:
                raise BadRequest400('FQDN %s already in use' % new_fqdn)

            labcontroller.record_activity(user=identity.current.user,
                                          service=u'HTTP',
                                          field=u'fqdn',
                                          action=u'Changed',
                                          old=labcontroller.fqdn,
                                          new=new_fqdn)
            labcontroller.fqdn = new_fqdn
            labcontroller.user.display_name = new_fqdn
            fqdn_changed = True
        if 'user_name' in data:
            user = find_user_or_create(data['user_name'])
            if labcontroller.user != user:
                user = update_user(user,
                                   display_name=new_fqdn,
                                   email_address=data.get(
                                       'email_address', user.email_address),
                                   password=data.get('password',
                                                     user.password))
                labcontroller.record_activity(user=identity.current.user,
                                              service=u'HTTP',
                                              field=u'User',
                                              action=u'Changed',
                                              old=labcontroller.user.user_name,
                                              new=user.user_name)
                labcontroller.user = user
        if 'email_address' in data:
            new_email_address = data.get('email_address')
            if labcontroller.user.email_address != new_email_address:
                labcontroller.user.email_address = new_email_address
        if data.get('password') is not None:
            labcontroller.user.password = data.get('password')
        if labcontroller.disabled != data.get('disabled',
                                              labcontroller.disabled):
            labcontroller.record_activity(user=identity.current.user,
                                          service=u'HTTP',
                                          field=u'disabled',
                                          action=u'Changed',
                                          old=unicode(labcontroller.disabled),
                                          new=data['disabled'])
            labcontroller.disabled = data['disabled']

    response = jsonify(labcontroller.__json__())
    if fqdn_changed:
        response.headers.add('Location', absolute_url(labcontroller.href))
    return response
예제 #29
0
def update_system(fqdn):
    system = _get_system_by_FQDN(fqdn)
    if not system.can_edit(identity.current.user):
        raise Forbidden403('Cannot edit system')
    data = read_json_request(request)

    # helper for recording activity below
    def record_activity(field, old, new, action=u'Changed'):
        system.record_activity(user=identity.current.user,
                               service=u'HTTP',
                               action=action,
                               field=field,
                               old=old,
                               new=new)

    with convert_internal_errors():
        # XXX what a nightmare... need to use a validation/conversion library,
        # and maybe simplify/relocate the activity recording stuff somehow
        changed = False
        renamed = False
        if 'fqdn' in data:
            new_fqdn = data['fqdn'].lower()
            if new_fqdn != system.fqdn:
                if System.query.filter(System.fqdn == new_fqdn).count():
                    raise Conflict409('System %s already exists' % new_fqdn)
                record_activity(u'FQDN', system.fqdn, new_fqdn)
                system.fqdn = new_fqdn
                changed = True
                renamed = True
        if 'owner' in data and data['owner'].get(
                'user_name') != system.owner.user_name:
            if not system.can_change_owner(identity.current.user):
                raise Forbidden403('Cannot change owner')
            new_owner = User.by_user_name(data['owner'].get('user_name'))
            if new_owner is None:
                raise BadRequest400('No such user %s' %
                                    data['owner'].get('user_name'))
            record_activity(u'Owner', system.owner, new_owner)
            system.owner = new_owner
            changed = True
        if 'status' in data:
            new_status = SystemStatus.from_string(data['status'])
            if new_status != system.status:
                record_activity(u'Status', system.status, new_status)
                system.status = new_status
                if not new_status.bad and system.status_reason:
                    # clear the status reason for "good" statuses
                    record_activity(u'Status Reason', system.status_reason,
                                    None)
                    system.status_reason = None
                changed = True
        if 'status_reason' in data:
            new_reason = data['status_reason'] or None
            if new_reason and not system.status.bad:
                raise ValueError('Cannot set status reason when status is %s' %
                                 system.status)
            if new_reason != system.status_reason:
                record_activity(u'Status Reason', system.status_reason,
                                new_reason)
                system.status_reason = new_reason
                changed = True
        if 'type' in data:
            new_type = SystemType.from_string(data['type'])
            if new_type != system.type:
                record_activity(u'Type', system.type, new_type)
                system.type = new_type
                changed = True
        if 'arches' in data:
            new_arches = [Arch.by_name(a) for a in (data['arches'] or [])]
            added_arches = set(new_arches).difference(system.arch)
            removed_arches = set(system.arch).difference(new_arches)
            if added_arches or removed_arches:
                for added_arch in added_arches:
                    record_activity(u'Arch', None, added_arch, u'Added')
                for removed_arch in removed_arches:
                    record_activity(u'Arch', removed_arch, None, u'Removed')
                system.arch[:] = new_arches
                changed = True
        if 'lab_controller_id' in data:
            if data['lab_controller_id']:
                new_lc = LabController.by_id(data['lab_controller_id'])
            else:
                new_lc = None
            if new_lc != system.lab_controller:
                if system.open_reservation is not None:
                    raise Conflict409(
                        'Unable to change lab controller while system '
                        'is in use (return the system first)')
                record_activity(u'Lab Controller', system.lab_controller,
                                new_lc)
                system.lab_controller = new_lc
                changed = True
        # If we're given any power-related keys, need to ensure system.power exists
        if not system.power and set(['power_type', 'power_address', 'power_user',
                'power_password', 'power_id', 'power_quiescent_period'])\
                .intersection(data.keys()):
            system.power = Power()
        if 'power_type' in data:
            new_power_type = PowerType.by_name(data['power_type'])
            if new_power_type != system.power.power_type:
                if not system.power.power_type:
                    old_power_type = ''
                else:
                    old_power_type = system.power.power_type.name
                record_activity(u'power_type', old_power_type,
                                new_power_type.name)
                system.power.power_type = new_power_type
                changed = True
        if 'power_address' in data:
            new_power_address = data['power_address']
            if not new_power_address:
                raise ValueError('Power address is required')
            if new_power_address != system.power.power_address:
                record_activity(u'power_address', system.power.power_address,
                                data['power_address'])
                system.power.power_address = new_power_address
                changed = True
        if 'power_user' in data:
            new_power_user = data['power_user'] or u''
            if new_power_user != (system.power.power_user or u''):
                record_activity(u'power_user', u'********', u'********')
                system.power.power_user = new_power_user
                changed = True
        if 'power_password' in data:
            new_power_password = data['power_password'] or u''
            if new_power_password != (system.power.power_passwd or u''):
                record_activity(u'power_passwd', u'********', u'********')
                system.power.power_passwd = new_power_password
                changed = True
        if 'power_id' in data:
            new_power_id = data['power_id'] or u''
            if new_power_id != (system.power.power_id or u''):
                record_activity(u'power_id', system.power.power_id,
                                new_power_id)
                system.power.power_id = new_power_id
                changed = True
        if 'power_quiescent_period' in data:
            new_qp = int(data['power_quiescent_period'])
            if new_qp != system.power.power_quiescent_period:
                record_activity(u'power_quiescent_period',
                                system.power.power_quiescent_period, new_qp)
                system.power.power_quiescent_period = new_qp
                changed = True
        if 'release_action' in data:
            new_release_action = ReleaseAction.from_string(
                data['release_action'])
            if new_release_action != (system.release_action
                                      or ReleaseAction.power_off):
                record_activity(
                    u'release_action',
                    (system.release_action or ReleaseAction.power_off),
                    new_release_action)
                system.release_action = new_release_action
                changed = True
        if 'reprovision_distro_tree' in data:
            if (not data['reprovision_distro_tree']
                    or 'id' not in data['reprovision_distro_tree']):
                new_rpdt = None
            else:
                new_rpdt = DistroTree.by_id(
                    data['reprovision_distro_tree']['id'])
            if new_rpdt != system.reprovision_distro_tree:
                record_activity(u'reprovision_distro_tree',
                                unicode(system.reprovision_distro_tree),
                                unicode(new_rpdt))
                system.reprovision_distro_tree = new_rpdt
                changed = True
        if 'location' in data:
            new_location = data['location'] or None
            if new_location != system.location:
                record_activity(u'Location', system.location, new_location)
                system.location = new_location
                changed = True
        if 'lender' in data:
            new_lender = data['lender'] or None
            if new_lender != system.lender:
                record_activity(u'Lender', system.lender, new_lender)
                system.lender = new_lender
                changed = True
        if 'kernel_type' in data:
            new_kernel_type = KernelType.by_name(data['kernel_type'])
            if new_kernel_type != system.kernel_type:
                record_activity(u'Kernel Type', system.kernel_type,
                                new_kernel_type)
                system.kernel_type = new_kernel_type
                changed = True
        if 'hypervisor' in data:
            if data['hypervisor']:
                new_hypervisor = Hypervisor.by_name(data['hypervisor'])
            else:
                new_hypervisor = None
            if new_hypervisor != system.hypervisor:
                record_activity(u'Hypervisor', system.hypervisor,
                                new_hypervisor)
                system.hypervisor = new_hypervisor
                changed = True
        if 'vendor' in data:
            new_vendor = data['vendor'] or None
            if new_vendor != system.vendor:
                record_activity(u'Vendor', system.vendor, new_vendor)
                system.vendor = new_vendor
                changed = True
        if 'model' in data:
            new_model = data['model'] or None
            if new_model != system.model:
                record_activity(u'Model', system.model, new_model)
                system.model = new_model
                changed = True
        if 'serial_number' in data:
            new_serial_number = data['serial_number'] or None
            if new_serial_number != system.serial:
                record_activity(u'Serial Number', system.serial,
                                new_serial_number)
                system.serial = new_serial_number
                changed = True
        if 'mac_address' in data:
            new_mac_address = data['mac_address'] or None
            if new_mac_address != system.mac_address:
                record_activity(u'MAC Address', system.mac_address,
                                new_mac_address)
                system.mac_address = new_mac_address
                changed = True
        if 'memory' in data:
            new_memory = int(data['memory']) if data['memory'] else None
            if new_memory != system.memory:
                record_activity(u'Memory', system.memory, new_memory)
                system.memory = new_memory
                changed = True
        if 'numa_nodes' in data:
            new_numa_nodes = int(
                data['numa_nodes']) if data['numa_nodes'] else None
            if not system.numa:
                system.numa = Numa()
            if new_numa_nodes != system.numa.nodes:
                record_activity(u'NUMA/Nodes', system.numa.nodes,
                                new_numa_nodes)
                system.numa.nodes = new_numa_nodes
                changed = True
        if changed:
            # XXX clear checksum!?
            system.date_modified = datetime.datetime.utcnow()
    response = jsonify(system.__json__())
    if renamed:
        response.headers.add('Location', url('/view/%s' % system.fqdn))
    return response