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"])
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})
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") """
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)
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
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"
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
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