25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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