Skip to content
Snippets Groups Projects
Unverified Commit bbf40158 authored by Théo Zimmermann's avatar Théo Zimmermann
Browse files

Fetch student works in snapshots/

parent 0b2c2f50
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id:6d924ae8-e462-4c47-86d9-8560ecedf78f tags: %% Cell type:markdown id:6d924ae8-e462-4c47-86d9-8560ecedf78f tags:
# Coder management # Coder management
%% Cell type:code id:bb33cb2d-8256-4d65-9442-153a5eb920a6 tags: %% Cell type:code id:bb33cb2d-8256-4d65-9442-153a5eb920a6 tags:
``` python ``` python
import csv import csv
import json import json
import requests import requests
``` ```
%% Cell type:code id:991fc1f2-61d2-443f-901b-df6acf094287 tags: %% Cell type:code id:991fc1f2-61d2-443f-901b-df6acf094287 tags:
``` python ``` python
cluster_name='inf110' cluster_name='inf110'
proxyJump='ubuntu@137.194.210.143' proxyJump='ubuntu@137.194.210.143'
``` ```
%% Cell type:code id:ae9a0955-2a17-499a-827b-8dfe8be56d65 tags: %% Cell type:code id:ae9a0955-2a17-499a-827b-8dfe8be56d65 tags:
``` python ``` python
token,=!source openrc && echo $CODER_TOKEN token,=!source openrc && echo $CODER_TOKEN
``` ```
%% Cell type:code id:904c792f-2229-44cb-a98b-7714af05e163 tags: %% Cell type:code id:904c792f-2229-44cb-a98b-7714af05e163 tags:
``` python ``` python
response = requests.get("https://tp-inf110.r2.enst.fr/api/v2/buildinfo") response = requests.get("https://tp-inf110.r2.enst.fr/api/v2/buildinfo")
response.raise_for_status() response.raise_for_status()
buildinfo = response.json() buildinfo = response.json()
print(f"Version: {buildinfo['version']}") print(f"Version: {buildinfo['version']}")
print(f"URL: {buildinfo['dashboard_url']}") print(f"URL: {buildinfo['dashboard_url']}")
``` ```
%% Cell type:markdown id:463b7432-7861-44f6-8a42-36f453bf0a24 tags: %% Cell type:markdown id:463b7432-7861-44f6-8a42-36f453bf0a24 tags:
To retrieve the ID of the default organization, we can list the organizations of the admin user. To retrieve the ID of the default organization, we can list the organizations of the admin user.
%% Cell type:code id:3d2d2fe7-c20b-4e7d-a5da-e0c8021cb6f8 tags: %% Cell type:code id:3d2d2fe7-c20b-4e7d-a5da-e0c8021cb6f8 tags:
``` python ``` python
user="Zimmi48" user="Zimmi48"
response = requests.get(f"https://tp-inf110.r2.enst.fr/api/v2/users/{user}/organizations", headers={"Coder-Session-Token": token}) response = requests.get(f"https://tp-inf110.r2.enst.fr/api/v2/users/{user}/organizations", headers={"Coder-Session-Token": token})
response.raise_for_status() response.raise_for_status()
organizations = response.json() organizations = response.json()
print(f"Organizations: {organizations}") print(f"Organizations: {organizations}")
organization_id = organizations[0]['id'] organization_id = organizations[0]['id']
``` ```
%% Cell type:markdown id:19a552b0-8bf8-4cd8-86a1-135b7e2253ed tags: %% Cell type:markdown id:19a552b0-8bf8-4cd8-86a1-135b7e2253ed tags:
## Create workspace template ## Create workspace template
If it doesn't exist yet. Otherwise, retrieve the template and template version IDs. If it doesn't exist yet. Otherwise, retrieve the template and template version IDs.
%% Cell type:code id:b4db687e-3e52-448d-b4d7-8c812cdaa2f7 tags: %% Cell type:code id:b4db687e-3e52-448d-b4d7-8c812cdaa2f7 tags:
``` python ``` python
# Test if template exists # Test if template exists
response = requests.get(f"https://tp-inf110.r2.enst.fr/api/v2/organizations/{organization_id}/templates", headers={"Coder-Session-Token": token}) response = requests.get(f"https://tp-inf110.r2.enst.fr/api/v2/organizations/{organization_id}/templates", headers={"Coder-Session-Token": token})
response.raise_for_status() response.raise_for_status()
templates = response.json() templates = response.json()
if len(templates) == 1: if len(templates) == 1:
template_id = templates[0]['id'] template_id = templates[0]['id']
template_version = templates[0]['active_version_id'] template_version = templates[0]['active_version_id']
print(f"Template found: {template_id} (version {template_version})") print(f"Template found: {template_id} (version {template_version})")
elif len(templates) == 0: elif len(templates) == 0:
print("No template found. Creating one...") print("No template found. Creating one...")
# Create zip file to upload # Create zip file to upload
!cd inf110-workspace && zip "template.zip" "main.tf" "README.md" !cd inf110-workspace && zip "template.zip" "main.tf" "README.md"
# Upload template files # Upload template files
with open("inf110-workspace/template.zip", "rb") as f: with open("inf110-workspace/template.zip", "rb") as f:
response = requests.post( response = requests.post(
"https://tp-inf110.r2.enst.fr/api/v2/files", "https://tp-inf110.r2.enst.fr/api/v2/files",
headers={ headers={
"Coder-Session-Token": token, "Coder-Session-Token": token,
"Content-Type": "application/zip" "Content-Type": "application/zip"
}, },
data=f data=f
) )
response.raise_for_status() response.raise_for_status()
file_hash = response.json()['hash'] file_hash = response.json()['hash']
# Create template version # Create template version
version_name='INF110-2024' version_name='INF110-2024'
response = requests.post( response = requests.post(
f"https://tp-inf110.r2.enst.fr/api/v2/organizations/{organization_id}/templateversions", f"https://tp-inf110.r2.enst.fr/api/v2/organizations/{organization_id}/templateversions",
headers={"Coder-Session-Token": token}, headers={"Coder-Session-Token": token},
json={ json={
"name": version_name, "name": version_name,
"file_id": file_hash, "file_id": file_hash,
"storage_method": "file", "storage_method": "file",
"provisioner": "terraform" "provisioner": "terraform"
} }
) )
response.raise_for_status() response.raise_for_status()
template_version = response.json()['id'] template_version = response.json()['id']
# Create template # Create template
template_name='INF110' template_name='INF110'
display_name='TP INF110' display_name='TP INF110'
description="Espace de travail pour les TP d'INF110" description="Espace de travail pour les TP d'INF110"
response = requests.post( response = requests.post(
f"https://tp-inf110.r2.enst.fr/api/v2/organizations/{organization_id}/templates", f"https://tp-inf110.r2.enst.fr/api/v2/organizations/{organization_id}/templates",
headers={"Coder-Session-Token": token}, headers={"Coder-Session-Token": token},
json={ json={
"name": template_name, "name": template_name,
"display_name": display_name, "display_name": display_name,
"description": description, "description": description,
"icon": "/emojis/1f4d0.png", "icon": "/emojis/1f4d0.png",
"template_version_id": template_version "template_version_id": template_version
} }
) )
response.raise_for_status() response.raise_for_status()
template_id = response.json()['id'] template_id = response.json()['id']
print(f"Template created: {template_id} (version {template_version})") print(f"Template created: {template_id} (version {template_version})")
else: else:
raise ValueError("Multiple templates found") raise ValueError("Multiple templates found")
``` ```
%% Cell type:markdown id:e20dfefb-0359-421a-92c6-ab403de529dc tags: %% Cell type:markdown id:e20dfefb-0359-421a-92c6-ab403de529dc tags:
The query below can be used to check that the template creation was successful. The query below can be used to check that the template creation was successful.
%% Cell type:code id:1ae74b43-8065-4e5f-9976-e00a879d7c99 tags: %% Cell type:code id:1ae74b43-8065-4e5f-9976-e00a879d7c99 tags:
``` python ``` python
response = requests.get(f"https://tp-inf110.r2.enst.fr/api/v2/templateversions/{template_version}", headers={"Coder-Session-Token": token}) response = requests.get(f"https://tp-inf110.r2.enst.fr/api/v2/templateversions/{template_version}", headers={"Coder-Session-Token": token})
response.raise_for_status() response.raise_for_status()
template_version = response.json() template_version = response.json()
print(f"Template version: {template_version['job']['status']}") print(f"Template version: {template_version['job']['status']}")
``` ```
%% Cell type:markdown id:5d900272-a3ee-461c-9cdd-df08b17b1d2a tags: %% Cell type:markdown id:5d900272-a3ee-461c-9cdd-df08b17b1d2a tags:
## Create users ## Create users
%% Cell type:code id:02384bfa tags: %% Cell type:code id:02384bfa tags:
``` python ``` python
def create_users(): def create_users():
with open("users.csv") as f: with open("users.csv") as f:
reader = csv.reader(f) reader = csv.reader(f)
for email, username, password in reader: for email, username, password in reader:
response = requests.post( response = requests.post(
"https://tp-inf110.r2.enst.fr/api/v2/users", "https://tp-inf110.r2.enst.fr/api/v2/users",
headers={"Coder-Session-Token": token}, headers={"Coder-Session-Token": token},
json={ json={
"email": email, "email": email,
"login_type": "password", "login_type": "password",
"password": password, "password": password,
"username": username "username": username
} }
) )
response.raise_for_status() response.raise_for_status()
print(f"User {username} created") print(f"User {username} created")
#create_users() #create_users()
``` ```
%% Cell type:code id:9f05d75f-c300-49ca-9faf-19a1a24dd6d8 tags: %% Cell type:code id:9f05d75f-c300-49ca-9faf-19a1a24dd6d8 tags:
``` python ``` python
def create_user(email,username): def create_user(email,username):
passwords=!pwgen -s 10 -1 passwords=!pwgen -s 10 -1
password=passwords[0] password=passwords[0]
!echo "{email},{username},{password}" >> users.csv && \ !echo "{email},{username},{password}" >> users.csv && \
https POST "tp-inf110.r2.enst.fr/api/v2/users" "Coder-Session-Token:{token}" "email={email}" "login_type=password" "password={password}" "username={username}" https POST "tp-inf110.r2.enst.fr/api/v2/users" "Coder-Session-Token:{token}" "email={email}" "login_type=password" "password={password}" "username={username}"
#create_user("", "") #create_user("", "")
``` ```
%% Cell type:code id:96595327-81a0-4a50-b090-a79d75a3134d tags: %% Cell type:code id:96595327-81a0-4a50-b090-a79d75a3134d tags:
``` python ``` python
def create_student_accounts(csv_filename): def create_student_accounts(csv_filename):
with open("students_2024-2025.csv") as f: with open("students_2024-2025.csv") as f:
reader = csv.DictReader(f, delimiter=';') reader = csv.DictReader(f, delimiter=';')
for student in reader: for student in reader:
create_user(student['mail'], student['login'].split('@')[0]) create_user(student['mail'], student['login'].split('@')[0])
#create_student_accounts('students_2024-2025.csv') #create_student_accounts('students_2024-2025.csv')
``` ```
%% Cell type:markdown id:9868d906-ca8c-4fda-ad96-ec00bea5fadc tags: %% Cell type:markdown id:9868d906-ca8c-4fda-ad96-ec00bea5fadc tags:
## Delete users ## Delete users
(Requires having deleted their workspaces first.) (Requires having deleted their workspaces first.)
%% Cell type:code id:30a56dca-7f8f-4839-94e7-36340f5f199f tags: %% Cell type:code id:30a56dca-7f8f-4839-94e7-36340f5f199f tags:
``` python ``` python
def delete_user(username): def delete_user(username):
!https DELETE "tp-inf110.r2.enst.fr/api/v2/users/{username}" "Coder-Session-Token:{token}" !https DELETE "tp-inf110.r2.enst.fr/api/v2/users/{username}" "Coder-Session-Token:{token}"
#delete_user("bbinder") #delete_user("bbinder")
``` ```
%% Cell type:markdown id:d6d20c1f-e231-488c-90ef-2daa811e89a2 tags: %% Cell type:markdown id:d6d20c1f-e231-488c-90ef-2daa811e89a2 tags:
## Create workspaces ## Create workspaces
%% Cell type:code id:80ff8f4e-fa5f-4308-a885-e3d382e2a171 tags: %% Cell type:code id:80ff8f4e-fa5f-4308-a885-e3d382e2a171 tags:
``` python ``` python
def create_workspace(username, name='tp'): def create_workspace(username, name='tp'):
!https POST "tp-inf110.r2.enst.fr/api/v2/organizations/{organization_id}/members/{username}/workspaces" "Coder-Session-Token:{token}" "name={name}" "template_id={template_id}" !https POST "tp-inf110.r2.enst.fr/api/v2/organizations/{organization_id}/members/{username}/workspaces" "Coder-Session-Token:{token}" "name={name}" "template_id={template_id}"
#create_workspace("Zimmi48") #create_workspace("Zimmi48")
``` ```
%% Cell type:markdown id:d2cea793-4b57-4718-bd17-7cbda610d5bd tags: %% Cell type:markdown id:d2cea793-4b57-4718-bd17-7cbda610d5bd tags:
Test auto-scaling by creating many workspaces at once. Test auto-scaling by creating many workspaces at once.
%% Cell type:code id:e3d06f0c-3183-47e4-a63e-254a6c08612a tags: %% Cell type:code id:e3d06f0c-3183-47e4-a63e-254a6c08612a tags:
``` python ``` python
#for i in range(0,99): #for i in range(0,99):
# create_workspace('Zimmi48', 'autoscaling-test-%d' % i) # create_workspace('Zimmi48', 'autoscaling-test-%d' % i)
``` ```
%% Cell type:code id:11d58691-691b-41a8-bdbf-51d3b313b64f tags: %% Cell type:code id:11d58691-691b-41a8-bdbf-51d3b313b64f tags:
``` python ``` python
def create_student_workspaces(csv_filename): def create_student_workspaces(csv_filename):
with open(csv_filename, mode='r') as csv_file: with open(csv_filename, mode='r') as csv_file:
csv_reader = csv.DictReader(csv_file) csv_reader = csv.DictReader(csv_file)
for student in csv_reader: for student in csv_reader:
create_workspace(student['login']) create_workspace(student['login'])
#create_student_workspaces('students_2024-2025.csv') #create_student_workspaces('students_2024-2025.csv')
``` ```
%% Cell type:code id:f26e86ea tags: %% Cell type:code id:f26e86ea tags:
``` python ``` python
def create_user_workspaces(): def create_user_workspaces():
with open("users.csv") as f: with open("users.csv") as f:
reader = csv.reader(f) reader = csv.reader(f)
for _, username, _ in reader: for _, username, _ in reader:
create_workspace(username) create_workspace(username)
#create_user_workspaces() #create_user_workspaces()
``` ```
%% Cell type:markdown id:1b405071-7dd5-4082-80f2-dbd60ea46262 tags: %% Cell type:markdown id:1b405071-7dd5-4082-80f2-dbd60ea46262 tags:
## Start / stop all workspaces from a student group ## Start / stop all workspaces from a student group
%% Cell type:code id:e9be7a12-c858-4baf-9ac7-53827330798a tags: %% Cell type:code id:e9be7a12-c858-4baf-9ac7-53827330798a tags:
``` python ``` python
def get_student_username_list(csv_filename): def get_student_username_list(csv_filename):
students = [] students = []
with open(csv_filename, mode='r') as csv_file: with open(csv_filename, mode='r') as csv_file:
csv_reader = csv.DictReader(csv_file) csv_reader = csv.DictReader(csv_file)
for student in csv_reader: for student in csv_reader:
students += [student['login']] students += [student['login']]
return students return students
#groupB = get_student_username_list('inf110-2023-B.csv') #groupB = get_student_username_list('inf110-2023-B.csv')
#groupD = get_student_username_list('inf110-2023-D.csv') #groupD = get_student_username_list('inf110-2023-D.csv')
``` ```
%% Cell type:code id:1640ad41-d82c-4519-88d3-ef2c2cfc2950 tags: %% Cell type:code id:1640ad41-d82c-4519-88d3-ef2c2cfc2950 tags:
``` python ``` python
len(groupB) len(groupB)
``` ```
%% Cell type:code id:6b0b126a-b7e4-43c5-9aab-2c27931ebf91 tags: %% Cell type:code id:6b0b126a-b7e4-43c5-9aab-2c27931ebf91 tags:
``` python ``` python
len(groupD) len(groupD)
``` ```
%% Cell type:code id:b495de0f-d085-4db6-a8a4-9a022f345251 tags: %% Cell type:code id:b495de0f-d085-4db6-a8a4-9a022f345251 tags:
``` python ``` python
def stop_workspaces_from_group(group): def stop_workspaces_from_group(group):
workspaces = !https GET "tp-inf110.r2.enst.fr/api/v2/workspaces" "Coder-Session-Token:{token}" "limit==150" "q==status:running" -b | jq -cr '.workspaces | .[]' workspaces = !https GET "tp-inf110.r2.enst.fr/api/v2/workspaces" "Coder-Session-Token:{token}" "limit==150" "q==status:running" -b | jq -cr '.workspaces | .[]'
workspaces = list(map(json.loads, workspaces)) workspaces = list(map(json.loads, workspaces))
for workspace in [workspace['id'] for workspace in workspaces if workspace['owner_name'] in group]: for workspace in [workspace['id'] for workspace in workspaces if workspace['owner_name'] in group]:
!https POST "tp-inf110.r2.enst.fr/api/v2/workspaces/{workspace}/builds" "Coder-Session-Token:{token}" "transition=stop" !https POST "tp-inf110.r2.enst.fr/api/v2/workspaces/{workspace}/builds" "Coder-Session-Token:{token}" "transition=stop"
stop_workspaces_from_group(['Zimmi48']) stop_workspaces_from_group(['Zimmi48'])
``` ```
%% Cell type:code id:13f05a6e-f591-4bcd-9857-63f5a21f1028 tags: %% Cell type:code id:13f05a6e-f591-4bcd-9857-63f5a21f1028 tags:
``` python ``` python
def start_workspaces_from_group(group): def start_workspaces_from_group(group):
workspaces = !https GET "tp-inf110.r2.enst.fr/api/v2/workspaces" "Coder-Session-Token:{token}" "limit==150" "q==status:stopped" -b | jq -cr '.workspaces | .[]' workspaces = !https GET "tp-inf110.r2.enst.fr/api/v2/workspaces" "Coder-Session-Token:{token}" "limit==150" "q==status:stopped" -b | jq -cr '.workspaces | .[]'
workspaces = list(map(json.loads, workspaces)) workspaces = list(map(json.loads, workspaces))
for workspace in [workspace['id'] for workspace in workspaces if workspace['owner_name'] in group]: for workspace in [workspace['id'] for workspace in workspaces if workspace['owner_name'] in group]:
!https POST "tp-inf110.r2.enst.fr/api/v2/workspaces/{workspace}/builds" "Coder-Session-Token:{token}" "transition=start" "template_version_id={template_version}" !https POST "tp-inf110.r2.enst.fr/api/v2/workspaces/{workspace}/builds" "Coder-Session-Token:{token}" "transition=start" "template_version_id={template_version}"
start_workspaces_from_group(mitro) start_workspaces_from_group(mitro)
``` ```
%% Cell type:code id:fd82a694-ba4b-4dba-aab1-08d1d606f625 tags: %% Cell type:code id:fd82a694-ba4b-4dba-aab1-08d1d606f625 tags:
``` python ``` python
def start_all_workspaces(): def start_all_workspaces():
workspaces = !https GET "tp-inf110.r2.enst.fr/api/v2/workspaces" "Coder-Session-Token:{token}" "limit==150" "q==status:stopped" -b | jq -cr '.workspaces | .[]' workspaces = !https GET "tp-inf110.r2.enst.fr/api/v2/workspaces" "Coder-Session-Token:{token}" "limit==150" "q==status:stopped" -b | jq -cr '.workspaces | .[]'
workspaces = list(map(json.loads, workspaces)) workspaces = list(map(json.loads, workspaces))
for workspace in [workspace['id'] for workspace in workspaces]: for workspace in [workspace['id'] for workspace in workspaces]:
!https POST "tp-inf110.r2.enst.fr/api/v2/workspaces/{workspace}/builds" "Coder-Session-Token:{token}" "transition=start" "template_version_id={template_version}" !https POST "tp-inf110.r2.enst.fr/api/v2/workspaces/{workspace}/builds" "Coder-Session-Token:{token}" "transition=start" "template_version_id={template_version}"
start_all_workspaces() start_all_workspaces()
``` ```
%% Cell type:markdown id:e8e88940-8c7c-4b3c-8923-aaf0b813f524 tags: %% Cell type:markdown id:e8e88940-8c7c-4b3c-8923-aaf0b813f524 tags:
## Delete all workspaces and users from a student group ## Delete all workspaces and users from a student group
%% Cell type:code id:5c22d1b3-923f-45fd-ac04-9f404e5002b6 tags: %% Cell type:code id:5c22d1b3-923f-45fd-ac04-9f404e5002b6 tags:
``` python ``` python
def delete_workspaces_from_group(group): def delete_workspaces_from_group(group):
workspaces = !https GET "tp-inf110.r2.enst.fr/api/v2/workspaces" "Coder-Session-Token:{token}" "limit==150" "q==status:stopped" -b | jq -cr '.workspaces | .[]' workspaces = !https GET "tp-inf110.r2.enst.fr/api/v2/workspaces" "Coder-Session-Token:{token}" "limit==150" "q==status:stopped" -b | jq -cr '.workspaces | .[]'
workspaces = list(map(json.loads, workspaces)) workspaces = list(map(json.loads, workspaces))
for workspace in [workspace['id'] for workspace in workspaces if workspace['owner_name'] in group]: for workspace in [workspace['id'] for workspace in workspaces if workspace['owner_name'] in group]:
!https POST "tp-inf110.r2.enst.fr/api/v2/workspaces/{workspace}/builds" "Coder-Session-Token:{token}" "transition=delete" !https POST "tp-inf110.r2.enst.fr/api/v2/workspaces/{workspace}/builds" "Coder-Session-Token:{token}" "transition=delete"
delete_workspaces_from_group(['Zimmi48']) delete_workspaces_from_group(['Zimmi48'])
``` ```
%% Cell type:code id:eafaba21-fdf9-46e9-ba8f-bc1f25de96a4 tags: %% Cell type:code id:eafaba21-fdf9-46e9-ba8f-bc1f25de96a4 tags:
``` python ``` python
def delete_students(group): def delete_students(group):
for student in group: for student in group:
delete_user(student) delete_user(student)
delete_students(groupD) delete_students(groupD)
``` ```
%% Cell type:markdown id:12c57f21-23fe-4752-ad28-b05bd33ff08f tags: %% Cell type:markdown id:12c57f21-23fe-4752-ad28-b05bd33ff08f tags:
## Stop all unhealthy workspaces ## Stop all unhealthy workspaces
%% Cell type:code id:73ce34f9-b0ad-4434-b448-6e2fdcfed6bd tags: %% Cell type:code id:73ce34f9-b0ad-4434-b448-6e2fdcfed6bd tags:
``` python ``` python
def stop_unhealthy_workspaces(): def stop_unhealthy_workspaces():
workspaces = !https GET "tp-inf110.r2.enst.fr/api/v2/workspaces" "Coder-Session-Token:{token}" "limit==150" "q==status:running" -b | jq -cr '.workspaces | .[]' workspaces = !https GET "tp-inf110.r2.enst.fr/api/v2/workspaces" "Coder-Session-Token:{token}" "limit==150" "q==status:running" -b | jq -cr '.workspaces | .[]'
workspaces = list(map(json.loads, workspaces)) workspaces = list(map(json.loads, workspaces))
for workspace in [workspace for workspace in workspaces if not workspace['health']['healthy']]: for workspace in [workspace for workspace in workspaces if not workspace['health']['healthy']]:
!https POST "tp-inf110.r2.enst.fr/api/v2/workspaces/{workspace['id']}/builds" "Coder-Session-Token:{token}" "transition=stop" !https POST "tp-inf110.r2.enst.fr/api/v2/workspaces/{workspace['id']}/builds" "Coder-Session-Token:{token}" "transition=stop"
stop_unhealthy_workspaces() stop_unhealthy_workspaces()
``` ```
%% Cell type:markdown id:acd9cb0e-9596-4091-ae35-82a34ff9f0b4 tags: %% Cell type:markdown id:acd9cb0e-9596-4091-ae35-82a34ff9f0b4 tags:
## Check health of running workspaces ## Check health of running workspaces
%% Cell type:code id:6c4beb11-717a-4d89-b9a4-e9b033b3e6a4 tags: %% Cell type:code id:6c4beb11-717a-4d89-b9a4-e9b033b3e6a4 tags:
``` python ``` python
servers = {} servers = {}
``` ```
%% Cell type:code id:9bcdc633-0b28-46e4-aa54-97dc20f7d091 tags: %% Cell type:code id:9bcdc633-0b28-46e4-aa54-97dc20f7d091 tags:
``` python ``` python
healthy_workspaces = [] healthy_workspaces = []
unhealthy_workspaces = [] unhealthy_workspaces = []
workspaces = !https GET "tp-inf110.r2.enst.fr/api/v2/workspaces" "Coder-Session-Token:{token}" "limit==150" "q==status:running" -b | jq -cr '.workspaces | .[]' workspaces = !https GET "tp-inf110.r2.enst.fr/api/v2/workspaces" "Coder-Session-Token:{token}" "limit==150" "q==status:running" -b | jq -cr '.workspaces | .[]'
workspaces = list(map(json.loads, workspaces)) workspaces = list(map(json.loads, workspaces))
for workspace in workspaces: for workspace in workspaces:
if workspace['health']['healthy']: if workspace['health']['healthy']:
healthy_workspaces += [workspace['owner_name'].lower()] healthy_workspaces += [workspace['owner_name'].lower()]
else: else:
unhealthy_workspaces += [workspace['owner_name'].lower()] unhealthy_workspaces += [workspace['owner_name'].lower()]
``` ```
%% Cell type:code id:ffb92e49-aa8b-4371-bade-a06104020e32 tags: %% Cell type:code id:ffb92e49-aa8b-4371-bade-a06104020e32 tags:
``` python ``` python
print("Healthy workspaces: %d" % len(healthy_workspaces)) print("Healthy workspaces: %d" % len(healthy_workspaces))
print("Unhealthy workspaces: %d" % len(unhealthy_workspaces)) print("Unhealthy workspaces: %d" % len(unhealthy_workspaces))
``` ```
%% Cell type:code id:08d53bc7-fd70-4a7f-97d3-be5e737cdbaa tags: %% Cell type:code id:08d53bc7-fd70-4a7f-97d3-be5e737cdbaa tags:
``` python ``` python
volumes=!source openrc && openstack volume list --long -f json | jq -c '.[] | { id: .Name, name: .Properties."csi.storage.k8s.io/pvc/name", status: .Status, location: .Name, attached_to: ."Attached to" } | select(.name != null) | select(.name | startswith("coder-pvc-") and contains("-tp-inf110")) | { name: .id, username: .name | split("coder-pvc-") | .[1] | split("-tp-inf110") | .[0], status: .status, server_id: .attached_to[0].server_id, location: ("/var/lib/kubelet/plugins/kubernetes.io/csi/pv/" + .location + "/globalmount") }' volumes=!source openrc && openstack volume list --long -f json | jq -c '.[] | { id: .Name, name: .Properties."csi.storage.k8s.io/pvc/name", status: .Status, location: .Name, attached_to: ."Attached to" } | select(.name != null) | select(.name | startswith("coder-pvc-") and contains("-tp-inf110")) | { name: .id, username: .name | split("coder-pvc-") | .[1] | split("-tp-inf110") | .[0], status: .status, server_id: .attached_to[0].server_id, location: ("/var/lib/kubelet/plugins/kubernetes.io/csi/pv/" + .location + "/globalmount") }'
volumes = list(map(json.loads, volumes)) volumes = list(map(json.loads, volumes))
``` ```
%% Cell type:code id:c183542f-6abf-4fbe-8b64-386da87a2c95 tags: %% Cell type:code id:c183542f-6abf-4fbe-8b64-386da87a2c95 tags:
``` python ``` python
[volume for volume in volumes if volume['server_id'] is not None and not volume['username'] in healthy_workspaces] [volume for volume in volumes if volume['server_id'] is not None and not volume['username'] in healthy_workspaces]
``` ```
%% Cell type:code id:db003235-11d9-4386-b8fe-944955e5e257 tags: %% Cell type:code id:db003235-11d9-4386-b8fe-944955e5e257 tags:
``` python ``` python
for server in servers: for server in servers:
servers[server]['users'] = [] servers[server]['users'] = []
for volume in volumes: for volume in volumes:
if volume['server_id'] is not None: if volume['server_id'] is not None:
if not volume['server_id'] in servers: if not volume['server_id'] in servers:
ip,=!source openrc && openstack server show "{volume['server_id']}" -f json | jq -r '.addresses."{cluster_name}"[0]' ip,=!source openrc && openstack server show "{volume['server_id']}" -f json | jq -r '.addresses."{cluster_name}"[0]'
servers[volume['server_id']] = { 'ip': ip, 'users': [volume['username']] } servers[volume['server_id']] = { 'ip': ip, 'users': [volume['username']] }
else: else:
servers[volume['server_id']]['users'] += [volume['username']] servers[volume['server_id']]['users'] += [volume['username']]
``` ```
%% Cell type:code id:8cee7a31-4e22-4ff4-9b06-5c6b014ddea8 tags: %% Cell type:code id:8cee7a31-4e22-4ff4-9b06-5c6b014ddea8 tags:
``` python ``` python
for server in servers: for server in servers:
print("Server: " + servers[server]['ip']) print("Server: " + servers[server]['ip'])
for user in servers[server]['users']: for user in servers[server]['users']:
print('User: ' + user, end='') print('User: ' + user, end='')
if user in healthy_workspaces: if user in healthy_workspaces:
print(' (healthy)') print(' (healthy)')
elif user in unhealthy_workspaces: elif user in unhealthy_workspaces:
print(' (unhealthy)') print(' (unhealthy)')
else: else:
print(' (unknown)') print(' (unknown)')
print() print()
print() print()
``` ```
%% Cell type:markdown id:79725809-695a-4ab4-9e58-79bb747b8b05 tags: %% Cell type:markdown id:79725809-695a-4ab4-9e58-79bb747b8b05 tags:
## Clean workspaces ## Clean workspaces
%% Cell type:markdown id:a5032d9b-aff8-459d-91fb-1b49709c232b tags: %% Cell type:markdown id:a5032d9b-aff8-459d-91fb-1b49709c232b tags:
Note that the `StrictHostKeyChecking=no` below does not apply to the proxy jump. Make sure you connected at least once to the proxy jump before running the following cells. Note that the `StrictHostKeyChecking=no` below does not apply to the proxy jump. Make sure you connected at least once to the proxy jump before running the following cells.
%% Cell type:code id:1a29e39d-2abb-4b2a-b663-3455f956b46d tags: %% Cell type:code id:1a29e39d-2abb-4b2a-b663-3455f956b46d tags:
``` python ``` python
def remove_lost_found(): def remove_lost_found():
for volume in volumes: for volume in volumes:
if volume['server_id'] is not None: if volume['server_id'] is not None:
machine_ip = servers[volume['server_id']]['ip'] machine_ip = servers[volume['server_id']]['ip']
lost_found = volume['location'] + "/lost+found" lost_found = volume['location'] + "/lost+found"
command = "set -xe; " command = "set -xe; "
command += "if [ -d " + lost_found + " ]; then rmdir -v " + lost_found + "; else echo 'No lost+found to remove'; fi; " command += "if [ -d " + lost_found + " ]; then rmdir -v " + lost_found + "; else echo 'No lost+found to remove'; fi; "
!ssh -o StrictHostKeyChecking=no -J {proxyJump} core@{machine_ip} sudo sh -c "\"{command}\"" !ssh -o StrictHostKeyChecking=no -J {proxyJump} core@{machine_ip} sudo sh -c "\"{command}\""
remove_lost_found() remove_lost_found()
``` ```
%% Cell type:markdown id:75661986-3bb2-42b0-abe6-1a5f18ea9615 tags: %% Cell type:markdown id:75661986-3bb2-42b0-abe6-1a5f18ea9615 tags:
## Copy / update files in workspace ## Copy / update files in workspace
%% Cell type:code id:13d7c970-4863-4fac-bb58-722bb9c27f34 tags: %% Cell type:code id:13d7c970-4863-4fac-bb58-722bb9c27f34 tags:
``` python ``` python
past_versions = { past_versions = {
'tp1.ipynb': [ 'tp1.ipynb': [
'e6f11284e2ba7d4a01350a1f2c0ab208', 'e6f11284e2ba7d4a01350a1f2c0ab208',
'c208201a6aaf72f102fbd2cf46b62e5b', 'c208201a6aaf72f102fbd2cf46b62e5b',
], ],
'tp2.mv': [ 'tp2.mv': [
'b3b2a3e7a8dde6ed8848300158d89e5d', 'b3b2a3e7a8dde6ed8848300158d89e5d',
'60a26b6a7d07579f63f6054c24b87ea2', '60a26b6a7d07579f63f6054c24b87ea2',
'190845731e26037dcbc7e3a74d239b1b', '190845731e26037dcbc7e3a74d239b1b',
'd010ae9ab0188b4cc77a3d5a45df2f1a', 'd010ae9ab0188b4cc77a3d5a45df2f1a',
], ],
'tp3.mv': [ 'tp3.mv': [
'91621d47a84e460e567dc51dfe1fcf45', '91621d47a84e460e567dc51dfe1fcf45',
], ],
'tp4.mv': [ 'tp4.mv': [
'a819a3d31373750cfcb8473a27cd5c3f', 'a819a3d31373750cfcb8473a27cd5c3f',
], ],
'tp5.mv': [], 'tp5.mv': [],
'settings.json': [ 'settings.json': [
'aca81e70023acea605dd44e829d04339', # Autogenerated by coq-lsp 'aca81e70023acea605dd44e829d04339', # Autogenerated by coq-lsp
'7378b13908523bfde3692518f61939cf', '7378b13908523bfde3692518f61939cf',
'2c2178abd6661d10ae492bf6fdc0454b', '2c2178abd6661d10ae492bf6fdc0454b',
'350ac51d8fea466958d9986c96c84842', '350ac51d8fea466958d9986c96c84842',
'ded5f984f385aa61ef30e01fef43f3e4', 'ded5f984f385aa61ef30e01fef43f3e4',
'8f3c325edd4f635fdaee9175701216df', '8f3c325edd4f635fdaee9175701216df',
'3ddc1036917034cec13503b74d3b051e', '3ddc1036917034cec13503b74d3b051e',
], ],
"_CoqProject": [], "_CoqProject": [],
} }
location = "inf110-workspace-contents/" location = "inf110-workspace-contents/"
``` ```
%% Cell type:code id:876c1a46-9dd4-4f4c-8a4e-185dc361d5a1 tags: %% Cell type:code id:876c1a46-9dd4-4f4c-8a4e-185dc361d5a1 tags:
``` python ``` python
current_version = { current_version = {
'tp1.ipynb': '009c42561f1853af966f95e9dcee9c24', 'tp1.ipynb': '009c42561f1853af966f95e9dcee9c24',
'tp2.mv': '78139922e6b6a531e7e70acc98c1019c', 'tp2.mv': '78139922e6b6a531e7e70acc98c1019c',
'tp3.mv': '0a0253e4825146da6f08eff073b10444', 'tp3.mv': '0a0253e4825146da6f08eff073b10444',
'tp4.mv': '203ce16afa53d60cfd8390fb3fb7d898', 'tp4.mv': '203ce16afa53d60cfd8390fb3fb7d898',
'tp5.mv': '3ec8626aa544cb075af1f78719a1fb48', 'tp5.mv': '3ec8626aa544cb075af1f78719a1fb48',
'settings.json': 'e8d0dd9b56ca76a521ef4d097b1d8ab9', 'settings.json': 'e8d0dd9b56ca76a521ef4d097b1d8ab9',
'_CoqProject': 'b1d60da8dd98106e00006d99428d1403', '_CoqProject': 'b1d60da8dd98106e00006d99428d1403',
} }
``` ```
%% Cell type:code id:a8f0c5e5-f995-43bd-9cb8-08099e6ea8fa tags: %% Cell type:code id:a8f0c5e5-f995-43bd-9cb8-08099e6ea8fa tags:
``` python ``` python
def copy_update_file(filename): def copy_update_file(filename):
file_hash, = !md5sum {location + filename} | cut -f1 -d' ' file_hash, = !md5sum {location + filename} | cut -f1 -d' '
if file_hash != current_version[filename]: if file_hash != current_version[filename]:
print("Hash of " + filename + " has changed. Please update past_versions and current_version. New hash is " + file_hash) print("Hash of " + filename + " has changed. Please update past_versions and current_version. New hash is " + file_hash)
return return
for server in servers: for server in servers:
!scp -o StrictHostKeyChecking=no -J {proxyJump} {location + filename} core@{servers[server]['ip']}:/tmp !scp -o StrictHostKeyChecking=no -J {proxyJump} {location + filename} core@{servers[server]['ip']}:/tmp
for volume in volumes: for volume in volumes:
if volume['server_id'] is not None: if volume['server_id'] is not None:
machine_ip = servers[volume['server_id']]['ip'] machine_ip = servers[volume['server_id']]['ip']
!ssh -J {proxyJump} core@{machine_ip} sudo cp -nv /tmp/{filename} {volume['location']} !ssh -J {proxyJump} core@{machine_ip} sudo cp -nv /tmp/{filename} {volume['location']}
file_hash, = !ssh -J {proxyJump} core@{machine_ip} sudo md5sum {volume['location'] + "/" + filename} | cut -f1 -d' ' file_hash, = !ssh -J {proxyJump} core@{machine_ip} sudo md5sum {volume['location'] + "/" + filename} | cut -f1 -d' '
if file_hash in past_versions[filename]: if file_hash in past_versions[filename]:
!ssh -J {proxyJump} core@{machine_ip} sudo cp -v /tmp/{filename} {volume['location']} !ssh -J {proxyJump} core@{machine_ip} sudo cp -v /tmp/{filename} {volume['location']}
!ssh -J {proxyJump} core@{machine_ip} sudo chmod go+rw {volume['location'] + "/" + filename} !ssh -J {proxyJump} core@{machine_ip} sudo chmod go+rw {volume['location'] + "/" + filename}
copy_update_file("tp1.ipynb") copy_update_file("tp1.ipynb")
copy_update_file("_CoqProject") copy_update_file("_CoqProject")
copy_update_file("tp2.mv") copy_update_file("tp2.mv")
copy_update_file("tp3.mv") copy_update_file("tp3.mv")
copy_update_file("tp4.mv") copy_update_file("tp4.mv")
copy_update_file("tp5.mv") copy_update_file("tp5.mv")
``` ```
%% Cell type:code id:13608dc8-78f6-41d3-9cc3-f96c603a9437 tags: %% Cell type:code id:13608dc8-78f6-41d3-9cc3-f96c603a9437 tags:
``` python ``` python
def copy_read_only_file(filename): def copy_read_only_file(filename):
for server in servers: for server in servers:
!scp -J {proxyJump} -o StrictHostKeyChecking=no {location + filename} core@{servers[server]['ip']}:/tmp !scp -J {proxyJump} -o StrictHostKeyChecking=no {location + filename} core@{servers[server]['ip']}:/tmp
for volume in volumes: for volume in volumes:
if volume['server_id'] is not None: if volume['server_id'] is not None:
machine_ip = servers[volume['server_id']]['ip'] machine_ip = servers[volume['server_id']]['ip']
!ssh -J {proxyJump} core@{machine_ip} sudo cp -v /tmp/{filename} {volume['location']} !ssh -J {proxyJump} core@{machine_ip} sudo cp -v /tmp/{filename} {volume['location']}
copy_read_only_file('README.md') copy_read_only_file('README.md')
#copy_read_only_file("tp1-mysterious-tm.png") #copy_read_only_file("tp1-mysterious-tm.png")
``` ```
%% Cell type:code id:4cc929db-08fe-4b7b-9293-d86b7124f7cf tags: %% Cell type:code id:4cc929db-08fe-4b7b-9293-d86b7124f7cf tags:
``` python ``` python
def copy_vscode_settings(): def copy_vscode_settings():
file_hash, = !md5sum {location + "settings.json"} | cut -f1 -d' ' file_hash, = !md5sum {location + "settings.json"} | cut -f1 -d' '
if file_hash != current_version['settings.json']: if file_hash != current_version['settings.json']:
print("Hash of settings.json has changed. Please update past_versions and current_version. New hash is " + file_hash) print("Hash of settings.json has changed. Please update past_versions and current_version. New hash is " + file_hash)
return return
for server in servers: for server in servers:
!scp -J {proxyJump} -o StrictHostKeyChecking=no {location + "settings.json"} core@{servers[server]['ip']}:/tmp !scp -J {proxyJump} -o StrictHostKeyChecking=no {location + "settings.json"} core@{servers[server]['ip']}:/tmp
for volume in volumes: for volume in volumes:
if volume['server_id'] is not None: if volume['server_id'] is not None:
machine_ip = servers[volume['server_id']]['ip'] machine_ip = servers[volume['server_id']]['ip']
vscode = volume['location'] + "/.vscode" vscode = volume['location'] + "/.vscode"
command = "set -xe; " command = "set -xe; "
command += "if [ ! -d " + vscode + " ]; then mkdir " + vscode + "; fi; " command += "if [ ! -d " + vscode + " ]; then mkdir " + vscode + "; fi; "
command += "cp -nv /tmp/settings.json " + vscode + "/settings.json; " command += "cp -nv /tmp/settings.json " + vscode + "/settings.json; "
!ssh -J {proxyJump} core@{machine_ip} sudo sh -c "\"{command}\"" !ssh -J {proxyJump} core@{machine_ip} sudo sh -c "\"{command}\""
file_hash, = !ssh -J {proxyJump} core@{machine_ip} sudo md5sum {vscode + "/settings.json"} | cut -f1 -d' ' file_hash, = !ssh -J {proxyJump} core@{machine_ip} sudo md5sum {vscode + "/settings.json"} | cut -f1 -d' '
if file_hash in past_versions['settings.json']: if file_hash in past_versions['settings.json']:
!ssh -J {proxyJump} core@{machine_ip} sudo cp -v /tmp/settings.json {vscode} !ssh -J {proxyJump} core@{machine_ip} sudo cp -v /tmp/settings.json {vscode}
!ssh -J {proxyJump} core@{machine_ip} sudo chmod go+rw {vscode + "/settings.json"} !ssh -J {proxyJump} core@{machine_ip} sudo chmod go+rw {vscode + "/settings.json"}
copy_vscode_settings() copy_vscode_settings()
``` ```
%% Cell type:markdown id:55bd39c3-794e-43f2-8bf0-342361d61b64 tags: %% Cell type:markdown id:55bd39c3-794e-43f2-8bf0-342361d61b64 tags:
## Save snapshots of modified files ## Save snapshots of modified files
%% Cell type:code id:db436f12-abb7-4b48-9e66-2f6ada19bdff tags: %% Cell type:code id:db436f12-abb7-4b48-9e66-2f6ada19bdff tags:
``` python ``` python
def snapshot(filename, snapshot_name): def snapshot(filename, snapshot_name):
!mkdir -p {snapshot_name} !mkdir -p {snapshot_name}
for volume in volumes: for volume in volumes:
if volume['server_id'] is not None: if volume['server_id'] is not None:
machine_ip = servers[volume['server_id']]['ip'] machine_ip = servers[volume['server_id']]['ip']
file_hash, = !ssh -o StrictHostKeyChecking=no -J {proxyJump} core@{machine_ip} sudo md5sum {volume['location'] + "/" + filename} | cut -f1 -d' ' file_hash, = !ssh -o StrictHostKeyChecking=no -J {proxyJump} core@{machine_ip} sudo md5sum {volume['location'] + "/" + filename} | cut -f1 -d' '
if not file_hash == current_version[filename] and not file_hash in past_versions[filename]: if not file_hash == current_version[filename] and not file_hash in past_versions[filename]:
snapshot_filename = "/tmp/" + volume['username'] + "-" + snapshot_name + "-" + filename snapshot_filename = "/tmp/" + volume['username'] + "-" + filename
!ssh -J {proxyJump} core@{machine_ip} sudo cp {volume['location'] + "/" + filename} {snapshot_filename} !ssh -J {proxyJump} core@{machine_ip} sudo cp {volume['location'] + "/" + filename} {snapshot_filename}
!scp -J {proxyJump} core@{machine_ip}:{snapshot_filename} {snapshot_name + "/" + volume['username'] + "_" + filename} !scp -J {proxyJump} core@{machine_ip}:{snapshot_filename} {snapshot_name + "/" + volume['username'] + "_" + filename}
#snapshot('tp1.ipynb', '2023-12-04-post-tp') snapshot('tp1.ipynb', 'snapshots/2024-12-18')
#snapshot('tp2.mv', '2023-12-13-post-tp') snapshot('tp2.mv', 'snapshots/2024-12-18')
#snapshot('tp3.mv', '2023-12-13-post-tp') snapshot('tp3.mv', 'snapshots/2024-12-18')
#snapshot('tp4.mv', '2024-01-12-post-tp')
#snapshot('tp5.mv', '2024-01-22-post-tp')
``` ```
%% Cell type:code id:35af9e82-e79c-4ad9-a843-3ebaab9f4d62 tags: %% Cell type:code id:35af9e82-e79c-4ad9-a843-3ebaab9f4d62 tags:
``` python ``` python
``` ```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment