Sunteți pe pagina 1din 72

Université Sidi Mohamed Ben Abdellah

Faculté des sciences et Techniques de Fès


Département d’informatique

Pr. Arsalane ZARGHILI

Master Systèmes Intelligents et Réseaux

1
Plan du cours
 Définitions générales

 Architecture Client-Serveur

 Middlewares

 Rappel RPC

 Systèmes à objets distribués

 RMI (Remote Method Invocation)

 CORBA (Common Object Request Broker Architecture)

2
3
Définition
 Un système distribué (réparti) est :

 un ensemble de machines autonomes connectées par un

réseau, et équipées d’un logiciel dédié à la coordination


des activités du système ainsi qu’au partage de ses
ressources.

 Un ensemble d'ordinateurs indépendants qui apparaissent

à leurs utilisateurs comme un seul système.

4
Systèmes centralisés et distribués
 Un système centralisé est un système dans lequel
une seule UC peut travailler
 Exemple : Mini-ordinateurs.

 Un système distribué est un système dans lequel


plusieurs UCs interconnectées travaillent ensemble

 Un logiciel distribué est un logiciel pouvant être


exécuté dans un système distribué

5
Historique

 1945 - 1985 : Ordinateurs gros et chers

 Mini-ordinateurs : plusieurs milliers de dollars

 A partir de 1985 : développement rapide des

microprocesseurs et des réseaux locaux (LAN)

 Émergence des systèmes distribués

6
Nature des SD: organisations réparties

Ingénierie
Comptabilité

Livraison/
réception
Paiement/
Ventes facturation

 Les organisations réparties nécessitent des logiciels distribués

7
Nature des SD: équipements répartis

 Les équipements répartis nécessitent des logiciels distribués

8
Caractéristiques d’un SD
 Un système formé de composants matériels ou logiciels localisés

sur des ordinateurs en réseau qui communiquent et

coordonnent leurs actions uniquement par l’envoi de messages,

le tout en vue de répondre à un besoin donné.

 Les différents éléments du système ne fonctionnent pas

indépendamment mais collaborent à une ou plusieurs

tâches communes.
9
Les objectifs d’un SD
 La réalisation d’un SD prend en compte les objectifs
suivants:

1) Connecter les usagers et les ressources

2) Transparence

3) Ouverture

4) Extensibilité (scalabilité)

10
Les objectifs d’un SD
❶ Connecter les usagers et les ressources
 But :
simplifier l’accès à des ressources distantes (remote) et
leurs partages avec les autres usagers de manière contrôlée
 Ressources :
imprimantes, ordinateurs, systèmes de stockage, fichiers,
données, pages web, réseaux
 Exemples:
Internet,…,etc.
 Problèmes reliés:
sécurité, confidentialité, authentification,etc.
11
Les objectifs d’un SD
❷ Transparence
Transparence Description
Accès à des ressources distantes aussi facilement que localement
Accès Accès aux données indépendamment de leur format de
représentation
Localisation Masquer l’endroit où une ressource est localisée
Masquer le fait qu’une ressource puisse se déplacer vers une autre
Migration
localisation
Masquer le fait qu’une ressource puisse être déplacée vers une autre
Translation
localisation alors qu’elle est en cours d’utilisation
Masquer le fait qu’une ressource est répliquée en plusieurs
Réplication
localisations
Masquer le fait qu’une ressource puisse être partagée par plusieurs
Concurrence
usagers en compétition
Panne Masquer la panne et le recouvrement d’une ressource
Masquer le fait qu’une ressource logicielle est en mémoire ou sur
Persistance
disque
12
Les objectifs d’un SD
❸ Ouverture
 Système distribué ouvert :
 système qui offre des services répondant à des règles
standardisées qui décrivent la syntaxe et la sémantique de
ces services.
 Comment spécifier les services ?
 Par des interfaces
 Décrites à l’aide d’un IDL (Interface Definition
Language)
 Rq: la sémantique est difficile à spécifier!

13
Les objectifs d’un SD
❸ Ouverture
 Interopérabilité:
Cœxistence de systèmes ou de composants provenant de fabricants
différents et pouvant fonctionner ensemble en se basant sur des services
spécifiés par des standards communs

 Portabilité:
Définit la mesure dans laquelle une application développée pour un
système distribué A peut s’exécuter sans modification sur un système
distribué B qui implante les mêmes interfaces que A

 Flexibilité:
Définit la mesure dans laquelle on peut utiliser des composants provenant
de fabricants différents pour construire un système donné 14
Les objectifs d’un SD
❹ Extensibilité
 C’est un des plus importants objectifs de conception de
systèmes distribués
 L’extensibilité concerne plusieurs dimensions:

On peut ajouter facilement des usagers et des


Taille
ressources sans diminuer la performance du système.

On peut distancier les usagers et les ressources sans


Géographie
affecter la performance du système.

On peut administrer facilement le système même s’il


Administration
couvre plusieurs organisations administratives.

15
Les objectifs d’un SD
Dans un SD on a besoin, au minimum :

 d’une infrastructure réseau normalisée ;

 d’un protocole de communication normalisé ;

 d’un mécanisme normalisé d’interaction entre composants ;

 de fonctions de conversion normalisées ;

 d’implantations sous les diverses plates-formes matérielles et


logicielles utilisées, en donnant l’illusion d’une plate-forme
unique: la plate-forme distribuée (Middleware).

16
Organisation des applications réparties
Un schéma commun : le “middleware” (intergiciel)
 “Middleware” : couche de logiciel (distribué) destinée à:
 masquer l’hétérogénéité des machines et systèmes:
fonctionnement en univers ouvert (supporte des
applications tournant sur des plates-formes matérielles et
logicielles différentes).
 masquer la répartition des traitements et données.
 fournir une interface commode aux applications:
 modèle de programmation

+
 API (Interface de programmation d'application)
17
Organisation des applications réparties
Un schéma de base : l’intergiciel (Middleware)

18
Principales catégories de Middleware
 Middleware à messages

 MOM: Message Oriented Middleware


IBMMQSeries, Microsoft Message Queues Server,
DECmessageQ, etc.
 Middleware de bases de données (ODBC)

 Middleware à appel de procédure distante (RPC)

 Middleware à objets répartis (CORBA, JAVA RMI,)

 Middleware à composants (EJB, .Net, )

19
20
Services et interfaces
 Définition

 Un système est un ensemble de composants (au sens non technique du

terme) qui interagissent


 Un service est un comportement défini par un contrat, qui peut être

implémenté et fourni par un composant pour être utilisé par un autre


composant, sur la base exclusive du ”contrat”
 Mise en œuvre

 Un service est accessible via une ou plusieurs interfaces

 Une interface décrit l’interaction entre le client et le fournisseur du service

 Contrat entre client et fournisseur.


 Définition des opérations et structures de données qui concourent à la
réalisation du service. 21
Définitions d’interfaces
 La fourniture d’un service met en jeu deux interfaces:
 Interface requise (côté client)
 Interface fournie (côté fournisseur )
 Le contrat spécifie la compatibilité (conformité) entre ces interfaces
 Au delà de l’interface, chaque partie est une “boîte noire” pour l’autre
(principe d’encapsulation)
 Conséquence : client ou fournisseur peuvent être remplacés du
moment que le composant remplaçant respecte le contrat (est
conforme)

22
Architecture Client-Serveur
 Le client demande l’exécution d’un service
 Le serveur réalise le service
 Client et serveur sont (pas nécessairement) localisés sur
deux machines distinctes
 Indépendance interface-réalisation

23
Architecture Client-Serveur : fonctionnement
 Communication par messages (plutôt que par
partage de données, mémoire ou fichiers)
 Requête : paramètres d’appel, spécification du service requis
 Réponse : résultats, indicateur éventuel d’exécution ou
d’erreur
 Communication synchrone: le client est bloqué tant que le
serveur n’a pas répondu.

24
Architecture Client-Serveur: Accès à un service

25
Mise en œuvre du schéma Client-serveur
 Utilisation d’un middleware spécialisé

 Contexte : langage de programmation

 Appel de procédure à distance (RPC)

 Contexte : Objets répartis

 Appel de méthodes, création d’objets à distance (RMI, CORBA)

 Contexte: Composants Répartis

 EJB, .NET, etc.

26
Généralisations du schéma Client-serveur
 Les notions de client et de serveur sont relatives
 Un serveur peut faire appel à d’autres serveurs dont il est
client
 Exemple: traitement utilisant une base de données

Architecture à 3 niveaux (architecture 3-tiers )


27
Généralisations du schéma Client-serveur
 Clients et serveurs jouent un rôle symétrique

 Tout site joue le rôle de serveur pour les autres: le client et le


serveur se trouvent au même niveau, chacun pouvant
indifféremment assumer un rôle différent, selon les besoins.

 Exemple: Systèmes pair à pair (Peer to Peer)

 Utilisation : partage de données à grande échelle.

 Napster, Emule, Edonkey, etc.

28
29
Appel de procédure à distance (RPC)
 Acronyme: RPC (Remote Procedure Call)

 Mécanisme normalisé d’interaction entre composants:

 La programmation impérative: appel de procédure.

 La programmation distribuée: appel de procédure à distance(RPC).

30
Appel de procédure à distance (RPC)
 Mode de communication entre deux programmes distants
 Un programme jouera le rôle de client

 L’autre programme jouera le rôle de serveur

 le client peut faire exécuter à distance une ou plusieurs procédures par le

serveur.

 Client-serveur: Interaction requête-réponse


 Envoi d’une requête par le client.

 Traitement de la requête
 Appel de méthode à distance
 Envoi de la réponse

31
Appel de procédure à distance (RPC)

 Sérialisation :
 permet de rendre un objet persistant: l’objet est mis sous une forme sous
laquelle il pourra être reconstitué à l'identique.
 Ainsi il pourra être stocké sur un disque dur ou transmis au travers d'un réseau
pour le créer dans une autre JVM
32
Appel de procédure à distance (RPC)
Objectifs d’appel de méthode à distance:
 Diminuer le travail de développement des serveurs et des clients
 Prise en charge de la sérialisation/désérialisation des arguments.

 Prise en charge de la conversion appel de méthode en protocole requête/réponse.

 Plus facile pour un serveur d’offrir plusieurs services (méthodes).

 Masquer une partie de la répartition


 Le client appelle une méthode locale.

 Cet appel est délégué au serveur.

 La méthode est exécutée par le serveur.

 Masquer l’hétérogénéité entre clients et serveurs


 Format pivot pour les données (XDR: External Data Representation,
sérialisationJava, etc).
33
Appel de procédure à distance (RPC)
Comment ?
 Une souche (stub ou talon client) d’appel est généré pour le client.

 Un squelette (skeleton ou talon serveur) du serveur est générée pour le serveur.

 Le développeur du client a la charge de trouver le serveur et d’appeler la méthode.


 Le développeur du serveur a la charge d’écrire la méthode.

34
Appel de procédure à distance (RPC)
Utilisation d’un langage IDL (Interface Developement Language)
 Langage pour la spécification des interfaces entre les clients et les
serveurs :
 Spécification du contrat entre le client et le serveur

 Définition des types et natures des paramètres

 Définition indépendante de la plate-forme

 Indépendante du langage, de l’OS et de la machine


 Utilisation de ces définitions pour générer automatiquement :
 Le Stub (client )

 Le Squelette (serveur)

 « projection » dans un langage de programmation

35
Appel de procédure à distance (RPC): Utilisation d’un IDL

36
Appel de procédure à distance (RPC)
 Localisation des procédures RPC: Serveur de nom (Annuaire)
 lorsqu'un service est lancé par un client sur un noeud du réseau, il
s'identifie par le serveur de nom(on utilise aussi les noms (Nommage,
Binding)).
 lorsqu'un client veut accéder à un service, il recherche l'information
dans le serveur de nom.
 la localisation du service de nom est connue.

 le service de nom peut éventuellement être distribué sur plusieurs


serveurs.
 Exemple de service de nom: le DNS, utilisé pour la localisation des
adresses IP à partir des noms d'hôtes.

37
Appel de procédure à distance (RPC)
Limitations:
 La structure de l’application est statique (mêmes fichiers sont présents dans
plusieurs clients et serveurs): pas de création dynamique de serveur, pas de
possibilité de redéploiement entre sites
 Pas de passage des paramètres par référence.
 La communication est réduite à un schéma synchrone.
 La persistance des données n’est pas assurée (il faut la réaliser explicitement par
sauvegarde des données dans des fichiers)
 Des mécanismes plus évolués visent à remédier à ces limitations
 Objets répartis (ex : Java RMI, CORBA)
 Bus à messages (Message Oriented Middleware)
 Composants répartis (ex : .Net,etc)

38
Objets répartis
 Application distribuée = ensemble d’objets répartis
(fournisseurs de services)
 Les services sont demandés par des clients connaissant le
contrat
 Les objets sont implantés par un ou plusieurs serveur(s)
 Exemples : CORBA, Java/RMI, etc.

39
Objets répartis
 Propriétés des objets:
 Encapsulation
 L’interface (méthodes + attributs) est la seule voie d’accès à l’état interne, non
directement accessible
 Classes et instances
 Mécanismes de génération d’exemplaires conformes à un même modèle
 Héritage
 Mécanisme de spécialisation : facilite récupération et réutilisation de l’existant
 Polymorphisme
 Mises en œuvre diverses des fonctions d’une interface
 Remplacement d’un objet par un autre si interfaces “compatibles”
 Facilite l’évolution et l’adaptation des applications
40
Objets répartis
 Extension du RPC aux objets
 Exemple : insérer une entrée dans un annuaire

41
Objets répartis

 Création d’instances d’une classe d’objets: Notion de


fabrique

Référence d’objet:
Contient tout ce qui est nécessaire pour
atteindre l’objet distant (Localisation,
protocole d’accès)
42
Objets répartis
 Références d’objet : Notion clé pour les objets répartis
 Référence = moyen d’accès à un objet distant.

 En général une référence est “opaque” (son contenu ne peut pas être
directement exploité) ; elle n’est utilisable que via un mécanisme
d’appel à distance
 Contenu d’une référence
 Toutes les informations nécessaires pour atteindre physiquement
l’objet
 Site de résidence
 Numéro de port sur le site
 Localisation interne au serveur
43
44
RMI : Définition

 un ensemble de classes en JAVA


permettant de manipuler des objets sur
des machines distantes (objets distants)
de manière similaire aux objets sur la
machine locale (objet locaux).

45
RMI : Définition
 permet la communication entre machines virtuelles Java
(JVM) qui peuvent se trouver physiquement sur la même
machine ou sur deux machines distinctes.

46
RMI : Définition

 C'est du "RPC orienté objet".

 Un objet local demande une fonctionnalité à un objet

distant.

 Les échanges respectent un protocole propriétaire :


Remote Method Protocol (RMP)

 RMI est une API intégrée au JDK 1.1 et plus

 Les interfaces (contrats) sont des interfaces Java

→ L’IDL est Java lui-même


47
Objet Distribué ?

 Un objet distribué doit pouvoir être vu comme un


objet « normal ».
 Soit la déclaration suivante :

ObjetDistribue monObjetDistribue;
 On doit pouvoir appeler une méthode de cet objet
situé sur une autre machine de la même façon qu’un
objet local :
monObjetDisribue.uneMethode();
48
Objet Distribué ?
 On doit pouvoir utiliser cet objet distribué (OD) sans
connaître sa localisation. On utilise pour cela un service
d’annuaire, qui doit nous renvoyer son adresse.

monObjetDistribue=ServiceDeNoms.recherche(‘OD’);

 On doit pouvoir utiliser un objet distribué (OD) comme


paramètre d’une méthode locale ou distante.

x=monObjetLocal.uneMethodeLocale(OD1);

y=monObjetDistribue.uneMethode(OD2);

49
Principe de fonctionnement

Stub
Skeleton

50
Stub et Skeleton

 assurent le rôle d’adaptateurs pour le transport des appels


distants.
 réalisent les appels sur la couche réseau

 réalisent l’assemblage et le désassemblage des paramètres

 Une référence d’objets distribué correspond à une référence


de stub ou squelette
 sont crées en JAVA par le générateur rmic.

51
Les références d’objets
 Permet d’obtenir une référence d’objet distribué à partir de la
référence locale au stub.
 Cette fonction est assurée grâce à un service de noms
rmiregister (qui possède une table de hachage dont les clés
sont des noms et les valeurs sont des objets distants).
 Un unique rmiregister par JVM.
 rmiregister s’exécute sur chaque machine hébergeant des
objets distants.
 rmiregister accepte des demandes de service sur le port 1099
(port par défaut pouvant être changé).

52
Mode Opératoire des JAVA-RMI
0- A la création de l’objet-serveur, un stub et un skeleton (avec un port de
communication) sont créés sur le serveur
1- L'objet-serveur s'enregistre auprès du Naming de sa JVM (méthode rebind)
2- Le Naming enregistre le stub de l’objet auprès du serveur de noms (la
commande rmiregistry)
3- Le serveur de noms est prêt à fournir des références sur l’objet-serveur

53
Mode Opératoire des JAVA-RMI
4 - L'objet client fait appel à son Naming pour localiser l'objet-serveur sur
le serveur (méthode lookup)
5 - Le Naming récupère le stub vers l'objet-serveur auprès de la rmiregistry
6 – Le Naming installe l’objet Stub sur le poste client et retourne sa référence
au client
7 - Le client effectue l'appel à l’objet serveur par appel à l’objet local Stub

54
Etapes de Développement en JAVA-RMI
1. Définir une interface distante (Xyy.java) ;
2. Créer une classe implémentant cette interface (XyyImpl.java) ;
3. Compiler cette classe (javac XyyImpl.java) ;
4. Créer une application serveur (XyyServer.java) ;
5. Compiler l’application serveur ;
6. Créer les classes stub et skeleton à l’aide de
rmic XyyImpl_Stub.java et XyyImpl_Skel.java
7. Démarrage du registre avec rmiregistry ;
8. Lancer le serveur pour la création d’objets et leur enregistrement
dans rmiregistry;
9. Créer une classe cliente qui appelle des méthodes distantes de
l’objet distribué (XyyClient.java) ;
10. Compiler cette classe et la lancer. 55
Application sur un Exemple
Objectif: Inversion d’une chaîne de caractères à l’aide d’un
objet distribué

 Invocation distante de la méthode reverseString() d’un


objet distribué qui inverse une chaîne de caractères fournie
par l’appelant.
 On définit :
 ReverseInterface.java: interface qui décrit l’objet
distribué
 Reverse.java: qui implémente l’objet distribué
 ReverseServer.java: le serveur RMI
 ReverseClient.java: le client qui utilise l’objet distribué
56
Fichiers nécessaires
Côté Client Côté Serveur

l’interface : ReverseInterface l’interface : ReverseInterface

le client : ReverseClient l’objet : Reverse

le serveur d’objets : ReverseServer

57
Interface de l’objet distribué
 Elle est partagée par le client et le serveur.
 Elle décrit les caractéristiques de l’objet.
 Elle étend l’interface Remote définie dans la package
java.rmi.
 Toutes les méthodes de cette interface peuvent déclencher une
exception du type RemoteException.
 Cette exception est levée :
 si connexion refusée à l’hôte distant.
 ou bien si l’objet n’existe plus.
 Ou autres types d’erreurs de connexion.

58
Interface de la classe distante (Remote)
import java.rmi.Remote;

import java.rmi.RemoteException;

public interface ReverseInterface extends Remote {

String reverseString(String chaine) throws


RemoteException;

59
Implémentation de l’objet distribué
 Une classe distante doit implémenter une interface elle-même
distante (Remote)
 L’implémentation doit étendre la classe RemoteServer de
java.rmi.server
 RemoteServer est une classe abstraite
 UnicastRemoteObject est une classe concrète qui gère la
communication et les stubs
 étend RemoteServer
 une instance de cette classe réside sur un serveur et est
disponible via le protocole TCP/IP.
 Une classe distante peut aussi avoir des méthodes appelables
seulement localement (ne font pas partie de son interface
Remote)

60
Implémentation de l’objet distribué
import java.rmi.*;
import java.rmi.server.*;
public class Reverse extends UnicastRemoteObject implements ReverseInterface {
public Reverse() throws RemoteException {
super();//appel du constructeur de la classe de base }
public String reverseString (String ChaineOrigine) throws RemoteException {
int longueur=ChaineOrigine.length();
StringBuffer temp=new StringBuffer(longueur);
for (int i=longueur; i>0; i--)
{
temp.append(ChaineOrigine.substring(i-1, i));
}
return temp.toString();
}
} 61
Les Services de Nommage

 Permettent l’obtention d'une référence sur un


objet distant

 Enregistrent des références d'objets dans


l'annuaire afin que des programmes distants
puissent les récupérer.

 Se fait à l’aide de rmiregistry

62
Les Services de Nommage
rmiregistry
 Programme exécutable fourni pour toutes les plates formes
 S'exécute sur un port (1099 par défaut) sur la machine serveur
 Pour des raisons de sécurité, seuls les objets résidant sur la
même machine sont autorisés à lier/délier des références
 Un service de Nommage est lui-même localisé à l'aide d'une
URL

63
La classe Naming
 du package java.rmi
 permet de manipuler le rmiregistry
 supporte des méthodes statiques permettant de
 Lier des références d'objets serveur
 Naming.bind(...) et Naming.rebind(...)
 Délier des références d'objets serveur
 Naming.unbind(...)
 Lister le contenu du Naming
 Naming.list(...)
 Obtenir une référence vers un objet distant
 Naming.lookup(...)
64
Le serveur
 Programme à l’écoute des clients.

 Enregistre l’objet distribué dans rmiregistry

Naming.rebind("rmi://hote.site.com:1099/MyReverse", rev);

 On installe un gestionnaire de sécurité si le serveur est amené


à charger des classes (inutile si les classes ne sont pas chargées
dynamiquement)

System.setSecurityManager(new RMISecurityManager());

65
Le serveur
import java.rmi.*;
import java.rmi.server.*;
public class ReverseServer{
public static void main(String[] args){
try {
System.out.println( "Serveur : Construction de l’implémentation ");
Reverse rev= new Reverse();
System.out.println("Objet Reverse lié dans le RMIregistry");
Naming.rebind("rmi://hote.site.com:1099/MyReverse", rev);
System.out.println("Attente des invocations des clients …");
}
catch (Exception e) {
System.out.println("Erreur de liaison de l'objet Reverse");
System.out.println(e.toString());
} } // fin du main } // fin de la classe
66
Le Client

 Le client obtient un stub pour accéder à l’objet par une URL


RMI
ReverseInterface ri = (ReverseInterface) Naming.lookup
("rmi://hote.site.com:1099/MyReverse");
 Une URL RMI commence par rmi://, le nom de machine,
un numéro de port optionnel et le nom de l’objet
distant.
rmi://hote:2110/nomObjet
Par défaut, le numéro de port est 1099 défini (ou à
définir)(sous linux) dans /etc/services :
rmi 1099/tcp
67
Le Client
 Installe un gestionnaire de sécurité pour contrôler si les stubs
chargés dynamiquement :
System.setSecurityManager(new RMISecurityManager());
 Obtient une référence d’objet distribué :
ReverseInterface ri = (ReverseInterface) Naming.lookup(
"rmi://192.168.0.49:1099/MyReverse");
 Exécute une méthode de l’objet :
String result = ri.reverseString ("Terre");

68
Le Client
import java.rmi.*;
import ReverseInterface;
public class ReverseClient
{
public static void main (String [] args){
System.setSecurityManager(new RMISecurityManager());
try{
ReverseInterface rev = (ReverseInterface) Naming.lookup(
"rmi://hote.site.com:1099/MyReverse");
String result = rev.reverseString (args [0]);
System.out.println ("L'inverse de "+args[0]+" est "+result);
}
catch (Exception e)
{
System.out.println ("Erreur d'accès à l'objet distant.");
System.out.println (e.toString());
}
}
}
69
Le Client
 Pour que le client puisse se connecter à rmiregistry, il faut lui fournir un
fichier de règles de sécurité client.policy.
$ more client1.policy
grant
{ permission java.net.SocketPermission":1024-65535", "connect" ;
permission java.net.SocketPermission":80", "connect";
};
$ more client2.policy
grant
{ permission java.security.AllPermission;
};

70
Compilation et Exécution
 Compiler les sources (interface, implémentation de l’objet,
le serveur et le client ) :
$ javac *.java
 Lancer rmic sur la classe d’implémentation :
$ rmic -v1.2 Reverse
transférer *Stub.class et ReverseInterface.class vers l’autre
machine
 Démarrer rmiregistry :
$ rmiregistry -J-Djava.security.policy=client1.policy&

71
Compilation et Exécution
 Lancer le serveur :
$ java ReverseServer &
Serveur :Construction de l’implémentation
Objet Reverse lié dans le RMIregistry
Attente des invocations des clients …
 Exécuter le client :
$ java -Djava.security.policy=client1.policy ReverseClient
Bonjour
L'inverse de Bonjour est ruojnoB

72

S-ar putea să vă placă și