You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

325 lines
12 KiB

  1. # -*- encoding: utf-8 -*-
  2. import PySimpleGUI as sg
  3. import ovh
  4. client = ovh.Client()
  5. service = client.get('/cloud/project')[0]
  6. service_url = f'/cloud/project/{service}'
  7. # regions = [f['region'] for f in flavors if f['name'] == 's1-2']
  8. regions = ['GRA7', 'SBG5', 'DE1', 'UK1', 'BHS5']
  9. def get_flavor_id(region, name='s1-2'):
  10. flavors = client.get(service_url + '/flavor')
  11. flavorId = [f['id'] for f in flavors if f['name']
  12. == name and f['region'] == region][0]
  13. return flavorId
  14. def get_image_id(region, name='Ubuntu 20.04'):
  15. images = client.get(service_url + '/image')
  16. imageId = [i['id'] for i in images if i['name']
  17. == name and i['region'] == region][0]
  18. return imageId
  19. def get_eleves():
  20. ovh_ssh_keys = client.get(service_url + '/sshkey')
  21. liste_eleves = [(k['id'], k['name'].split('_')[1], k['publicKey'])
  22. for k in ovh_ssh_keys
  23. if k['name'].startswith('ssh_')]
  24. return liste_eleves
  25. def delete_eleve(eleve_id):
  26. client.delete(service_url + '/sshkey/' + eleve_id)
  27. def create_eleve(prenom, publicKey):
  28. client.post(service_url + '/sshkey',
  29. name='ssh_' + prenom,
  30. publicKey=publicKey
  31. )
  32. def get_instances():
  33. ovh_instances = client.get(service_url + '/instance')
  34. instances = []
  35. for i in ovh_instances:
  36. id_inst = i['id']
  37. name = i['name']
  38. if not name.startswith('eica-'):
  39. continue
  40. if i['ipAddresses']:
  41. ip = i['ipAddresses'][0]['ip']
  42. else:
  43. ip = 'Waiting...'
  44. region = i['region']
  45. status = i['status']
  46. instances.append((id_inst, name, ip, region, status,))
  47. return instances
  48. def create_instance(eleve_id, name, region):
  49. image_id = get_image_id(region)
  50. flavor_id = get_flavor_id(region)
  51. client.post(service_url + '/instance',
  52. name='eica-' + name,
  53. sshKeyId=eleve_id,
  54. flavorId=flavor_id,
  55. imageId=image_id,
  56. region=region
  57. )
  58. def delete_instance(instance_id):
  59. print(service_url + '/instance/' + instance_id)
  60. client.delete(service_url + '/instance/' + instance_id)
  61. def make_main_window():
  62. liste_eleves = get_eleves()
  63. liste_instances = get_instances()
  64. col = [
  65. [sg.Button('Ajouter', size=(12, 1))],
  66. [sg.Button('Modifier', size=(12, 1))],
  67. [sg.Button('Supprimer', size=(12, 1))],
  68. [sg.Combo(regions, size=(12, 1), default_value=regions[0], k='region')],
  69. [sg.Button('Instancier', size=(12, 1),
  70. button_color=('white', 'green'))],
  71. [sg.Button('Quitter', size=(12, 1))],
  72. ]
  73. col1 = [
  74. [sg.Table(values=liste_instances,
  75. headings=['id', 'Nom', 'Adresse IP', 'Région', 'Statut'],
  76. max_col_width=25,
  77. col_widths=[0, 15, 12, 10, 10],
  78. hide_vertical_scroll=True,
  79. background_color='light blue',
  80. text_color='black',
  81. auto_size_columns=False,
  82. justification='right',
  83. num_rows=len(liste_instances),
  84. alternating_row_color='lightyellow',
  85. key='table_instances',
  86. tooltip='Liste des instances actives')],
  87. ]
  88. col2 = [
  89. [sg.Button('Détruire', size=(12, 1), button_color=('white', 'red'))],
  90. [sg.Button('Actualiser', size=(12, 1))],
  91. ]
  92. layout = [
  93. [sg.Text('Liste des élèves')],
  94. [sg.Table(values=liste_eleves,
  95. headings=['', 'Prénom', ''],
  96. max_col_width=25,
  97. col_widths=[0, 20, 0],
  98. hide_vertical_scroll=True,
  99. background_color='light blue',
  100. text_color='black',
  101. auto_size_columns=False,
  102. justification='right',
  103. num_rows=len(liste_eleves),
  104. alternating_row_color='lightyellow',
  105. key='table_eleves',
  106. tooltip='Liste des élèves'),
  107. sg.Column(col),
  108. sg.Column(col1),
  109. sg.Column(col2)],
  110. ]
  111. window = sg.Window('OVH - Gestion des instances',
  112. layout=layout,
  113. size=(900, 300),
  114. finalize=True)
  115. window.liste_eleves = liste_eleves
  116. window.liste_instances = liste_instances
  117. return window
  118. def make_add_window(caption, role='create', initial_values=None):
  119. if initial_values:
  120. eleve_id, prenom, pk = initial_values
  121. else:
  122. eleve_id = prenom = pk = ''
  123. layout = [
  124. [sg.InputText(eleve_id, k='eleve_id', visible=False)],
  125. [sg.Text(text='Prénom', size=(10, 2)), sg.InputText(
  126. default_text=prenom, size=(20, 2), k='prenom')],
  127. [sg.Text(text='Clé publique', size=(10, 2)), sg.InputText(
  128. default_text=pk, size=(20, 2), k='pk')],
  129. [sg.Button('Valider', bind_return_key=True),
  130. sg.Button('Annuler', bind_return_key=True)]
  131. ]
  132. window = sg.Window(caption,
  133. layout=layout,
  134. finalize=True)
  135. window.role = role
  136. return window
  137. window1, window2 = make_main_window(), None
  138. while True:
  139. window, event, values = sg.read_all_windows()
  140. print(f'window : {window}, event : {event}, values : {values}')
  141. if window == window1:
  142. if event in (sg.WIN_CLOSED, 'Quitter'):
  143. break
  144. if event == 'Ajouter':
  145. window2 = make_add_window('Ajouter', role='create')
  146. window2.make_modal()
  147. if event == 'Supprimer':
  148. try:
  149. # dans le cas d'un tableau, la valeur est un tableau de(s)
  150. # index sélectionnés. On garde le premier quoi qu'il arrive
  151. selected_line = values['table_eleves'][0]
  152. # la colonne id est cachée au niveau de l'affichage
  153. id_eleve = window1.liste_eleves[selected_line][0]
  154. except IndexError:
  155. sg.popup_ok(
  156. 'Veuillez sélectionner un enregistrement à supprimer')
  157. continue
  158. confirmation = sg.popup("Confirmez-vous la suppression ?",
  159. button_type=sg.POPUP_BUTTONS_OK_CANCEL,
  160. custom_text=("Oui", "Non"))
  161. if confirmation == "Non":
  162. continue
  163. sg.PopupAnimated("sablier.png")
  164. delete_eleve(id_eleve)
  165. liste_eleves = get_eleves()
  166. sg.PopupAnimated(None)
  167. window1['table_eleves'].update(values=liste_eleves,
  168. num_rows=len(liste_eleves))
  169. window1.liste_eleves = liste_eleves
  170. if event == 'Modifier':
  171. try:
  172. # voir 'Supprimer' pour une explication
  173. selected_line = values['table_eleves'][0]
  174. id_eleve, prenom, pk = window1.liste_eleves[selected_line]
  175. except IndexError:
  176. sg.popup_ok(
  177. 'Veuillez sélectionner un enregistrement à modifier')
  178. continue
  179. window2 = make_add_window('Modifier',
  180. initial_values=[id_eleve, prenom, pk],
  181. role='modify')
  182. window2.make_modal()
  183. if event == 'Instancier':
  184. selected_lines = values['table_eleves']
  185. if len(selected_lines) == 0:
  186. sg.popup_ok(
  187. 'Veuillez sélectionner un élève')
  188. continue
  189. eleves = []
  190. for row in selected_lines:
  191. id_eleve = window1.liste_eleves[row][0]
  192. prenom = window1.liste_eleves[row][1]
  193. eleves.append((id_eleve, prenom,))
  194. nb_inst = len(eleves)
  195. confirmation = sg.popup(f"Confirmez-vous le lancement de {nb_inst} instances ?",
  196. button_type=sg.POPUP_BUTTONS_OK_CANCEL,
  197. custom_text=("Oui", "Non"))
  198. if confirmation == "Non":
  199. continue
  200. sg.PopupAnimated("sablier.png")
  201. for el in eleves:
  202. active_instances_names = [i[1].split(
  203. '-')[1] for i in window1.liste_instances]
  204. if not el[1] in active_instances_names:
  205. create_instance(el[0], el[1], values['region'])
  206. liste_instances = get_instances()
  207. sg.PopupAnimated(None)
  208. window1['table_instances'].update(values=liste_instances,
  209. num_rows=len(liste_instances))
  210. window1.liste_instances = liste_instances
  211. if event == 'Détruire':
  212. selected_lines = values['table_instances']
  213. if len(selected_lines) == 0:
  214. sg.popup_ok(
  215. 'Veuillez sélectionner une instance au moins')
  216. continue
  217. instances = []
  218. for row in selected_lines:
  219. instances.append(window1.liste_instances[row][0])
  220. nb_inst = len(instances)
  221. confirmation = sg.popup(f"Confirmez-vous la suppression de {nb_inst} instances ?",
  222. button_type=sg.POPUP_BUTTONS_OK_CANCEL,
  223. custom_text=("Oui", "Non"))
  224. if confirmation == "Non":
  225. continue
  226. sg.PopupAnimated("sablier.png")
  227. for id_inst in instances:
  228. delete_instance(id_inst)
  229. liste_instances = get_instances()
  230. sg.PopupAnimated(None)
  231. window1['table_instances'].update(values=liste_instances,
  232. num_rows=len(liste_instances))
  233. window1.liste_instances = liste_instances
  234. if event == 'Actualiser':
  235. sg.PopupAnimated("sablier.png")
  236. liste_instances = get_instances()
  237. sg.PopupAnimated(None)
  238. window1['table_instances'].update(values=liste_instances,
  239. num_rows=len(liste_instances))
  240. window1.liste_instances = liste_instances
  241. if window == window2:
  242. if event in (sg.WIN_CLOSED, 'Annuler'):
  243. window2.close()
  244. window2 = None
  245. if event == 'Valider' and window.role == 'create':
  246. prenom = values['prenom'].lower() # TODO : accents ?
  247. pk = values['pk']
  248. create_eleve(prenom, pk)
  249. liste_eleves = get_eleves()
  250. window1['table_eleves'].update(values=liste_eleves,
  251. num_rows=len(liste_eleves))
  252. window1.liste_eleves = liste_eleves
  253. window2.close()
  254. window2 = None
  255. if event == 'Valider' and window.role == 'modify':
  256. confirmation = sg.popup("Confirmez-vous la modification ?",
  257. button_type=sg.POPUP_BUTTONS_OK_CANCEL,
  258. custom_text=("Oui", "Non"))
  259. if confirmation == "Non":
  260. continue
  261. prenom = values['prenom'].lower()
  262. pk = values['pk']
  263. eleve_id = values['eleve_id']
  264. delete_eleve(eleve_id)
  265. create_eleve(prenom, pk)
  266. liste_eleves = get_eleves()
  267. window1['table_eleves'].update(values=liste_eleves,
  268. num_rows=len(liste_eleves))
  269. window1.liste_eleves = liste_eleves
  270. window2.close()
  271. window2 = None
  272. window1.close()
  273. if window2 is not None:
  274. window2.close()
  275. print('Bye !')