Пример #1
0
    def validate_group_responses(self, device_map):
        """Checks whether the device_map corresponds to the server's view of
        the current groups, using all the possible ways to query for this.
        device_map is a map of device to group."""

        groups = []
        groups_map = {}
        devices_with_group = []
        devices_without_group = []
        for device in device_map:
            group = device_map[device]
            if group is not None:
                groups.append(group)
                devices_with_group.append(device)
            else:
                devices_without_group.append(device)

            if groups_map.get(group):
                groups_map[group].append(device)
            else:
                groups_map[group] = [device]

        assert(sorted(inv.get_groups()) == sorted(groups))
        assert(sorted([device['id'] for device in inv.get_devices(has_group=True)]) == sorted(devices_with_group))
        assert(sorted([device['id'] for device in inv.get_devices(has_group=False)]) == sorted(devices_without_group))
        assert(sorted([device['id'] for device in inv.get_devices()]) == sorted(device_map.keys()))

        for group in groups:
            assert(sorted(inv.get_devices_in_group(group)) == sorted(groups_map[group]))
        for device in device_map:
            assert(inv.get_device_group(device)['group'] == device_map[device])
    def test_clients_exclusive_to_user(self):
        users = [
            {
              "email": "*****@*****.**",
              "password": "******",
              "username": "******",
              "container": "mender-client-exclusive-1",
              "client_id": "",
              "device_id": ""
            },
            {
               "email": "*****@*****.**",
               "password": "******",
               "username": "******",
               "container": "mender-client-exclusive-2",
               "client_id": "",
               "device_id": ""
            }
        ]

        for user in users:
            auth.set_tenant(user["username"], user["email"], user["password"])

            t = auth.current_tenant["tenant_token"]
            new_tenant_client(user["container"], t)
            adm.accept_devices(1)

            # get the new devices client_id and setting it to the our test parameter
            assert len(inv.get_devices()) == 1
            user["client_id"] = inv.get_devices()[0]["id"]
            user["device_id"] = adm.get_devices()[0]["device_id"]

        for user in users:
            # make sure that the correct number of clients appear for the given tenant
            auth.set_tenant(user["username"], user["email"], user["password"])
            assert len(inv.get_devices()) == 1
            assert inv.get_devices()[0]["id"] == user["client_id"]

        for user in users:
            # wait until inventory is populated
            auth.set_tenant(user["username"], user["email"], user["password"])
            deviceauth.decommission(user["client_id"])
            timeout = time.time() + (60 * 5)
            device_id = user["device_id"]
            while time.time() < timeout:
                    newAdmissions = adm.get_devices()[0]
                    if device_id != newAdmissions["device_id"] \
                       and user["client_id"] != newAdmissions["id"]:
                        logger.info("device [%s] not found in inventory [%s]" % (device_id, str(newAdmissions)))
                        break
                    else:
                        logger.info("device [%s] found in inventory..." % (device_id))
                    time.sleep(.5)
            else:
                assert False, "decommissioned device still available in admissions"
    def test_multi_tenancy_deployment(self):
        """ Simply make sure we are able to run the multi tenancy setup and
           bootstrap 2 different devices to different tenants """

        auth.reset_auth_token()

        users = [
            {
                "email": "*****@*****.**",
                "password": "******",
                "username": "******",
                "container": "mender-client-deployment-1",
                "fail": False
            },
            {
                "email": "*****@*****.**",
                "password": "******",
                "username": "******",
                "container": "mender-client-deployment-2",
                "fail": True
            }
        ]

        for user in users:
            auth.new_tenant(user["username"], user["email"], user["password"])
            t = auth.current_tenant["tenant_token"]
            new_tenant_client(user["container"], t)
            adm.accept_devices(1)

        for user in users:
            auth.new_tenant(user["username"], user["email"], user["password"])

            assert len(inv.get_devices()) == 1
            self.perform_update(mender_client_container=user["container"],
                                fail=user["fail"])
Пример #4
0
    def test_basic_groups(self):
        """Tests various group operations."""

        devices = [device['id'] for device in inv.get_devices()]
        assert(len(devices) == 2)

        # Purely for easier reading: Assign labels to each device.
        alpha = devices[0]
        bravo = devices[1]

        # Start out with no groups.
        self.validate_group_responses({alpha: None, bravo: None})

        # Test various group operations.
        inv.put_device_in_group(alpha, "Red")
        self.validate_group_responses({alpha: "Red", bravo: None})

        inv.put_device_in_group(bravo, "Blue")
        self.validate_group_responses({alpha: "Red", bravo: "Blue"})

        inv.delete_device_from_group(alpha, "Red")
        self.validate_group_responses({alpha: None, bravo: "Blue"})

        # Note that this *moves* the device into the group.
        inv.put_device_in_group(bravo, "Red")
        self.validate_group_responses({alpha: None, bravo: "Red"})

        # Important: Leave the groups as you found them: Empty.
        inv.delete_device_from_group(bravo, "Red")
        self.validate_group_responses({alpha: None, bravo: None})
Пример #5
0
    def test_device_decommissioning(self):
        """ Decommission a device successfully """

        if not env.host_string:
            execute(self.test_device_decommissioning, hosts=get_mender_clients())
            return

        adm.check_expected_status("pending", len(get_mender_clients()))
        adm_id = adm.get_devices()[0]["id"]
        device_id = adm.get_devices()[0]["device_id"]

        adm.set_device_status(adm_id, "accepted")

        # wait until inventory is populated
        timeout = time.time() + (60 * 5)
        while time.time() < timeout:
            inventoryJSON = inv.get_devices()
            if "attributes" in inventoryJSON[0]:
                break
            time.sleep(.5)
        else:
            assert False, "never got inventory"

        # decommission actual device
        deviceauth.decommission(device_id)

        # now check that the device no longer exists in admissions
        timeout = time.time() + (60 * 5)
        while time.time() < timeout:
                newAdmissions = adm.get_devices()[0]
                if device_id != newAdmissions["device_id"] \
                   and adm_id != newAdmissions["id"]:
                    logger.info("device [%s] not found in inventory [%s]" % (device_id, str(newAdmissions)))
                    break
                else:
                    logger.info("device [%s] found in inventory..." % (device_id))
                time.sleep(.5)
        else:
            assert False, "decommissioned device still available in admissions"

        # disabled for time being due to new deployment process


        # make sure a deployment to the decommissioned device fails
        # try:
        #    time.sleep(120)  # sometimes deployment microservice hasn't removed the device yet
        #    logger.info("attempting to deploy to decommissioned device: %s" % (device_id))
        #    deployment_id, _ = common_update_procedure(install_image=conftest.get_valid_image(),
        #                                               devices=[device_id],
        #                                               verify_status=False)
        #except AssertionError:
        #    logging.info("Failed to deploy upgrade to rejected device, as expected.")
        #else:
        #    assert False, "No error while trying to deploy to rejected device"

        # authtoken has been removed
        #run("strings /data/mender/mender-store | grep -q 'authtoken' || false")

        """
Пример #6
0
    def test_device_decommissioning(self):
        """ Decommission a device successfully """

        if not env.host_string:
            execute(self.test_device_decommissioning,
                    hosts=get_mender_clients())
            return

        adm.check_expected_status("pending", len(get_mender_clients()))
        adm_id = adm.get_devices()[0]["id"]
        device_id = adm.get_devices()[0]["device_id"]

        adm.set_device_status(adm_id, "accepted")

        # wait until inventory is populated
        timeout = time.time() + (60 * 5)

        while time.time() < timeout:
            inventoryJSON = inv.get_devices()

            # we haven't gotten an inventory data yet.
            if len(inventoryJSON) == 0:
                continue

            if "attributes" in inventoryJSON[0]:
                break
            time.sleep(.5)
        else:
            assert False, "never got inventory"

        # get all completed decommission_device WFs for reference
        c = Conductor(get_mender_conductor())
        initial_wfs = c.get_decommission_device_wfs(device_id)

        # decommission actual device
        deviceauth.decommission(device_id)

        # check that the workflow completed successfully
        timeout = time.time() + (60 * 5)
        while time.time() < timeout:
            wfs = c.get_decommission_device_wfs(device_id)
            if wfs['totalHits'] == initial_wfs['totalHits'] + 1:
                break
            else:
                logger.info("waiting for decommission_device workflow...")
                time.sleep(.5)
        else:
            assert False, "decommission_device workflow didn't complete for [%s]" % (
                device_id, )

        # check device gone from inventory
        self.check_gone_from_inventory(device_id)

        # check device gone from deviceauth
        self.check_gone_from_deviceauth(device_id)

        # now check that the device no longer exists in admission
        self.check_gone_from_deviceadm(adm_id, device_id)
Пример #7
0
    def test_inventory(self):
        """Test that device reports inventory after having bootstrapped."""

        attempts = 3

        while True:
            attempts = attempts - 1
            try:
                inv_json = inv.get_devices()
                adm_json = adm.get_devices()

                adm_ids = [device['device_id'] for device in adm_json]

                assert (len(inv_json) > 0)

                for device in inv_json:
                    try:
                        # Check that admission and inventory agree.
                        assert (device['id'] in adm_ids)

                        attrs = device['attributes']

                        # Check individual attributes.
                        assert (json.loads(
                            '{"name": "network_interfaces", "value": "eth0"}')
                                in attrs)
                        assert (json.loads(
                            '{"name": "hostname", "value": "vexpress-qemu"}')
                                in attrs)
                        assert (json.loads(
                            '{"name": "device_type", "value": "vexpress-qemu"}'
                        ) in attrs)

                        # Check that all known keys are present.
                        keys = [attr['name'] for attr in attrs]
                        expected_keys = [
                            "hostname", "network_interfaces", "cpu_model",
                            "mem_total_kB", "device_type", "ipv4_eth0",
                            "mac_eth0", "mender_client_version",
                            "artifact_name", "kernel"
                        ]
                        assert (sorted(keys) == sorted(expected_keys))

                    except:
                        print("Exception caught, 'device' json: ", device)
                        raise
                break

            except:
                # This may pass only after the client has had some time to
                # report.
                if attempts > 0:
                    time.sleep(5)
                    continue
                else:
                    raise
Пример #8
0
    def test_inventory_post_upgrade(self):
        inventory = inv.get_devices()
        for inventory_item in inventory:
            for inventory_pair in inventory_item["attributes"]:

                # make sure time was updated recently
                if inventory_pair["name"] == "time":
                    assert int(time.time()) - int(inventory_pair["value"]) <= 10

                # and other invetory items are still present
                elif inventory_pair["name"] == "device_type":
                    assert inventory_pair["value"] == "test"
                elif inventory_pair["name"] == "image_id":
                    assert inventory_pair["value"] == "test"
Пример #9
0
    def test_inventory(self):
        """Test that device reports inventory after having bootstrapped."""

        attempts = 10

        while True:
            attempts = attempts - 1
            try:
                inv_json = inv.get_devices()
                adm_json = adm.get_devices()

                adm_ids = [device['device_id'] for device in adm_json]

                assert (len(inv_json) > 0)

                for device in inv_json:
                    try:
                        # Check that admission and inventory agree.
                        assert (device['id'] in adm_ids)

                        attrs = device['attributes']

                        # Check individual attributes.
                        network_interfaces = [
                            elem for elem in attrs
                            if elem['name'] == "network_interfaces"
                        ]
                        assert len(network_interfaces) == 1
                        network_interfaces = network_interfaces[0]
                        if type(network_interfaces['value']) is str:
                            assert any(network_interfaces['value'] == iface
                                       for iface in ["eth0", "enp0s3"])
                        else:
                            assert any(iface in network_interfaces['value']
                                       for iface in ["eth0", "enp0s3"])
                        assert (json.loads(
                            '{"name": "hostname", "value": "%s"}' %
                            conftest.machine_name) in attrs)
                        assert (json.loads(
                            '{"name": "device_type", "value": "%s"}' %
                            conftest.machine_name) in attrs)

                        # Check that all known keys are present.
                        keys = [str(attr['name']) for attr in attrs]
                        expected_keys = [
                            "hostname",
                            "network_interfaces",
                            "cpu_model",
                            "mem_total_kB",
                            "device_type",
                            ["ipv4_enp0s3", "ipv6_enp0s3",
                             "ipv4_eth0"],  # Multiple possibilities
                            ["mac_enp0s3", "mac_eth0"],
                            "mender_client_version",
                            "artifact_name",
                            "kernel"
                        ]
                        for key in expected_keys:
                            if type(key) is list:
                                assert any([subkey in keys for subkey in key])
                            else:
                                assert key in keys

                    except:
                        print("Exception caught, 'device' json: ", device)
                        raise
                break

            except:
                # This may pass only after the client has had some time to
                # report.
                if attempts > 0:
                    time.sleep(5)
                    continue
                else:
                    raise
Пример #10
0
    def test_device_decommissioning(self, standard_setup_one_client):
        """ Decommission a device successfully """

        if not env.host_string:
            execute(self.test_device_decommissioning,
                    standard_setup_one_client,
                    hosts=get_mender_clients())
            return

        adm.check_expected_status("pending", len(get_mender_clients()))
        adm_id = adm.get_devices()[0]["id"]
        device_id = adm.get_devices()[0]["device_id"]

        adm.set_device_status(adm_id, "accepted")

        # wait until inventory is populated
        timeout = time.time() + (60 * 5)
        while time.time() < timeout:
            inventoryJSON = inv.get_devices()
            if "attributes" in inventoryJSON[0]:
                break
            time.sleep(.5)
        else:
            pytest.fail("never got inventory")

        # decommission actual device
        deviceauth.decommission(device_id)

        # now check that the device no longer exists in admissions
        timeout = time.time() + (60 * 5)
        while time.time() < timeout:
            newAdmissions = adm.get_devices()[0]
            if device_id != newAdmissions["device_id"] \
               and adm_id != newAdmissions["id"]:
                logger.info("device [%s] not found in inventory [%s]" %
                            (device_id, str(newAdmissions)))
                break
            else:
                logger.info("device [%s] found in inventory..." % (device_id))
            time.sleep(.5)
        else:
            pytest.fail("decommissioned device still available in admissions")

        # make sure a deployment to the decommissioned device fails
        try:
            time.sleep(
                120
            )  # sometimes deployment microservice hasn't removed the device yet
            logger.info("attempting to deploy to decommissioned device: %s" %
                        (device_id))
            deployment_id, _ = common_update_procedure(
                install_image=conftest.get_valid_image(),
                devices=[device_id],
                verify_status=False)
        except AssertionError:
            logging.info("Failed to deploy upgrade to rejected device")
            # authtoken has been removed
            run("strings /data/mender/mender-store | grep -q 'authtoken' || false"
                )
        else:
            pytest.fail("No error while trying to deploy to rejected device")
        """
            at this point, the device will re-appear, since it's actually still
            online, and not actually decomissioned
        """
        adm.check_expected_status("pending", len(get_mender_clients()))

        # make sure inventory is empty as well
        assert len(inv.get_devices()) == 0