示例#1
0
def test_sending_requests_without_auth_token(controller_url: str):
    client_library = ClientLibrary(controller_url,
                                   username="******",
                                   password="******",
                                   ssl_verify=False,
                                   allow_http=True)

    # it probably won't be a common case to override `auth` by ClientLibrary users
    # but missing auth token may happen when using API directly via HTTP:
    client_library.session.auth = None
    with pytest.raises(requests.exceptions.HTTPError) as exc:
        client_library.create_lab()
    exc.match('401 Client Error: Unauthorized for url')
示例#2
0
def test_server_node_deletion(client_library: ClientLibrary):
    lab = client_library.create_lab("lab_1")

    lab.auto_sync = False

    s1 = lab.create_node("s1", "server", 5, 100)
    s2 = lab.create_node("s2", "server", 102, 201)

    s1_iface = lab.create_interface(s1, 2)
    s2_iface = lab.create_interface(s2, 2)
    lab.create_link(s1_iface, s2_iface)

    lab.start()

    s3 = lab.create_node("s3", "server", 200, 400)
    s3_iface = lab.create_interface(s3)

    s2.stop()

    lab.create_link(s2.interfaces()[0], s3_iface)

    lab.start()

    # can't remove node while running
    with pytest.raises(requests.exceptions.HTTPError) as exc:
        lab.remove_node(s3)
    assert exc.value.response.status_code == 403

    # need to stop and wipe to be able to remove node.
    s3.stop()
    s3.wipe()
    lab.remove_node(s3)
示例#3
0
def test_lab_state(client_library: ClientLibrary):
    lab = client_library.create_lab("lab_1")

    s1 = lab.create_node("s1", "server", 5, 100)
    s2 = lab.create_node("s2", "server", 102, 201)

    s1_iface = lab.create_interface(s1, 2)
    s2_iface = lab.create_interface(s2, 2)
    lab.create_link(s1_iface, s2_iface)

    state = lab.state()
    assert state == "DEFINED_ON_CORE"

    lab.start()
    state = lab.state()
    assert state == "STARTED"

    assert lab.is_active()

    lab.stop()
    state = lab.state()
    assert state == "STOPPED"

    lab.wipe()
    state = lab.state()
    assert state == "DEFINED_ON_CORE"
示例#4
0
def test_connect(client_library: ClientLibrary):
    lab = client_library.create_lab("my lab name")
    lab = client_library.join_existing_lab(lab.id)

    lab.auto_sync = False

    s1 = lab.create_node("s1", "server", 50, 100)
    s2 = lab.create_node("s2", "server", 50, 200)
    print(s1, s2)

    # create a link between s1 and s2
    s1_i1 = s1.create_interface()
    s2_i1 = s2.create_interface()
    lab.create_link(s1_i1, s2_i1)

    # this must remove the link between s1 and s2
    lab.remove_node(s2)

    lab.sync_states()
    for node in lab.nodes():
        print(node, node.state)
        for iface in node.interfaces():
            print(iface, iface.state)

    assert [link for link in lab.links() if link.state is not None] == []
示例#5
0
def test_lab_details(client_library: ClientLibrary):
    lab = client_library.create_lab("lab_1")

    s1 = lab.create_node("s1", "server", 5, 100)
    s2 = lab.create_node("s2", "server", 102, 201)

    s1_iface = lab.create_interface(s1, 2)
    s2_iface = lab.create_interface(s2, 2)
    lab.create_link(s1_iface, s2_iface)

    expected_keys = (
        "state",
        "created",
        "lab_title",
        "lab_description",
        "node_count",
        "link_count",
        "id",
    )

    details = lab.details()
    assert all(k in details.keys() for k in expected_keys)
    assert details["node_count"] == 2
    assert details["link_count"] == 1
    assert details["state"] == "DEFINED_ON_CORE"
示例#6
0
def test_node_with_unavailable_vnc(client_library: ClientLibrary):
    lab = client_library.create_lab("lab_111")
    node = lab.create_node("s1", "unmanaged_switch", 5, 100)
    lab.start()
    assert lab.state() == "STARTED"
    with pytest.raises(requests.exceptions.HTTPError) as err:
        node.vnc_key()
    assert err.value.response.status_code == 404
def test_link_conditioning(register_licensing,
                           client_library_keep_labs: ClientLibrary):
    lab = client_library_keep_labs.create_lab()

    alpine = lab.create_node("alpine-0", "alpine", 0, 0)
    ums = lab.create_node("unmanaged-switch-0", "unmanaged_switch", 100, 0)
    ext = lab.create_node("ext", "external_connector", 200, 0)

    lab.connect_two_nodes(alpine, ums)
    lab.connect_two_nodes(ums, ext)

    lab.start(wait=True)

    alpine = lab.get_node_by_label("alpine-0")
    ums = lab.get_node_by_label("unmanaged-switch-0")
    link = lab.get_link_by_nodes(alpine, ums)

    pylab = ClPyats(lab)
    pylab.sync_testbed("cml2", "cml2cml2")

    # ensure there's no link condition
    result = link.get_condition()
    assert result is None

    # remove, just to be sure
    link.remove_condition()
    result = pylab.run_command("alpine-0", "time ping -Aqc100  192.168.255.1")
    check_result(result, False, 0.0, 10.0)

    # link.set_condition_by_name("dsl1")

    # 2mbps, 50ms delay, 0ms jitter, 5.1% loss)
    # 5.1 to ensure that the float is understood and returned
    link.set_condition(2000, 50, 0, 5.1)

    result = link.get_condition()
    assert result == {
        "bandwidth": 2000,
        "latency": 50,
        "loss": 5.1,
        "jitter": 0
    }

    result = pylab.run_command("alpine-0", "time ping -Aqc100 192.168.255.1")
    check_result(result, True, 90.0, 110.0)

    link.remove_condition()
    result = pylab.run_command("alpine-0", "time ping -Aqc100  192.168.255.1")
    check_result(result, False, 0.0, 10.0)

    lab.stop()
    lab.wipe()
    lab.remove()
示例#8
0
def test_sync_lab(register_licensing, client_library: ClientLibrary):
    lab = client_library.create_lab("my test lab name")
    lab = client_library.join_existing_lab(lab.id)

    r1 = lab.create_node("r1", "server", 5, 100)
    r2 = lab.create_node("r2", "server", 102, 201)
    r3 = lab.create_node("r3", "server", 200, 400)
    # print(r1, r2, r3)

    r1.x = 400
    r1.label = "abc"

    r1_i1 = r1.create_interface()
    r1_i2 = r1.create_interface()

    r2_i1 = r2.create_interface()
    r2_i2 = r2.create_interface()

    r3_i1 = r3.create_interface()
    r3_i2 = r3.create_interface()

    #
    lab.create_link(r1_i1, r2_i1)
    lab.create_link(r2_i2, r3_i1)
    lab.create_link(r3_i2, r1_i2)

    r1.start()
    r2.start()
    r3.start()

    # lab.stop()
    r1.stop()
    r2.stop()
    r3.stop()

    # lab.remove_link(link_1)
    # lab.remove_link(link_2)
    # lab.remove_link(link_3)
    # lab.remove_node(r1)
    # lab.remove_node(r2)
    # lab.remove_node(r3)

    # TODO: wait for convergence here
    lab.stop()
示例#9
0
def test_node_console_logs(client_library_session: ClientLibrary):
    lab = client_library_session.create_lab("lab_space")
    ext_conn = lab.create_node("ec", "external_connector", 100, 50, wait=False)
    server = lab.create_node("s1", "server", 100, 100)
    iosv = lab.create_node("n", "iosv", 50, 0)
    lab.start()
    assert lab.state() == "STARTED"
    # server has one serial console on id 0
    logs = server.console_logs(console_id=0)
    assert type(logs) == str

    # external connector - no serial console
    with pytest.raises(requests.exceptions.HTTPError) as err:
        ext_conn.console_logs(console_id=0)
    assert err.value.response.status_code == 400
    assert "Serial port does not exist on node" in err.value.response.text

    # test limited number of lines
    num_lines = 5
    logs = server.console_logs(console_id=0, lines=num_lines)
    assert type(logs) == str
    assert len(logs.split("\n")) == num_lines

    # assert 400 for non existent console id for server >0
    with pytest.raises(requests.exceptions.HTTPError) as err:
        server.console_logs(console_id=55)
    assert err.value.response.status_code == 400
    assert "Serial port does not exist on node" in err.value.response.text

    # iosv has 2 serial consoles
    logs = iosv.console_logs(console_id=0)
    assert type(logs) == str
    logs = iosv.console_logs(console_id=1)
    assert type(logs) == str
    with pytest.raises(requests.exceptions.HTTPError) as err:
        iosv.console_logs(console_id=2)
    assert err.value.response.status_code == 400
    assert "Serial port does not exist on node" in err.value.response.text

    lab.stop()
    lab.wipe()
    lab.remove()
class DSTTopology(object):
    __client = None
    __lab = None

    __started = False
    __wiped = True

    __base_config_dir = None

    __nodes = {
        "Internet Router": {
            "type": "iosv",
            "node": None,
            "config": "internet_router.txt"
        },
        "HQ Firewall": {
            "type": "asav",
            "node": None,
            "config": "hq_firewall.txt"
        },
        "HQ Switch": {
            "type": "unmanaged_switch",
            "node": None
        },
        "HQ Server": {
            "type": "ubuntu",
            "node": None,
            "config": "hq_server.txt"
        },
        "Internet": {
            "type": "external_connector",
            "node": None
        },
        "OOB Management": {
            "type": "external_connector",
            "node": None,
            "config": "oob_management.txt"
        },
    }

    def __init__(self, cml_controller, base_config_dir):
        self.__base_config_dir = base_config_dir

        ssl_cert = False

        if "CA_BUNDLE" in os.environ:
            ssl_cert = os.environ["CA_BUNDLE"]

        # Create a client and use the environment to provide the username, password, and CA bundle
        self.__client = ClientLibrary(cml_controller, ssl_verify=ssl_cert)

    @staticmethod
    def __get_lab_suffix():
        return "".join(
            random.choice(string.ascii_lowercase + string.digits)
            for i in range(8))

    def __create_lab(self):
        # Wait for the low-level drive to connect
        self.__client.wait_for_lld_connected()

        lab_prefix = "Dynamic Split Tunnel Test-"
        lab_suffix = DSTTopology.__get_lab_suffix()

        # Find a unique name for this lab
        while True:
            labs = self.__client.find_labs_by_title(lab_prefix + lab_suffix)
            if labs is not None and len(labs) > 0:
                lab_suffix = DSTTopology.__get_lab_suffix()
            else:
                break

        self.__lab = self.__client.create_lab(title=lab_prefix + lab_suffix)
        self.__lab.description = "This lab is for testing a Dynamic Split Tunnel config change (created at: {ctime})".format(
            ctime=time.ctime())
        self.__lab.wait_for_convergence = False

    def __add_nodes(self):
        # Create each node
        for node in list(self.__nodes.keys()):
            self.__nodes[node]["node"] = self.__lab.create_node(
                node, self.__nodes[node]["type"], populate_interfaces=True)

    def __connect_nodes(self):
        """
        Connect all nodes in the test topology is a known, static way.
        """

        # First connect Gi0/0 of the Internet Router to the Internet
        igi0 = self.__nodes["Internet Router"]["node"].get_interface_by_label(
            "GigabitEthernet0/0")
        iport = self.__nodes["Internet"]["node"].get_interface_by_label("port")
        self.__lab.create_link(igi0, iport)

        # Next connect Gi0/1 of the Internet Router to Gi0/0 of the HQ Firewall
        igi1 = self.__nodes["Internet Router"]["node"].get_interface_by_label(
            "GigabitEthernet0/1")
        fgi0 = self.__nodes["HQ Firewall"]["node"].get_interface_by_label(
            "GigabitEthernet0/0")
        self.__lab.create_link(igi1, fgi0)

        # Next connect Gi0/1 of the HQ Firewall to port0 of the HQ Switch
        # ...But before we can do that, we need to add a new interface.
        self.__nodes["HQ Firewall"]["node"].create_interface()
        fgi1 = self.__nodes["HQ Firewall"]["node"].get_interface_by_label(
            "GigabitEthernet0/1")
        sport0 = self.__nodes["HQ Switch"]["node"].get_interface_by_label(
            "port0")
        self.__lab.create_link(fgi1, sport0)

        # Next connect Management0/0 of HQ Firewall to the OOB Management network
        fm0 = self.__nodes["HQ Firewall"]["node"].get_interface_by_label(
            "Management0/0")
        oport = self.__nodes["OOB Management"]["node"].get_interface_by_label(
            "port")
        self.__lab.create_link(fm0, oport)

        # Next connect port1 of HQ Switch to port enp0s2 of the HQ Server
        sport1 = self.__nodes["HQ Switch"]["node"].get_interface_by_label(
            "port1")
        seth = self.__nodes["HQ Server"]["node"].get_interface_by_label(
            "enp0s2")
        self.__lab.create_link(sport1, seth)

    def __configure_nodes(self):
        for node, properties in list(self.__nodes.items()):
            if "config" in properties:
                config = self.__base_config_dir + "/" + properties["config"]
                if not os.path.exists(config):
                    raise FileNotFoundError(config)

                with open(config, "r") as fd:
                    conf_contents = fd.read()
                    properties["node"].config = conf_contents

    def create_topology(self):
        """
        Create a DST test topology and configure it.
        """

        self.__create_lab()
        self.__add_nodes()
        self.__connect_nodes()
        self.__configure_nodes()

    def start(self):
        """
        Start the DST test lab.
        """

        if self.__started:
            return

        self.__lab.start()
        self.__started = True
        self.__wiped = False

    def stop(self):
        """
        Stop the DST test lab.
        """

        if not self.__started:
            return

        self.__lab.stop(wait=True)
        self.__started = False

    def is_ready(self):
        """
        Check if the overall lab is ready.

        Returns:
            Boolean: True if all nodes have converged, False otherwise.
        """

        if not self.__started:
            raise Exception("Lab has not been started yet.")

        ready = True
        for node, properties in list(self.__nodes.items()):
            if not properties["node"].has_converged(
            ) or properties["node"].has_converged(
            ) == 0 or not properties["node"].is_booted():
                ready = False
                break

        return ready

    def get_fw_ip(self, wait=False):
        """
        Return the IP address of the OOB Management interface on the firewall node.

        Parameters:
            wait (Boolean): Whether or not to wait for the firewall node to converge (default: False)

        Returns:
            string: The first IP address on Management0/0 if found, else None
        """

        if not self.__started:
            raise Exception("Lab has not been started yet.")

        if not wait and not self.__nodes["HQ Firewall"]["node"].has_converged(
        ):
            raise Exception("Firewall node has not yet converged.")
        elif not self.__nodes["HQ Firewall"]["node"].has_converged():
            while not self.__nodes["HQ Firewall"]["node"].has_converged():
                time.sleep(1)

        fm0 = self.__nodes["HQ Firewall"]["node"].get_interface_by_label(
            "Management0/0")
        ip4_addr = fm0.discovered_ipv4
        if len(ip4_addr) > 0:
            return ip4_addr[0]

        return None

    def wipe(self):
        """
        Wipe the DST test lab
        """

        if self.__started:
            raise Exception("Lab must be stopped first.")

        self.__lab.wipe(wait=True)
        self.__wiped = True

    def remove(self):
        """
        Remove the lab from the CML controller.
        """

        if not self.__wiped:
            raise Exception("Lab must be wiped before it can be removed.")

        self.__lab.remove()
示例#11
0
def test_group_api_permissions(controller_url,
                               client_library_session: ClientLibrary):
    cl_admin = client_library_session
    # create non-admin user
    username = "******"
    satoshi_pwd = "super-secret-pwd"
    satoshi = cl_admin.user_management.create_user(username=username,
                                                   pwd=satoshi_pwd)
    halfinn = cl_admin.user_management.create_user(username="******",
                                                   pwd=satoshi_pwd)
    satoshi_uid = satoshi["id"]
    cml2_uid = client_library_session.user_management.user_id(username="******")
    halfinn_uid = client_library_session.user_management.user_id(
        username="******")
    # assert there is no lab
    assert cl_admin.all_labs(show_all=True) == []
    # create lab
    lab0 = cl_admin.create_lab(title="lab0")
    lab1 = cl_admin.create_lab(title="lab1")
    # create students group
    lab0_ro = [{"id": lab0.id, "permission": "read_only"}]
    lab0_1_rw = [
        {
            "id": lab0.id,
            "permission": "read_write"
        },
        {
            "id": lab1.id,
            "permission": "read_write"
        },
    ]
    students_group = cl_admin.group_management.create_group(
        name="students",
        description="students group",
        members=[satoshi_uid],
        labs=lab0_ro,
    )
    teachers_group = cl_admin.group_management.create_group(
        name="teachers",
        description="teachers group",
        members=[],
        labs=lab0_1_rw)
    all_groups = cl_admin.group_management.groups()
    assert len(all_groups) == 2
    all_groups_names = [group["id"] for group in all_groups]
    assert students_group["id"] in all_groups_names
    assert teachers_group["id"] in all_groups_names

    # log in as non-admin satoshi user
    cl_satoshi = ClientLibrary(
        controller_url,
        username=username,
        password=satoshi_pwd,
        ssl_verify=False,
        allow_http=True,
    )
    # satoshi must only see groups that he is part of
    satoshi_groups = cl_satoshi.group_management.groups()
    assert len(satoshi_groups) == 1
    assert satoshi_groups[0]["name"] == "students"
    assert cl_satoshi.user_management.user_groups(user_id=satoshi_uid) == [
        students_group["id"]
    ]

    # cannot check other user info
    with pytest.raises(requests.exceptions.HTTPError) as err:
        cl_satoshi.user_management.user_groups(user_id=cml2_uid)
    assert err.value.response.status_code == 403
    assert "User does not have required access" in err.value.response.text

    # user cannot see groups he is not part of
    with pytest.raises(requests.exceptions.HTTPError) as err:
        cl_satoshi.group_management.get_group(group_id=teachers_group["id"])
    assert err.value.response.status_code == 403
    assert "User does not have required access" in err.value.response.text
    # can see those where he is member
    students_group = cl_satoshi.group_management.get_group(
        group_id=students_group["id"])
    assert students_group["members"] == [satoshi_uid]
    # only admin can create, delete and modify group
    # create
    with pytest.raises(requests.exceptions.HTTPError) as err:
        cl_satoshi.group_management.create_group(name="xxx")
    assert err.value.response.status_code == 403
    assert "User does not have required access" in err.value.response.text
    # update
    with pytest.raises(requests.exceptions.HTTPError) as err:
        cl_satoshi.group_management.update_group(group_id=teachers_group["id"],
                                                 description="new")
    assert err.value.response.status_code == 403
    assert "User does not have required access" in err.value.response.text
    # delete
    with pytest.raises(requests.exceptions.HTTPError) as err:
        cl_satoshi.group_management.delete_group(group_id=teachers_group["id"])
    assert err.value.response.status_code == 403
    assert "User does not have required access" in err.value.response.text
    # user cannot see members of group that he is not part of
    with pytest.raises(requests.exceptions.HTTPError) as err:
        cl_satoshi.group_management.group_members(
            group_id=teachers_group["id"])
    assert err.value.response.status_code == 403
    assert "User does not have required access" in err.value.response.text
    # can see those where he is member
    students_group_members = cl_satoshi.group_management.group_members(
        group_id=students_group["id"])
    assert students_group_members == [satoshi_uid]
    # user cannot see labs of group that he is not part of
    with pytest.raises(requests.exceptions.HTTPError) as err:
        cl_satoshi.group_management.group_labs(group_id=teachers_group["id"])
    assert err.value.response.status_code == 403
    assert "User does not have required access" in err.value.response.text
    # can see those where he is member
    students_group_labs = cl_satoshi.group_management.group_labs(
        group_id=students_group["id"])
    assert students_group_labs == [lab0.id]

    # we need to get lab objects again so that they are bound to satoshi user
    lab0 = cl_satoshi.find_labs_by_title(title="lab0")[0]
    # satishi can only see groups where he is a member - in this case students
    assert lab0.groups == [
        {
            "id": students_group["id"],
            "permission": "read_only"
        },
    ]
    # we cannot modify groups associations as satoshi is not owner or admin
    with pytest.raises(requests.exceptions.HTTPError) as err:
        lab0.update_lab_groups(group_list=[])
    assert err.value.response.status_code == 403
    assert "User does not have required access" in err.value.response.text

    # we cannot modify notes
    with pytest.raises(requests.exceptions.HTTPError) as err:
        lab0.notes = "new note"
    assert err.value.response.status_code == 403
    assert "User does not have write permission to lab" in err.value.response.text

    # we cannot modify description
    with pytest.raises(requests.exceptions.HTTPError) as err:
        lab0.description = "new description"
    assert err.value.response.status_code == 403
    assert "User does not have write permission to lab" in err.value.response.text

    # change students association to lab0 to read_write
    assert cl_admin.group_management.update_group(
        group_id=students_group["id"],
        labs=[{
            "id": lab0.id,
            "permission": "read_write"
        }],
    )
    # now user can perform writes to associated lab
    lab0.notes = "new note"
    assert lab0.notes == "new note"
    lab0.description = "new description"
    assert lab0.description == "new description"
    # get students groups association to lab0 back to read only
    # satoshi cannot - he is not admin or owner
    with pytest.raises(requests.exceptions.HTTPError) as err:
        lab0.update_lab_groups(group_list=[
            {
                "id": students_group["id"],
                "permission": "read_only"
            },
        ])
    assert err.value.response.status_code == 403
    assert "User does not have required access" in err.value.response.text
    # admin can
    lab0 = cl_admin.find_labs_by_title(title="lab0")[0]
    lab0.update_lab_groups(group_list=[
        {
            "id": students_group["id"],
            "permission": "read_only"
        },
    ])
    lab0 = cl_satoshi.find_labs_by_title(title="lab0")[0]
    assert lab0.groups == [
        {
            "id": students_group["id"],
            "permission": "read_only"
        },
    ]
    # add teachers group rw association to lab0 (admin action)
    teachers_group = cl_admin.group_management.update_group(
        group_id=teachers_group["id"], labs=lab0_1_rw)
    # we cannot modify groups associations as satoshi is not admin or owner
    with pytest.raises(requests.exceptions.HTTPError) as err:
        lab0.update_lab_groups(group_list=[])
    assert err.value.response.status_code == 403
    assert "User does not have required access" in err.value.response.text

    # we cannot modify notes
    with pytest.raises(requests.exceptions.HTTPError) as err:
        lab0.notes = "new note"
    assert err.value.response.status_code == 403
    assert "User does not have write permission to lab" in err.value.response.text

    # we cannot modify description
    with pytest.raises(requests.exceptions.HTTPError) as err:
        lab0.description = "new description"
    assert err.value.response.status_code == 403
    assert "User does not have write permission to lab" in err.value.response.text

    # as satoshi has no access to lab1 - below list is empty
    assert cl_satoshi.find_labs_by_title(title="lab1") == []
    # add satoshi to teachers group - by doing this now he gains read write
    # access to both ;ab0 and lab1
    cl_admin.group_management.update_group(group_id=teachers_group["id"],
                                           members=[satoshi_uid])
    # now we can access teachers group and related data
    assert cl_satoshi.group_management.get_group(group_id=teachers_group["id"])
    assert cl_satoshi.group_management.group_members(
        group_id=teachers_group["id"]) == [satoshi_uid]
    assert (len(
        cl_satoshi.group_management.group_labs(
            group_id=teachers_group["id"])) == 2)
    user_groups = cl_satoshi.user_management.user_groups(user_id=satoshi_uid)
    assert students_group["id"] in user_groups and teachers_group[
        "id"] in user_groups
    associated_groups_names = [
        group["name"] for group in cl_satoshi.group_management.groups()
    ]
    assert ("students" in associated_groups_names
            and "teachers" in associated_groups_names)
    # test adjusting lab groups (only owner and admin can change lab group associations)
    # admin must see all associations
    # owner and non-admin users can only see those associations where they are members of group
    # log in as non-admin satoshi user
    cl_halfinn = ClientLibrary(
        controller_url,
        username="******",
        password=satoshi_pwd,
        ssl_verify=False,
        allow_http=True,
    )
    # create lab owned by halfin
    lab2 = cl_halfinn.create_lab(title="lab2")
    # only satoshi in students group + add lab2 association
    cl_admin.group_management.update_group(
        group_id=students_group["id"],
        members=[satoshi_uid],
        labs=[{
            "id": lab2.id,
            "permission": "read_only"
        }],
    )
    # only halfinney in teachers group + add lab2 association
    cl_admin.group_management.update_group(
        group_id=teachers_group["id"],
        members=[halfinn_uid],
        labs=[{
            "id": lab2.id,
            "permission": "read_only"
        }],
    )
    halfinn_lab2 = cl_halfinn.find_labs_by_title(title="lab2")[0]
    # get lab owned by halfinney with satoshi (who is not owner)
    satoshi_lab2 = cl_satoshi.find_labs_by_title(title="lab2")[0]
    # get lab owned by halfinney with admin
    admin_lab2 = cl_admin.find_labs_by_title(title="lab2")[0]

    # admin must see both groups associated with lab2
    assert admin_lab2.groups == [
        {
            "id": students_group["id"],
            "permission": "read_only"
        },
        {
            "id": teachers_group["id"],
            "permission": "read_only"
        },
    ]
    # halfinney only sees group that he is member of (teachers)
    assert halfinn_lab2.groups == [
        {
            "id": teachers_group["id"],
            "permission": "read_only"
        },
    ]
    # satoshi only sees group that he is member of (students)
    assert satoshi_lab2.groups == [
        {
            "id": students_group["id"],
            "permission": "read_only"
        },
    ]
    # satoshi cannot update lab groups associations for lab2 -> 403 (not owner or admin)
    with pytest.raises(requests.exceptions.HTTPError) as err:
        satoshi_lab2.update_lab_groups(group_list=[])
    assert err.value.response.status_code == 403
    assert "User does not have required access" in err.value.response.text
    # associations mus still be present after above failure
    assert admin_lab2.groups == [
        {
            "id": students_group["id"],
            "permission": "read_only"
        },
        {
            "id": teachers_group["id"],
            "permission": "read_only"
        },
    ]
    # halfinney cannot add/remove students association to lab2 as he is not member of students
    halfinn_lab2.update_lab_groups(group_list=[])
    # above only removed the group teachers as halfinn is owner and also member of teachers
    assert halfinn_lab2.groups == []  # sees nothing
    assert satoshi_lab2.groups == [
        {
            "id": students_group["id"],
            "permission": "read_only"
        },
    ]  # sees students
    assert admin_lab2.groups == [
        {
            "id": students_group["id"],
            "permission": "read_only"
        },
    ]  # admin too sees only students as that is now only associtation
    # halfinney cannot add students group as he is not member
    with pytest.raises(requests.exceptions.HTTPError) as err:
        halfinn_lab2.update_lab_groups(group_list=[{
            "id": students_group["id"],
            "permission": "read_only"
        }])
    assert err.value.response.status_code == 403
    assert "User does not have required access" in err.value.response.text
    # halfinney can add teachers as he is a member
    halfinn_lab2.update_lab_groups(group_list=[{
        "id": teachers_group["id"],
        "permission": "read_only"
    }])
    # halfinney only sees group that he is member of (teachers)
    assert halfinn_lab2.groups == [
        {
            "id": teachers_group["id"],
            "permission": "read_only"
        },
    ]
    # add halfinney to students group
    cl_admin.group_management.update_group(
        group_id=students_group["id"],
        members=[satoshi_uid, halfinn_uid],
    )
    # halfinney now sees both students and teachers
    # associations mus still be present after above failure
    assert halfinn_lab2.groups == [
        {
            "id": students_group["id"],
            "permission": "read_only"
        },
        {
            "id": teachers_group["id"],
            "permission": "read_only"
        },
    ]
    # he can now also remove both associations
    halfinn_lab2.update_lab_groups(group_list=[])
    assert admin_lab2.groups == []
    assert halfinn_lab2.groups == []
    # satoshi lost access --> 404
    with pytest.raises(requests.exceptions.HTTPError) as err:
        assert satoshi_lab2.groups == []
    assert err.value.response.status_code == 404
    assert "Lab not found" in err.value.response.text
    # add also possible
    halfinn_lab2.update_lab_groups(group_list=[
        {
            "id": students_group["id"],
            "permission": "read_only"
        },
        {
            "id": teachers_group["id"],
            "permission": "read_only"
        },
    ])
    assert halfinn_lab2.groups == [
        {
            "id": students_group["id"],
            "permission": "read_only"
        },
        {
            "id": teachers_group["id"],
            "permission": "read_only"
        },
    ]
    assert satoshi_lab2.groups == [
        {
            "id": students_group["id"],
            "permission": "read_only"
        },
    ]  # sees students as he is only part of students not teachers
    assert admin_lab2.groups == [
        {
            "id": students_group["id"],
            "permission": "read_only"
        },
        {
            "id": teachers_group["id"],
            "permission": "read_only"
        },
    ]
    # admin can do whatever he pleases
    admin_lab2.update_lab_groups(group_list=[])
    assert admin_lab2.groups == []
    assert halfinn_lab2.groups == []
    # satoshi lost access --> 404
    with pytest.raises(requests.exceptions.HTTPError) as err:
        assert satoshi_lab2.groups == []
    assert err.value.response.status_code == 404
    assert "Lab not found" in err.value.response.text

    # CLEAN UP
    # again need to get lab0 from admin account
    lab0 = cl_admin.find_labs_by_title(title="lab0")[0]
    lab0.remove()
    lab1.remove()
    lab2.remove()
    cl_admin.user_management.delete_user(user_id=satoshi_uid)
    cl_admin.user_management.delete_user(user_id=halfinn_uid)
    assert cl_admin.group_management.delete_group(
        group_id=students_group["id"]) is None
    assert cl_admin.group_management.delete_group(
        group_id=teachers_group["id"]) is None

    assert cl_admin.group_management.groups() == []
    assert cl_admin.all_labs(show_all=True) == []
示例#12
0
def test_topology_owner(client_library_keep_labs: ClientLibrary):
    lab = client_library_keep_labs.create_lab("owned_by_cml2")
    lab.sync(topology_only=True)
    assert lab.owner == "cml2"
def test_links_on_various_slots(client_library: ClientLibrary):
    """
    Creating a link between two nodes on higher interfaces,
    then removing the link and re-adding a link on lower interfaces.
    """
    lab = client_library.create_lab()

    s1 = lab.create_node("s1", "server", 50, 100)
    s2 = lab.create_node("s2", "server", 50, 200)

    assert s1.interfaces() == []
    assert s2.interfaces() == []

    # create a link between s1 and s2
    s1_i1 = s1.create_interface(slot=4)
    s2_i1 = s2.create_interface(slot=4)

    assert len(s1.interfaces()) == 5
    assert len(s2.interfaces()) == 5

    link = lab.create_link(s1_i1, s2_i1)

    assert link.interface_a.slot == 4
    assert link.interface_b.slot == 4

    lab.remove_link(link)

    # verify that removing the link doesn't delete interfaces:
    assert len(s1.interfaces()) == 5
    assert len(s2.interfaces()) == 5

    # create a link between s1 and s2 on lower slot than before
    s1_i1 = s1.create_interface(slot=0)
    s2_i1 = s2.create_interface(slot=0)
    link = lab.create_link(s1_i1, s2_i1)
    assert link.interface_a.slot == 0
    assert link.interface_b.slot == 0

    assert list(lab._interfaces.keys()) == [
        "i0",
        "i1",
        "i2",
        "i3",
        "i4",
        "i5",
        "i6",
        "i7",
        "i8",
        "i9",
    ]
    assert [ifc.label for ifc in lab.interfaces()] == [
        "eth0",
        "eth1",
        "eth2",
        "eth3",
        "eth4",
        "eth0",
        "eth1",
        "eth2",
        "eth3",
        "eth4",
    ]
    # create a link between s1 and s2, again on the 4th slot
    s1_i1 = s1.create_interface(slot=4)
    s2_i1 = s2.create_interface(slot=4)
    link = lab.create_link(s1_i1, s2_i1)

    assert link.interface_a.slot == 4
    assert link.interface_b.slot == 4

    lab.remove_link(link)
示例#14
0
def test_create_client_lab(client_library: ClientLibrary):
    lab = client_library.create_lab()
    lab.auto_sync = False

    print("Created lab {}".format(lab.id))
    # using server nodes, not IOSv nodes as they are not available
    # without a reference platform ISO attached
    r1 = lab.create_node("r1", "server", 5, 100)
    r2 = lab.create_node("r2", "server", 102, 201)
    r3 = lab.create_node("r3", "server", 200, 400)
    print(r1, r2, r3)

    r1_i1 = r1.create_interface()
    r1_i2 = r1.create_interface()
    print(r1_i1, r1_i2)

    r2_i1 = r2.create_interface()
    r2_i2 = r2.create_interface()

    r3_i1 = r3.create_interface()
    r3_i2 = r3.create_interface()

    link_1 = lab.create_link(r1_i1, r2_i1)
    link_2 = lab.create_link(r2_i2, r3_i1)
    link_3 = lab.create_link(r3_i2, r1_i2)

    # r1.config = "test"
    # r2.x = 50
    # r2.y = 200
    #

    # r1.start()
    # r2.start()
    # r3.start()

    # r1.stop()
    # r2.stop()
    # r3.stop()

    r1.label = "r1_test"

    # lab.remove_node(r1)
    lab.remove_link(link_1)
    lab.remove_link(link_2)
    lab.remove_link(link_3)
    lab.remove_node(r1)
    lab.remove_node(r2)
    lab.remove_node(r3)

    lab.sync_states()

    for node in lab.nodes():
        print(node, node.state)
        for iface in node.interfaces():
            print(iface, iface.state)

    for link in lab.links():
        print(link, link.state)

    # lab.remove()

    # print("clear lab")
    # lab.clear()
    # print("remove lab")
    # events = lab.sync_events()
    # for event in lab.events:
    #     print(event)
    # lab.wait_until_lab_converged()
    lab.remove()
                       ssl_verify=False,
                       raise_for_auth_failure=True,
                       allow_http=True)
log.info("LOGGING INFO: Successfully connected with CML through the API")

# Read in the config file
config_files = os.listdir(path='./config')
config_files = [file for file in config_files if ".txt" in file]
log.info("LOGGING INFO: Successfully read in the config files")

routers = []
for file in config_files:
    routers.append(file[:-4])

# Create a new lab in CML
lab = client.create_lab(title=LAB_TITLE)
log.info("LOGGING INFO: Successfully created the lab in CML")

# Create the nodes in the lab
coordinates = [(0, 0), (200, 0), (200, 200), (0, 200)]
coordinates_counter = 0
for router in routers:
    x, y = coordinates[coordinates_counter]
    lab.create_node(label=router,
                    node_definition='csr1000v',
                    populate_interfaces=8,
                    x=x,
                    y=y)
    coordinates_counter += 1
log.info("LOGGING INFO: Successfully created the nodes in the lab")
示例#16
0
# cl.licensing.licensing.set_transport(ssms=ssms, proxy_server="172.16.1.100", proxy_port=8888)
cl.licensing.set_transport(ssms=SSMS)
cl.licensing.install_certificate(cert=CERT)
# 'register_wait' method waits max 45s for registration status to become COMPLETED
# and another 45s for authorization status to become IN_COMPLIANCE
cl.licensing.register_wait(token=TOKEN)


lab_list = cl.get_lab_list()
for lab_id in lab_list:
    lab = cl.join_existing_lab(lab_id)
    lab.stop()
    lab.wipe()
    cl.remove_lab(lab_id)

lab = cl.create_lab()
lab = cl.join_existing_lab(lab_id="lab_1")

s1 = lab.create_node("s1", "server", 50, 100)
s2 = lab.create_node("s2", "server", 50, 200)
print(s1, s2)

# create a link between s1 and s2, equivalent to
#   s1_i1 = s1.create_interface()
#   s2_i1 = s2.create_interface()
#   lab.create_link(s1_i1, s2_i1)
lab.connect_two_nodes(s1, s2)

# this must remove the link between s1 and s2
lab.remove_node(s2)
示例#17
0
def test_user_role_change(controller_url,
                          client_library_session: ClientLibrary):
    cl_admin = client_library_session
    cl_admin_uid = client_library_session.user_management.user_id(
        cl_admin.username)
    # create non admin users
    cl_user1, cl_user2 = "cl_user1", "cl_user2"
    password = "******"
    res = cl_admin.user_management.create_user(username=cl_user1, pwd=password)
    cl_user1_uid = res["id"]
    res = cl_admin.user_management.create_user(username=cl_user2, pwd=password)
    cl_user2_uid = res["id"]

    cl_user1 = ClientLibrary(
        controller_url,
        username=cl_user1,
        password=password,
        ssl_verify=False,
        allow_http=True,
    )
    cl_user2 = ClientLibrary(
        controller_url,
        username=cl_user2,
        password=password,
        ssl_verify=False,
        allow_http=True,
    )

    cl_user1.create_lab("lab1-cl_user1")
    cl_user1.create_lab("lab2-cl_user1")

    assert cl_user2.all_labs(show_all=True) == []
    # promote cl_user2 to admin
    cl_admin.user_management.update_user(user_id=cl_user2_uid, admin=True)
    # check if cl_user2 can see all the labs as admin
    all_labs = cl_user2.all_labs(show_all=True)
    assert len(all_labs) == 2
    assert all_labs[0].owner == cl_user1_uid

    # check if cl_user2 can create user and delete users
    res = cl_user2.user_management.create_user(username="******",
                                               pwd=password)
    assert cl_user2.user_management.get_user(user_id=res["id"])

    cl_user2.user_management.delete_user(user_id=res["id"])
    with pytest.raises(requests.exceptions.HTTPError) as err:
        cl_user2.user_management.get_user(user_id=res["id"])
    assert err.value.response.status_code == 404

    # check cl_user2 can see licensing
    assert cl_user2.licensing.status()

    for lab in all_labs:
        cl_user2.remove_lab(lab.id)
    assert cl_user2.all_labs(show_all=True) == []

    # promote cl_user1 to admin
    cl_admin.user_management.update_user(user_id=cl_user1_uid, admin=True)

    # check if cl_user1 can remove admin cl_user2
    cl_user1.user_management.delete_user(user_id=cl_user2_uid)
    with pytest.raises(requests.exceptions.HTTPError) as err:
        cl_user1.user_management.get_user(user_id=cl_user2_uid)
    assert err.value.response.status_code == 404

    # remove admin rights from cl_user1
    cl_admin.user_management.update_user(user_id=cl_user1_uid, admin=False)
    lab = cl_admin.create_lab("origin-lab")
    assert cl_user1.all_labs(show_all=True) == []

    with pytest.raises(requests.exceptions.HTTPError) as err:
        cl_user1.user_management.create_user(username="******", pwd=password)
    assert err.value.response.status_code == 403

    with pytest.raises(requests.exceptions.HTTPError) as err:
        cl_user1.licensing.status()
    assert err.value.response.status_code == 403

    cl_admin.user_management.delete_user(user_id=cl_user1_uid)

    # check that user cannot update its own user role
    with pytest.raises(requests.exceptions.HTTPError) as err:
        cl_admin.user_management.update_user(user_id=cl_admin_uid, admin=False)
    assert err.value.response.status_code == 400

    # cleanup
    cl_admin.remove_lab(lab.id)
示例#18
0
def test_topology_owner(client_library_session: ClientLibrary):
    cml2_uid = client_library_session.user_management.user_id("cml2")
    lab = client_library_session.create_lab("owned_by_cml2")
    lab.sync(topology_only=True)
    assert lab.owner == cml2_uid
    lab.remove()
示例#19
0
if 'programmatic_network_build' in [lab.title for lab in all_labs]:
    print(f"\nprogrammatic_network_build exists, deleting lab..")
    lab = client.find_labs_by_title(title='programmatic_network_build')[0]
    try:
        lab.stop()
        lab.wipe()
        lab.remove()
    except Exception as e:
        print(f"Unable to stop programmatic_network_build lab, error: {e}")
    print(f"\nprogrammatic_network_build has been successfully deleted..")

print(f"\nprogrammatic_network_build doesn't exist, creating lab..")

# create new programmatic_network_build lab
try:
    lab = client.create_lab(title='programmatic_network_build')

    # create nodes
    print(f"\nCreating nodes..")
    spine1 = lab.create_node("spine1",
                             "iosv",
                             300,
                             100,
                             populate_interfaces=True)
    spine2 = lab.create_node("spine2",
                             "iosv",
                             500,
                             100,
                             populate_interfaces=True)
    leaf1 = lab.create_node("leaf1", "iosv", 0, 300, populate_interfaces=True)
    leaf2 = lab.create_node("leaf2",
示例#20
0
class virlModule(object):
    def __init__(self, module, function=None):
        self.module = module
        self.params = module.params
        self.result = dict(changed=False)
        self.headers = dict()
        self.function = function
        self.cookies = None
        self.json = None

        self.method = None
        self.path = None
        self.response = None
        self.status = None
        self.url = None
        self.params['force_basic_auth'] = True
        self.user = self.params['user']
        self.password = self.params['password']
        self.host = self.params['host']
        self.timeout = self.params['timeout']
        self.modifiable_methods = ['POST', 'PUT', 'DELETE']

        self.client = None

        self.login()

    def login(self):
        self.client = ClientLibrary('https://{0}'.format(self.host),
                                    self.user,
                                    self.password,
                                    ssl_verify=False)

    def get_lab_by_name(self, name):
        for lab in self.client.all_labs():
            if lab.name == name:
                return lab
        return None

    def get_node_by_name(self, lab, name):
        for node in lab.nodes():
            if node.label == name:
                return node
        return None

    def get_lab_by_id(self, id):
        try:
            lab = self.client.join_existing_lab(id, sync_lab=True)
        except:
            lab = None

        return lab

    def create_lab(self, name):
        lab = self.client.create_lab(name=name)
        lab.set_title(name)
        lab.sync()
        return lab

    def exit_json(self, **kwargs):

        self.result.update(**kwargs)
        self.module.exit_json(**self.result)

    def fail_json(self, msg, **kwargs):

        self.result.update(**kwargs)
        self.module.fail_json(msg=msg, **self.result)