Quellcode durchsuchen

initial_commit

main
Fabien Toune vor 3 Jahren
Commit
f3dd764963
4 geänderte Dateien mit 456 neuen und 0 gelöschten Zeilen
  1. +134
    -0
      .gitignore
  2. +7
    -0
      ovh_.conf
  3. +315
    -0
      ovh_management.py
  4. BIN
     

+ 134
- 0
.gitignore Datei anzeigen

@@ -0,0 +1,134 @@
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
.vscode/
*.sqlite3
ovh.conf

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/


+ 7
- 0
ovh_.conf Datei anzeigen

@@ -0,0 +1,7 @@
[default]
endpoint=ovh-eu

[ovh-eu]
application_key=
application_secret=
consumer_key=

+ 315
- 0
ovh_management.py Datei anzeigen

@@ -0,0 +1,315 @@
# -*- encoding: utf-8 -*-
import PySimpleGUI as sg
import ovh

client = ovh.Client()
service = client.get('/cloud/project')[0]
service_url = f'/cloud/project/{service}'

# regions = [f['region'] for f in flavors if f['name'] == 's1-2']
regions = ['GRA7', 'SBG5', 'DE1', 'UK1', 'BHS5']


def get_flavor_id(region, name='s1-2'):
flavors = client.get(service_url + '/flavor')
flavorId = [f['id'] for f in flavors if f['name'] == name and f['region']==region][0]
return flavorId

def get_image_id(region, name='Ubuntu 20.04'):
images = client.get(service_url + '/image')
imageId = [i['id'] for i in images if i['name']==name and i['region']==region][0]
return imageId

def get_eleves():
ovh_ssh_keys = client.get(service_url + '/sshkey')
liste_eleves = [(k['id'], k['name'].split('_')[1], k['publicKey'])
for k in ovh_ssh_keys
if k['name'].startswith('ssh_')]
return liste_eleves

def delete_eleve(eleve_id):
client.delete(service_url + '/sshkey/' + eleve_id)

def create_eleve(prenom, publicKey):
client.post(service_url + '/sshkey',
name = 'ssh_' + prenom,
publicKey = publicKey
)

def get_instances():
ovh_instances = client.get(service_url + '/instance')
instances = []
for i in ovh_instances:
id_inst = i['id']
name = i['name']
if not name.startswith('eica-'):
continue
if i['ipAddresses']:
ip = i['ipAddresses'][0]['ip']
else:
ip = 'Waiting...'
region = i['region']
status = i['status']
instances.append((id_inst, name, ip, region, status,))
return instances

def create_instance(eleve_id, name, region):
image_id = get_image_id(region)
flavor_id = get_flavor_id(region)
client.post(service_url + '/instance',
name = 'eica-' + name,
sshKeyId = eleve_id,
flavorId = flavor_id,
imageId = image_id,
region = region
)

def delete_instance(instance_id):
print(service_url + '/instance/' + instance_id)
client.delete(service_url + '/instance/' + instance_id)

def make_main_window():
liste_eleves = get_eleves()
liste_instances = get_instances()
col = [
[sg.Button('Ajouter', size=(12, 1))],
[sg.Button('Modifier', size=(12, 1))],
[sg.Button('Supprimer', size=(12, 1))],
[sg.Combo(regions, size=(12, 1), default_value=regions[0], k='region')],
[sg.Button('Instancier', size=(12, 1), button_color=('white', 'green'))],
[sg.Button('Quitter', size=(12, 1))],
]
col1 = [
[sg.Table(values=liste_instances,
headings=['id', 'Nom', 'Adresse IP', 'Région', 'Statut'],
max_col_width=25,
col_widths=[0, 15, 12, 10, 10],
hide_vertical_scroll=True,
background_color='light blue',
text_color='black',
auto_size_columns=False,
justification='right',
num_rows=len(liste_instances),
alternating_row_color='lightyellow',
key='table_instances',
tooltip='Liste des instances actives')],
]
col2 = [
[sg.Button('Détruire', size=(12, 1), button_color=('white', 'red'))],
[sg.Button('Actualiser', size=(12, 1))],
]
layout = [
[sg.Text('Liste des élèves')],
[sg.Table(values=liste_eleves,
headings=['', 'Prénom', ''],
max_col_width=25,
col_widths=[0, 20, 0],
hide_vertical_scroll=True,
background_color='light blue',
text_color='black',
auto_size_columns=False,
justification='right',
num_rows=len(liste_eleves),
alternating_row_color='lightyellow',
key='table_eleves',
tooltip='Liste des élèves'),
sg.Column(col),
sg.Column(col1),
sg.Column(col2)],
]
window = sg.Window('OVH - Gestion des instances',
layout=layout,
size=(900, 300),
finalize=True)
window.liste_eleves = liste_eleves
window.liste_instances = liste_instances
return window


def make_add_window(caption, role='create', initial_values=None):
if initial_values:
eleve_id, prenom, pk = initial_values
else:
eleve_id = prenom = pk = ''
layout = [
[sg.InputText(eleve_id, k='eleve_id', visible=True)],
[sg.Text(text='Prénom', size=(10, 2)), sg.InputText(
default_text=prenom, size=(20, 2), k='prenom')],
[sg.Text(text='Clé publique', size=(10, 2)), sg.InputText(
default_text=pk, size=(20, 2), k='pk')],
[sg.Button('Valider', bind_return_key=True),
sg.Button('Annuler', bind_return_key=True)]
]
window = sg.Window(caption,
layout=layout,
finalize=True)
window.role = role
return window


window1, window2 = make_main_window(), None

while True:
window, event, values = sg.read_all_windows()
print(f'window : {window}, event : {event}, values : {values}')
if window == window1:
if event in (sg.WIN_CLOSED, 'Quitter'):
break

if event == 'Ajouter':
window2 = make_add_window('Ajouter', role='create')
window2.make_modal()

if event == 'Supprimer':
try:
# dans le cas d'un tableau, la valeur est un tableau de(s)
# index sélectionnés. On garde le premier quoi qu'il arrive
selected_line = values['table_eleves'][0]
# la colonne id est cachée au niveau de l'affichage
id_eleve = window1.liste_eleves[selected_line][0]
except IndexError:
sg.popup_ok(
'Veuillez sélectionner un enregistrement à supprimer')
continue
confirmation = sg.popup("Confirmez-vous la suppression ?",
button_type=sg.POPUP_BUTTONS_OK_CANCEL,
custom_text=("Oui", "Non"))
if confirmation == "Non":
continue
sg.PopupAnimated("sablier.png")
delete_eleve(id_eleve)
liste_eleves = get_eleves()

sg.PopupAnimated(None)
window1['table_eleves'].update(values=liste_eleves,
num_rows=len(liste_eleves))
window1.liste_eleves = liste_eleves

if event == 'Modifier':
try:
# voir 'Supprimer' pour une explication
selected_line = values['table_eleves'][0]
id_eleve, prenom, pk = window1.liste_eleves[selected_line]
except IndexError:
sg.popup_ok(
'Veuillez sélectionner un enregistrement à modifier')
continue
window2 = make_add_window('Modifier',
initial_values=[id_eleve, prenom, pk],
role='modify')
window2.make_modal()
if event == 'Instancier':
selected_lines = values['table_eleves']
if len(selected_lines) == 0:
sg.popup_ok(
'Veuillez sélectionner un élève')
continue
eleves = []
for row in selected_lines:
id_eleve = window1.liste_eleves[row][0]
prenom = window1.liste_eleves[row][1]
eleves.append((id_eleve, prenom,))
nb_inst = len(eleves)
confirmation = sg.popup(f"Confirmez-vous le lancement de {nb_inst} instances ?",
button_type=sg.POPUP_BUTTONS_OK_CANCEL,
custom_text=("Oui", "Non"))
if confirmation == "Non":
continue

sg.PopupAnimated("sablier.png")
for el in eleves:
active_instances_names = [i[1].split('-')[1] for i in window1.liste_instances]
if not el[1] in active_instances_names:
create_instance(el[0], el[1], values['region'])
liste_instances = get_instances()

sg.PopupAnimated(None)

window1['table_instances'].update(values=liste_instances,
num_rows=len(liste_instances))
window1.liste_instances = liste_instances

if event == 'Détruire':
selected_lines = values['table_instances']
if len(selected_lines) == 0:
sg.popup_ok(
'Veuillez sélectionner une instance au moins')
continue
instances = []
for row in selected_lines:
instances.append(window1.liste_instances[row][0])
nb_inst = len(instances)
confirmation = sg.popup(f"Confirmez-vous la suppression de {nb_inst} instances ?",
button_type=sg.POPUP_BUTTONS_OK_CANCEL,
custom_text=("Oui", "Non"))
if confirmation == "Non":
continue
sg.PopupAnimated("sablier.png")

for id_inst in instances:
delete_instance(id_inst)


liste_instances = get_instances()

sg.PopupAnimated(None)

window1['table_instances'].update(values=liste_instances,
num_rows=len(liste_instances))
window1.liste_instances = liste_instances


if event == 'Actualiser':
sg.PopupAnimated("sablier.png")
liste_instances = get_instances()
sg.PopupAnimated(None)
window1['table_instances'].update(values=liste_instances,
num_rows=len(liste_instances))
window1.liste_instances = liste_instances


if window == window2:
if event in (sg.WIN_CLOSED, 'Annuler'):
window2.close()
window2 = None

if event == 'Valider' and window.role == 'create':
prenom = values['prenom'].lower() # TODO : accents ?
pk = values['pk']
create_eleve(prenom, pk)
liste_eleves = get_eleves()
window1['table_eleves'].update(values=liste_eleves,
num_rows=len(liste_eleves))
window1.liste_eleves = liste_eleves
window2.close()
window2 = None

if event == 'Valider' and window.role == 'modify':
confirmation = sg.popup("Confirmez-vous la modification ?",
button_type=sg.POPUP_BUTTONS_OK_CANCEL,
custom_text=("Oui", "Non"))
if confirmation == "Non":
continue
prenom = values['prenom'].lower()
pk = values['pk']
eleve_id = values['eleve_id']
delete_eleve(eleve_id)
create_eleve(prenom, pk)
liste_eleves = get_eleves()
window1['table_eleves'].update(values=liste_eleves,
num_rows=len(liste_eleves))
window1.liste_eleves = liste_eleves
window2.close()
window2 = None

window1.close()
if window2 is not None:
window2.close()

print('Bye !')


Laden…
Abbrechen
Speichern