Beispiel #1
0
def project_detach_node(project, node):
    """Remove a node from a project.

    If the node or project does not exist, a NotFoundError will be raised.

    If the node has network attachments or pending network actions, a
    BlockedError will be raised.
    """
    project = _must_find(model.Project, project)
    get_auth_backend().require_project_access(project)
    node = _must_find(model.Node, node)
    if node not in project.nodes:
        raise NotFoundError("Node not in project")
    num_attachments = model.NetworkAttachment.query \
        .filter(model.Nic.owner == node,
                model.NetworkAttachment.nic_id == model.Nic.id).count()
    if num_attachments != 0:
        raise BlockedError("Node attached to a network")
    for nic in node.nics:
        if nic.current_action is not None:
            raise BlockedError("Node has pending network actions")
    node.obm.stop_console()
    node.obm.delete_console()
    project.nodes.remove(node)
    db.session.commit()
Beispiel #2
0
def user_set_admin(user, is_admin):
    get_auth_backend().require_admin()
    user = api._must_find(User, user)
    if user.label == local.auth.label:
        raise IllegalStateError("Cannot set own admin status")
    user.is_admin = is_admin
    db.session.commit()
Beispiel #3
0
def show_node(nodename):
    """Show the details of a node.

    Returns a JSON object representing a node.
    """

    node = _must_find(model.Node, nodename)
    if node.project is not None:
        get_auth_backend().require_project_access(node.project)

    # build list of nics
    nic = [{'label': n.label,
            'macaddr': n.mac_addr,
            'port': None if n.port is None else n.port.label,
            'switch': None if n.port is None else n.port.owner.label,
            'networks': dict([(attachment.channel,
                               attachment.network.label)
                             for attachment in n.attachments]),
            } for n in node.nics]

    # remove port and switch info if the user is not an admin
    if not get_auth_backend().have_admin():
        for nics in nic:
            del nics['port']
            del nics['switch']

    return json.dumps({
        'name': node.label,
        'project': None if node.project_id is None else node.project.label,
        'nics': nic,
        'metadata': {m.label: m.value for m in node.metadata}
    }, sort_keys=True)
Beispiel #4
0
def project_delete(project):
    """Delete project.

    If the project does not exist, a NotFoundError will be raised.
    """
    get_auth_backend().require_admin()
    project = _must_find(model.Project, project)
    if project.nodes:
        raise BlockedError("Project has nodes still")
    if project.networks_created:
        raise BlockedError("Project still has networks")
    if project.networks_access:
        # FIXME: This is not the user's fault, and they cannot fix it.  The
        # only reason we need to error here is that, with how network access
        # is done, the following bad thing happens.  If there's a network
        # that only the project can access, its "access" field will be the
        # project.  When you then delete that project, "access" will be set
        # to None instead.  Counter-intuitively, this then makes that
        # network accessible to ALL PROJECTS!  Once we use real ACLs, this
        # will not be an issue---instead, the network will be accessible by
        # NO projects.
        raise BlockedError("Project can still access networks")
    if project.headnodes:
        raise BlockedError("Project still has a headnode")
    db.session.delete(project)
    db.session.commit()
Beispiel #5
0
def headnode_create(headnode, project, base_img):
    """Create headnode.

    If a headnode with the same name already exists, a DuplicateError will be
    raised.

    If the project does not exist, a NotFoundError will be raised.

    If the base image does not exist (is not specified in hil.cfg) a
    BadArgumentError will be raised.
    """

    valid_imgs = cfg.get('headnode', 'base_imgs')
    valid_imgs = [img.strip() for img in valid_imgs.split(',')]

    if base_img not in valid_imgs:
        raise BadArgumentError('Provided image is not a valid image.')

    _assert_absent(model.Headnode, headnode)
    project = _must_find(model.Project, project)
    get_auth_backend().require_project_access(project)

    headnode = model.Headnode(project, headnode, base_img)

    db.session.add(headnode)
    db.session.commit()
Beispiel #6
0
def headnode_connect_network(headnode, hnic, network):
    """Connect a headnode's hnic to a network.

    Raises IllegalStateError if the headnode has already been started.

    Raises ProjectMismatchError if the project does not have access rights to
    the given network.

    Raises BadArgumentError if the network is a non-allocated network. This
    is currently unsupported due to an implementation limitation, but will be
    supported in a future release. See issue #333.
    """
    headnode = _must_find(model.Headnode, headnode)
    get_auth_backend().require_project_access(headnode.project)
    hnic = _must_find_n(headnode, model.Hnic, hnic)
    network = _must_find(model.Network, network)

    if not network.allocated:
        raise BadArgumentError("Headnodes may only be connected to networks "
                               "allocated by the project.")

    if not headnode.dirty:
        raise IllegalStateError

    project = headnode.project

    if (network.access) and (project not in network.access):
        raise ProjectMismatchError(
            "Project does not have access to given network.")

    hnic.network = network
    db.session.commit()
Beispiel #7
0
def show_headnode(nodename):
    """Show details of a headnode.

    Returns a JSON object representing a headnode.
    The obect will have at least the following fields:
        * "name", the name/label of the headnode (string).
        * "project", the project to which the headnode belongs.
        * "hnics", a JSON array of hnic labels that are attached to this
            headnode.
        * "vncport", the vnc port that the headnode VM is listening on; this
            value can be None if the VM is powered off or has not been
            created yet.

    Example:  '{"name": "headnode1",
                "project": "project1",
                "hnics": ["hnic1", "hnic2"],
                "vncport": 5900
               }'
    """
    headnode = _must_find(model.Headnode, nodename)
    get_auth_backend().require_project_access(headnode.project)
    return json.dumps({
        'name': headnode.label,
        'project': headnode.project.label,
        'hnics': [n.label for n in headnode.hnics],
        'vncport': headnode.get_vncport(),
        'uuid': headnode.uuid,
        'base_img': headnode.base_img,
    }, sort_keys=True)
Beispiel #8
0
def node_set_bootdev(node, bootdev):
    """Set the node's boot device."""
    node = get_or_404(model.Node, node)
    get_auth_backend().require_project_access(node.project)

    node.obm.require_legal_bootdev(bootdev)

    node.obm.set_bootdev(bootdev)
Beispiel #9
0
def user_set_admin(user, is_admin):
    """Set whether the user is an admin."""
    get_auth_backend().require_admin()
    user = api.get_or_404(User, user)
    if user.label == local.auth.label:
        raise errors.IllegalStateError("Cannot set own admin status")
    user.is_admin = is_admin
    db.session.commit()
Beispiel #10
0
def node_power_cycle(node, force=False):
    """Reboot the node.

    Force indicates whether the node should be forced off, or allowed
    to respond to the shutdown signal.
    """
    node = get_or_404(model.Node, node)
    get_auth_backend().require_project_access(node.project)
    node.obm.power_cycle(force)
Beispiel #11
0
def node_delete_nic(node, nic):
    """Delete nic with given name from it's node.

    If the node or nic does not exist, a NotFoundError will be raised.
    """
    get_auth_backend().require_admin()
    nic = _must_find_n(_must_find(model.Node, node), model.Nic, nic)
    db.session.delete(nic)
    db.session.commit()
Beispiel #12
0
def list_users():
    """List all users with database authentication"""
    get_auth_backend().require_admin()
    users = User.query.all()
    result = {}
    for u in users:
        user = {'is_admin': u.is_admin,
                'projects': sorted(p.label for p in u.projects)}
        result[u.label] = user
    return json.dumps(result, sort_keys=True)
Beispiel #13
0
def headnode_stop(headnode):
    """Stop the headnode.

    This powers off the headnode. This is a hard poweroff; the VM is not given
    the opportunity to shut down cleanly. This does *not* unfreeze the VM;
    headnode_start will be the only valid API call after the VM is powered off.
    """
    headnode = _must_find(model.Headnode, headnode)
    get_auth_backend().require_project_access(headnode.project)
    headnode.stop()
Beispiel #14
0
def switch_delete(switch):
    get_auth_backend().require_admin()
    switch = _must_find(model.Switch, switch)

    if switch.ports != []:
        raise BlockedError("Switch %r has ports; delete them first." %
                           switch.label)

    db.session.delete(switch)
    db.session.commit()
Beispiel #15
0
def project_create(project):
    """Create a project.

    If the project already exists, a DuplicateError will be raised.
    """
    get_auth_backend().require_admin()
    _assert_absent(model.Project, project)
    project = model.Project(project)
    db.session.add(project)
    db.session.commit()
Beispiel #16
0
def list_switches():
    """List all switches.

    Returns a JSON array of strings representing a list of switches.

    Example:  '["cisco3", "brocade1", "mock2"]'
    """
    get_auth_backend().require_admin()
    switches = model.Switch.query.all()
    snames = sorted([s.label for s in switches])
    return json.dumps(snames)
Beispiel #17
0
def list_projects():
    """List all projects.

    Returns a JSON array of strings representing a list of projects.

    Example:  '["project1", "project2", "project3"]'
    """
    get_auth_backend().require_admin()
    projects = model.Project.query.all()
    projects = sorted([p.label for p in projects])
    return json.dumps(projects)
Beispiel #18
0
def switch_delete(switch):
    """Delete a switch"""
    get_auth_backend().require_admin()
    switch = get_or_404(model.Switch, switch)

    if switch.ports != []:
        raise errors.BlockedError(
            "Switch %r has ports; delete them first." % switch.label)

    db.session.delete(switch)
    db.session.commit()
Beispiel #19
0
def node_delete_metadata(node, label):
    """Delete a metadata from a node.

    If the metadata does not exist, a NotFoundError will be raised.
    """
    get_auth_backend().require_admin()
    node = _must_find(model.Node, node)
    metadata = _must_find_n(node, model.Metadata, label)

    db.session.delete(metadata)
    db.session.commit()
Beispiel #20
0
def list_project_nodes(project):
    """List all nodes belonging the given project.

    Returns a JSON array of strings representing a list of nodes.

    Example:  '["node1", "node2", "node3"]'
    """
    project = _must_find(model.Project, project)
    get_auth_backend().require_project_access(project)
    nodes = project.nodes
    nodes = [n.label for n in nodes]
    return json.dumps(nodes)
Beispiel #21
0
def list_project_networks(project):
    """List all private networks the project can access.

    Returns a JSON array of strings representing a list of networks.

    Example:  '["net1", "net2", "net3"]'
    """
    project = _must_find(model.Project, project)
    get_auth_backend().require_project_access(project)
    networks = project.networks_access
    networks = sorted([n.label for n in networks])
    return json.dumps(networks)
Beispiel #22
0
def switch_register_port(switch, port):
    """Register a port on a switch.

    If the port already exists, a DuplicateError will be raised.
    """
    get_auth_backend().require_admin()
    switch = _must_find(model.Switch, switch)
    _assert_absent_n(switch, model.Port, port)
    port = model.Port(port, switch)

    db.session.add(port)
    db.session.commit()
Beispiel #23
0
def list_project_headnodes(project):
    """List all headnodes belonging the given project.

    Returns a JSON array of strings representing a list of headnodes.

    Example:  '["headnode1", "headnode2", "headnode3"]'
    """
    project = _must_find(model.Project, project)
    get_auth_backend().require_project_access(project)
    headnodes = project.headnodes
    headnodes = sorted([hn.label for hn in headnodes])
    return json.dumps(headnodes)
Beispiel #24
0
def user_remove_project(user, project):
    """Remove a user from a project.

    If the project or user does not exist, a NotFoundError will be raised.
    """
    get_auth_backend().require_admin()
    user = api.get_or_404(User, user)
    project = api.get_or_404(model.Project, project)
    if project not in user.projects:
        raise errors.NotFoundError(
            "User %s is not in project %s" % (user.label, project.label))
    user.projects.remove(project)
    db.session.commit()
Beispiel #25
0
def user_delete(user):
    """Delete user.

    If the user does not exist, a NotFoundError will be raised.
    """
    get_auth_backend().require_admin()

    # XXX: We need to do a bit of refactoring, so this is available outside of
    # hil.api:
    user = api.get_or_404(User, user)

    db.session.delete(user)
    db.session.commit()
Beispiel #26
0
def user_add_project(user, project):
    """Add a user to a project.

    If the project or user does not exist, a NotFoundError will be raised.
    """
    get_auth_backend().require_admin()
    user = api.get_or_404(User, user)
    project = api.get_or_404(model.Project, project)
    if project in user.projects:
        raise errors.DuplicateError(
            'User %s is already in project %s' % (user.label, project.label))
    user.projects.append(project)
    db.session.commit()
Beispiel #27
0
def node_register_nic(node, nic, macaddr):
    """Register existence of nic attached to given node.

    If the node does not exist, a NotFoundError will be raised.

    If there is already an nic with that name, a DuplicateError will be raised.
    """
    get_auth_backend().require_admin()
    node = _must_find(model.Node, node)
    _assert_absent_n(node, model.Nic, nic)
    nic = model.Nic(node, nic, macaddr)
    db.session.add(nic)
    db.session.commit()
Beispiel #28
0
def headnode_delete(headnode):
    """Delete headnode.

    If the node does not exist, a NotFoundError will be raised.
    """
    headnode = _must_find(model.Headnode, headnode)
    get_auth_backend().require_project_access(headnode.project)
    if not headnode.dirty:
        headnode.delete()
    for hnic in headnode.hnics:
        db.session.delete(hnic)
    db.session.delete(headnode)
    db.session.commit()
Beispiel #29
0
def project_connect_node(project, node):
    """Add a node to a project.

    If the node or project does not exist, a NotFoundError will be raised.

    If node is already owned by a project, a BlockedError will be raised.
    """
    project = _must_find(model.Project, project)
    get_auth_backend().require_project_access(project)
    node = _must_find(model.Node, node)
    if node.project is not None:
        raise BlockedError("Node is already owned by a project.")
    project.nodes.append(node)
    db.session.commit()
Beispiel #30
0
def switch_delete_port(switch, port):
    """Delete a port on a switch.

    If the port does not exist, a NotFoundError will be raised.
    """
    get_auth_backend().require_admin()
    switch = _must_find(model.Switch, switch)
    port = _must_find_n(switch, model.Port, port)
    if port.nic is not None:
        raise BlockedError("Port %r is attached to a nic; please detach "
                           "it first." % port.label)

    db.session.delete(port)
    db.session.commit()
Beispiel #31
0
def node_detach_network(node, nic, network):
    """Detach network ``network`` from physical nic ``nic``.

    Raises ProjectMismatchError if the node is not in a project.

    Raises BlockedError if there is already a pending network action.

    Raises BadArgumentError if the network is not attached to the nic.
    """
    auth_backend = get_auth_backend()

    node = _must_find(model.Node, node)
    network = _must_find(model.Network, network)
    nic = _must_find_n(node, model.Nic, nic)

    if not node.project:
        raise errors.ProjectMismatchError("Node not in project")
    auth_backend.require_project_access(node.project)

    if nic.current_action:
        raise errors.BlockedError(
            "A networking operation is already active on the nic.")
    attachment = model.NetworkAttachment.query \
        .filter_by(nic=nic, network=network).one_or_none()
    if attachment is None:
        raise errors.BadArgumentError(
            "The network is not attached to the nic.")

    switch = nic.port.owner
    switch.ensure_legal_operation(nic, 'detach', attachment.channel)

    db.session.add(
        model.NetworkingAction(type='modify_port',
                               nic=nic,
                               channel=attachment.channel,
                               new_network=None))
    db.session.commit()
    return '', 202
Beispiel #32
0
def network_grant_project_access(project, network):
    """Add access to <network> to <project>.

    If the project or network does not exist, a NotFoundError will be raised.
    If the project already has access to the network a DuplicateError will be
    raised.
    """
    network = _must_find(model.Network, network)
    project = _must_find(model.Project, project)
    auth_backend = get_auth_backend()

    # Must be admin or the owner of the network to add projects
    if network.owner is None:
        auth_backend.require_admin()
    else:
        auth_backend.require_project_access(network.owner)

    if project in network.access:
        raise errors.DuplicateError('Network %s is already in project %s' %
                                    (network.label, project.label))

    network.access.append(project)
    db.session.commit()
Beispiel #33
0
def node_connect_network(node, nic, network, channel=None):
    """Connect a physical NIC to a network, on channel.

    If channel is ``None``, use the allocator default.

    Raises ProjectMismatchError if the node is not in a project, or if the
    project does not have access rights to the given network.

    Raises BlockedError if there is a pending network action, or if the network
    is already attached to the nic, or if the channel is in use.

    Raises BadArgumentError if the channel is invalid for the network.
    """
    def _have_attachment(nic, query):
        """Return whether there are any attachments matching ``query`` for ``nic``.

        ``query`` should an argument suitable to pass to db.query(...).filter
        """
        return model.NetworkAttachment.query.filter(
            model.NetworkAttachment.nic == nic,
            query,
        ).first() is not None

    auth_backend = get_auth_backend()

    node = get_or_404(model.Node, node)
    nic = get_child_or_404(node, model.Nic, nic)
    network = get_or_404(model.Network, network)

    if not node.project:
        raise errors.ProjectMismatchError("Node not in project")
    auth_backend.require_project_access(node.project)

    project = node.project

    allocator = get_network_allocator()

    if nic.port is None:
        raise errors.NotFoundError("No port is connected to given nic.")

    check_pending_action(nic)

    if (network.access) and (project not in network.access):
        raise errors.ProjectMismatchError(
            "Project does not have access to given network.")

    if _have_attachment(nic, model.NetworkAttachment.network == network):
        raise errors.BlockedError(
            "The network is already attached to the nic.")

    if channel is None:
        channel = allocator.get_default_channel()

    if _have_attachment(nic, model.NetworkAttachment.channel == channel):
        raise errors.BlockedError("The channel is already in use on the nic.")

    if not allocator.is_legal_channel_for(channel, network.network_id):
        raise errors.BadArgumentError(
            "Channel %r, is not legal for this network." % channel)

    switch = nic.port.owner
    switch.ensure_legal_operation(nic, 'connect', channel)

    unique_id = str(uuid.uuid4())
    db.session.add(
        model.NetworkingAction(type='modify_port',
                               nic=nic,
                               new_network=network,
                               channel=channel,
                               uuid=unique_id,
                               status='PENDING'))
    db.session.commit()
    return json.dumps({'status_id': unique_id}), 202
Beispiel #34
0
def auth_backend():
    """Fixture returning the auth backend"""
    return get_auth_backend()
Beispiel #35
0
def node_power_off(node):
    """Power off the node."""
    node = get_or_404(model.Node, node)
    get_auth_backend().require_project_access(node.project)
    node.obm.power_off()
Beispiel #36
0
def node_connect_network(node, nic, network, channel=None):
    """Connect a physical NIC to a network, on channel.

    If channel is ``None``, use the allocator default.

    Raises ProjectMismatchError if the node is not in a project, or if the
    project does not have access rights to the given network.

    Raises BlockedError if there is a pending network action, or if the network
    is already attached to the nic, or if the channel is in use.

    Raises BadArgumentError if the channel is invalid for the network.
    """
    def _have_attachment(nic, query):
        """Return whether there are any attachments matching ``query`` for ``nic``.

        ``query`` should an argument suitable to pass to db.query(...).filter
        """
        return model.NetworkAttachment.query.filter(
            model.NetworkAttachment.nic == nic,
            query,
        ).count() != 0

    auth_backend = get_auth_backend()

    node = _must_find(model.Node, node)
    nic = _must_find_n(node, model.Nic, nic)
    network = _must_find(model.Network, network)

    if not node.project:
        raise errors.ProjectMismatchError("Node not in project")
    auth_backend.require_project_access(node.project)

    project = node.project

    allocator = get_network_allocator()

    if nic.port is None:
        raise errors.NotFoundError("No port is connected to given nic.")

    if nic.current_action:
        raise errors.BlockedError(
            "A networking operation is already active on the nic.")

    if (network.access) and (project not in network.access):
        raise errors.ProjectMismatchError(
            "Project does not have access to given network.")

    if _have_attachment(nic, model.NetworkAttachment.network == network):
        raise errors.BlockedError(
            "The network is already attached to the nic.")

    if channel is None:
        channel = allocator.get_default_channel()

    if _have_attachment(nic, model.NetworkAttachment.channel == channel):
        raise errors.BlockedError("The channel is already in use on the nic.")

    if not allocator.is_legal_channel_for(channel, network.network_id):
        raise errors.BadArgumentError(
            "Channel %r, is not legal for this network." % channel)

    db.session.add(
        model.NetworkingAction(type='modify_port',
                               nic=nic,
                               new_network=network,
                               channel=channel))
    db.session.commit()
    return '', 202
Beispiel #37
0
def set_admin_auth():
    """Set admin auth for all calls"""
    get_auth_backend().set_admin(True)
Beispiel #38
0
def auth_backend():
    return get_auth_backend()
Beispiel #39
0
def list_active_extensions():
    """List all active extensions"""
    get_auth_backend().require_admin()
    extensions = sorted([ext[0] for ext in cfg.items('extensions')])
    return json.dumps(extensions)