Exemple #1
0
def headnode_create(headnode, project, base_img):
    """Create headnode.

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

    If the project already has a headnode, a DuplicateError will be raised.

    If the project does not exist, a NotFoundError 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.')
    db = model.Session()

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

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

    db.add(headnode)
    db.commit()
Exemple #2
0
def project_delete(project):
    """Delete project.

    If the project does not exist, a NotFoundError will be raised.
    """
    db = model.Session()
    project = _must_find(db, 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.headnode:
        raise BlockedError("Project still has a headnode")
    db.delete(project)
    db.commit()
Exemple #3
0
def show_node(nodename):
    """Show details of a node.

    Returns a JSON object representing a node.
    The object will have at least the following fields:
        * "name", the name/label of the node (string).
        * "free", indicates whether the node is free or has been allocated
            to a project.
        * "nics", a list of nics, each represted by a JSON object having
            at least the following fields:
                - "label", the nic's label.
                - "macaddr", the nic's mac address.

    Example:  '{"name": "node1",
                "free": True,
                "nics": [{"label": "nic1", "macaddr": "01:23:45:67:89"},
                         {"label": "nic2", "macaddr": "12:34:56:78:90"}]
               }'
    """
    db = model.Session()
    node = _must_find(db, model.Node, nodename)
    return json.dumps({
        'name':
        node.label,
        'free':
        node.project_id is None,
        'nics': [{
            'label': n.label,
            'macaddr': n.mac_addr,
        } for n in node.nics],
    })
Exemple #4
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.
    """
    db = model.Session()

    headnode = _must_find(db, model.Headnode, headnode)
    hnic = _must_find_n(db, headnode, model.Hnic, hnic)
    network = _must_find(db, 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 is not None) and (network.access is not project):
        raise ProjectMismatchError(
            "Project does not have access to given network.")

    hnic.network = network
    db.commit()
Exemple #5
0
def headnode_detach_network(headnode, hnic):
    """Detach a headnode's nic from any network it's on.

    Raises IllegalStateError if the headnode has already been started.
    """
    db = model.Session()

    headnode = _must_find(db, model.Headnode, headnode)
    hnic = _must_find_n(db, headnode, model.Hnic, hnic)

    if not headnode.dirty:
        raise IllegalStateError

    if cfg.getboolean('recursive', 'rHaaS'):
        project = headnode.project.label
        bHaaS_out = check_output([
            'haas', 'headnode_detach_network', headnode.label + '_' + project,
            hnic.label + '_' + project
        ],
                                 stderr=STDOUT,
                                 shell=False)
        error_checker(bHaaS_out)

    hnic.network = None

    db.commit()
Exemple #6
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
               }'
    """
    db = model.Session()
    headnode = _must_find(db, model.Headnode, nodename)
    return json.dumps({
        'name': headnode.label,
        'project': headnode.project.label,
        'hnics': [n.label for n in headnode.hnics],
        'vncport': headnode.get_vncport(),
    })
Exemple #7
0
def headnode_delete_hnic(headnode, hnic):
    """Delete hnic on a given headnode.

    If the hnic does not exist, a NotFoundError will be raised.
    """
    db = model.Session()
    headnode = _must_find(db, model.Headnode, headnode)
    hnic = _must_find_n(db, headnode, model.Hnic, hnic)

    if not headnode.dirty:
        raise IllegalStateError
    if not hnic:
        raise NotFoundError("Hnic: " + hnic.label)

    if cfg.getboolean('recursive', 'rHaaS'):
        project = headnode.project.label
        bHaaS_out = check_output([
            'haas', 'headnode_delete_hnic', headnode.label + '_' + project,
            hnic.label + '_' + project
        ],
                                 stderr=STDOUT,
                                 shell=False)
        error_checker(bHaaS_out)

    db.delete(hnic)
    db.commit()
Exemple #8
0
def headnode_create_hnic(headnode, hnic):
    """Create hnic attached to given headnode.

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

    If there is already an hnic with that name, a DuplicateError will
    be raised.
    """
    db = model.Session()
    headnode = _must_find(db, model.Headnode, headnode)
    _assert_absent_n(db, headnode, model.Hnic, hnic)

    if not headnode.dirty:
        raise IllegalStateError

    hnic = model.Hnic(headnode, hnic)
    db.add(hnic)

    if cfg.getboolean('recursive', 'rHaaS'):
        project = headnode.project.label
        bHaaS_out = check_output([
            'haas', 'headnode_create_hnic', headnode.label + '_' + project,
            hnic.label + '_' + project
        ],
                                 stderr=STDOUT,
                                 shell=False)
        error_checker(bHaaS_out)

    db.commit()
Exemple #9
0
def headnode_start(headnode):
    """Start the headnode.

    This actually boots up the headnode virtual machine. The VM is created
    within libvirt if needed. Once the VM has been started once, it is
    "frozen," and all other headnode-related api calls will fail (by raising
    an IllegalStateException), with the exception of headnode_stop.
    """
    db = model.Session()
    headnode = _must_find(db, model.Headnode, headnode)

    if cfg.getboolean('recursive', 'rHaaS'):
        bHaaS_out = check_output([
            'haas', 'headnode_start',
            headnode.label + '_' + headnode.project.label
        ],
                                 stderr=STDOUT,
                                 shell=False)
        error_checker(bHaaS_out)
        #TODO: is there some way to record headnode.dirty on the rHaaS database also? headnode.dirty = False breaks things

    else:
        if headnode.dirty:
            headnode.create()
        headnode.start()

    db.commit()
Exemple #10
0
def node_detach_network(node, nic):
    """Detach a physical nic from any network it's on.

    Raises ProjectMismatchError if the node is not in a project.
    """
    db = model.Session()
    node = _must_find(db, model.Node, node)
    nic = _must_find_n(db, node, model.Nic, nic)

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

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

    if cfg.getboolean('recursive', 'rHaaS'):
        bHaaS_out = check_output(
            ['haas', 'node_detach_network', node.label, nic.label],
            stderr=STDOUT,
            shell=False)
        error_checker(bHaaS_out)

    db.add(model.NetworkingAction(nic, None))
    db.commit()
Exemple #11
0
def node_connect_network(node, nic, network):
    """Connect a physical NIC to a network.

    Raises ProjectMismatchError if the node is not in a project, or if the
    project does not have access rights to the given network.
    """
    db = model.Session()

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

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

    project = node.project

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

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

    db.add(model.NetworkingAction(nic, network))
    db.commit()
Exemple #12
0
def user_delete(user):
    """Delete user.

    If the user does not exist, a NotFoundError will be raised.
    """
    db = model.Session()
    user = _must_find(db, model.User, user)
    db.delete(user)
    db.commit()
Exemple #13
0
def node_delete_nic(node, nic):
    """Delete nic with given name.

    If the nic does not exist, a NotFoundError will be raised.
    """
    db = model.Session()
    nic = _must_find_n(db, _must_find(db, model.Node, node), model.Nic, nic)
    db.delete(nic)
    db.commit()
Exemple #14
0
def show_console(nodename):
    """Show the contents of the console log."""
    db = model.Session()
    node = _must_find(db, model.Node, nodename)
    log = node.get_console()
    if log is None:
        raise NotFoundError('The console log for %s '
                            'does not exist.' % nodename)
    return log
Exemple #15
0
def network_create(network, creator, access, net_id):
    """Create a network.

    If the network with that name already exists, a DuplicateError will be
    raised.

    If the combination of creator, access, and net_id is illegal, a
    BadArgumentError will be raised.

    If network ID allocation was requested, and the network cannot be
    allocated (due to resource exhaustion), an AllocationError will be raised.

    Pass 'admin' as creator for an administrator-owned network.  Pass '' as
    access for a publicly accessible network.  Pass '' as net_id if you wish
    to use the HaaS's network-id allocation pool.

    Details of the various combinations of network attributes are in
    docs/networks.md
    """
    db = model.Session()
    _assert_absent(db, model.Network, network)

    # Check legality of arguments, and find correct 'access' and 'creator'
    if creator != "admin":
        # Project-owned network
        if access != creator:
            raise BadArgumentError(
                "Project-created networks must be accessed only by that project."
            )
        if net_id != "":
            raise BadArgumentError(
                "Project-created networks must use network ID allocation")
        creator = _must_find(db, model.Project, creator)
        access = _must_find(db, model.Project, access)
    else:
        # Administrator-owned network
        creator = None
        if access == "":
            access = None
        else:
            access = _must_find(db, model.Project, access)

    # Allocate net_id, if requested
    if net_id == "":
        driver_name = cfg.get('general', 'driver')
        driver = importlib.import_module('haas.drivers.' + driver_name)
        net_id = driver.get_new_network_id(db)
        if net_id is None:
            raise AllocationError('No more networks')
        allocated = True
    else:
        allocated = False

    network = model.Network(creator, access, allocated, net_id, network)
    db.add(network)
    db.commit()
Exemple #16
0
def user_create(user, password):
    """Create user with given password.

    If the user already exists, a DuplicateError will be raised.
    """
    db = model.Session()
    _assert_absent(db, model.User, user)
    user = model.User(user, password)
    db.add(user)
    db.commit()
Exemple #17
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.
    """
    db = model.Session()
    headnode = _must_find(db, model.Headnode, headnode)
    headnode.stop()
Exemple #18
0
def project_create(project):
    """Create a project.

    If the project already exists, a DuplicateError will be raised.
    """
    db = model.Session()
    _assert_absent(db, model.Project, project)
    project = model.Project(project)
    db.add(project)
    db.commit()
Exemple #19
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.
    """
    db = model.Session()
    project = _must_find(db, model.Project, project)
    node = _must_find(db, model.Node, node)
    project.nodes.append(node)
    db.commit()
Exemple #20
0
def node_register(node, ipmi_host, ipmi_user, ipmi_pass):
    """Create node.

    If the node already exists, a DuplicateError will be raised.
    """
    db = model.Session()
    _assert_absent(db, model.Node, node)
    node = model.Node(node, ipmi_host, ipmi_user, ipmi_pass)
    db.add(node)
    db.commit()
Exemple #21
0
def node_delete(node):
    """Delete node.

    If the node does not exist, a NotFoundError will be raised.
    """
    db = model.Session()
    node = _must_find(db, model.Node, node)
    node.stop_console()
    node.delete_console()
    db.delete(node)
    db.commit()
Exemple #22
0
def list_free_nodes():
    """List all nodes not in any project.

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

    Example:  '["node1", "node2", "node3"]'
    """
    db = model.Session()
    nodes = db.query(model.Node).filter_by(project_id=None).all()
    nodes = [n.label for n in nodes]
    return json.dumps(nodes)
Exemple #23
0
def start_console(nodename):
    """Start logging output from the console."""
    db = model.Session()
    node = _must_find(db, model.Node, nodename)
    if cfg.getboolean('recursive', 'rHaaS'):
        bHaaS_out = check_output(['haas', 'start_console', node.label],
                                 stderr=STDOUT,
                                 shell=False)
        error_checker(bHaaS_out)
    else:
        node.start_console()
Exemple #24
0
def list_projects():
    """List all projects.

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

    Example:  '["project1", "project2", "project3"]'
    """
    db = model.Session()
    projects = db.query(model.Project).all()
    projects = [p.label for p in projects]
    return json.dumps(projects)
Exemple #25
0
def port_delete(port):
    """Delete a port on a switch.

    If the port does not exist, a NotFoundError will be raised.
    """
    db = model.Session()

    port = _must_find(db, model.Port, port)

    db.delete(port)
    db.commit()
Exemple #26
0
def list_nodes():
    """List all nodes.

    Returns a JSON array of strings representing a list of projects.
    Example:  '["node1", "node2", "node3"]'

    """
    db = model.Session()
    nodes = db.query(model.Node).all()
    nodes = [n.label for n in nodes]
    return json.dumps(nodes)
Exemple #27
0
def list_project_headnodes(project):
    """Show the headnode belonging the given project.

    Returns a JSON representation of headnode.

    Example:  '["headnode1", "headnode2", "headnode3"]'
    """
    db = model.Session()
    project = _must_find(db, model.Project, project)
    headnodes = project.headnode
    headnodes = [h.label for h in headnodes]
    return json.dumps(headnodes)
Exemple #28
0
def port_register(port):
    """Register a port on a switch.

    If the port already exists, a DuplicateError will be raised.
    """
    db = model.Session()

    _assert_absent(db, model.Port, port)
    port = model.Port(port)

    db.add(port)
    db.commit()
Exemple #29
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"]'
    """
    db = model.Session()
    project = _must_find(db, model.Project, project)
    networks = project.networks_access
    networks = [n.label for n in networks]
    return json.dumps(networks)
Exemple #30
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"]'
    """
    db = model.Session()
    project = _must_find(db, model.Project, project)
    nodes = project.nodes
    nodes = [n.label for n in nodes]
    return json.dumps(nodes)