Beispiel #1
0
                           username,
                           password,
                           ssl_verify=False)
    client.is_system_ready()
except:
    print(
        f"\nUnable to contact CML2.x server, please check server connectivity."
    )

# get list of labs
all_labs = client.all_labs()

# check if programmatic_network_build exists
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
from virl2_client import ClientLibrary

VIRL_CONTROLLER = "virl2-controller"
VIRL_USERNAME = input("username: "******"password: "******"enter lab name: ")

client = ClientLibrary(VIRL_CONTROLLER,
                       VIRL_USERNAME,
                       VIRL_PASSWORD,
                       ssl_verify=False)

# Find the lab by title and join it as long as it's the only
# lab with that title.
labs = client.find_labs_by_title(LAB_NAME)

if not labs or len(labs) != 1:
    print("ERROR: Unable to find a unique lab named {}".format(LAB_NAME))
    exit(1)

lobj = client.join_existing_lab(labs[0].id)

if not lobj:
    print("ERROR: Failed to join lab {}".format(LAB_NAME))
    exit(1)

# Print all links in the lab and ask which link to condition.
i = 1
liobjs = []
for link in lobj.links():
Beispiel #3
0
    def parse(self, inventory, loader, path, cache=True):

        # call base method to ensure properties are available for use with other helper methods
        super(InventoryModule, self).parse(inventory, loader, path, cache)

        # this method will parse 'common format' inventory sources and
        # update any options declared in DOCUMENTATION as needed
        # config = self._read_config_data(self, path)
        self._read_config_data(path)

        # if NOT using _read_config_data you should call set_options directly,
        # to process any defined configuration for this plugin,
        # if you dont define any options you can skip
        # self.set_options()

        if 'VIRL_HOST' in os.environ and len(os.environ['VIRL_HOST']):
            self.host = os.environ['VIRL_HOST']
        else:
            self.host = self.get_option('host')

        self.display.vvv("virl2.py - VIRL_HOST: {0}".format(self.host))

        if 'VIRL_USERNAME' in os.environ and len(os.environ['VIRL_USERNAME']):
            self.username = os.environ['VIRL_USERNAME']
        else:
            self.username = self.get_option('username')

        self.display.vvv("virl2.py - VIRL_USERNAME: {0}".format(self.username))

        if 'VIRL_PASSWORD' in os.environ and len(os.environ['VIRL_PASSWORD']):
            self.password = os.environ['VIRL_PASSWORD']
        else:
            self.password = self.get_option('password')

        if 'VIRL_LAB' in os.environ and len(os.environ['VIRL_LAB']):
            self.lab = os.environ['VIRL_LAB']
        else:
            self.lab = self.get_option('lab')

        self.display.vvv("virl2.py - VIRL_LAB: {0}".format(self.lab))

        if not self.lab:
            self.display.vvv("No lab defined.  Nothing to do.")
            return

        self.group = self.get_option('group')
        if self.group is None:
            self.group = 'virl_hosts'

        self.display.vvv("virl2.py - Group: {0}".format(self.group))

        self.inventory.set_variable('all', 'virl_host', self.host)
        self.inventory.set_variable('all', 'virl_username', self.username)
        self.inventory.set_variable('all', 'virl_password', self.password)
        self.inventory.set_variable('all', 'virl_lab', self.lab)

        url = 'https://{0}'.format(self.host)
        try:
            client = ClientLibrary(url, username=self.username, password=self.password, ssl_verify=False)
        except:
            raise AnsibleParserError('Unable to log into {0}'.format(url))

        labs = (client.find_labs_by_title(self.lab))
        if not labs:
            return

        try:
            group = self.inventory.add_group(self.group)
        except AnsibleError as e:
            raise AnsibleParserError("Unable to add group %s: %s" % (group, to_text(e)))
        group_dict = {}

        lab = labs[0]
        lab.sync()
        for node in lab.nodes():
            self.inventory.add_host(node.label, group=self.group)
            virl = {
                'state': node.state,
                'image_definition': node.image_definition,
                'node_definition': node.node_definition,
                'cpus': node.cpus,
                'ram': node.ram,
                'config': node.config,
                'data_volume': node.data_volume,
            }
            interface_list = []
            ansible_host = None
            for interface in node.interfaces():
                if interface.discovered_ipv4 and not ansible_host:
                    ansible_host = interface.discovered_ipv4[0]
                interface_dict = {
                    'name': interface.label,
                    'state': interface.state,
                    'ipv4_addresses': interface.discovered_ipv4,
                    'ipv6_addresses': interface.discovered_ipv6,
                    'mac_address': interface.discovered_mac_address
                }
                interface_list.append(interface_dict)
            virl.update({'interfaces': interface_list})
            if ansible_host:
                self.inventory.set_variable(node.label, 'ansible_host', ansible_host)
            self.inventory.set_variable(node.label, 'virl_facts', virl)
            self.display.vvv("Adding {0}({1}) to group {2}, state: {3}, ansible_host: {4}".format(
                node.label, node.node_definition, self.group, node.state, ansible_host))
            # Group by node_definition
            if node.node_definition not in group_dict:
                try:
                    group_dict[node.node_definition] = self.inventory.add_group(node.node_definition)
                except AnsibleError as e:
                    raise AnsibleParserError("Unable to add group %s: %s" % (group, to_text(e)))
            self.inventory.add_host(node.label, group=node.node_definition)
                                data=payload,
                                files=files)
    response.raise_for_status()


if __name__ == "__main__":
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    client = ClientLibrary(cml_server_url,
                           cml_username,
                           cml_password,
                           ssl_verify=False,
                           raise_for_auth_failure=True,
                           allow_http=True)

    #get lab
    lab = client.find_labs_by_title("Jupyter Lab")[0]

    #get lab testbed
    pyats_testbed = lab.get_pyats_testbed()

    #add credentials to testbed
    add_cml_credentials(pyats_testbed, "lab_testbed.yaml", cml_username,
                        cml_password)

    #create directories if doesn't exist
    if not os.path.exists("./learn_results"):
        os.makedirs("./learn_results")
    if not os.path.exists("./diff_results"):
        os.makedirs("./diff_results")

    #load testbed
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()
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) == []
Beispiel #7
0
def config_worker(param):

    netmiko_delay = 0.1

    client = ClientLibrary(
        param["virl_controller"],
        param["virl_username"],
        param["virl_password"],
        ssl_verify=False,
    )
    client.wait_for_lld_connected()

    with print_lock:
        print(f"{param['hostname']}: Connected to VIRL")

    our_lab = client.find_labs_by_title(param["lab_id"])[0]
    our_node = our_lab.get_node_by_label(param["hostname"])

    with print_lock:
        print(
            f"{param['hostname']}: Identified lab and device: /{our_lab.id}/{our_node.id}/0"
        )

    c = netmiko.ConnectHandler(
        device_type="terminal_server",
        host=param["virl_controller"],
        username=param["virl_username"],
        password=param["virl_password"],
    )

    with print_lock:
        print(f"{param['hostname']}: Connected to terminal server")

    c.write_channel("\r\n")
    time.sleep(1)
    c.write_channel("\r\n")
    time.sleep(1)

    c.write_channel(f"open /{our_lab.id}/{our_node.id}/0\r")

    c.write_channel("\r\n")
    time.sleep(1)
    c.write_channel("\r\n")
    time.sleep(1)
    c.write_channel("\r\n")
    time.sleep(1)
    c.write_channel("\r\n")

    with print_lock:
        print(f"{param['hostname']} : Switching to IOS interpreter")
    try:
        netmiko.redispatch(c, device_type="cisco_ios")
    except Exception as e:
        with print_lock:
            print(
                f"{param['hostname']} : Failed to switch to IOS interpreter. {e}"
            )
    c.find_prompt()
    # c.enable()

    with print_lock:
        print(f"{param['hostname']} : Preparing config")
    try:
        with open("swtemplate.j2", "r") as f:
            template = jinja2.Template(f.read())
        config_to_send = template.render(device=param).split("\n")
    except:
        with print_lock:
            print(f"{param['hostname']} : Failed to prepare config")

    with print_lock:
        print(f"{param['hostname']} : Sending config")

    try:
        # I have found that console messages can upset netmiko,
        # so turn them off with a timed command
        c.send_command_timing("enable", netmiko_delay)
        c.send_command_timing("conf t", netmiko_delay)
        c.send_command_timing("no logging console", netmiko_delay)
        c.send_command_timing("end", netmiko_delay)
        time.sleep(1)
        c.write_channel("\r\n")
        c.find_prompt()
        c.send_config_set(config_to_send)
        with print_lock:
            print(f"{param['hostname']} : Config sent")

    except Exception as e:
        with print_lock:
            print(f"{param['hostname']} : Error, send config failed. {e}")
Beispiel #8
0
log = logging.getLogger(__name__)

#Script for gathering testbed from CML

#Environment variables
cml_server_url = env.config['CML_SERVER_URL']
cml_username = env.config['CML_USERNAME']
cml_password = env.config['CML_PASSWORD']

#connect
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
client = ClientLibrary(cml_server_url,
                       cml_username,
                       cml_password,
                       ssl_verify=False,
                       raise_for_auth_failure=True,
                       allow_http=True)

#setup config files
config_files = os.listdir(path='./config')
config_files = [file for file in config_files if ".txt" in file]

#get lab
lab = client.find_labs_by_title("BRAIN 16.2")[0]
print(lab)

#get lab testbed
pyats_testbed = lab.get_pyats_testbed()
# Write the YAML testbed out to a file
with open("lab_testbed.yaml", "w") as f:
    f.write(pyats_testbed)
LAB_USERNAME = '******'
LAB_PASSWORD = '******'
VIRL_CONTROLLER = 'virl.twpsyn.com'
VIRL_USERNAME = input('username: '******'password: '******'s exactly one lab with this title
our_lab = client.find_labs_by_title('Lab1')[0]
xr_node = our_lab.get_node_by_label('S4')

logging.info("Identified lab and device")
# open the Netmiko connection via the terminal server
# (SSH to the controller connects to the terminal server)
c = netmiko.ConnectHandler(device_type='terminal_server',
                           host=VIRL_CONTROLLER,
                           username=VIRL_USERNAME,
                           password=VIRL_PASSWORD)

logging.info("Netmiko connection created")

# send CR, get a prompt on terminal server
c.write_channel('\r\n')
sleep(1)