예제 #1
0
파일: api.py 프로젝트: djfinn14/hil
def network_delete(network):
    """Delete network.

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

    If the network is connected to nodes or headnodes, or there are pending
    network actions involving it, a BlockedError will be raised.
    """
    auth_backend = get_auth_backend()

    network = _must_find(model.Network, network)

    if network.owner is None:
        auth_backend.require_admin()
    else:
        auth_backend.require_project_access(network.owner)

    if len(network.attachments) != 0:
        raise errors.BlockedError("Network still connected to nodes")
    if network.hnics:
        raise errors.BlockedError("Network still connected to headnodes")
    if len(network.scheduled_nics) != 0:
        raise errors.BlockedError("There are pending actions on this network")
    if network.allocated:
        get_network_allocator().free_network_id(network.network_id)

    db.session.delete(network)
    db.session.commit()
예제 #2
0
파일: api.py 프로젝트: razaaliraza/hil
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 = get_or_404(model.Project, project)
    get_auth_backend().require_project_access(project)
    node = get_or_404(model.Node, node)
    if node not in project.nodes:
        raise errors.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 errors.BlockedError("Node attached to a network")
    for nic in node.nics:
        if nic.current_action is not None and \
           nic.current_action.status == 'PENDING':
            raise errors.BlockedError("Node has pending network actions")

    node.obm.stop_console()
    node.obm.delete_console()
    project.nodes.remove(node)
    _maintain(project, node, node.label)
    db.session.commit()
예제 #3
0
파일: api.py 프로젝트: razaaliraza/hil
def project_delete(project):
    """Delete project.

    If the project does not exist, a NotFoundError will be raised.
    """
    get_auth_backend().require_admin()
    project = get_or_404(model.Project, project)
    if project.nodes:
        raise errors.BlockedError("Project has nodes still")
    if project.networks_created:
        raise errors.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 errors.BlockedError("Project can still access networks")
    if project.headnodes:
        raise errors.BlockedError("Project still has a headnode")
    db.session.delete(project)
    db.session.commit()
예제 #4
0
파일: api.py 프로젝트: djfinn14/hil
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).first()
    if attachment is None:
        raise errors.BadArgumentError(
            "The network is not attached to the nic.")
    db.session.add(
        model.NetworkingAction(type='modify_port',
                               nic=nic,
                               channel=attachment.channel,
                               new_network=None))
    db.session.commit()
    return '', 202
예제 #5
0
파일: api.py 프로젝트: mikelyy/hil
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)
    if not node.obm_is_enabled():
        raise errors.BlockedError("OBM is not enabled")
    return _obmd_redirect(node, '/boot_device')
예제 #6
0
파일: api.py 프로젝트: mikelyy/hil
def network_revoke_project_access(project, network):
    """Remove access to <network> from <project>.

    If the project or network does not exist, a NotFoundError will be raised.
    If the project is the owner of the network a BlockedError will be raised.
    """
    auth_backend = get_auth_backend()
    network = get_or_404(model.Network, network)
    project = get_or_404(model.Project, project)
    # must be admin, the owner of the network, or <project> to remove
    # <project>.

    if network.access:
        if not (auth_backend.have_admin() or
                (network.owner is not None and
                    auth_backend.have_project_access(network.owner)) or
                (project in network.access and
                    auth_backend.have_project_access(project))):
            raise errors.AuthorizationError(
                "You are not authorized to remove the "
                "specified project from this network.")

    if project not in network.access:
        raise errors.NotFoundError(
            "Network %r is not in project %r" %
            (network.label, project.label))

    if project is network.owner:
        raise errors.BlockedError(
            "Project %r is owner of network %r and "
            "its access cannot be removed" % (project.label,
                                              network.label))

    # TODO: Make this and the next loop more SQLAlchemy-friendly
    for attachment in network.attachments:
        if attachment.nic.owner.project.label == project.label:
            raise errors.BlockedError(
                "Project still has node(s) attached to the network")

    for hnic in network.hnics:
        if hnic.owner.project.label == project.label:
            raise errors.BlockedError(
                "Project still has headnode(s) attached to the network")

    network.access.remove(project)
    db.session.commit()
예제 #7
0
파일: api.py 프로젝트: razaaliraza/hil
def node_delete(node):
    """Delete node.

    If the node does not exist, a NotFoundError will be raised.
    """
    get_auth_backend().require_admin()
    node = get_or_404(model.Node, node)
    if node.project:
        raise errors.BlockedError("Node %r is part of project %r; remove from "
                                  "project before deleting" %
                                  (node.label, node.project.label))
    if node.nics != []:
        raise errors.BlockedError(
            "Node %r has nics; remove them before deleting %r." %
            (node.label, node.label))
    node.obm.stop_console()
    node.obm.delete_console()
    db.session.delete(node)
    db.session.commit()
예제 #8
0
파일: api.py 프로젝트: djfinn14/hil
def switch_delete(switch):
    get_auth_backend().require_admin()
    switch = _must_find(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()
예제 #9
0
파일: api.py 프로젝트: razaaliraza/hil
def check_pending_action(nic):
    """Raises an error if the nic has a pending action
    Otherwise deletes the completed action"""
    if nic.current_action:
        if nic.current_action.status == 'PENDING':
            raise errors.BlockedError(
                "A networking operation is already active on the nic.")
        else:
            db.session.delete(nic.current_action)
    return
예제 #10
0
파일: api.py 프로젝트: mikelyy/hil
def _node_power_on_off(node, op):
    """helper for node_power_{on,off}

    This implements the actual logic for both calls. `op` should be
    one of 'on' or 'off'
    """
    node = get_or_404(model.Node, node)
    get_auth_backend().require_project_access(node.project)
    if not node.obm_is_enabled():
        raise errors.BlockedError("OBM is not enabled")
    return _obmd_redirect(node, '/power_' + op)
예제 #11
0
파일: api.py 프로젝트: mikelyy/hil
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)
    if not node.obm_is_enabled():
        raise errors.BlockedError("OBM is not enabled")
    return _obmd_redirect(node, '/power_cycle')
예제 #12
0
파일: api.py 프로젝트: razaaliraza/hil
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 = get_or_404(model.Project, project)
    get_auth_backend().require_project_access(project)
    node = get_or_404(model.Node, node)
    if node.project is not None:
        raise errors.BlockedError("Node is already owned by a project.")
    project.nodes.append(node)
    db.session.commit()
예제 #13
0
파일: api.py 프로젝트: razaaliraza/hil
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 = get_or_404(model.Switch, switch)
    port = get_child_or_404(switch, model.Port, port)
    if port.nic is not None:
        raise errors.BlockedError(
            "Port %r is attached to a nic; please detach "
            "it first." % port.label)

    db.session.delete(port)
    db.session.commit()
예제 #14
0
파일: api.py 프로젝트: djfinn14/hil
def port_revert(switch, port):
    get_auth_backend().require_admin()
    switch = _must_find(model.Switch, switch)
    port = _must_find_n(switch, model.Port, port)

    if port.nic is None:
        raise errors.NotFoundError(port.label + " not attached")
    if port.nic.current_action:
        raise errors.BlockedError("Port already has a pending action.")

    db.session.add(
        model.NetworkingAction(type='revert_port',
                               nic=port.nic,
                               channel='',
                               new_network=None))
    db.session.commit()
예제 #15
0
파일: api.py 프로젝트: razaaliraza/hil
def port_detach_nic(switch, port):
    """Detach a port from the nic it's attached to

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

    If the port is not connected to anything, a NotFoundError will be raised.

    If the port is attached to a node which is not free, a BlockedError
    will be raised.
    """
    get_auth_backend().require_admin()
    switch = get_or_404(model.Switch, switch)
    port = get_child_or_404(switch, model.Port, port)

    if port.nic is None:
        raise errors.NotFoundError(port.label + " not attached")
    if port.nic.owner.project is not None:
        raise errors.BlockedError("The port is attached to a node which is "
                                  "not free")

    port.nic = None
    db.session.commit()
예제 #16
0
파일: api.py 프로젝트: djfinn14/hil
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
예제 #17
0
파일: api.py 프로젝트: razaaliraza/hil
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