Reupload (purge)
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,533 @@
|
||||
from datetime import date
|
||||
from typing import Iterator, Callable
|
||||
|
||||
|
||||
class Service:
|
||||
"""
|
||||
Un service deploye.
|
||||
"""
|
||||
|
||||
__slots__ = ('_nom', '_port', '_protocole', '_critique')
|
||||
|
||||
def __init__(self, nom: str, port: int, protocole: str, *, critique: bool = False):
|
||||
self._nom = nom
|
||||
self._port = port
|
||||
self._protocole = protocole
|
||||
self._critique = critique
|
||||
|
||||
def est_critique(self) -> bool:
|
||||
"""Ce service est-il critique pour le SI?"""
|
||||
return self._critique
|
||||
|
||||
def ecoute_sur(self, port: int) -> bool:
|
||||
"""Ce service ecoute-t-il sur ce port?"""
|
||||
return self._port == port
|
||||
|
||||
def utilise_protocole(self, protocole: str) -> bool:
|
||||
"""Ce service utilise-t-il ce protocole?"""
|
||||
return self._protocole.lower() == protocole.lower()
|
||||
|
||||
def __eq__(self, autre: object) -> bool:
|
||||
if not isinstance(autre, Service):
|
||||
return NotImplemented
|
||||
return self._nom == autre._nom and self._port == autre._port
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Service({self._nom!r}, {self._port}, {self._protocole!r}, critique={self._critique})"
|
||||
|
||||
|
||||
class Services:
|
||||
"""
|
||||
Une collection de services. Encapsule la logique de gestion.
|
||||
Cet objet sait filtrer, compter, itérer sur ses services.
|
||||
"""
|
||||
|
||||
__slots__ = ('_services',)
|
||||
|
||||
def __init__(self, *services: Service):
|
||||
self._services: tuple[Service, ...] = services
|
||||
|
||||
def avec(self, service: Service) -> 'Services':
|
||||
"""Retourne une nouvelle collection incluant ce service."""
|
||||
if service in self._services:
|
||||
return self
|
||||
return Services(*self._services, service)
|
||||
|
||||
def sans(self, service: Service) -> 'Services':
|
||||
"""Retourne une nouvelle collection sans ce service."""
|
||||
return Services(*(s for s in self._services if s != service))
|
||||
|
||||
def critiques(self) -> 'Services':
|
||||
"""Retourne uniquement les services critiques."""
|
||||
return Services(*(s for s in self._services if s.est_critique()))
|
||||
|
||||
def sur_port(self, port: int) -> 'Services':
|
||||
"""Retourne les services écoutant sur ce port."""
|
||||
return Services(*(s for s in self._services if s.ecoute_sur(port)))
|
||||
|
||||
def contient(self, service: Service) -> bool:
|
||||
"""Cette collection contient-elle ce service?"""
|
||||
return service in self._services
|
||||
|
||||
def est_vide(self) -> bool:
|
||||
"""Cette collection est-elle vide?"""
|
||||
return len(self._services) == 0
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self._services)
|
||||
|
||||
def __iter__(self) -> Iterator[Service]:
|
||||
return iter(self._services)
|
||||
|
||||
def __contains__(self, service: Service) -> bool:
|
||||
return service in self._services
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Services({', '.join(repr(s) for s in self._services)})"
|
||||
|
||||
|
||||
class Serveur:
|
||||
"""
|
||||
Un serveur hebergeant des services.
|
||||
"""
|
||||
|
||||
def __init__(self, nom: str, ip: str, os: str, mise_en_service: date):
|
||||
self._nom = nom
|
||||
self._ip = ip
|
||||
self._os = os
|
||||
self._mise_en_service = mise_en_service
|
||||
self._services = Services()
|
||||
|
||||
def heberge(self, service: Service) -> None:
|
||||
"""Ajoute un service a ce serveur."""
|
||||
self._services = self._services.avec(service)
|
||||
|
||||
def retire(self, service: Service) -> None:
|
||||
"""Retire un service de ce serveur."""
|
||||
self._services = self._services.sans(service)
|
||||
|
||||
def services_critiques(self) -> Services:
|
||||
"""Retourne les services critiques heberges."""
|
||||
return self._services.critiques()
|
||||
|
||||
def nombre_services(self) -> int:
|
||||
"""Combien de services ce serveur heberge-t-il?"""
|
||||
return len(self._services)
|
||||
|
||||
def repond_au_nom(self, nom: str) -> bool:
|
||||
"""Ce serveur repond-il a ce nom?"""
|
||||
return self._nom == nom
|
||||
|
||||
def a_pour_ip(self, ip: str) -> bool:
|
||||
"""Ce serveur a-t-il cette IP?"""
|
||||
return self._ip == ip
|
||||
|
||||
def fonctionne_sous(self, os: str) -> bool:
|
||||
"""Ce serveur fonctionne-t-il sous cet OS?"""
|
||||
return self._os.lower() == os.lower()
|
||||
|
||||
def en_service_depuis(self, depuis: date) -> bool:
|
||||
"""Ce serveur est-il en service depuis au moins cette date?"""
|
||||
return self._mise_en_service <= depuis
|
||||
|
||||
def fiche(self) -> str:
|
||||
"""Retourne une fiche descriptive complete du serveur."""
|
||||
lignes = [
|
||||
f"Serveur: {self._nom}",
|
||||
f" IP: {self._ip}",
|
||||
f" OS: {self._os}",
|
||||
f" En service depuis: {self._mise_en_service}",
|
||||
f" Services ({len(self._services)}):",
|
||||
]
|
||||
for service in self._services:
|
||||
lignes.append(f" - {service}")
|
||||
return "\n".join(lignes)
|
||||
|
||||
def __eq__(self, autre: object) -> bool:
|
||||
if not isinstance(autre, Serveur):
|
||||
return NotImplemented
|
||||
return self._nom == autre._nom and self._ip == autre._ip
|
||||
|
||||
def __len__(self) -> int:
|
||||
"""Nombre de services heberges."""
|
||||
return len(self._services)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Serveur({self._nom!r}, {self._ip!r}, {self._os!r}, {self._mise_en_service!r})"
|
||||
|
||||
|
||||
class ServeurPhysique(Serveur):
|
||||
"""
|
||||
Un serveur physique dans un rack.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
nom: str,
|
||||
ip: str,
|
||||
os: str,
|
||||
mise_en_service: date,
|
||||
*,
|
||||
rack: str,
|
||||
consommation_kw: float,
|
||||
sous_garantie: bool = True
|
||||
):
|
||||
super().__init__(nom, ip, os, mise_en_service)
|
||||
self._rack = rack
|
||||
self._consommation_kw = consommation_kw
|
||||
self._sous_garantie = sous_garantie
|
||||
|
||||
def est_sous_garantie(self) -> bool:
|
||||
"""Ce serveur est-il encore sous garantie?"""
|
||||
return self._sous_garantie
|
||||
|
||||
def consomme_plus_que(self, seuil_kw: float) -> bool:
|
||||
"""Ce serveur consomme-t-il plus que le seuil?"""
|
||||
return self._consommation_kw > seuil_kw
|
||||
|
||||
def dans_rack(self, rack: str) -> bool:
|
||||
"""Ce serveur est-il dans ce rack?"""
|
||||
return self._rack == rack
|
||||
|
||||
def fiche(self) -> str:
|
||||
"""Retourne une fiche descriptive complete du serveur."""
|
||||
base = super().fiche()
|
||||
garantie = "Oui" if self._sous_garantie else "Non"
|
||||
return "\n".join([
|
||||
base,
|
||||
f" Rack: {self._rack}",
|
||||
f" Consommation: {self._consommation_kw} kW",
|
||||
f" Sous garantie: {garantie}",
|
||||
])
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"ServeurPhysique({self._nom!r}, rack={self._rack!r})"
|
||||
|
||||
|
||||
class ServeurVirtuel(Serveur):
|
||||
"""
|
||||
Un serveur virtuel (VM).
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
nom: str,
|
||||
ip: str,
|
||||
os: str,
|
||||
mise_en_service: date,
|
||||
*,
|
||||
hyperviseur: str,
|
||||
allocation: str
|
||||
):
|
||||
super().__init__(nom, ip, os, mise_en_service)
|
||||
self._hyperviseur = hyperviseur
|
||||
self._allocation = allocation
|
||||
|
||||
def tourne_sur_hyperviseur(self, hyperviseur: str) -> bool:
|
||||
"""Cette VM tourne-t-elle sur cet hyperviseur?"""
|
||||
return self._hyperviseur.lower() == hyperviseur.lower()
|
||||
|
||||
def fiche(self) -> str:
|
||||
"""Retourne une fiche descriptive complete du serveur."""
|
||||
base = super().fiche()
|
||||
return "\n".join([
|
||||
base,
|
||||
f" Hyperviseur: {self._hyperviseur}",
|
||||
f" Allocation: {self._allocation}",
|
||||
])
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"ServeurVirtuel({self._nom!r}, hyperviseur={self._hyperviseur!r})"
|
||||
|
||||
|
||||
class Technicien:
|
||||
"""
|
||||
Un technicien.
|
||||
"""
|
||||
|
||||
__slots__ = ('_identifiant', '_nom', '_specialite')
|
||||
|
||||
def __init__(self, identifiant: str, nom: str, specialite: str):
|
||||
self._identifiant = identifiant
|
||||
self._nom = nom
|
||||
self._specialite = specialite
|
||||
|
||||
def est_specialise_en(self, domaine: str) -> bool:
|
||||
"""Ce technicien est-il specialise dans ce domaine?"""
|
||||
return self._specialite.lower() == domaine.lower()
|
||||
|
||||
def __eq__(self, autre: object) -> bool:
|
||||
if not isinstance(autre, Technicien):
|
||||
return NotImplemented
|
||||
return self._identifiant == autre._identifiant
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Technicien({self._identifiant!r}, {self._nom!r}, {self._specialite!r})"
|
||||
|
||||
|
||||
class Maintenance:
|
||||
"""
|
||||
Une intervention de maintenance sur un serveur.
|
||||
"""
|
||||
|
||||
__slots__ = ('_identifiant', '_date', '_type', '_serveur', '_technicien')
|
||||
|
||||
PREVENTIVE = "preventive"
|
||||
CORRECTIVE = "corrective"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
identifiant: str,
|
||||
date_intervention: date,
|
||||
type_maintenance: str,
|
||||
serveur: Serveur,
|
||||
technicien: Technicien
|
||||
):
|
||||
if type_maintenance not in (self.PREVENTIVE, self.CORRECTIVE):
|
||||
raise ValueError(f"Type de maintenance invalide: {type_maintenance}")
|
||||
self._identifiant = identifiant
|
||||
self._date = date_intervention
|
||||
self._type = type_maintenance
|
||||
self._serveur = serveur
|
||||
self._technicien = technicien
|
||||
|
||||
def concerne_serveur(self, serveur: Serveur) -> bool:
|
||||
"""Cette maintenance concerne-t-elle ce serveur?"""
|
||||
return self._serveur == serveur
|
||||
|
||||
def effectuee_par(self, technicien: Technicien) -> bool:
|
||||
"""Cette maintenance a-t-elle ete effectuee par ce technicien?"""
|
||||
return self._technicien == technicien
|
||||
|
||||
def est_preventive(self) -> bool:
|
||||
"""Est-ce une maintenance preventive?"""
|
||||
return self._type == self.PREVENTIVE
|
||||
|
||||
def est_corrective(self) -> bool:
|
||||
"""Est-ce une maintenance corrective?"""
|
||||
return self._type == self.CORRECTIVE
|
||||
|
||||
def a_eu_lieu_apres(self, depuis: date) -> bool:
|
||||
"""Cette maintenance a-t-elle eu lieu après cette date?"""
|
||||
return self._date >= depuis
|
||||
|
||||
def rapport(self) -> str:
|
||||
"""Retourne un rapport formater de la maintenance."""
|
||||
sep = "=" * 50
|
||||
return "\n".join([
|
||||
sep,
|
||||
f"MAINTENANCE {self._identifiant}",
|
||||
sep,
|
||||
f"Date: {self._date}",
|
||||
f"Type: {self._type.upper()}",
|
||||
f"Serveur: {self._serveur}",
|
||||
f"Technicien: {self._technicien}",
|
||||
sep,
|
||||
])
|
||||
|
||||
def __eq__(self, autre: object) -> bool:
|
||||
if not isinstance(autre, Maintenance):
|
||||
return NotImplemented
|
||||
return self._identifiant == autre._identifiant
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Maintenance({self._identifiant!r}, {self._date!r}, {self._type!r})"
|
||||
|
||||
|
||||
class Datacenter:
|
||||
"""
|
||||
Un datacenter regroupant des serveurs.
|
||||
"""
|
||||
|
||||
def __init__(self, nom: str, localisation: str):
|
||||
self._nom = nom
|
||||
self._localisation = localisation
|
||||
self._serveurs: list[Serveur] = []
|
||||
self._maintenances: list[Maintenance] = []
|
||||
|
||||
def accueille(self, serveur: Serveur) -> None:
|
||||
"""Accueille un nouveau serveur dans le datacenter."""
|
||||
if serveur not in self._serveurs:
|
||||
self._serveurs.append(serveur)
|
||||
|
||||
def retire_serveur(self, serveur: Serveur) -> None:
|
||||
"""Retire un serveur du datacenter."""
|
||||
if serveur in self._serveurs:
|
||||
self._serveurs.remove(serveur)
|
||||
|
||||
def enregistre(self, maintenance: Maintenance) -> None:
|
||||
"""Enregistre une maintenance effectuee."""
|
||||
self._maintenances.append(maintenance)
|
||||
|
||||
def services_critiques(self) -> Services:
|
||||
"""Tous les services critiques heberges dans ce datacenter."""
|
||||
critiques = []
|
||||
for serveur in self._serveurs:
|
||||
for service in serveur.services_critiques():
|
||||
critiques.append(service)
|
||||
return Services(*critiques)
|
||||
|
||||
def total_services(self) -> int:
|
||||
"""Nombre total de services heberges."""
|
||||
return sum(serveur.nombre_services() for serveur in self._serveurs)
|
||||
|
||||
def serveurs_maintenus_par(self, technicien: Technicien) -> list[Serveur]:
|
||||
"""Liste des serveurs ayant ete maintenus par ce technicien."""
|
||||
serveurs_trouves = []
|
||||
for maintenance in self._maintenances:
|
||||
if maintenance.effectuee_par(technicien):
|
||||
for serveur in self._serveurs:
|
||||
if maintenance.concerne_serveur(serveur) and serveur not in serveurs_trouves:
|
||||
serveurs_trouves.append(serveur)
|
||||
return serveurs_trouves
|
||||
|
||||
def pour_chaque_serveur(self, action: Callable[[Serveur], None]) -> None:
|
||||
"""Applique une action a chaque serveur"""
|
||||
for serveur in self._serveurs:
|
||||
action(serveur)
|
||||
|
||||
def pour_chaque_serveur_physique(self, action: Callable[[ServeurPhysique], None]) -> None:
|
||||
"""Applique une action a chaque serveur physique."""
|
||||
for serveur in self._serveurs:
|
||||
if isinstance(serveur, ServeurPhysique):
|
||||
action(serveur)
|
||||
|
||||
def inventaire(self) -> str:
|
||||
"""Retourne l'inventaire complet du datacenter."""
|
||||
sep = "#" * 60
|
||||
lignes = [
|
||||
"",
|
||||
sep,
|
||||
f"DATACENTER: {self._nom}",
|
||||
f"Localisation: {self._localisation}",
|
||||
sep,
|
||||
"",
|
||||
f"Nombre de serveurs: {len(self._serveurs)}",
|
||||
f"Total services: {self.total_services()}",
|
||||
f"Services critiques: {len(self.services_critiques())}",
|
||||
"",
|
||||
]
|
||||
for serveur in self._serveurs:
|
||||
lignes.append(serveur.fiche())
|
||||
lignes.append("")
|
||||
return "\n".join(lignes)
|
||||
|
||||
def __len__(self) -> int:
|
||||
"""Nombre de serveurs dans le datacenter."""
|
||||
return len(self._serveurs)
|
||||
|
||||
def __contains__(self, serveur: Serveur) -> bool:
|
||||
"""Ce serveur est-il dans le datacenter?"""
|
||||
return serveur in self._serveurs
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Datacenter({self._nom!r}, {self._localisation!r})"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Creation de services
|
||||
nginx = Service("nginx", 80, "HTTP", critique=True)
|
||||
api = Service("api-backend", 8080, "HTTP", critique=True)
|
||||
ssh = Service("sshd", 22, "TCP")
|
||||
postgres = Service("postgresql", 5432, "TCP", critique=True)
|
||||
redis = Service("redis", 6379, "TCP")
|
||||
|
||||
# Creation de serveurs
|
||||
srv_web = ServeurPhysique(
|
||||
"srv-web-01",
|
||||
"192.168.1.10",
|
||||
"Debian 12",
|
||||
date(2023, 6, 15),
|
||||
rack="R01-U12",
|
||||
consommation_kw=0.8,
|
||||
sous_garantie=True
|
||||
)
|
||||
srv_web.heberge(nginx)
|
||||
srv_web.heberge(ssh)
|
||||
|
||||
srv_api = ServeurVirtuel(
|
||||
"srv-api-01",
|
||||
"192.168.1.20",
|
||||
"Ubuntu 22.04",
|
||||
date(2024, 1, 10),
|
||||
hyperviseur="Proxmox",
|
||||
allocation="4 vCPU / 8 Go RAM"
|
||||
)
|
||||
srv_api.heberge(api)
|
||||
srv_api.heberge(redis)
|
||||
|
||||
srv_db = ServeurPhysique(
|
||||
"srv-db-01",
|
||||
"192.168.1.30",
|
||||
"Rocky Linux 9",
|
||||
date(2022, 3, 1),
|
||||
rack="R02-U08",
|
||||
consommation_kw=1.2,
|
||||
sous_garantie=False
|
||||
)
|
||||
srv_db.heberge(postgres)
|
||||
srv_db.heberge(ssh)
|
||||
|
||||
# Creation du datacenter
|
||||
dc_paris = Datacenter("DC-Paris-01", "Paris, France")
|
||||
dc_paris.accueille(srv_web)
|
||||
dc_paris.accueille(srv_api)
|
||||
dc_paris.accueille(srv_db)
|
||||
|
||||
# Creation de techniciens
|
||||
alice = Technicien("T001", "Alice Martin", "Linux")
|
||||
bob = Technicien("T002", "Bob Dupont", "Virtualisation")
|
||||
|
||||
# Creation de maintenances
|
||||
maint_1 = Maintenance(
|
||||
"M2024-001",
|
||||
date(2024, 11, 15),
|
||||
Maintenance.PREVENTIVE,
|
||||
srv_web,
|
||||
alice
|
||||
)
|
||||
|
||||
maint_2 = Maintenance(
|
||||
"M2024-002",
|
||||
date(2024, 12, 3),
|
||||
Maintenance.CORRECTIVE,
|
||||
srv_db,
|
||||
alice
|
||||
)
|
||||
|
||||
maint_3 = Maintenance(
|
||||
"M2025-001",
|
||||
date(2025, 1, 8),
|
||||
Maintenance.PREVENTIVE,
|
||||
srv_api,
|
||||
bob
|
||||
)
|
||||
|
||||
dc_paris.enregistre(maint_1)
|
||||
dc_paris.enregistre(maint_2)
|
||||
dc_paris.enregistre(maint_3)
|
||||
|
||||
# Inventaire complet
|
||||
print(dc_paris.inventaire())
|
||||
|
||||
# Services critiques
|
||||
print("--- SERVICES CRITIQUES ---")
|
||||
print(dc_paris.services_critiques())
|
||||
|
||||
# Serveurs maintenus par Alice
|
||||
print("\n--- SERVEURS MAINTENUS PAR ALICE ---")
|
||||
for srv in dc_paris.serveurs_maintenus_par(alice):
|
||||
print(f" - {srv}")
|
||||
|
||||
# Rapport de maintenance
|
||||
print("\n--- RAPPORT MAINTENANCE ---")
|
||||
print(maint_1.rapport())
|
||||
|
||||
print("\n--- SERVEURS HORS GARANTIE ---")
|
||||
dc_paris.pour_chaque_serveur_physique(
|
||||
lambda s: print(f" ! {s}") if not s.est_sous_garantie() else None
|
||||
)
|
||||
|
||||
print("\n--- TEST ÉGALITÉ ---")
|
||||
nginx_copie = Service("nginx", 80, "HTTPS") # Meme nom/port, protocole different
|
||||
print(f"nginx == nginx_copie: {nginx == nginx_copie}") # True (egalite sur nom+port)
|
||||
@@ -0,0 +1,28 @@
|
||||
def persistance(num: int):
|
||||
"""
|
||||
A partir d'un entier positif, renvoie la persistance multiplicative,
|
||||
à savoir le nombre de fois qu'on peut multiplier les chiffres de l'entier
|
||||
entre eux jusqu'à un résultat d'un seul chiffre.
|
||||
|
||||
Exemples :
|
||||
4 -> 0
|
||||
39 -> 3 (3*9=27, 2*7=14, 1*4=4)
|
||||
"""
|
||||
if num < 0:
|
||||
return "Merci d'utiliser un entier positif."
|
||||
|
||||
steps = 0
|
||||
start = num
|
||||
|
||||
while len(str(num)) > 1:
|
||||
base = 1
|
||||
|
||||
for n in str(num):
|
||||
base *= int(n)
|
||||
|
||||
steps += 1
|
||||
num = base
|
||||
|
||||
if steps == 0:
|
||||
return f"Partant de {start}, pas besoin de multiplication."
|
||||
return f"Partant de {start}, la persistance multiplicative est de {steps} étapes."
|
||||
@@ -0,0 +1,22 @@
|
||||
def numeral_square(num: int):
|
||||
"""
|
||||
A partir d'un entier positif, renvoie la racine numérique,
|
||||
à savoir la somme récursive de tous les chiffres d'un nombre.
|
||||
|
||||
Exemples :
|
||||
16 -> 1+6=7
|
||||
1567 -> 1+5+6+7=19, 1+9=10, 1+0=1
|
||||
"""
|
||||
if num < 0:
|
||||
return "Merci d'utiliser un entier positif."
|
||||
start = num
|
||||
|
||||
while len(str(num)) > 1:
|
||||
base = 0
|
||||
|
||||
for n in str(num):
|
||||
base += int(n)
|
||||
|
||||
num = base
|
||||
|
||||
return f"La racine numérique de {start} donne {base}."
|
||||
@@ -0,0 +1,18 @@
|
||||
def gen_pyramid(num: int) -> list[str]:
|
||||
"""
|
||||
A partir d'un entier, renvoie sous forme de tableau une
|
||||
pyramide composée d'autant d'étages avec le caractère *
|
||||
"""
|
||||
if num == 0:
|
||||
return ["Merci d'utiliser un entier non nul."]
|
||||
if num < 0:
|
||||
num = +abs(num)
|
||||
|
||||
pyramid = []
|
||||
|
||||
for n in range(num):
|
||||
white_spaces = ' ' * (num - n - 1)
|
||||
bloc_spaces = '*' * (2 * n + 1)
|
||||
pyramid.append(f"{white_spaces}{bloc_spaces}{white_spaces}")
|
||||
|
||||
return pyramid
|
||||
@@ -0,0 +1,45 @@
|
||||
from datetime import date, time, datetime, timedelta
|
||||
from pprint import pprint
|
||||
|
||||
from exo_01 import persistance
|
||||
from exo_02 import numeral_square
|
||||
from exo_03 import gen_pyramid
|
||||
from prog_or_obj import Service,\
|
||||
ServeurPhysique,\
|
||||
ServeurVirtuel,\
|
||||
Technicien,\
|
||||
Maintenance,\
|
||||
Datacenter
|
||||
|
||||
# Exercice 1
|
||||
print("\n----- Exercice [1] -----\n")
|
||||
exo_1_test_list = [-7, 4, 39, 999]
|
||||
for test in exo_1_test_list:
|
||||
print(persistance(test))
|
||||
|
||||
# Exercice 2
|
||||
print("\n----- Exercice [2] -----\n")
|
||||
exo_2_test_list = [-7, 16, 942, 132189, 493193]
|
||||
for test in exo_2_test_list:
|
||||
print(numeral_square(test))
|
||||
|
||||
# Exercice 3
|
||||
print("\n----- Exercice [3] -----\n")
|
||||
exo_3_test_list = [-7, 0, 6, 12]
|
||||
for test in exo_3_test_list:
|
||||
pprint(gen_pyramid(test), width= 30)
|
||||
|
||||
# Exercice de Programmation Orientée Objet - Centre de données
|
||||
|
||||
today = date.today()
|
||||
two_days_ago = date.today() - timedelta(days= 2)
|
||||
five_days_ago = date.today() - timedelta(days= 5)
|
||||
|
||||
service_01 = Service("HTTP", 80, "TCP", True)
|
||||
service_02 = Service("HTTPS", "443", "TCP", True)
|
||||
service_03 = Service("PostGresql", 5432, "TCP", False)
|
||||
service_04 = Service("Counter-Strike LAN", 36729, "UDP", False)
|
||||
|
||||
server_physical_01 = ServeurPhysique("Thorium", "10.10.19.94", "Debian 13", today, "HP version 4.2", 45, True)
|
||||
server_physical_02 = ServeurPhysique("Iridium", "10.10.18.94", "Arch Linux 4", two_days_ago, "HP version 4.2", 37, True)
|
||||
server_physical_03 = ServeurPhysique("Polonium", "10.10.17.94", "Apple Server mdr", five_days_ago, "HP version 3.3", 445, False)
|
||||
@@ -0,0 +1,255 @@
|
||||
from datetime import date
|
||||
import json
|
||||
|
||||
class Service:
|
||||
"""
|
||||
Application déployée sur un serveur.
|
||||
"""
|
||||
def __init__(self, name: str, port: str | int, protocol: str, is_critical: bool):
|
||||
self.name = name
|
||||
self.port = int(port)
|
||||
self.protocol = protocol
|
||||
self.is_critical = is_critical
|
||||
|
||||
def __eq__(self, other: "Service"):
|
||||
return self.name == other.name and self.port == other.port
|
||||
|
||||
def serialized_services(self):
|
||||
"""Converti la classe \"Services\" en dictionnaire JSONable"""
|
||||
return {
|
||||
"Name": self.name,
|
||||
"Port": self.port,
|
||||
"Protocol": self.protocol,
|
||||
"Is_Critical": self.is_critical,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def deserialized_services(cls, dictionnary):
|
||||
"""Lis un JSON pour le retranscrire en classe \"Services\""""
|
||||
return cls(
|
||||
name= dictionnary["Name"],
|
||||
port= dictionnary["Port"],
|
||||
protocol= dictionnary["Protocol"],
|
||||
is_critical= dictionnary["Is_Critical"],
|
||||
)
|
||||
|
||||
class Serveur:
|
||||
"""
|
||||
Serveur, classe maîtresse. NE PAS UTILISER DIRECTEMENT.
|
||||
Préférez les classes héritées :
|
||||
- ServeurPhysique
|
||||
- ServeurVirtuel
|
||||
"""
|
||||
def __init__(self, name: str, ip_address: str, os_name: str, commission_date: date):
|
||||
self.name = name
|
||||
self.ip_address = ip_address
|
||||
self.os_name = os_name
|
||||
self.commission_date = commission_date
|
||||
self.services = self.load_services()
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"\
|
||||
[Serveur] > {self.name}\n\
|
||||
[Addresse IP] > {self.ip_address}\n\
|
||||
[Système d'Exploitation] > {self.os_name}\n\
|
||||
[Date de mise en prod] > {self.commission_date}"
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.services)
|
||||
|
||||
def list_services(self):
|
||||
return self.services
|
||||
|
||||
def add_service(self, service: Service):
|
||||
"""Ajout d'un service à la liste des services disponibles"""
|
||||
if service in self.services:
|
||||
return f"Le service [{service.name.capitalize()}] est déjà présent."
|
||||
self.services.append(service)
|
||||
self.save_services()
|
||||
return f"{service.name.capitalize()} a été ajouté."
|
||||
|
||||
def remove_service(self, service_str: str):
|
||||
"""Retire un service de la liste des services disponibles"""
|
||||
for service in self.services:
|
||||
if service.name.lower() == service_str.lower()\
|
||||
or str(service.port) == service_str.lower()\
|
||||
or service.protocol.lower() == service_str.lower():
|
||||
self.services.remove(service)
|
||||
self.save_services()
|
||||
return f"{service.name.capitalize} a été retiré."
|
||||
return f"{service.name.capitalize()} n'est pas dans la liste."
|
||||
|
||||
def serialized_servers(self):
|
||||
"""Converti la classe \"Services\" en dictionnaire JSONable"""
|
||||
return {
|
||||
"Name": self.name,
|
||||
"IP_Address": self.ip_address,
|
||||
"OS_Name": self.os_name,
|
||||
"Commission_Date": self.commission_date,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def deserialized_servers(cls, dictionnary):
|
||||
"""Lis un JSON pour le retranscrire en classe \"Services\""""
|
||||
return cls(
|
||||
name= dictionnary["Name"],
|
||||
ip_address= dictionnary["IP_Address"],
|
||||
os_name= dictionnary["OS_Name"],
|
||||
commission_date= dictionnary["Commission_Date"],
|
||||
)
|
||||
|
||||
def save_services(self):
|
||||
"""
|
||||
Inscris dans un fichier JSON le contenu des services disponibles
|
||||
"""
|
||||
services_dict = [services.serialized_services() for services in self.services]
|
||||
with open("services.json", "w", encoding= "utf-8") as json_file:
|
||||
json.dump(services_dict, json_file, indent= 4)
|
||||
|
||||
def load_services(self) -> list[Service]:
|
||||
"""
|
||||
Récupère le contenu d'un fichier JSON contenant les services
|
||||
"""
|
||||
with open("services.json", encoding= "utf-8") as json_file:
|
||||
return json.load(json_file, object_hook= Service.deserialized_services)
|
||||
|
||||
class ServeurPhysique(Serveur):
|
||||
def __init__(self, name: str, ip_address: str, os_name: str, commission_date: date, rack: str, electric_cons: int, warranty: bool):
|
||||
super().__init__(name, ip_address, os_name, commission_date)
|
||||
self.rack = rack
|
||||
self.electric_cons = electric_cons
|
||||
warranty_bools = ("Non", "Oui")
|
||||
self.warranty = warranty_bools[warranty]
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"\
|
||||
{super().__str__()}\n\
|
||||
[Châssis] > {self.rack}\n\
|
||||
[Consommation en kWh] > {self.electric_cons}\n\
|
||||
[Sous garantie] > {self.warranty}"
|
||||
|
||||
def __len__(self) -> int:
|
||||
return super().__len__()
|
||||
|
||||
class ServeurVirtuel(Serveur):
|
||||
def __init__(self, name: str, ip_address: str, os_name: str, commission_date: date, hypervisor: str, vcpus: int, giga_ram: float):
|
||||
super().__init__(name, ip_address, os_name, commission_date)
|
||||
self.hypervisor = hypervisor
|
||||
self.vcpus = vcpus
|
||||
self.giga_ram = giga_ram
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"\
|
||||
{super().__str__()}\n\
|
||||
[Hyperviseur] > {self.hypervisor}\n\
|
||||
[Coeurs virtuels] > {self.vcpus}\n\
|
||||
[Mémoire vive (Go)] > {self.giga_ram}"
|
||||
|
||||
def __len__(self) -> int:
|
||||
return super().__len__()
|
||||
|
||||
class Maintenance:
|
||||
def __init__(self, id: int, commission_date: date, type: str, affected_technician: "Technicien", associated_server: "ServeurPhysique | ServeurVirtuel"):
|
||||
self.id = id
|
||||
self.commission_date = commission_date
|
||||
self.type = type
|
||||
self.affected_technician = affected_technician
|
||||
self.associated_server = associated_server
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"\
|
||||
[ID] > {self.id}\n\
|
||||
[Serveur associé] > {self.associated_server}\n\
|
||||
[Date de mise en prod] > {self.commission_date}\n\
|
||||
[Type de maintenance] > {self.type}\n\
|
||||
[Technicien affecté] > {self.affected_technician}"
|
||||
|
||||
# J'ai le sentiment que ce n'est PAS ce qui est demandé. Mais il est 16h25 et je n'ai plus d'idée sur comment le faire
|
||||
def link_to_server(self, server: ServeurPhysique | ServeurVirtuel):
|
||||
return f"La maintenance est liée au serveur {server.name.upper()}, addresse IP {server.ip_address}."
|
||||
|
||||
def serialized_maintenances(self):
|
||||
"""Converti la classe \"Maintenance\" en dictionnaire JSONable"""
|
||||
return {
|
||||
"ID": self.id,
|
||||
"Associated_Server": self.associated_server,
|
||||
"Commission_Date": self.commission_date,
|
||||
"Type": self.type,
|
||||
"Affected_Technician": self.affected_technician,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def deserialized_maintenances(cls, dictionnary):
|
||||
"""Lis un JSON pour le retranscrire en classe \"Maintenance\""""
|
||||
return cls(
|
||||
id= dictionnary["ID"],
|
||||
associated_server= dictionnary["Associated_Server"],
|
||||
commission_date= dictionnary["Commission_Date"],
|
||||
type= dictionnary["Type"],
|
||||
affected_technician= dictionnary["Affected_Technician"],
|
||||
)
|
||||
|
||||
class Technicien:
|
||||
def __init__(self, fullname: str, speciality: str, id: int):
|
||||
self.name = fullname
|
||||
self.speciality = speciality
|
||||
self.id = id
|
||||
self.maintenances = self.load_maintenances()
|
||||
|
||||
def list_affected_jobs(self):
|
||||
return self.maintenances
|
||||
|
||||
def affect_maintenance(self):
|
||||
pass
|
||||
|
||||
def save_maintenances(self):
|
||||
"""
|
||||
Inscris dans un fichier JSON le contenu des maintenances disponibles
|
||||
"""
|
||||
maintenances_dict = [maintenances.serialized_maintenances() for maintenances in self.maintenances]
|
||||
with open("maintenances.json", "w", encoding= "utf-8") as json_file:
|
||||
json.dump(maintenances_dict, json_file, indent= 4)
|
||||
|
||||
def load_maintenances(self) -> list[Maintenance]:
|
||||
"""
|
||||
Récupère le contenu d'un fichier JSON contenant les maintenances
|
||||
"""
|
||||
with open("maintenances.json", encoding= "utf-8") as json_file:
|
||||
return json.load(json_file, object_hook= Maintenance.deserialized_maintenances)
|
||||
|
||||
class Datacenter:
|
||||
def __init__(self, name: str, location: str, id: int):
|
||||
self.name = name
|
||||
self.location = location
|
||||
self.id = id
|
||||
self.servers = self.load_servers()
|
||||
|
||||
def list_servers(self):
|
||||
return self.servers
|
||||
|
||||
def list_critical_services(self):
|
||||
for server in self.servers:
|
||||
server.list_services()
|
||||
# Là j'ai cherché à récupérer un genre de 'if server.list_services().is_critical'
|
||||
# pour avoir le "True/False" et renvoyer le résultat en cas de "True" mais j'ai craqué
|
||||
|
||||
def list_services_number(self):
|
||||
services = 0
|
||||
for server in self.servers:
|
||||
services += len(server)
|
||||
return services
|
||||
|
||||
def save_servers(self):
|
||||
"""
|
||||
Inscris dans un fichier JSON le contenu des serveurs disponibles
|
||||
"""
|
||||
servers_dict = [servers.serialized_servers() for servers in self.servers]
|
||||
with open("servers.json", "w", encoding= "utf-8") as json_file:
|
||||
json.dump(servers_dict, json_file, indent= 4)
|
||||
|
||||
def load_servers(self) -> list[Serveur]:
|
||||
"""
|
||||
Récupère le contenu d'un fichier JSON contenant les serveurs
|
||||
"""
|
||||
with open("servers.json", encoding= "utf-8") as json_file:
|
||||
return json.load(json_file, object_hook= Serveur.deserialized_servers)
|
||||
Reference in New Issue
Block a user