Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add Linux VM support with Docker implementation
- Remove Windows-specific wording
- Adjust Python path for cross-platform compatibility
- Provide Docker-based Linux VM implementation
- Update README with Linux setup instructions
- Add graceful VM setup and cleanup procedures
  • Loading branch information
esmitperez committed Mar 29, 2025
commit b9e315bc9103ebc1df98123b0739bb6eeac5727f
2 changes: 1 addition & 1 deletion omnitool/gradio/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ def valid_params(user_input, state):
"""Validate all requirements and return a list of error messages."""
errors = []

for server_name, url in [('Windows Host', 'localhost:5000'), ('OmniParser Server', args.omniparser_server_url)]:
for server_name, url in [('Guest Host', 'localhost:5000'), ('OmniParser Server', args.omniparser_server_url)]:
try:
url = f'http://{url}/probe'
response = requests.get(url, timeout=3)
Expand Down
1 change: 1 addition & 0 deletions omnitool/omnibox/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ vm/win11iso/custom.iso
vm/win11storage
vm/win11setup/setupscripts/firstboot_log.txt
vm/win11setup/setupscripts/server/server.log
vm.linux/storage/
84 changes: 84 additions & 0 deletions omnitool/omnibox/Dockerfile.linux
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Copyright 2025 esmit<[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This Dockerfile is based on https://github.com/Tiryoh/docker-ros-desktop-vnc/tree/master/noetic
# which is released under the Apache-2.0 license.

FROM ubuntu:focal-20241011

ARG TARGETPLATFORM
LABEL maintainer="esmit<[email protected]>"

SHELL ["/bin/bash", "-c"]

# Upgrade OS
RUN apt-get update -q && \
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y && \
apt-get autoclean && \
apt-get autoremove && \
rm -rf /var/lib/apt/lists/*

# Install Ubuntu Mate desktop
RUN apt-get update -q && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
ubuntu-mate-desktop && \
apt-get autoclean && \
apt-get autoremove && \
rm -rf /var/lib/apt/lists/*

# Add Package
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
tigervnc-standalone-server tigervnc-common \
supervisor wget curl gosu git sudo python3-pip tini \
build-essential vim sudo lsb-release locales \
bash-completion tzdata terminator && \
apt-get autoclean && \
apt-get autoremove && \
rm -rf /var/lib/apt/lists/*

# noVNC and Websockify
RUN git clone https://github.com/AtsushiSaito/noVNC.git -b add_clipboard_support /usr/lib/novnc
RUN pip install --no-cache-dir git+https://github.com/novnc/[email protected]
RUN ln -s /usr/lib/novnc/vnc.html /usr/lib/novnc/index.html

# Set remote resize function enabled by default
RUN sed -i "s/UI.initSetting('resize', 'off');/UI.initSetting('resize', 'remote');/g" /usr/lib/novnc/app/ui.js

# Disable auto update and crash report
RUN sed -i 's/Prompt=.*/Prompt=never/' /etc/update-manager/release-upgrades
RUN sed -i 's/enabled=1/enabled=0/g' /etc/default/apport

# Install Firefox
RUN DEBIAN_FRONTEND=noninteractive add-apt-repository ppa:mozillateam/ppa -y && \
echo 'Package: *' > /etc/apt/preferences.d/mozilla-firefox && \
echo 'Pin: release o=LP-PPA-mozillateam' >> /etc/apt/preferences.d/mozilla-firefox && \
echo 'Pin-Priority: 1001' >> /etc/apt/preferences.d/mozilla-firefox && \
apt-get update -q && \
apt-get install -y --allow-downgrades \
firefox && \
apt-get autoclean && \
apt-get autoremove && \
rm -rf /var/lib/apt/lists/*


# Enable apt-get completion after running `apt-get update` in the container
RUN rm /etc/apt/apt.conf.d/docker-clean

COPY --chmod=755 ./vm.linux/buildcontainer/entry.sh /run/
#ENTRYPOINT ["/usr/bin/tini", "-s", "/run/entrypoint.sh"]
ENTRYPOINT [ "/bin/bash", "-c", "/run/entry.sh" ]

ENV USER ubuntu
ENV PASSWD ubuntu
20 changes: 20 additions & 0 deletions omnitool/omnibox/compose.linux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
services:
linux:
image: linux-local
container_name: omni-linux
privileged: true
environment:
RAM_SIZE: "8G"
CPU_CORES: "4"
DISK_SIZE: "20G"
devices:
- /dev/kvm
- /dev/net/tun
cap_add:
- NET_ADMIN
ports:
- 8006:80 # Web Viewer access
- 5000:5000 # Computer control server
volumes:
- ./vm.linux/storage:/data
- ./vm/win11setup/setupscripts/server:/controlserver # reuse the same server code for windows and linux
127 changes: 104 additions & 23 deletions omnitool/omnibox/scripts/manage_vm.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
#!/bin/bash

# Default VM type is windows if not specified
VM_TYPE="windows"

# Get the directory where the script is located
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Get the parent directory (omnibox directory)
OMNIBOX_DIR="$( cd "$SCRIPT_DIR/.." && pwd )"

create_vm() {
if ! docker images windows-local -q | grep -q .; then
local dockerfile="Dockerfile"
local compose_file="compose.yml"
local image_name="windows-local"

if [ "$VM_TYPE" == "linux" ]; then
dockerfile="Dockerfile.linux"
compose_file="compose.linux.yml"
image_name="linux-local"
fi

if ! docker images $image_name -q | grep -q .; then
echo "Image not found locally. Building..."
docker build -t windows-local ..
docker build --no-cache --pull -t $image_name -f "$OMNIBOX_DIR/$dockerfile" "$OMNIBOX_DIR"
else
echo "Image found locally. Skipping build."
fi

docker compose -f ../compose.yml up -d
docker compose -f "$OMNIBOX_DIR/$compose_file" up -d

# Wait for the VM to start up
while true; do
Expand All @@ -20,12 +38,39 @@ create_vm() {
sleep 5
done

echo "VM + server is up and running!"
echo "$VM_TYPE VM + server is up and running!"
}

start_vm() {
echo "Starting VM..."
docker compose -f ../compose.yml start
local compose_file="compose.yml"

if [ "$VM_TYPE" == "linux" ]; then
compose_file="compose.linux.yml"
fi

echo "Starting $VM_TYPE VM..."

# Show container status before starting
echo "Container status before starting:"
docker compose -f "$OMNIBOX_DIR/$compose_file" ps

# Start the containers
docker compose -f "$OMNIBOX_DIR/$compose_file" start

# Show container status after starting
echo "Container status after starting:"
docker compose -f "$OMNIBOX_DIR/$compose_file" ps

# Check if containers are running
if docker compose -f "$OMNIBOX_DIR/$compose_file" ps --status running | grep -q .; then
echo "Containers are running."
else
echo "Warning: No containers appear to be running. Check logs for details."
echo "Container logs:"
docker compose -f "$OMNIBOX_DIR/$compose_file" logs --tail=20
fi

# Uncomment this section if you want to wait for the server to respond
while true; do
response=$(curl --write-out '%{http_code}' --silent --output /dev/null localhost:5000/probe)
if [ $response -eq 200 ]; then
Expand All @@ -34,29 +79,70 @@ start_vm() {
echo "Waiting for a response from the computer control server"
sleep 5
done
echo "VM started"

echo "$VM_TYPE VM started"
}

stop_vm() {
echo "Stopping VM..."
docker compose -f ../compose.yml stop
echo "VM stopped"
local compose_file="compose.yml"

if [ "$VM_TYPE" == "linux" ]; then
compose_file="compose.linux.yml"
fi

echo "Stopping $VM_TYPE VM..."
docker compose -f "$OMNIBOX_DIR/$compose_file" stop
echo "$VM_TYPE VM stopped"
}

delete_vm() {
echo "Removing VM and associated containers..."
docker compose -f ../compose.yml down
echo "VM removed"
local compose_file="compose.yml"
local image_name="windows-local"

if [ "$VM_TYPE" == "linux" ]; then
compose_file="compose.linux.yml"
image_name="linux-local"
fi

echo "Removing $VM_TYPE VM and associated containers..."
docker compose -f "$OMNIBOX_DIR/$compose_file" down
docker rmi $image_name
echo "$VM_TYPE VM removed"
}

# Check if control parameter is provided
if [ -z "$1" ]; then
echo "Usage: $0 [create|start|stop|delete]"
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case "$1" in
create|start|stop|delete)
COMMAND="$1"
shift
;;
--linux)
VM_TYPE="linux"
shift
;;
--windows)
VM_TYPE="windows"
shift
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 [create|start|stop|delete] [--linux|--windows]"
exit 1
;;
esac
done

# Check if command is provided
if [ -z "$COMMAND" ]; then
echo "Usage: $0 [create|start|stop|delete] [--linux|--windows]"
echo " --linux Use Linux VM configuration (default is Windows)"
echo " --windows Use Windows VM configuration"
exit 1
fi

# Execute the appropriate function based on the control parameter
case "$1" in
# Execute the appropriate function based on the command
case "$COMMAND" in
"create")
create_vm
;;
Expand All @@ -69,9 +155,4 @@ case "$1" in
"delete")
delete_vm
;;
*)
echo "Invalid option: $1"
echo "Usage: $0 [create|start|stop|delete]"
exit 1
;;
esac
Loading