Exemplo n.º 1
0
def _maintain(project, node, node_label):
    """Helper function to execute maintenance tasks.
    Powers off the node, checks for the existence of maintenance pool
    config options, and posts to the maintenance URL if
    they exist."""
    logger = logging.getLogger(__name__)
    if (cfg.has_option('maintenance', 'maintenance_project')
            and cfg.has_option('maintenance', 'url')):
        maintenance_proj = get_or_404(
            model.Project, cfg.get('maintenance', 'maintenance_project'))
        if (project == maintenance_proj):
            # Already in maintenance pool
            return
    elif (cfg.has_option('maintenance', 'maintenance_project')):
        raise errors.NotFoundError("Maintenance URL not in hil.cfg.")
    elif (cfg.has_option('maintenance', 'url')):
        raise errors.NotFoundError("Maintenance project not in hil.cfg.")
    else:
        return

    if (cfg.has_option('maintenance', 'shutdown')):
        node.obm.power_off()
    maintenance_proj.nodes.append(node)
    url = cfg.get('maintenance', 'url')
    payload = json.dumps({'node': node_label})
    try:
        response = requests.post(url,
                                 headers={'Content-Type': 'application/json'},
                                 data=payload)
    except requests.ConnectionError:
        logger.warn('POST to maintenance service' ' failed: connection failed')
    if (not 200 <= response < 300):
        logger.warn('POST to maintenance service'
                    ' failed with response: %s', response.text)
Exemplo n.º 2
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 = 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()
Exemplo n.º 3
0
def show_networking_action(status_id):
    """Returns the status of the networking action by finding the status_id
    in the networking actions table.
    """
    action = model.NetworkingAction.query.filter_by(uuid=status_id).first()
    if action is None:
        raise errors.NotFoundError('status_id not found')

    project = action.nic.owner.project
    get_auth_backend().require_project_access(project)

    action_info = {
        'status': action.status,
        'node': action.nic.owner.label,
        'nic': action.nic.label,
        'type': action.type,
        'channel': action.channel
    }

    if action.new_network is None:
        action_info['new_network'] = None
    else:
        action_info['new_network'] = action.new_network.label

    return json.dumps(action_info)
Exemplo n.º 4
0
def show_console(nodename):
    """Show the contents of the console log."""
    node = get_or_404(model.Node, nodename)
    log = node.obm.get_console()
    if log is None:
        raise errors.NotFoundError('The console log for %s does not exist.' %
                                   nodename)
    return log
Exemplo n.º 5
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._must_find(User, user)
    project = api._must_find(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()
Exemplo n.º 6
0
Arquivo: api.py Projeto: 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()
Exemplo n.º 7
0
Arquivo: api.py Projeto: 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()
Exemplo n.º 8
0
def get_or_404(cls, name):
    """Raises a NotFoundError if the given object doesn't exist in the datbase.
    Otherwise returns the object

    This is useful for most of the *_delete functions.

    Arguments:

    cls - the class of the object to query.
    name - the name of the object in question.

    Must be called within a request context.
    """
    obj = db.session.query(cls).filter_by(label=name).first()
    if not obj:
        raise errors.NotFoundError("%s %s does not exist." %
                                   (cls.__name__, name))
    return obj
Exemplo n.º 9
0
def get_child_or_404(obj_outer, cls_inner, name_inner):
    """Searches the database for a "namespaced" object, such as a nic on a node.

    Raises NotFoundError if there is none.  Otherwise returns the object.

    Arguments:

    obj_outer - the "owner" object
    cls_inner - the "owned" class
    name_inner - the name of the "owned" object

    Must be called within a request context.
    """
    obj_inner = _namespaced_query(obj_outer, cls_inner, name_inner)
    if obj_inner is None:
        raise errors.NotFoundError(
            "%s %s on %s %s does not exist." %
            (cls_inner.__name__, name_inner, obj_outer.__class__.__name__,
             obj_outer.label))
    return obj_inner
Exemplo n.º 10
0
def port_revert(switch, port):
    """Detach the port from all networks."""
    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")
    check_pending_action(port.nic)
    unique_id = str(uuid.uuid4())

    action = model.NetworkingAction(type='revert_port',
                                    nic=port.nic,
                                    channel='',
                                    uuid=unique_id,
                                    status='PENDING',
                                    new_network=None)

    db.session.add(action)
    db.session.commit()
    return json.dumps({'status_id': unique_id})
Exemplo n.º 11
0
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()
Exemplo n.º 12
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
Exemplo n.º 13
0
Arquivo: api.py Projeto: 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