Use OTII in docker

Hi there,

I have been using the product locally for a while and it works perfectly fine. Now our team wants to integrate OTII into Jenkins and running in a docker container environment, but right now seems have some issue. It is not able to find the device if I run
“otiicli -l”
No device
No compatible device found

I believe OTII using /dev/ttyACM0 to connect to computer, and I di mount the /dev/ttyACM0 port to the docker, is there any suggestion or tutorial on how to setup OTII in docker environment? what else should I mount to the docker too?

Thanks

Hi jcheng,

For the otii/otiicli software to be able to detect the device we need to be able to see it as a USB device, not just a serial device (we’re filtering on USB Vendor ID and Product ID). Typically on a Linux system at least a subset of /dev/bus/usb needs to be passed through. If you have lsusb present inside the container you can verify if the Qoitech Arc device shows up in its output.

As an initial test, if you pass through the entire /dev/bus/usb in privileged mode, does the device show up in otiicli?

Are you running as root or some other user inside the container? The reason I’m asking is if there could be permission issues with either accessing the /dev/bus/usb/* or the /dev/tty* paths.

for me simply passing /dev/bus/usb doesn’t work. No matter I pass or not the --volume=/dev/bus/usb:/dev/bus/usb to docker, lsusb shows

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 025: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO)
Bus 001 Device 004: ID 046d:c077 Logitech, Inc. M105 Optical Mouse
Bus 001 Device 024: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO)
Bus 001 Device 026: ID 0fce:d1e6 Sony Ericsson Mobile Communications AB
Bus 001 Device 011: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO)
Bus 001 Device 012: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO)
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

for both inside docker and in local, but still, local can find it and docker cannot.
Do I miss something?

That is odd indeed. Device 26 in this case (vid:pid 0fce:d1e6) is the Qoitech Arc hardware.

Which distribution are you running on the host? And which user are you running otiicli as inside docker?

I am running the root, and Docker is 18.04, otii I download through curl https://www.qoitech.com/downloads/otii_2.6.3.deb

I gave it a quick spin on a Ubuntu 20.04 LTS machine with Docker version 19.03.12 and it looks like I can reproduce the issue.

Ubuntu host:
wjo@ubuntu:~$ lsusb
Bus 001 Device 004: ID 0fce:d1e6 Sony Ericsson Mobile Communications AB Arc
wjo@ubuntu:~$ otiicli -l
otiicli - Copyright © Qoitech AB 2016-2019. All Rights Reserved.
ttyACM0

Docker container:
root@1d856e771a2a:~# lsusb
Bus 001 Device 003: ID 0fce:d1e6 Qoitech Arc
root@1d856e771a2a:~# otiicli -l
otiicli - Copyright © Qoitech AB 2016-2019. All Rights Reserved.
No device
No compatible device found

Looking at the otii.log seems to indicate that the Arc isn’t recognized as a Qoitech device but as a generic UART by otiicli inside the container. This will require some additional investigation.

Thanks, that is exactly what I encoutered. Let me know if you got any update.

Thanks so much for your help.

After some digging it turns out that the required identification data is queried through udev, so on my Ubuntu host and simple ubuntu container I was able to get it to run using:

docker run -it --device=/dev/ttyACM0 -v /run/udev:/run/udev:ro ubuntu

This will pass the read-only udev state into the container and the serial library is able to detect the correct USB ID.

There is another approach that might work better for you though:
You can run the otiicli application in your host system and enable the TCP server functionality. A script running in the container can then connect to the TCP server in otiicli without you having to pass the serial device through. This also avoids having to reserve the license inside the container.

The most common client is the Python one: GitHub - qoitech/otii-tcp-client-python: Python client for Otii TCP-server

Thanks so much for your help, it works, we have to use the otiicli in docker environment cause we try to running in Jenkins and our CI is fully dockerized, but thanks again.

Sincerely

Perfect, glad we could sort it out!!

Hi there, got another issue I guess I will directly post here

Somehow seems otiicli -r -R parameters doesn’t return or logout the account?

I use command

otiicli --server --username --password -t 300 -r

After I kiill the process, doesn’t seems return the license, I have to manully do it in the GUI application.
I existing process by either ctrl+c or use kill command, is there a proper way to exsting?

also is there way just release the license from otiicli like otiicli -r ?
Thanks

Hi,

Are you using the latest software?
We have made changes to the license server and this was pushed last weekend.

I have used the -r and -R and the license is returned as it should.
Below are some explanations regarding TCP server and otiicli.

otiicli -h

shows all options for otiicli
New for this release is the option -i which should be followed with the ID of the license to be reserved.
Option -L is also updated. Now it returns the list, with ID’s, of the licenses connected to the user logged in.

Example:

otiicli -u YOUR_USER_NAME -P -i LICENSE_ID -s -R

This line, logs in as user YOUR_USER_NAME, prompts for password, reserves license LICENSE_ID, starts the TCP server and returns the license and logs out when otiicli stops.

I hope this helps!

Best regards,
Björn

Thanks Bjorn,

I tried with the latest and it works by exiting the otiicli using ctrl+z. I tried run otiicli at background using command otiicli -u YOUR_USER_NAME -P -i LICENSE_ID -s -R & and kill the process by kill %1.

In this way, I am not able to return the license, and right now I’m not able to return that license since that one running in docker and it has been removed.

This leading 2 questions:

  1. How should I correctly exiting the otiicli beside ctrl+z
  2. Is there a way to return the license reserved from another place in a different machine? (In my case I want to return the license reserved in the docker container on my host machine)

Also seems -t parameters is not available anymore and when I reserve, I reserve for me over 1 year, is there a way to change this?

Thanks

Hi,

A “regular” kill command and the resulting SIGTERM signal should definitely bring the server down and if -r is supplied to otiicli it will also return the license. -R isn’t really necessary in this case (you can safely leave the client logged in).
Could it be that the container is shutting down hard before the SIGTERM cleanup is done?

There is a shutdown command that can be sent from the Python client that will shutdown the TCP server, that would ensure that the license is returned before the script will finish. Take a look at the shutdown method in the otii object.

If this is a container that is cycled repeatedly I would definitely suggest running otiicli with its TCP server on the host instead and only run the Python scripts from within the container. That way you don’t have to start and stop the TCP server (otiicli) every time you cycle the container. The TCP server can be configured from the GUI to listen on specific interfaces and only allow connections from certain IPs. By default it will only listen on connections from localhost for security reasons, so this will require some configuration depending on how your container network setup is done.

Regarding returning the license, you need to contact us (either create a case in our case system or send a mail to support@qoitech.com) with information about the license and we will help you retrieve the license.

Correct, the -t parameter is removed. The reservation time you see is the time your license is valid until it expires.

Best regards,
Björn

Thanks for your advise, I will try to setup the TCP server on a host machine. Would it possible to config TCP like port and IP through CLI, we plan to run the server on a VM which does not have a GUI

Also, I guess shutting down the TCP server would not return the license? What do you mean by

Hi,

We are working on an update that makes it possible, in otiicli, to configure address and port, this will soon be released.

In otii.py, there is a command shutdown(), use this to shut down the started TCP server, then the license will be returned if you have specified -r or -R.

Best regards,
Björn

Hello,
It is always when I run: otiicli -l in my ubuntu container :
otiicli -l
otiicli - Copyright © Qoitech AB 2016-2020. All Rights Reserved.
“Failed to create default Uart blacklist file: otii/uart_blacklist.json”
ttyACM1

I can not setting the account by using “otiicli -u xxx -p xxx”, and also cannot reserve, so I cannot start the TCP server by otiicli -s

The “Failed to create…” error indicates that otiicli doesn’t have permission to create files in the user document folder inside the container (normally ~/Documents, which means that the default files are created in ~/Documents/otii).

listen-ip and listen-port options were added to otiicli in version 2.7.1 of the software, this would make it easier to start otiicli outside the Docker environment and communicate with its TCP server from inside Docker. This would eliminate any issues with device and file accesses, as long as your Docker instance can establish a TCP connection to the host. Would that work around your issue?