def update_image_failed(install_image="broken_update.ext4", expected_mender_clients=1): """ Perform a upgrade using a broken image (random data) The device will reboot, uboot will detect this is not a bootable image, and revert to the previous partition. The resulting upgrade will be considered a failure. """ devices_accepted = get_mender_clients() original_image_id = Helpers.yocto_id_installed_on_machine() previous_active_part = Helpers.get_active_partition() with Helpers.RebootDetector() as reboot: deployment_id, _ = common_update_procedure(install_image, broken_image=True) reboot.verify_reboot_performed() with Helpers.RebootDetector() as reboot: assert Helpers.get_active_partition() == previous_active_part deploy.check_expected_statistics(deployment_id, "failure", expected_mender_clients) for d in adm.get_devices(): assert "got invalid entrypoint into the state machine" in deploy.get_logs( d["device_id"], deployment_id) assert Helpers.yocto_id_installed_on_machine() == original_image_id reboot.verify_reboot_not_performed() deploy.check_expected_status("finished", deployment_id)
def test_original_deployments_persisted(self): auth.reset_auth_token() auth.get_auth_token() # wait for 10 devices to be available devices = adm.get_devices_status("accepted", 10) provisioned_devices = eval(self.provisioned_devices) # check that devices and provisioned_devices are the same assert len(devices) == provisioned_devices # not sure what else I can do here, the device admission changed from 1.0 to master assert deploy.get_statistics( self.provisioned_deployment_id)["success"] == 7 assert deploy.get_statistics( self.provisioned_deployment_id)["failure"] == 3 # check failures still contain logs for device_deployment in deploy.get_deployment_overview( self.provisioned_deployment_id): if device_deployment["status"] == "failure": assert "damn" in deploy.get_logs( device_deployment["id"], self.provisioned_deployment_id) deployments_in_progress = deploy.get_status("inprogress") deployments_pending = deploy.get_status("pending") deployments_finished = deploy.get_status("finished") assert len(deployments_in_progress) == 0 assert len(deployments_pending) == 0 assert len(deployments_finished) == 1 assert self.provisioned_artifact_id in str(deployments_finished)
def test_update_image_failed(self, install_image="broken_update.ext4"): """ Perform a upgrade using a broken image (random data) The device will reboot, uboot will detect this is not a bootable image, and revert to the previous partition. The resulting upgrade will be considered a failure. """ if not env.host_string: execute(self.test_update_image_failed, hosts=get_mender_clients(), install_image=install_image) return devices_accepted = get_mender_clients() original_image_id = Helpers.yocto_id_installed_on_machine() previous_active_part = Helpers.get_active_partition() deployment_id, _ = common_update_proceduce(install_image, broken_image=True) Helpers.verify_reboot_performed() assert Helpers.get_active_partition() == previous_active_part deploy.check_expected_status(deployment_id, "failure", len(devices_accepted)) for d in adm.get_devices(): assert "running rollback image" in deploy.get_logs( d["id"], deployment_id) assert Helpers.yocto_id_installed_on_machine() == original_image_id Helpers.verify_reboot_not_performed()
def update_image_successful(install_image, regenerate_image_id=True, signed=False, skip_reboot_verification=False, expected_mender_clients=1): """ Perform a successful upgrade, and assert that deployment status/logs are correct. A reboot is performed, and running partitions have been swapped. Deployment status will be set as successful for device. Logs will not be retrieved, and result in 404. """ previous_inactive_part = Helpers.get_passive_partition() with Helpers.RebootDetector() as reboot: deployment_id, expected_image_id = common_update_procedure(install_image, regenerate_image_id, signed=signed) reboot.verify_reboot_performed() with Helpers.RebootDetector() as reboot: try: assert Helpers.get_active_partition() == previous_inactive_part except AssertionError: logs = [] for d in adm.get_devices(): logs.append(deploy.get_logs(d["device_id"], deployment_id)) pytest.fail("device did not flip partitions during update, here are the device logs:\n\n %s" % (logs)) deploy.check_expected_statistics(deployment_id, "success", expected_mender_clients) for d in adm.get_devices(): deploy.get_logs(d["device_id"], deployment_id, expected_status=404) if not skip_reboot_verification: reboot.verify_reboot_not_performed() assert Helpers.yocto_id_installed_on_machine() == expected_image_id deploy.check_expected_status("finished", deployment_id) # make sure backend recognizes signed and unsigned images artifact_id = deploy.get_deployment(deployment_id)["artifacts"][0] artifact_info = deploy.get_artifact_details(artifact_id) assert artifact_info["signed"] is signed, "image was not correct recognized as signed/unsigned" return deployment_id
def abort_deployment(self, abort_step=None, mender_performs_reboot=False): """ Trigger a deployment, and cancel it within 15 seconds, make sure no deployment is performed. Args: mender_performs_reboot: if set to False, a manual reboot is performed and checks are performed. if set to True, wait until device is rebooted. """ if not env.host_string: execute(self.abort_deployment, abort_step=abort_step, mender_performs_reboot=mender_performs_reboot, hosts=get_mender_clients()) return install_image=conftest.get_valid_image() expected_partition = Helpers.get_active_partition() expected_image_id = Helpers.yocto_id_installed_on_machine() with Helpers.RebootDetector() as reboot: deployment_id, _ = common_update_procedure(install_image, verify_status=False) if abort_step is not None: deploy.check_expected_statistics(deployment_id, abort_step, len(get_mender_clients())) deploy.abort(deployment_id) deploy.check_expected_statistics(deployment_id, "aborted", len(get_mender_clients())) # no deployment logs are sent by the client, is this expected? for d in adm.get_devices(): deploy.get_logs(d["device_id"], deployment_id, expected_status=404) if mender_performs_reboot: # If Mender performs reboot, we need to wait for it to reboot # back into the original filesystem. reboot.verify_reboot_performed(number_of_reboots=2) else: # Else we reboot ourselves, just to make sure that we have not # unintentionally switched to the new partition. reboot.verify_reboot_not_performed() run("( sleep 10 ; reboot ) 2>/dev/null >/dev/null &") reboot.verify_reboot_performed() assert Helpers.get_active_partition() == expected_partition assert Helpers.yocto_id_installed_on_machine() == expected_image_id deploy.check_expected_status("finished", deployment_id)
def abort_deployment(self, abort_step=None, mender_performs_reboot=False): """ Trigger a deployment, and cancel it within 15 seconds, make sure no deployment is performed. Args: mender_performs_reboot: if set to False, a manual reboot is performed and checks are performed. if set to True, wait until device is rebooted. """ if not env.host_string: execute(self.abort_deployment, abort_step=abort_step, mender_performs_reboot=mender_performs_reboot, hosts=get_mender_clients()) return install_image = conftest.get_valid_image() expected_partition = Helpers.get_active_partition() expected_image_id = Helpers.yocto_id_installed_on_machine() token = Helpers.place_reboot_token() deployment_id, _ = common_update_procedure(install_image, verify_status=False) if abort_step is not None: deploy.check_expected_statistics(deployment_id, abort_step, len(get_mender_clients())) deploy.abort(deployment_id) deploy.check_expected_statistics(deployment_id, "aborted", len(get_mender_clients())) # no deployment logs are sent by the client, is this expected? for d in adm.get_devices(): deploy.get_logs(d["device_id"], deployment_id, expected_status=404) if not mender_performs_reboot: token.verify_reboot_not_performed() run("( sleep 10 ; reboot ) 2>/dev/null >/dev/null &") token.verify_reboot_performed() assert Helpers.get_active_partition() == expected_partition assert Helpers.yocto_id_installed_on_machine() == expected_image_id deploy.check_expected_status("finished", deployment_id)
def update_image_successful( install_image=conftest.get_valid_image(), regenerate_image_id=True): """ Perform a successful upgrade, and assert that deployment status/logs are correct. A reboot is performed, and running partitions have been swapped. Deployment status will be set as successful for device. Logs will not be retrieved, and result in 404. """ previous_inactive_part = Helpers.get_passive_partition() deployment_id, expected_image_id = common_update_procedure( install_image, regenerate_image_id) Helpers.verify_reboot_performed() try: assert Helpers.get_active_partition() == previous_inactive_part except AssertionError: logs = [] for d in adm.get_devices(): logs.append(deploy.get_logs(d["device_id"], deployment_id)) pytest.fail( "device did not flip partitions during update, here are the device logs:\n\n %s" % (logs)) deploy.check_expected_statistics(deployment_id, "success", len(get_mender_clients())) for d in adm.get_devices(): deploy.get_logs(d["device_id"], deployment_id, expected_status=404) Helpers.verify_reboot_not_performed() assert Helpers.yocto_id_installed_on_machine() == expected_image_id deploy.check_expected_status("finished", deployment_id)
def test_unsigned_artifact_fails_deployment(self, standard_setup_with_signed_artifact_client): """ Make sure that an unsigned image fails, and is handled by the backend. Notice that this test needs a fresh new version of the backend, since we installed a signed image earlier without a verification key in mender.conf """ if not env.host_string: execute(self.test_unsigned_artifact_fails_deployment, standard_setup_with_signed_artifact_client, hosts=get_mender_clients()) return deployment_id, _ = common_update_procedure(install_image=conftest.get_valid_image()) deploy.check_expected_status("finished", deployment_id) deploy.check_expected_statistics(deployment_id, "failure", 1) for d in adm.get_devices(): assert "expecting signed artifact, but no signature file found" in \ deploy.get_logs(d["device_id"], deployment_id)
def test_update_device_group(self): """ Perform a successful upgrade on one group of devices, and assert that: * deployment status/logs are correct. * only the correct group is updated, not the other one. A reboot is performed, and running partitions have been swapped. Deployment status will be set as successful for device. Logs will not be retrieved, and result in 404. """ # Beware that there will two parallel things going on below, one for # each group, hence a lot of separate execute() calls for each. We aim # to update the group alpha, not beta. clients = get_mender_clients() assert(len(clients) == 2) alpha = clients[0] bravo = clients[1] ip_to_device_id = Helpers.ip_to_device_id_map(clients) id_alpha = ip_to_device_id[alpha] id_bravo = ip_to_device_id[bravo] print("ID of alpha host: %s\nID of bravo host: %s" % (id_alpha, id_bravo)) ret = execute(Helpers.get_passive_partition, hosts=clients) pass_part_alpha = ret[alpha] pass_part_bravo = ret[bravo] inv.put_device_in_group(id_alpha, "Update") @parallel def place_reboot_tokens(): return Helpers.place_reboot_token() tokens = execute(place_reboot_tokens, hosts=clients) deployment_id, expected_image_id = common_update_procedure(conftest.get_valid_image(), devices=[id_alpha]) @parallel def verify_reboot_performed_for_alpha_only(tokens): if env.host_string == alpha: tokens[alpha].verify_reboot_performed() elif env.host_string == bravo: # Extra long wait here, because a real update takes quite a lot # of time. tokens[bravo].verify_reboot_not_performed(180) else: raise Exception("verify_reboot_performed_for_alpha_only() called with unknown host") execute(verify_reboot_performed_for_alpha_only, tokens, hosts=clients) ret = execute(Helpers.get_passive_partition, hosts=clients) assert ret[alpha] != pass_part_alpha assert ret[bravo] == pass_part_bravo ret = execute(Helpers.get_active_partition, hosts=clients) assert ret[alpha] == pass_part_alpha assert ret[bravo] != pass_part_bravo deploy.check_expected_statistics(deployment_id, expected_status="success", expected_count=1) # No logs for either host: alpha because it was successful, bravo # because it should never have attempted an update in the first place. for id in [id_alpha, id_bravo]: deploy.get_logs(id, deployment_id, expected_status=404) assert execute(Helpers.yocto_id_installed_on_machine, hosts=alpha)[alpha] == expected_image_id assert execute(Helpers.yocto_id_installed_on_machine, hosts=bravo)[bravo] != expected_image_id # Important: Leave the groups as you found them: Empty. inv.delete_device_from_group(id_alpha, "Update")