Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Added tailscale support #30

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ usage: clearml-session [-h] [--version] [--attach [ATTACH]]
[--queue-include-tag [QUEUE_INCLUDE_TAG [QUEUE_INCLUDE_TAG ...]]]
[--skip-docker-network [true/false]]
[--password PASSWORD] [--username USERNAME]
[--force_dropbear [true/false]] [--verbose] [--yes]
[--force_dropbear [true/false]] [--verbose] [--yes] [--tailscale]

clearml-session - CLI for launching JupyterLab / VSCode on a remote machine

Expand Down Expand Up @@ -354,6 +354,7 @@ optional arguments:
e.g. the remote machine setup process log
--yes, -y Automatic yes to prompts; assume "yes" as answer to
all prompts and run non-interactively
--tailscale Use tailscale to network (host and client need tailscale access)

Notice! all arguments are stored as new defaults for the next session
```
4 changes: 4 additions & 0 deletions clearml_session/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,7 @@ def clone_task(state, project_id=None):
task_params["{}/vscode_version".format(section)] = state.get('vscode_version') or ''
task_params["{}/vscode_extensions".format(section)] = state.get('vscode_extensions') or ''
task_params["{}/force_dropbear".format(section)] = bool(state.get('force_dropbear'))
task_params["{}/tailscale".format(section)] = bool(state.get('tailscale'))
if state.get('user_folder'):
task_params['{}/user_base_directory'.format(section)] = state.get('user_folder')
docker = state.get('docker') or task.get_base_docker()
Expand Down Expand Up @@ -1087,6 +1088,9 @@ def setup_parser(parser):
action='store_true', default=False,
help='Automatic yes to prompts; assume \"yes\" as answer '
'to all prompts and run non-interactively',)
parser.add_argument('--tailscale',
action='store_true', default=False,
help='Use tailscale to network (host and client need tailscale access)',)


def get_version():
Expand Down
29 changes: 29 additions & 0 deletions clearml_session/interactive_session_task.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import base64
import ipaddress
import json
import os
import socket
Expand Down Expand Up @@ -910,6 +911,33 @@ def setup_user_env(param, task):


def get_host_name(task, param):
hostname = []
hostnames = []


if task.get_parameter(name='interactive_session/tailscale'):
def get_tailscale_interfaces():
interfaces = psutil.net_if_addrs()
tailscale_address = None
for interface_name, interface_addresses in interfaces.items():
for address in interface_addresses:
if "tailscale" in interface_name:
print(address)
try:
ipaddress.IPv4Address(address.address)
except ValueError:
pass
else:
tailscale_address = address.address
return tailscale_address

tl_addr = get_tailscale_interfaces()
if tl_addr:
hostname = tl_addr
hostnames = tl_addr
task.set_parameter(name='properties/external_address', value=str(tl_addr))
return hostname, hostnames

# noinspection PyBroadException
try:
hostname = socket.gethostname()
Expand Down Expand Up @@ -1014,6 +1042,7 @@ def main():
"public_ip": False,
"ssh_ports": None,
"force_dropbear": False,
"tailscale": False
}
task = init_task(param, default_ssh_fingerprint)

Expand Down