def test_simple_mapping(tmpdir): device_info = {"foo": "bar"} add_device_container_mapping("1", device_info, "mycontainer") data = yaml_load(open(tmpdir / "1" / "usbmap.yaml"))[0] assert data["device_info"] == device_info assert data["container"] == "mycontainer" assert data["container_type"] == "lxc"
def test_share_device_setup_logger(mocker): check_call = mocker.patch("subprocess.check_call") add_device_container_mapping("1", {"serial_number": "1234567890"}, "mycontainer") setup_logger = mocker.Mock() share_device_with_container( Namespace(device="foo", serial_number="1234567890"), setup_logger) setup_logger.assert_called_once_with(mocker.ANY)
def test_only_adds_slash_dev_if_needed(mocker): share = mocker.patch( "lava_dispatcher_host.share_device_with_container_lxc") add_device_container_mapping("1", {"serial_number": "1234567890"}, "mycontainer") share_device_with_container( Namespace(device="/dev/foo/bar", serial_number="1234567890")) share.assert_called_once_with("mycontainer", "/dev/foo/bar")
def test_device_missing(mocker): mocker.patch("os.path.exists", return_value=False) check_call = mocker.patch("subprocess.check_call") add_device_container_mapping("1", {"serial_number": "1234567890"}, "mycontainer") share_device_with_container( Namespace(device="foo/bar", serial_number="1234567890")) check_call.assert_not_called()
def test_simple_share_device_with_container(mocker): check_call = mocker.patch("subprocess.check_call") add_device_container_mapping("1", {"serial_number": "1234567890"}, "mycontainer") share_device_with_container( Namespace(device="foo/bar", serial_number="1234567890")) check_call.assert_called_once_with( ["lxc-device", "-n", "mycontainer", "add", "/dev/foo/bar"])
def handle_devices_map(options): container = options.container container_type = options.container_type job_id = "0" # fake map fields = ["serial_number", "usb_vendor_id", "usb_product_id", "fs_label"] device_info = { k: options.__dict__[k] for k in fields if k in options and options.__dict__[k] } add_device_container_mapping(job_id, device_info, container, container_type)
def run(self, connection, max_end_time): connection = super().run(connection, max_end_time) # this may be the device namespace - the lxc namespace may not be # accessible lxc_name = None protocols = [ protocol for protocol in self.job.protocols if protocol.name == LxcProtocol.name ] if protocols: lxc_name = protocols[0].lxc_name if not lxc_name: self.logger.debug("No LXC device requested") return connection # If there is no device_info then this action should be idempotent. if "device_info" not in self.job.device: return connection device_info = self.job.device.get("device_info", []) logging_url = master_cert = slave_cert = socks_proxy = ipv6 = None job_id = self.job.job_id if self.logger.handler: logging_url = self.logger.handler.logging_url master_cert = self.logger.handler.master_cert slave_cert = self.logger.handler.slave_cert socks_proxy = self.logger.handler.socks_proxy ipv6 = self.logger.handler.ipv6 job_id = self.logger.handler.job_id logging = { "logging_url": logging_url, "master_cert": master_cert, "slave_cert": slave_cert, "socks_proxy": socks_proxy, "ipv6": ipv6, "job_id": job_id, } job_prefix = self.job.parameters["dispatcher"].get("prefix", "") for device in device_info: data = { "serial_number": str(device.get("board_id", "")), "vendor_id": device.get("usb_vendor_id"), "product_id": device.get("usb_product_id"), "fs_label": device.get("fs_label"), } add_device_container_mapping( job_prefix + job_id, data, lxc_name, container_type="lxc", logging_info=logging, ) return connection
def test_second_mapping_does_not_invalidate_first(mocker): share = mocker.patch( "lava_dispatcher_host.share_device_with_container_lxc") add_device_container_mapping("1", {"serial_number": "1234567890"}, "mycontainer1") add_device_container_mapping("1", {"serial_number": "badbeeb00c"}, "mycontainer1") share_device_with_container( Namespace(device="/dev/foo/bar", serial_number="1234567890")) share.assert_called_once_with("mycontainer1", "/dev/foo/bar")
def test_unknown_container_type(mocker): add_device_container_mapping( "1", {"serial_number": "1234567890"}, "mycontainer", container_type="unsupported", ) with pytest.raises(InfrastructureError): share_device_with_container( Namespace(device="foo/bar", serial_number="1234567890"))
def test_two_concurrent_jobs(mocker, pass_device_lxc, device_links): add_device_container_mapping("1", {"serial_number": "1234567890"}, "container1") add_device_container_mapping("2", {"serial_number": "9876543210"}, "container2") share_device_with_container( Namespace(device="baz/qux", serial_number="9876543210")) pass_device_lxc.assert_called_once_with("container2", "/dev/baz/qux", device_links, "2")
def run(self, connection, max_end_time): # obtain lava overlay # start container # create USB device mapping to container # connect to container, and run lava-test-shell over it location = self.get_namespace_data(action="test", label="shared", key="location") overlay = self.get_namespace_data( action="test", label="results", key="lava_test_results_dir").strip("/") image = self.parameters["docker"]["image"] container = "lava-docker-test-shell-%s-%s" % (self.job.job_id, self.level) board_id = self.get_board_id() device_info = {"board_id": board_id} add_device_container_mapping( job_id=self.job.job_id, device_info=device_info, container=container, container_type="docker", logging_info=self.get_logging_info(), ) docker = DockerRun(image) docker.bind_mount(os.path.join(location, overlay), "/" + overlay) docker.interactive() docker.hostname("lava") docker.name(container) docker.environment("PS1", "docker-test-shell:$ ") if self.wait_for_device: devices = get_udev_devices(device_info=[device_info]) for dev in devices: docker.add_device(dev) docker_cmd = docker.cmdline("bash", "--norc", "-i") cmd = " ".join([shlex.quote(s) for s in docker_cmd]) self.logger.debug("Starting docker test shell container: %s" % cmd) shell = ShellCommand(cmd, self.timeout, logger=self.logger) shell_connection = ShellSession(self.job, shell) shell_connection.prompt_str = "docker-test-shell:" self.__set_connection__(shell_connection) super().run(shell_connection, max_end_time) # finish the container shell_connection.finalise() # return the original connection untouched self.__set_connection__(connection) return connection
def test_two_concurrent_jobs(mocker): check_call = mocker.patch("subprocess.check_call") add_device_container_mapping("1", {"serial_number": "1234567890"}, "container1") add_device_container_mapping("2", {"serial_number": "9876543210"}, "container2") share_device_with_container( Namespace(device="baz/qux", serial_number="9876543210")) check_call.assert_called_once_with( ["lxc-device", "-n", "container2", "add", "/dev/baz/qux"])
def test_share_device_setup_logger(mocker): check_call = mocker.patch("subprocess.check_call") add_device_container_mapping( "1", {"serial_number": "1234567890"}, "mycontainer", logging_info={"logging_url": "proto://host"}, ) setup_logger = mocker.Mock() share_device_with_container( Namespace(device="foo", serial_number="1234567890"), setup_logger) setup_logger.assert_called()
def test_two_devices_two_containers(mocker): share = mocker.patch("lava_dispatcher_host.share_device_with_container_lxc") add_device_container_mapping("1", {"serial_number": "1234567890"}, "mycontainer1") add_device_container_mapping("1", {"serial_number": "badbeeb00c"}, "mycontainer2") share_device_with_container( Namespace(device="/dev/foo/bar", serial_number="1234567890") ) share.assert_called_once_with("mycontainer1", "/dev/foo/bar") share.reset_mock() share_device_with_container( Namespace(device="/dev/foo/bar", serial_number="badbeeb00c") ) share.assert_called_once_with("mycontainer2", "/dev/foo/bar")
def test_map_by_vendor_id_and_product_id(mocker, pass_device_lxc, device_links): add_device_container_mapping( "1", {"vendor_id": "aaaa", "product_id": "xxxx"}, "container1" ) share_device_with_container( Namespace( device="bus/usb/001/099", serial_number="9876543210", vendor_id="aaaa", product_id="xxxx", ) ) pass_device_lxc.assert_called_once_with( "container1", "/dev/bus/usb/001/099", device_links )
def test_map_by_vendor_id_and_product_id(mocker): check_call = mocker.patch("subprocess.check_call") add_device_container_mapping("1", { "vendor_id": "aaaa", "product_id": "xxxx" }, "container1") share_device_with_container( Namespace( device="bus/usb/001/099", serial_number="9876543210", vendor_id="aaaa", product_id="xxxx", )) check_call.assert_called_once_with( ["lxc-device", "-n", "container1", "add", "/dev/bus/usb/001/099"])
def add_device_container_mappings(self, container, container_type): device_info = self.job.device.get("device_info", []) job_id = self.job.job_id job_prefix = self.job.parameters["dispatcher"].get("prefix", "") devices = [] for origdevice in device_info: device = origdevice.copy() if "board_id" in device: device["serial_number"] = device["board_id"] del device["board_id"] devices.append(device) for device in devices: add_device_container_mapping(job_prefix + job_id, device, container, container_type=container_type)
def add_device_container_mappings(self, container, container_type): device_info = self.job.device.get("device_info", []) static_info = self.job.device.get("static_info", []) job_id = self.job.job_id job_prefix = self.job.parameters["dispatcher"].get("prefix", "") devices = [] for origdevice in device_info + static_info: device = origdevice.copy() if "board_id" in device: device["serial_number"] = device["board_id"] del device["board_id"] devices.append(device) for device in devices: add_device_container_mapping(job_prefix + job_id, device, container, container_type=container_type) logger = logging.getLogger("dispatcher") logger.info( f"Added mapping for {device} to {container_type} container {container}" )
def test_mapping_with_serial_number_but_called_with_vendor_product_id_too( mocker, pass_device_lxc, device_links): add_device_container_mapping( "1", { "serial_number": "1234567890", "vendor_id": None, "product_id": None, "fs_label": None, }, "mycontainer", ) share_device_with_container( Namespace( device="foo/bar", serial_number="1234567890", vendor_id="0123", product_id="4567", )) pass_device_lxc.assert_called_once_with("mycontainer", "/dev/foo/bar", device_links, "1")
def test_mapping_with_serial_number_but_called_with_vendor_product_id_too( mocker): check_call = mocker.patch("subprocess.check_call") add_device_container_mapping( "1", { "serial_number": "1234567890", "vendor_id": None, "product_id": None, "fs_label": None, }, "mycontainer", ) share_device_with_container( Namespace( device="foo/bar", serial_number="1234567890", vendor_id="0123", product_id="4567", )) check_call.assert_called_once_with( ["lxc-device", "-n", "mycontainer", "add", "/dev/foo/bar"])
def run(self, connection, max_end_time): connection = super().run(connection, max_end_time) # this may be the device namespace - the lxc namespace may not be # accessible lxc_name = None protocols = [ protocol for protocol in self.job.protocols if protocol.name == LxcProtocol.name ] if protocols: lxc_name = protocols[0].lxc_name if not lxc_name: self.logger.debug("No LXC device requested") return connection # If there is no device_info then this action should be idempotent. if "device_info" not in self.job.device: return connection device_info = self.job.device.get("device_info", []) job_id = self.job.job_id job_prefix = self.job.parameters["dispatcher"].get("prefix", "") for device in device_info: data = { "serial_number": str(device.get("board_id", "")), "vendor_id": device.get("usb_vendor_id"), "product_id": device.get("usb_product_id"), "fs_label": device.get("fs_label"), } add_device_container_mapping( job_prefix + job_id, data, lxc_name, container_type="lxc", logging_info=self.get_logging_info(), ) return connection
def test_mapping_for_new_container_overrides_previous_mapping(tmpdir): add_device_container_mapping( "1", { "serial_number": "1234567890", "vendor_id": None, "product_id": None, "fs_label": None, }, "mycontainer1", ) add_device_container_mapping( "1", { "serial_number": "1234567890", "vendor_id": None, "product_id": None, "fs_label": None, }, "mycontainer2", ) data = yaml_load(open(tmpdir / "1" / "usbmap.yaml")) assert len(data) == 1 assert data[0]["container"] == "mycontainer2"
def test_device_info_keys_required(mocker): with pytest.raises(ValueError): add_device_container_mapping("1", {"serial_number": None}, "mycontainer")
def test_device_info_required(mocker): with pytest.raises(ValueError): add_device_container_mapping("1", {}, "mycontainer")
def test_add_mapping_without_job_dir(tmpdir): os.rmdir(tmpdir / "1") add_device_container_mapping("1", {"foo": "bar"}, "mycontainer") assert os.path.exists(tmpdir / "1" / "usbmap.yaml")
def test_simple_share_device_with_container(mocker, pass_device_lxc, device_links): add_device_container_mapping("1", {"serial_number": "1234567890"}, "mycontainer") share_device_with_container(Namespace(device="foo/bar", serial_number="1234567890")) pass_device_lxc.assert_called_once_with("mycontainer", "/dev/foo/bar", device_links)