Skip to content

Commit c4a382e

Browse files
committed
fixes
1 parent b9865bc commit c4a382e

File tree

1 file changed

+149
-8
lines changed

1 file changed

+149
-8
lines changed

bota/src/bota/vm.py

Lines changed: 149 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def wait_till_up(ip):
6464
Exception: If the IP is not up after 180 seconds.
6565
"""
6666
timeout = 180 # Total time to wait in seconds
67-
interval = 10 # Time to wait between checks in seconds
67+
interval = 1 # Time to wait between checks in seconds
6868
elapsed_time = 0
6969

7070
while elapsed_time <= timeout:
@@ -100,7 +100,7 @@ def remove_empty_lines(text):
100100
def validateRepository(git_repo_url):
101101
"""Checks if a GitHub repository exists. Raises an exception if not."""
102102
try:
103-
response = requests.head(git_repo_url)
103+
response = requests.head(git_repo_url, allow_redirects=True, timeout=20)
104104
response.raise_for_status()
105105
except requests.exceptions.RequestException as e:
106106
if "Not Found" in str(e):
@@ -341,16 +341,16 @@ def setup_apache_load_balancer():
341341

342342
def setup_systemctl(folder_name, uname):
343343
systemctl_commands=f"""
344-
sudo a2enmod proxy
345-
sudo a2enmod proxy_http
346-
sudo systemctl restart apache2
347344
sudo chmod +x /home/{uname}/{folder_name}/backend.sh || true
348345
sudo chmod +x /home/{uname}/{folder_name}/frontend.sh || true
349346
sudo systemctl daemon-reload
350347
sudo systemctl enable backend.service
351348
sudo systemctl start backend.service
352349
sudo systemctl enable frontend.service
353350
sudo systemctl start frontend.service
351+
sudo a2enmod proxy
352+
sudo a2enmod proxy_http
353+
sudo systemctl restart apache2
354354
"""
355355
subprocess.run(remove_empty_lines(systemctl_commands), shell=True,
356356
check=True,
@@ -456,7 +456,6 @@ def setup_systemctl_for_data_scraper(launch_file_path, service_name):
456456

457457
def install_scraper(git_repo_url, folder_name, max_retry):
458458
uname = get_username()
459-
460459
install_chrome(uname)
461460
clone_repository(git_repo_url, folder_name)
462461

@@ -469,7 +468,7 @@ def install_scraper(git_repo_url, folder_name, max_retry):
469468
def install_ui_scraper_in_vm(git_repo_url, folder_name):
470469
validateRepository(git_repo_url)
471470
install_ui_scraper(git_repo_url, folder_name)
472-
click.echo("Successfully installed the Scraper.")
471+
click.echo("Successfully installed the Web Scraper.")
473472
click.echo("Now, Checking VM Status...")
474473
ip = get_vm_ip()
475474
wait_till_up(ip)
@@ -480,7 +479,149 @@ def install_scraper_in_vm(git_repo_url, folder_name, max_retry):
480479
install_scraper(git_repo_url, folder_name, max_retry)
481480
click.echo("Successfully installed the Scraper.")
482481
# todo check status is it running or error?
483-
# if error show it
482+
def get_filename_from_url(url):
483+
from urllib.parse import urlparse
484+
return os.path.basename(urlparse(url).path.rstrip("/"))
485+
486+
def install_desktop_app_in_vm(
487+
debian_installer_url,
488+
port,
489+
skip_apache_request_routing,
490+
api_path_prefix
491+
):
492+
# Validate api_path_prefix
493+
api_path_prefix = api_path_prefix if api_path_prefix else ""
494+
if api_path_prefix:
495+
if not api_path_prefix.startswith("/"):
496+
api_path_prefix = "/" + api_path_prefix
497+
if api_path_prefix.endswith("/"):
498+
api_path_prefix = api_path_prefix[:-1]
499+
500+
# Validate URL
501+
validate_url(debian_installer_url)
502+
503+
# Install the app
504+
uname = get_username()
505+
install_chrome(uname)
506+
default_name = get_filename_from_url(debian_installer_url)
507+
508+
delete_installer(default_name)
509+
wget_command = f"wget {debian_installer_url}"
510+
subprocess.run(wget_command, shell=True, check=True, stderr=subprocess.STDOUT)
511+
install_command = f"sudo apt --fix-broken install ./{default_name} -y"
512+
subprocess.run(install_command, shell=True, check=True, stderr=subprocess.STDOUT)
513+
package_name = subprocess.check_output(f"dpkg-deb -f ./{default_name} Package", shell=True).decode().strip()
514+
delete_installer(default_name)
515+
516+
# Create systemd service for Xvfb
517+
xvfb_service_name = f"xvfb.service"
518+
xvfb_service_content = f"""[Unit]
519+
Description=Xvfb Service
520+
After=network.target
521+
[Service]
522+
Type=simple
523+
User={uname}
524+
ExecStart=/usr/bin/Xvfb -ac :99 -screen 0 1280x1024x16
525+
Restart=no
526+
[Install]
527+
WantedBy=multi-user.target"""
528+
write_file_sudo(xvfb_service_content, f"/etc/systemd/system/{xvfb_service_name}")
529+
530+
# Create systemd service for the package
531+
package_service_name = f"{package_name}.service"
532+
package_service_content = f"""[Unit]
533+
Description={package_name} Service
534+
After=network.target
535+
StartLimitInterval=0
536+
[Service]
537+
Type=simple
538+
User={uname}
539+
Environment="DISPLAY=:99"
540+
ExecStart=/usr/bin/{package_name} --port {port} {'--api_path_prefix ' + api_path_prefix if api_path_prefix else ''}
541+
Restart=on-failure
542+
RestartSec=10
543+
[Install]
544+
WantedBy=multi-user.target"""
545+
write_file_sudo(package_service_content, f"/etc/systemd/system/{package_service_name}")
546+
547+
if not skip_apache_request_routing:
548+
setup_apache_load_balancer_desktop_app(port, api_path_prefix)
549+
550+
# Enable and start services
551+
systemctl_commands = f"""
552+
sudo systemctl daemon-reload
553+
sudo systemctl enable {xvfb_service_name}
554+
sudo systemctl start {xvfb_service_name}
555+
sudo systemctl enable {package_service_name}
556+
sudo systemctl start {package_service_name}"""
557+
if not skip_apache_request_routing:
558+
systemctl_commands += """
559+
sudo a2enmod proxy
560+
sudo a2enmod proxy_http
561+
sudo systemctl restart apache2"""
562+
subprocess.run(remove_empty_lines(systemctl_commands), shell=True, check=True, stderr=subprocess.STDOUT)
563+
564+
click.echo("Successfully installed the Desktop App.")
565+
click.echo("Now, Checking API Status...")
566+
ip = get_vm_ip()
567+
wait_till_desktop_api_up(ip, api_path_prefix)
568+
click.echo(f"Hurray! your desktop app is up and running. Visit http://{ip}{api_path_prefix}/ to see the API Docs.")
569+
570+
def delete_installer(default_name):
571+
if os.path.exists(default_name):
572+
os.remove(default_name)
573+
574+
def setup_apache_load_balancer_desktop_app(port, api_path_prefix):
575+
apache_conf = f"""<VirtualHost *:80>
576+
ServerAdmin webmaster@localhost
577+
DocumentRoot /var/www/html
578+
ErrorLog ${{APACHE_LOG_DIR}}/error.log
579+
CustomLog ${{APACHE_LOG_DIR}}/access.log combined
580+
ProxyPass {api_path_prefix}/ http://127.0.0.1:{port}{api_path_prefix}/
581+
ProxyPassReverse {api_path_prefix}/ http://127.0.0.1:{port}{api_path_prefix}/
582+
</VirtualHost>"""
583+
write_file_sudo(apache_conf, "/etc/apache2/sites-available/000-default.conf")
584+
585+
def validate_url(url):
586+
try:
587+
response = requests.head(url, allow_redirects=True, timeout=20)
588+
response.raise_for_status()
589+
except requests.exceptions.RequestException as e:
590+
raise Exception(f"URL validation failed: {e}")
591+
592+
def wait_till_desktop_api_up(ip, api_path_prefix):
593+
"""
594+
Polls the given IP address every 10 seconds for 180 seconds to check if it's up.
595+
596+
Args:
597+
ip (str): The IP address to check.
598+
api_path_prefix (str): The API path prefix.
599+
600+
Raises:
601+
Exception: If the IP is not up after 180 seconds.
602+
"""
603+
timeout = 180 # Total time to wait in seconds
604+
interval = 1 # Time to wait between checks in seconds
605+
elapsed_time = 0
606+
607+
while elapsed_time <= timeout:
608+
try:
609+
# Attempt to connect to the IP address
610+
response = requests.get(f"http://{ip}{api_path_prefix}/ui/app-props", timeout=5)
611+
612+
# If the response is successful, return without raising an exception
613+
if response.status_code == 200:
614+
return
615+
except requests.ConnectionError:
616+
# If a connection error occurs, just wait and try again
617+
pass
618+
619+
time.sleep(interval)
620+
elapsed_time += interval
621+
622+
# If the function hasn't returned after the loop, raise an exception
623+
raise Exception(f"The Desktop App at http://{ip}/ is not up after {timeout} seconds.")
624+
484625
# python -m bota.vm
485626
if __name__ == "__main__":
486627
pass

0 commit comments

Comments
 (0)