Created
November 18, 2021 13:12
-
-
Save bphucc/ad6741da88478c149d3e0ebd4c96f10b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import apt, apt.debfile | |
import pathlib, stat, shutil, urllib.request, subprocess, getpass, time, tempfile | |
import secrets, json, re | |
import IPython.utils.io | |
import ipywidgets | |
import os | |
from IPython.display import clear_output | |
class _NoteProgress(apt.progress.base.InstallProgress, apt.progress.base.AcquireProgress, apt.progress.base.OpProgress): | |
def __init__(self): | |
apt.progress.base.InstallProgress.__init__(self) | |
self._label = ipywidgets.Label() | |
display(self._label) | |
self._float_progress = ipywidgets.FloatProgress(min = 0.0, max = 1.0, layout = {'border':'1px solid #118800'}) | |
display(self._float_progress) | |
def close(self): | |
self._float_progress.close() | |
self._label.close() | |
def fetch(self, item): | |
self._label.value = "fetch: " + item.shortdesc | |
def pulse(self, owner): | |
self._float_progress.value = self.current_items / self.total_items | |
return True | |
def status_change(self, pkg, percent, status): | |
self._label.value = "%s: %s" % (pkg, status) | |
self._float_progress.value = percent / 100.0 | |
def update(self, percent=None): | |
self._float_progress.value = self.percent / 100.0 | |
self._label.value = self.op + ": " + self.subop | |
def done(self, item=None): | |
pass | |
class _MyApt: | |
def __init__(self): | |
self._progress = _NoteProgress() | |
self._cache = apt.Cache(self._progress) | |
def close(self): | |
self._cache.close() | |
self._cache = None | |
self._progress.close() | |
self._progress = None | |
def update_upgrade(self): | |
self._cache.update() | |
self._cache.open(None) | |
self._cache.upgrade() | |
def commit(self): | |
self._cache.commit(self._progress, self._progress) | |
self._cache.clear() | |
def installPkg(self, *args): | |
for name in args: | |
pkg = self._cache[name] | |
if pkg.is_installed: | |
print(f"{name} is already installed") | |
else: | |
pkg.mark_install() | |
def installDebPackage(self, name): | |
apt.debfile.DebPackage(name, self._cache).install() | |
def deleteInstalledPkg(self, *args): | |
for pkg in self._cache: | |
if pkg.is_installed: | |
for name in args: | |
if pkg.name.startswith(name): | |
#print(f"Delete {pkg.name}") | |
pkg.mark_delete() | |
def _download(url, path): | |
try: | |
with urllib.request.urlopen(url) as response: | |
with open(path, 'wb') as outfile: | |
shutil.copyfileobj(response, outfile) | |
except: | |
print("Failed to download ", url) | |
raise | |
def _get_gpu_name(): | |
r = subprocess.run(["nvidia-smi", "--query-gpu=name", "--format=csv,noheader"], stdout = subprocess.PIPE, universal_newlines = True) | |
if r.returncode != 0: | |
return None | |
return r.stdout.strip() | |
def _check_gpu_available(): | |
gpu_name = _get_gpu_name() | |
if gpu_name == None: | |
print("This is not a runtime with GPU") | |
else: | |
return True | |
return True | |
def _setupSSHDImpl(ngrok_token, ngrok_region, is_VNC): | |
msg = "" | |
if not os.path.exists('ngrok.zip'): | |
_download("https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip", "ngrok.zip") | |
shutil.unpack_archive("ngrok.zip") | |
pathlib.Path("ngrok").chmod(stat.S_IXUSR) | |
root_password = "12345678" | |
user_password = "12345678" | |
user_name = "colab" | |
msg += "✂️"*24 + "\n" | |
msg += f"root password: {root_password}\n" | |
msg += f"{user_name} password: {user_password}\n" | |
msg += "✂️"*24 + "\n" | |
subprocess.run(["useradd", "-s", "/bin/bash", "-m", user_name]) | |
subprocess.run(["adduser", user_name, "sudo"], check = True) | |
subprocess.run(["chpasswd"], input = f"root:{root_password}", universal_newlines = True) | |
subprocess.run(["chpasswd"], input = f"{user_name}:{user_password}", universal_newlines = True) | |
if not pathlib.Path('/root/.ngrok2/ngrok.yml').exists(): | |
subprocess.run(["./ngrok", "authtoken", ngrok_token]) | |
ngrok_proc = subprocess.Popen(["./ngrok", "tcp", "-region", ngrok_region, "5901"]) | |
time.sleep(2) | |
with urllib.request.urlopen("http://localhost:4040/api/tunnels") as response: | |
url = json.load(response)['tunnels'][0]['public_url'] | |
m = re.match("tcp://(.+):(\d+)", url) | |
hostname = m.group(1) | |
port = m.group(2) | |
if is_VNC: | |
msg += "Ready to Connect TurboVNC viewer:\n" | |
msg += f"{hostname}:{port}\n" | |
return msg | |
def _setupSSHDMain(ngrok_region, check_gpu_available, is_VNC): | |
if check_gpu_available and not _check_gpu_available(): | |
return (False, "") | |
gpu_name = _get_gpu_name() | |
if gpu_name == None: | |
print("------------------------------") | |
ngrok_token = "" | |
clear_output() | |
if not ngrok_region: | |
print("Select your ngrok region :") | |
print("us - United States (Ohio)") | |
print("eu - Europe (Frankfurt)") | |
print("ap - Asia/Pacific (Singapore)") | |
print("au - Australia (Sydney)") | |
print("sa - South America (Sao Paulo)") | |
print("jp - Japan (Tokyo)") | |
print("in - India (Mumbai)") | |
ngrok_region = region = input() | |
clear_output() | |
apps() | |
return (True, _setupSSHDImpl(ngrok_token, ngrok_region, is_VNC)) | |
def _setup_nvidia_gl(): | |
ret = subprocess.run( | |
["nvidia-smi", "--query-gpu=driver_version", "--format=csv,noheader"], | |
stdout = subprocess.PIPE, | |
check = True, | |
universal_newlines = True) | |
nvidia_version = ret.stdout.strip() | |
nvidia_url = "https://us.download.nvidia.com/tesla/{0}/NVIDIA-Linux-x86_64-{0}.run".format(nvidia_version) | |
_download(nvidia_url, "nvidia.run") | |
pathlib.Path("nvidia.run").chmod(stat.S_IXUSR) | |
subprocess.run(["./nvidia.run", "--no-kernel-module", "--ui=none"], input = "1\n", check = True, universal_newlines = True) | |
#https://virtualgl.org/Documentation/HeadlessNV | |
subprocess.run(["nvidia-xconfig", | |
"-a", | |
"--allow-empty-initial-configuration", | |
"--virtual=1920x1200", | |
"--busid", "PCI:0:4:0"], | |
check = True | |
) | |
with open("/etc/X11/xorg.conf", "r") as f: | |
conf = f.read() | |
conf = re.sub('(Section "Device".*?)(EndSection)', | |
'\\1 MatchSeat "seat-1"\n\\2', | |
conf, | |
1, | |
re.DOTALL) | |
with open("/etc/X11/xorg.conf", "w") as f: | |
f.write(conf) | |
subprocess.run(["/opt/VirtualGL/bin/vglserver_config", "-config", "+s", "+f"], check = True) | |
subprocess.Popen(["Xorg", "-seat", "seat-1", "-allowMouseOpenFail", "-novtswitch", "-nolisten", "tcp"]) | |
def _setupVNC(): | |
libjpeg_ver = "2.0.5" | |
virtualGL_ver = "2.6.4" | |
turboVNC_ver = "2.2.5" | |
libjpeg_url = "https://github.com/demotomohiro/turbovnc/releases/download/2.2.5/libjpeg-turbo-official_{0}_amd64.deb".format(libjpeg_ver) | |
virtualGL_url = "https://github.com/demotomohiro/turbovnc/releases/download/2.2.5/virtualgl_{0}_amd64.deb".format(virtualGL_ver) | |
turboVNC_url = "https://github.com/demotomohiro/turbovnc/releases/download/2.2.5/turbovnc_{0}_amd64.deb".format(turboVNC_ver) | |
_download(libjpeg_url, "libjpeg-turbo.deb") | |
_download(virtualGL_url, "virtualgl.deb") | |
_download(turboVNC_url, "turbovnc.deb") | |
my_apt = _MyApt() | |
my_apt.installDebPackage("libjpeg-turbo.deb") | |
my_apt.installDebPackage("virtualgl.deb") | |
my_apt.installDebPackage("turbovnc.deb") | |
my_apt.commit() | |
my_apt.close() | |
vnc_sec_conf_p = pathlib.Path("/etc/turbovncserver-security.conf") | |
vnc_sec_conf_p.write_text("""\ | |
no-remote-connections | |
no-httpd | |
no-x11-tcp-connections | |
""") | |
gpu_name = _get_gpu_name() | |
if gpu_name != None: | |
_setup_nvidia_gl() | |
vncrun_py = tempfile.gettempdir() / pathlib.Path("vncrun.py") | |
vncrun_py.write_text("""\ | |
import subprocess, secrets, pathlib | |
vnc_passwd = "12345678"[:8] | |
vnc_viewonly_passwd = "87654321"[:8] | |
print("✂️"*24) | |
print("VNC password: {}".format(vnc_passwd)) | |
print("VNC view only password: {}".format(vnc_viewonly_passwd)) | |
print("✂️"*24) | |
vncpasswd_input = "{0}\\n{1}".format(vnc_passwd, vnc_viewonly_passwd) | |
vnc_user_dir = pathlib.Path.home().joinpath(".vnc") | |
vnc_user_dir.mkdir(exist_ok=True) | |
vnc_user_passwd = vnc_user_dir.joinpath("passwd") | |
with vnc_user_passwd.open('wb') as f: | |
subprocess.run( | |
["/opt/TurboVNC/bin/vncpasswd", "-f"], | |
stdout=f, | |
input=vncpasswd_input, | |
universal_newlines=True) | |
vnc_user_passwd.chmod(0o600) | |
subprocess.run( | |
["/opt/TurboVNC/bin/vncserver"], | |
cwd = pathlib.Path.home() | |
) | |
#Disable screensaver because no one would want it. | |
(pathlib.Path.home() / ".xscreensaver").write_text("mode: off\\n") | |
""") | |
r = subprocess.run( | |
["su", "-c", "python3 " + str(vncrun_py), "colab"], | |
check = True, | |
stdout = subprocess.PIPE, | |
universal_newlines = True) | |
return r.stdout | |
def setupVNC(ngrok_region = None, check_gpu_available = True): | |
stat, msg = _setupSSHDMain(ngrok_region, check_gpu_available, True) | |
if stat: | |
msg += _setupVNC() | |
clear_output() | |
_check_gpu_available() | |
print(msg) | |
def apps(): | |
!sudo add-apt-repository ppa:qbittorrent-team/qbittorrent-stable -y | |
#!sudo apt-get update && sudo apt-get install qbittorrent -y | |
clear_output() | |
my_apt = _MyApt() | |
my_apt.installPkg("qbittorrent", "firefox", "xarchiver", "xfce4", "xfce4-goodies") | |
my_apt.commit() | |
clear_output() | |
setupVNC() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment