Diswork-commits
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 136 discussions
Author: bleny
Date: 2010-07-30 11:52:48 +0200 (Fri, 30 Jul 2010)
New Revision: 117
Url: http://nuiton.org/repositories/revision/diswork/117
Log:
ajout presentation pour reunion 30-07-2010
Added:
trunk/src/site/diswork_2010-07-30.odp
Added: trunk/src/site/diswork_2010-07-30.odp
===================================================================
(Binary files differ)
Property changes on: trunk/src/site/diswork_2010-07-30.odp
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
1
0
Author: bleny
Date: 2010-07-29 16:56:07 +0200 (Thu, 29 Jul 2010)
New Revision: 116
Url: http://nuiton.org/repositories/revision/diswork/116
Log:
diswork 0.2
Modified:
trunk/src/site/rst/devel-draft-0.2.rst
Modified: trunk/src/site/rst/devel-draft-0.2.rst
===================================================================
--- trunk/src/site/rst/devel-draft-0.2.rst 2010-07-28 12:24:33 UTC (rev 115)
+++ trunk/src/site/rst/devel-draft-0.2.rst 2010-07-29 14:56:07 UTC (rev 116)
@@ -8,8 +8,8 @@
État actuel de la version 0.1
=============================
-Sur les choix de conceptions
-----------------------------
+Sur les choix de conception
+---------------------------
Hormis les problèmes de sécurité du système, le choix qui a été fait de découper
le problème en trois couches semble justifié :
@@ -258,3 +258,135 @@
Pistes pour la version 0.2
==========================
+Implémenter une DHT qui assure toutes les propriétés nécessaires
+----------------------------------------------------------------
+
+1. Nécéssité de pouvoir connecté des nœuds qui se trouvent sur des machines
+ différentes
+
+2. Une DHT fonctionnelle : et un get() qui suit un put() doit pouvoir permettre
+ de récupérer la valeur publiée juste avant.
+
+3. Nécéssité de gérer la réplication pour ne pas perdre de données
+
+4. Nécessité d'être robuste vis-à-vis des connexions/déconnexions (dynamicité de
+ structure du réseau)
+
+5. Implémenter le contrat Map tel que définit dans java.util.Map, ce qui implique
+ notamment de permettre de récupérer l'ancienne valeur lors d'un put() ou
+ d'un remove().
+
+6. La nécessité de pouvoir publier des valeurs qui sont volumineuses. On souhaite
+ découper les fichiers en morceaux de 10 Mo. Notamment, cela exlue d'utiliser
+ UDP et nécessite d'utiliser TCP pour les échanges, car TCP peut découper
+ d'aussi gros messages ce qui n'est pas le cas d'UDP.
+
+
+::
+
+ application
+ ↓ ↑
+ blocks
+ ↑ ↓
+ overlay
+ ↑ ↓
+ network
+
+** La couche application **
+
+Elle contient le code spécifique à l'application P2P, elle est développée
+en utilisant des briques fournies par la couche blocks.
+
+** La couche blocks **
+
+La couche blocks devrait fournir les éléments constitutifs d'une application
+P2P : collections distribuées notamment. Les blocks doivent être implémentés
+de façon à gérer la réplication (propriété 3).
+Ces blocks doivent suffir pour écrire une application P2P. Au niveau
+des blocks, il faudra veiller à limiter le parallèlisme pour assurer
+la propriété 2.
+
+Un des block proposé dans le couche block sera évidemment une Map. Il faudrait
+également proposé MultiMap et Tree. Ce dernier sera idéal pour écrire le FS.
+
+Idéalement, il faudrait prévoir l'utilisation de plusieurs instances d'un même
+block dans une même application. Par exemple, un système de fichier pourrait
+utiliser Tree pour stocker l'arborescence, une Map pour stocker les données
+et une autre Map pour stoker les utilisateurs.
+
+Au niveau des blocs collections, il faudra proposer plusieurs méthodes de stockage
+des clés stockées localement dont l'une stockera les données sur le système
+de fichier local. D'autres implémentations pourront utiliser HashMap, une BdD
+embarquée, Cassandra...
+
+Pour assurer le réplication, la couche overlay doit fournir un ensemble de noeud
+accessibles rapidement (des proches). Chaque noeud doit répliquer les clés/valeurs
+sur tous les noeuds proches, par exemple en utilisant un algorithme de transaction
+distribué comme Two Phase Commit.
+
+Il faudrait gérer les droits à ce niveau-là.
+
+** La couche overlay **
+
+La couche overlay se charge d'entretenir une table de routage et l'algorithme
+pour atteindre tous les noeuds du réseau à partir d'une table de routage partielle.
+Dans cette couche se trouve les algorithmes de routages (kademlia, pastry...).
+
+L'implémentation devra veiller à bien gérer les erreurs et éventuellement,
+attendre que le système se stabilise avant de pouvoir exécuter les opérations
+demandées au niveau block. La gestion d'erreur peut avoir quelque-chose à voir
+avec http://en.wikipedia.org/wiki/Byzantine_fault_tolerance
+
+L'overlay doit également gérer l'entretien d'un groupe restreint de noeuds proches
+(tels que les leafset de Pastry).
+
+Cette couche doit être implémentée en ayant toujours l'hypothèse qu'un noeud
+a pu se déconnecter depuis le dernier message échangé.
+
+** La couche network **
+
+La couche network permet à l'overlay d'envoyer des messages et d'en recevoir
+et de pinguer un noeud (pour que la couche overlay puisse assurer la propriété
+4).
+
+Une implémentation réseau pourrait faire usage
+d'Apache Mina pour assurer les points 1 et 6 (Mina est basé sur TCP). C'est à ce
+niveau qu'on peut intervenir sur la sécurité bas niveau (connexion cryptées via
+TLS) et sur le passage de Firewall. D'autres implémentations plus fantaisistes
+peuvent se baser sur REST (cf Riak).
+
+On peut envisager que les connexions entre un
+noeud et les noeuds membres de son Leafset soient permanentes.
+
+Éventuellement, on pourra avoir une sous-couche décourverte qui permet de
+d'essayer de découvrir un noeud ou une liste de noeud de bootstrap. Possibilité
+de cumuler les méthodes :
+
+* Aller chercher une liste noeuds souvent connectés dans un fichier (fichier
+ local livré avec l'appli ou dispo via http)
+
+* Découverte dynamique de noeuds sur le réseau local via Zeroconf
+
+Ne plus utiliser de DHT comme base pour le sytème de fichiers
+-------------------------------------------------------------
+
+Comment faire ?
+
+Ne plus utiliser de système de fichier
+--------------------------------------
+
+On pourrait préférer faire en sorte que chaque
+noeud conserve ses données localement et les propose à qui les demande.
+
+Ça évite tout risque de perte de données mises en ligne mais ça à l'inconvénient
+de nécessiter à un noeud d'être présent et d'attendre que quelqu'un demande
+un fichier alors qu'avec la solution précédente, on peut publier un fichier
+et quitter le système juste après, le fichier est toujours disponible.
+
+Ça pose également le problème de la modification d'un fichier qui se trouve
+chez l'autre.
+
+Il faut aussi trouver le moyen de mettre les noeuds en relation, une solution
+serait d'avoir, à la eMule, des serveurs centralisés dont le seul rôle est
+d'indexé les fichiers proposés par les noeuds. Les noeuds peuvent ensuite faire
+des recherches via ce serveur central.
\ No newline at end of file
1
0
r115 - in trunk: diswork-daemon/src/main/java/org/nuiton/diswork/daemon diswork-fs/src/main/java/org/nuiton/diswork/fs diswork-fs/src/main/java/org/nuiton/diswork/fs/storage diswork-fs/src/test/java/org/nuiton/diswork/fs diswork-fs/src/test/java/org/nuiton/diswork/fs/storage
by bleny@users.nuiton.org 28 Jul '10
by bleny@users.nuiton.org 28 Jul '10
28 Jul '10
Author: bleny
Date: 2010-07-28 14:24:33 +0200 (Wed, 28 Jul 2010)
New Revision: 115
Url: http://nuiton.org/repositories/revision/diswork/115
Log:
gestion des exceptions dans le FS
Added:
trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkAlreadyExistsException.java
Modified:
trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkDaemon.java
trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkFileSystem.java
trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkFileSystemException.java
trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/KademliaDisworkMap.java
trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/PastryDisworkMap.java
trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/Storage.java
trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/AbstractDisworkFileSystemTest.java
trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/storage/KademliaDisworkMapTest.java
Modified: trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkDaemon.java
===================================================================
--- trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkDaemon.java 2010-07-28 12:22:28 UTC (rev 114)
+++ trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkDaemon.java 2010-07-28 12:24:33 UTC (rev 115)
@@ -42,10 +42,10 @@
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.nuiton.diswork.fs.DisworkAlreadyExistsException;
import org.nuiton.diswork.fs.DisworkFileSystem;
import org.nuiton.diswork.fs.DisworkFileSystemConfig;
import org.nuiton.diswork.fs.DisworkFileSystemException;
-import org.nuiton.diswork.fs.DisworkFileSystemException.Type;
import org.nuiton.util.FileUtil;
/**
@@ -609,13 +609,9 @@
// there is a risk that jobs be proposed at the same time
fileSystem.createSymbolicLink(TODO + "/" + linkName, jobDir);
success = true;
- } catch (DisworkFileSystemException e) {
- if (e.getType() == Type.ALREADY_EXISTS) {
- // retry
- success = false;
- } else {
- throw e;
- }
+ } catch (DisworkAlreadyExistsException e) {
+ // retry
+ success = false;
}
}
config.addOneJobSubmitted();
Added: trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkAlreadyExistsException.java
===================================================================
--- trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkAlreadyExistsException.java (rev 0)
+++ trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkAlreadyExistsException.java 2010-07-28 12:24:33 UTC (rev 115)
@@ -0,0 +1,20 @@
+package org.nuiton.diswork.fs;
+
+/** thrown when if path lead to something that already exists */
+public class DisworkAlreadyExistsException extends DisworkFileSystemException {
+
+ private static final long serialVersionUID = 1L;
+
+ public DisworkAlreadyExistsException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public DisworkAlreadyExistsException(String message) {
+ super(message);
+ }
+
+ public DisworkAlreadyExistsException(Throwable cause) {
+ super(cause);
+ }
+
+}
Modified: trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkFileSystem.java
===================================================================
--- trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkFileSystem.java 2010-07-28 12:22:28 UTC (rev 114)
+++ trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkFileSystem.java 2010-07-28 12:24:33 UTC (rev 115)
@@ -33,7 +33,6 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.nuiton.diswork.fs.DisworkFileSystemException.Type;
import org.nuiton.diswork.fs.storage.DisworkMap;
import org.nuiton.diswork.fs.storage.EntryUtil;
import org.nuiton.diswork.fs.storage.Storage;
@@ -145,7 +144,7 @@
String newTarget = EntryUtil.resolveLink(path, link);
result = read(newTarget);
} else if (EntryUtil.isDirectory(entry)) {
- throw new DisworkFileSystemException(Type.NOT_FILE, "target is not a file: " + path);
+ throw new IllegalArgumentException(path + " is not a file but a directory");
} else if (EntryUtil.isFile(entry)) {
log.info("reading file " + path);
String id = EntryUtil.getIdFromEntry(entry);
@@ -178,8 +177,7 @@
String entryParent = walk(parent);
if (entryParent == null) {
- throw new DisworkFileSystemException(Type.NO_SUCH_DIRECTORY, parent
- + " directory doesn't exists");
+ throw new IllegalArgumentException(parent + " directory doesn't exists");
}
if (EntryUtil.isDirectory(entryParent)) {
@@ -223,7 +221,7 @@
Thread.sleep(LOCK_WAIT);
} catch (InterruptedException e) {
log.info("wait for lock interrupted", e);
- throw new DisworkFileSystemException(Type.INTERRUPTION,
+ throw new DisworkFileSystemException(
"interrupted while trying to acquire lock", e);
}
}
@@ -240,11 +238,10 @@
String newTarget = EntryUtil.resolveLink(parent, linkTarget);
write(newTarget, fileName, source);
} else if (EntryUtil.isFile(entryParent)) {
- throw new DisworkFileSystemException(Type.NOT_DIRECTORY, parent);
+ throw new IllegalArgumentException(parent + " is not a directory");
} else {
log.warn("strange entry" + entryParent);
- throw new DisworkFileSystemException(Type.CORRUPTED_DATA,
- "strange entry" + entryParent);
+ throw new DisworkFileSystemException("strange entry" + entryParent);
}
}
@@ -268,7 +265,7 @@
String entryParent = walk(parent);
if (entryParent == null) {
- throw new DisworkFileSystemException(Type.NO_SUCH_DIRECTORY, parent);
+ throw new IllegalArgumentException(parent + " directory doesn't exists");
}
if (EntryUtil.isDirectory(entryParent)) {
@@ -279,7 +276,7 @@
String findResult = EntryUtil.findEntryInDirectory
(content, dirName);
if (findResult != null) {
- throw new DisworkFileSystemException(Type.ALREADY_EXISTS, parent
+ throw new DisworkAlreadyExistsException(parent
+ " already contains an element named " + dirName);
}
@@ -306,7 +303,7 @@
Thread.sleep(LOCK_WAIT);
} catch (InterruptedException e) {
log.info("wait for lock interrupted", e);
- throw new DisworkFileSystemException(Type.INTERRUPTION,
+ throw new DisworkFileSystemException(
"interrupted while trying to acquire lock", e);
}
}
@@ -323,11 +320,10 @@
String newTarget = EntryUtil.resolveLink(parent, linkTarget);
createDirectory(newTarget, dirName);
} else if (EntryUtil.isFile(entryParent)) {
- throw new DisworkFileSystemException(Type.NOT_DIRECTORY, parent);
+ throw new IllegalArgumentException(parent + " is not a directory");
} else {
log.warn("strange entry" + entryParent);
- throw new DisworkFileSystemException(Type.CORRUPTED_DATA,
- "strange entry" + entryParent);
+ throw new DisworkFileSystemException("strange entry" + entryParent);
}
}
@@ -340,6 +336,9 @@
*/
public void createSymbolicLink(String path, String target)
throws DisworkFileSystemException {
+ if (exists(path)) {
+ throw new DisworkAlreadyExistsException(path);
+ }
checkPathSyntax(path);
String parent = EntryUtil.getParentFromPath(path);
String name = EntryUtil.getNameFromPath(path);
@@ -367,8 +366,7 @@
String entryParent = walk(parent);
if (entryParent == null) {
- throw new DisworkFileSystemException(Type.NO_SUCH_DIRECTORY,
- parent);
+ throw new IllegalArgumentException(parent + " doesn't exists");
}
if (EntryUtil.isDirectory(entryParent)) {
@@ -380,7 +378,7 @@
String findResult = EntryUtil.findEntryInDirectory
(content, name);
if (findResult != null) {
- throw new DisworkFileSystemException(Type.ALREADY_EXISTS,
+ throw new DisworkFileSystemException(
parent + " already contains an element named " + name);
}
@@ -406,7 +404,7 @@
Thread.sleep(LOCK_WAIT);
} catch (InterruptedException e) {
log.info("wait for lock interrupted", e);
- throw new DisworkFileSystemException(Type.INTERRUPTION,
+ throw new DisworkFileSystemException(
"interrupted while trying to acquire lock", e);
}
}
@@ -424,16 +422,15 @@
String newTarget = EntryUtil.resolveLink(parent, linkTarget);
createSymbolicLink(newTarget, name, target);
} else if (EntryUtil.isFile(entryParent)) {
- throw new DisworkFileSystemException(Type.NOT_DIRECTORY, parent);
+ throw new IllegalArgumentException(parent + " is not a directory");
} else {
log.warn("strange entry" + entryParent);
- throw new DisworkFileSystemException(Type.CORRUPTED_DATA,
+ throw new DisworkFileSystemException(
"strange entry" + entryParent);
}
-
-
} else {
- throw new DisworkFileSystemException(Type.INVALID_TARGET, target);
+ throw new IllegalArgumentException(target + " is not a valid " +
+ "target (do not exists)");
}
}
@@ -446,7 +443,7 @@
public void delete(String path) throws DisworkFileSystemException {
checkPathSyntax(path);
if (!exists(path)) {
- throw new DisworkFileSystemException(Type.NO_SUCH_ENTITY, path);
+ throw new DisworkFileSystemException(path + " doesn't not exists");
}
String parent = EntryUtil.getParentFromPath(path);
String name = EntryUtil.getNameFromPath(path);
@@ -478,7 +475,7 @@
if (!innerDirectoryContent.equals(
EntryUtil.EMPTY_DIRECTORY_CONTENT)) {
// directory is not empty
- throw new DisworkFileSystemException(Type.DIRECTORY_NOT_EMPTY,
+ throw new IllegalArgumentException(
"trying to remove a non-empty directory");
}
@@ -491,7 +488,7 @@
storage.removeLink(idToRemove);
} else {
log.warn("strange entry" + entryParent);
- throw new DisworkFileSystemException(Type.CORRUPTED_DATA,
+ throw new DisworkFileSystemException(
"strange entry" + entryParent);
}
@@ -513,7 +510,7 @@
Thread.sleep(LOCK_WAIT);
} catch (InterruptedException e) {
log.info("wait for lock interrupted", e);
- throw new DisworkFileSystemException(Type.INTERRUPTION,
+ throw new DisworkFileSystemException(
"interrupted while trying to acquire lock", e);
}
}
@@ -531,11 +528,10 @@
String newTarget = EntryUtil.resolveLink(parent, linkTarget);
delete(newTarget, name);
} else if (EntryUtil.isFile(entryParent)) {
- throw new DisworkFileSystemException(Type.NOT_DIRECTORY, parent);
+ throw new IllegalArgumentException(parent + " is not a directory");
} else {
log.warn("strange entry" + entryParent);
- throw new DisworkFileSystemException(Type.CORRUPTED_DATA,
- "strange entry" + entryParent);
+ throw new DisworkFileSystemException("strange entry" + entryParent);
}
}
@@ -552,7 +548,7 @@
List<String> result = null;
if (entry == null) {
- throw new DisworkFileSystemException(Type.NO_SUCH_DIRECTORY, path);
+ throw new IllegalArgumentException(path + " directory doesn't exists");
} else {
// path may be a link, if it's the case,
// entry become the actual directory
@@ -574,12 +570,10 @@
}
}
} else if (EntryUtil.isFile(entry)) {
- throw new DisworkFileSystemException(Type.NOT_DIRECTORY, path +
- " is not a directory but a file");
+ throw new IllegalArgumentException(path + " is not a directory but a file");
} else {
log.warn("strange entry" + entry);
- throw new DisworkFileSystemException(Type.CORRUPTED_DATA,
- "strange entry" + entry);
+ throw new DisworkFileSystemException("strange entry" + entry);
}
}
@@ -600,8 +594,7 @@
checkPathSyntax(destination);
if (exists(destination)) {
- throw new DisworkFileSystemException(Type.ALREADY_EXISTS,
- destination + " already exists");
+ throw new DisworkAlreadyExistsException(destination + " already exists");
}
String pathParent = EntryUtil.getParentFromPath(path);
@@ -620,16 +613,14 @@
String entryParent = walk(pathParent);
if (entryParent == null) {
- throw new DisworkFileSystemException(Type.NO_SUCH_DIRECTORY,
- pathParent);
+ throw new IllegalArgumentException(pathParent + " doesn't exists");
}
if (EntryUtil.isDirectory(entryParent)) {
String destinationParentEntry = walk(destinationParent);
if (destinationParentEntry == null) {
- throw new DisworkFileSystemException(Type.NO_SUCH_DIRECTORY,
- destinationParentEntry);
+ throw new IllegalArgumentException(destinationParent + " doesn't exists");
}
if (EntryUtil.isDirectory(destinationParentEntry)) {
@@ -641,8 +632,7 @@
String oldEntry = EntryUtil.findEntryInDirectory(parentContent,
pathName);
if (oldEntry == null) {
- throw new DisworkFileSystemException(Type.NO_SUCH_ENTITY,
- "no element " + pathName + " in " + pathParent);
+ throw new IllegalArgumentException("no element " + pathName + " in " + pathParent);
}
String parentId = EntryUtil.getIdFromEntry(entryParent);
@@ -676,7 +666,7 @@
Thread.sleep(LOCK_WAIT);
} catch (InterruptedException e) {
log.info("wait for lock interrupted", e);
- throw new DisworkFileSystemException(Type.INTERRUPTION,
+ throw new DisworkFileSystemException(
"interrupted while trying to acquire lock", e);
}
}
@@ -694,11 +684,11 @@
String newTarget = EntryUtil.resolveLink(destinationParent, linkTarget);
move(newTarget, pathName, destinationParent, destinationName);
} else if (EntryUtil.isFile(destinationParentEntry)) {
- throw new DisworkFileSystemException(Type.NOT_DIRECTORY, destinationParent);
+ throw new IllegalArgumentException(destinationParent + " is not a directory");
} else {
log.warn("strange entry" + destinationParentEntry);
- throw new DisworkFileSystemException(Type.CORRUPTED_DATA,
- "strange entry" + destinationParentEntry);
+ throw new DisworkFileSystemException("strange entry" +
+ destinationParentEntry);
}
} else if (EntryUtil.isLink(entryParent)) {
@@ -707,11 +697,10 @@
String newTarget = EntryUtil.resolveLink(pathParent, linkTarget);
move(pathParent, pathName, newTarget, destinationName);
} else if (EntryUtil.isFile(entryParent)) {
- throw new DisworkFileSystemException(Type.NOT_DIRECTORY, pathParent);
+ throw new IllegalArgumentException(pathParent + " is not a directory");
} else {
log.warn("strange entry" + entryParent);
- throw new DisworkFileSystemException(Type.CORRUPTED_DATA,
- "strange entry" + entryParent);
+ throw new DisworkFileSystemException("strange entry" + entryParent);
}
}
@@ -720,7 +709,7 @@
checkPathSyntax(path);
String entry = walk(path);
if (entry == null) {
- throw new DisworkFileSystemException(Type.NO_SUCH_ENTITY, path);
+ throw new IllegalArgumentException(path + " doesn't not exists");
}
return EntryUtil.isLink(entry);
}
@@ -729,7 +718,7 @@
checkPathSyntax(path);
String entry = walk(path);
if (entry == null) {
- throw new DisworkFileSystemException(Type.NO_SUCH_FILE, path);
+ throw new IllegalArgumentException(path + " doesn't not exists");
}
return EntryUtil.isFile(entry);
}
@@ -738,7 +727,7 @@
checkPathSyntax(path);
String entry = walk(path);
if (entry == null) {
- throw new DisworkFileSystemException(Type.NO_SUCH_FILE, path);
+ throw new IllegalArgumentException(path + " doesn't not exists");
}
return EntryUtil.isDirectory(entry);
}
Modified: trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkFileSystemException.java
===================================================================
--- trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkFileSystemException.java 2010-07-28 12:22:28 UTC (rev 114)
+++ trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkFileSystemException.java 2010-07-28 12:24:33 UTC (rev 115)
@@ -35,60 +35,17 @@
private static final long serialVersionUID = 1L;
- public static enum Type {
- /** Something with this path already exists */
- ALREADY_EXISTS,
- /** Error while writing because another node is writing at this place */
- CONCURRENT_MODIFICATION,
- /** The directory has a content */
- DIRECTORY_NOT_EMPTY,
- /** directory doesn't exists */
- NO_SUCH_DIRECTORY,
- /** file doesn't exists */
- NO_SUCH_FILE,
- /** nothing at a given path */
- NO_SUCH_ENTITY,
- /** The path leads to something that exists but is not a directory */
- NOT_DIRECTORY,
- /** The path leads to something that exists but is not a file */
- NOT_FILE,
- /** The connection to the DHT failed
- * this is due to a network failure or a bad configuration
- */
- BOOTSTRAP_FAILURE,
- /** an IO errors at low-level network occured */
- NETWORK_FAILURE,
- /** a source data on the local OS is not readable */
- READ_LOCAL_DATA_FAILURE,
- /** error while reading data in the map */
- READ_MAP_DATA_FAILURE,
- /** a process was interrupted */
- INTERRUPTION,
- /** if map contains corrupted data */
- CORRUPTED_DATA,
- /** the symlink point to a target that is not valid */
- INVALID_TARGET
- }
-
- protected Type type;
- public DisworkFileSystemException(Type type, String message,
- Throwable cause) {
- super("[" + type + "]" + message, cause);
- this.type = type;
+ public DisworkFileSystemException(String message, Throwable cause) {
+ super(message, cause);
}
- public DisworkFileSystemException(Type type, String message) {
- super("[" + type + "]" + message);
- this.type = type;
+ public DisworkFileSystemException(String message) {
+ super(message);
}
- public DisworkFileSystemException(Type type, Throwable cause) {
- this(type, "", cause);
+ public DisworkFileSystemException(Throwable cause) {
+ super(cause);
}
-
- public Type getType() {
- return type;
- }
}
Modified: trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/KademliaDisworkMap.java
===================================================================
--- trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/KademliaDisworkMap.java 2010-07-28 12:22:28 UTC (rev 114)
+++ trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/KademliaDisworkMap.java 2010-07-28 12:24:33 UTC (rev 115)
@@ -39,7 +39,6 @@
import org.apache.commons.logging.LogFactory;
import org.nuiton.diswork.fs.DisworkFileSystemConfig;
import org.nuiton.diswork.fs.DisworkFileSystemException;
-import org.nuiton.diswork.fs.DisworkFileSystemException.Type;
import org.planx.xmlstore.routing.Identifier;
import org.planx.xmlstore.routing.Kademlia;
import org.planx.xmlstore.routing.RoutingException;
@@ -66,8 +65,8 @@
kad.connect(bootstrap);
} catch (RoutingException e) {
log.error("bootstrap node is unreachable", e);
- throw new DisworkFileSystemException(Type.BOOTSTRAP_FAILURE,
- "bootstrap node is unreachable", e);
+ throw new DisworkFileSystemException("bootstrap failure : "
+ + "bootstrap node is unreachable", e);
}
}
@@ -76,8 +75,7 @@
//Identifier.IDSIZE = 1024;
log.info("using " + Identifier.IDSIZE + " bytes for identifiers");
} catch (IOException e) {
- throw new DisworkFileSystemException(Type.NETWORK_FAILURE,
- "failure while bootstraping", e);
+ throw new DisworkFileSystemException("failure while bootstraping", e);
}
}
Modified: trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/PastryDisworkMap.java
===================================================================
--- trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/PastryDisworkMap.java 2010-07-28 12:22:28 UTC (rev 114)
+++ trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/PastryDisworkMap.java 2010-07-28 12:24:33 UTC (rev 115)
@@ -38,7 +38,6 @@
import org.apache.commons.logging.LogFactory;
import org.nuiton.diswork.fs.DisworkFileSystemConfig;
import org.nuiton.diswork.fs.DisworkFileSystemException;
-import org.nuiton.diswork.fs.DisworkFileSystemException.Type;
import rice.Continuation;
import rice.environment.Environment;
@@ -219,7 +218,8 @@
""
);
} catch (IOException e) {
- throw new DisworkFileSystemException(Type.NETWORK_FAILURE, e);
+ throw new DisworkFileSystemException("network failure while"
+ + " bootstraping", e);
}
}
Modified: trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/Storage.java
===================================================================
--- trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/Storage.java 2010-07-28 12:22:28 UTC (rev 114)
+++ trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/Storage.java 2010-07-28 12:24:33 UTC (rev 115)
@@ -36,7 +36,6 @@
import org.apache.commons.logging.LogFactory;
import org.nuiton.diswork.fs.DisworkFileSystemConfig;
import org.nuiton.diswork.fs.DisworkFileSystemException;
-import org.nuiton.diswork.fs.DisworkFileSystemException.Type;
/**
* This class is the middle layer between the File System operations and
@@ -232,7 +231,7 @@
log.debug("getDirectory(\"" + id + "\") returns \n" + content);
return content;
} catch (IOException e) {
- throw new DisworkFileSystemException(Type.READ_MAP_DATA_FAILURE, e);
+ throw new DisworkFileSystemException(e);
}
}
@@ -261,7 +260,7 @@
+ " bytes)");
put(id, content);
} catch (IOException e) {
- throw new DisworkFileSystemException(Type.READ_LOCAL_DATA_FAILURE, e);
+ throw new DisworkFileSystemException(e);
}
}
@@ -368,12 +367,12 @@
unLock(key);
} catch (IOException e) {
throw new DisworkFileSystemException
- (Type.READ_LOCAL_DATA_FAILURE, "can't read value", e);
+ ("can't read value", e);
}
} else {
- throw new DisworkFileSystemException(Type.CONCURRENT_MODIFICATION,
- "key " + key + " is locked");
+ throw new DisworkFileSystemException("key " + key + " is locked"
+ + " another node way being writing it");
}
}
@@ -407,8 +406,7 @@
map.close();
} catch (IOException e) {
log.error("error while closing map", e);
- throw new DisworkFileSystemException(Type.NETWORK_FAILURE,
- "unable to close the map", e);
+ throw new DisworkFileSystemException("unable to close the map", e);
}
}
Modified: trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/AbstractDisworkFileSystemTest.java
===================================================================
--- trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/AbstractDisworkFileSystemTest.java 2010-07-28 12:22:28 UTC (rev 114)
+++ trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/AbstractDisworkFileSystemTest.java 2010-07-28 12:24:33 UTC (rev 115)
@@ -44,7 +44,6 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import org.nuiton.diswork.fs.DisworkFileSystemException.Type;
import org.nuiton.util.FileUtil;
@@ -231,8 +230,8 @@
source = new FileInputStream(randomFilePath);
fileSystem.write("/my_folder/my_file", source);
fail();
- } catch (DisworkFileSystemException e ){
- assertEquals(Type.NO_SUCH_DIRECTORY, e.getType());
+ } catch (IllegalArgumentException e ){
+ assertTrue(true);
} finally {
IOUtils.closeQuietly(source);
}
@@ -339,8 +338,8 @@
try {
fileSystem.createSymbolicLink("/my_link", "/wrong_target_path");
fail();
- } catch (DisworkFileSystemException e) {
- assertEquals(Type.INVALID_TARGET, e.getType());
+ } catch (IllegalArgumentException e) {
+ assertTrue(true);
}
}
@@ -387,8 +386,8 @@
try {
fileSystem.delete("/my_folder");
fail();
- } catch (DisworkFileSystemException e) {
- assertEquals(Type.DIRECTORY_NOT_EMPTY, e.getType());
+ } catch (IllegalArgumentException e) {
+ assertTrue(true);
}
}
@@ -516,8 +515,8 @@
fileSystem.createDirectory("/dir2");
try {
fileSystem.move("/dir", "/dir2");
- } catch (DisworkFileSystemException e) {
- assertEquals(Type.ALREADY_EXISTS, e.getType());
+ } catch (IllegalArgumentException e) {
+ assertTrue(true);
}
}
Modified: trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/storage/KademliaDisworkMapTest.java
===================================================================
--- trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/storage/KademliaDisworkMapTest.java 2010-07-28 12:22:28 UTC (rev 114)
+++ trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/storage/KademliaDisworkMapTest.java 2010-07-28 12:24:33 UTC (rev 115)
@@ -26,6 +26,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
@@ -37,7 +38,6 @@
import org.junit.Test;
import org.nuiton.diswork.fs.DisworkFileSystemConfig;
import org.nuiton.diswork.fs.DisworkFileSystemException;
-import org.nuiton.diswork.fs.DisworkFileSystemException.Type;
import org.planx.xmlstore.routing.Identifier;
public class KademliaDisworkMapTest extends AbstractDisworkMapTest {
@@ -104,7 +104,7 @@
new KademliaDisworkMap(config1);
fail();
} catch (DisworkFileSystemException e) {
- assertEquals(Type.BOOTSTRAP_FAILURE, e.getType());
+ assertTrue(true);
}
}
}
1
0
Author: bleny
Date: 2010-07-28 14:22:28 +0200 (Wed, 28 Jul 2010)
New Revision: 114
Url: http://nuiton.org/repositories/revision/diswork/114
Log:
draft diswork 0.2
Added:
trunk/src/site/rst/devel-draft-0.2.rst
Modified:
trunk/src/site/rst/diswork-fs/devel.rst
trunk/src/site/site_en.xml
Added: trunk/src/site/rst/devel-draft-0.2.rst
===================================================================
--- trunk/src/site/rst/devel-draft-0.2.rst (rev 0)
+++ trunk/src/site/rst/devel-draft-0.2.rst 2010-07-28 12:22:28 UTC (rev 114)
@@ -0,0 +1,260 @@
+========================
+Draft pour Diswork v 0.2
+========================
+
+Ce document part de l'expérience acquise lors du développement de la version 0.1
+et donne les pistes pour la suite des développements.
+
+État actuel de la version 0.1
+=============================
+
+Sur les choix de conceptions
+----------------------------
+
+Hormis les problèmes de sécurité du système, le choix qui a été fait de découper
+le problème en trois couches semble justifié :
+
+* Diswork daemon est un petit logiciel qui tourne sur une machine et qui propose
+ à Isis de lui soumettre des jobs.
+
+* Diswork File System est un système de fichiers utilisé comme sous-couche du
+ démon. Le truc, c'est que tous les daemon utilisent tous le même système de
+ fichiers : c'est ce qui les relie entre eux. Lorsqu'un démon reçoit une
+ soumission de job, en fait, il écrit le job sur le FS, et comme tous les
+ démons ont accès au FS, il suffit d'aller lire ce qui se trouve sur le FS
+ pour trouver de jobs.
+
+* Pour assurer la distribution du système de fichiers sur tous les noeuds.
+ Diswork FS écrit toutes les données du système dans une seule Map (telle que
+ java.util.Map). C'est cette Map qui est distribuée entre toutes les machines,
+ et comme toutes les machines ont accès à la même Map, le système de fichier se
+ trouve être distribué. Cette Map distribuée, c'est la fameuse DHT, c'est sur
+ elle que repose tout le système.
+
+Cette conception est globalement satisfaisante. Le seul problème est inhérent à
+l'utilisation d'une DHT : les blocs sont répartis de façon uniforme sur tous
+les nœuds sans tenir compte des capacités de stockage de chacun. Il s'agit
+du fameux problème dit de « satisfaction » dans les DHT. Pour que le système
+marche, personne ne choisit les données dont il est responsable.
+
+Problèmes de la DHT
+-------------------
+
+Il est difficile de trouver une implémentation de DHT qui soit fiable et qui
+corresponde à nos besoins. Nos besoins sont :
+
+1. Nécéssité de pouvoir connecté des nœuds qui se trouvent sur des machines
+ différentes
+
+2. Une DHT fonctionnelle : et un get() qui suit un put() doit pouvoir permettre
+ de récupérer la valeur publiée juste avant.
+
+3. Nécéssité de gérer la réplication pour ne pas perdre de données
+
+4. Nécessité d'être robuste vis-à-vis des connexions/déconnexions (dynamicité de
+ structure du réseau)
+
+5. Implémenter le contrat Map tel que définit dans java.util.Map, ce qui implique
+ notamment de permettre de récupérer l'ancienne valeur lors d'un put() ou
+ d'un remove().
+
+6. La nécessité de pouvoir publier des valeurs qui sont volumineuses. On souhaite
+ découper les fichiers en morceaux de 10 Mo. Notamment, cela exlue d'utiliser
+ UDP et nécessite d'utiliser TCP pour les échanges, car TCP peut découper
+ d'aussi gros messages ce qui n'est pas le cas d'UDP.
+
+Les tentatives de réutiliser les DHT ont été nombreuses :
+
+* JDHT ne valide pas le point 2.
+
+* Pastry a nécessité un correctif pour valider le poitn 1. Elle ne vérifie pas
+ le point 6 et dès que l'utilisation est intense
+ (plusieurs put et get en quelques secondes sur une même clé) le point 2
+ devient ératique
+
+* XMLStore après deux corrections (pour valider les points 1 et 6) s'avère
+ la solution la plus fiable. Son comportement reste soumis à erreur au niveau
+ du point 4 dès qu'un noeud quitte le système de façon innopinée
+
+* Mojito ne valide pas le point 6
+
+Sécurité dans Diswork 0.1
+-------------------------
+
+Les systèmes distribués en général et P2P en particulier comme Diswork sont
+réputés pour être difficiles à concevoir de façon sûre.
+
+Le problème qui se pose qui nous intéresse ici est le suivant : que se passe-t-il
+si on imagine qu'un individu mal intentionné (au hasard, appelons-le Juan)
+décide de nuire au système.
+
+Juan a de nombreuses possibilités :
+
+* au niveau du démon on peut déjà soumettre toutes les seconds des jobs qui ne
+ finissent jamais. Des jobs qui, en fait, envoient du spam ou font crasher la
+ machine qui les lances (fork bombs) ou encore envoyer des tas de requêtes HTTP
+ vers un serveur cible ce qui aurait pour effet (en soumettant ce job plusieurs)
+ de faire participer tous les noeuds diswork à un DDoS. On peut modifier le
+ code du démon pour réserver un job comme si on allait le faire, puis, en fait,
+ ne jamais le faire.
+
+* au niveau du File System, c'est simple, les droits ne sont pas gérés
+ (et pour cause, voir la suite). Tout est accessible en lecture/écriture.
+ Juan peut donc faire un petit « rm -rf / ».
+
+* au niveau de la DHT, nous avons vu que c'est une Map. C'est donc une mémoire
+ partagée entre tous les nœuds du réseau : et ça, c'est bon pour Juan. Les DHT
+ ont pour particularité de ne pas permettre, contrairement à toutes les Map
+ habituelles, de pouvoir parcourir l'ensemble des clés (espace trop grand).
+ Toutefois, en se documentant un peu (oui, j'ai fait de la doc.) Juan pourra
+ vite trouver un moyen de trouver tout un tas de clés utilisées dans la Map et
+ pourra, à loisirs, faire des map.remove() dessus. Je vais pas m'attarder
+ m'attarde pas sur les attaques possibles qui sont intrinsèques à l'algorithme
+ et/ou à l'implémentation de la DHT utilisée mais si on parle de l'algo
+ Kademlia, on peut parler d'attaque Sybil (ou Spartacus)
+
+Comme on peut le voir, il y a trop de problèmes à trop de niveaux pour espérer
+tout réglé mais on va quand même essayé.
+
+Tentons de régler les problèmes, niveaux par niveaux :
+
+Commençons par le démon. Envisageons de filtrer les jobs pour ne faire que des
+jobs qui sont "gentils" : sur quel critère se baser pour dire que tel ou tel de
+job est mauvais ?
+
+* L'application utilisée ? On peut créer des jobs qui dépendent de Isis (isis
+ sera téléchargé) mais préciser une ligne de commande pour ce job qui n'a rien
+ à voir (fork bomb)
+
+* Le nœud qui a soumis le job ou les résultats d'un job ? Comment savoir quel
+ nœud a posé ce job sur le FS. Vu que le FS est accessible en écriture pour
+ Juan, Juan pourrait changer les informations concernant le propriétaire du job
+ et donc poser un job vicieux et dire qu'il est à Éric (qui est un ange, comme
+ chacun sait). Même si ce n'était pas le cas, comme savoir que Éric est gentil
+ et Juan méchant ? Pas moyen. Pour s'assurer de l'origine d'un job, on pense
+ tout de suite à signer les jobs avec un système de clés asymétriques. Ça ne
+ change rien, Juan peut signer des jobs et des résultats aussi. Vient alors
+ encore une idée, on a qu'à faire faire le job par 4 machines différentes,
+ comparer les quatre résultats et voir si les résultats sont différent. Si un
+ résultat diffère des trois autres, on considère qu'il a été mal fait par une
+ machine contrôlée par Juan et on exclue ce résultat pour se baser sur les
+ trois restants, supposés fiables. Sauf que, comme dit, les jobs ne sont pas
+ poussés vers ceux qui les font mais posés sur le file-system, d'autres nœud,
+ en parcourant le FS les trouve. Du coup, Juan peut facilement lancer quatre
+ nœud (voire un seul nœud), réserver les quatre jobs, calculer (une fois) de
+ faux résultats, les signer avec des clés différentes et les publier 4 fois
+ comme 4 résultats faits par des machines différentes (avec un pti délai entre
+ chaque dépôt pour pas qu'on voit que tout a été fait en même temps...). Juan
+ est vraiment vicieux. En plus, ça impliquerait de mettre en place un système
+ pour échanger les clés publiques, il ne faut surtout pas les mettre sur le FS,
+ Juan pourrait remplacer celle d'Éric par la sienne. On peut imaginer les
+ mettre toutes sur un serveur à côté, où les clés sont publiées une fois pour
+ toutes mais comment éviter que Juan y publie ses propres clés ?
+
+Passons au système de fichier. Pour résoudre les problèmes évoqués ci dessus, on
+pourrait souhaiter des droits de le forme UNIX pour le FS distribué (des
+utilisateurs, des groupes et des droits lectures/écritures par fichier pour le
+propriétaire, le groupe et les autres). Il faudrait stocker ces nouvelles
+données dans la Map, c'est pas un problème. Cependant, comme, de toute façon,
+c'est Juan qui choisit d'interpréter les données qu'il peut lire dans la Map,
+il pourra lire les droits, les ignorer, et lire le fichier quand même : il
+suffit de faire des get().
+
+Et si on crypte ? Et bien Juan n'arrivera pas à lire les données, c'est déjà ça
+de pris. Encore faut-il savoir avec quelle clé crypter. Celle du propriétaire ?
+Non, le membres du groupe ne pourrait pas lire. Celle du groupe alors ? Oui,
+c'est déjà mieux. En fait, il faut choisir le clé en fonction des droits. Quand
+on écrit le fichier, il faut crypter avec la clé du groupe si le groupe a accès
+en lecture, celle du proprio si le groupe n'a pas accès en lecture et ne pas
+crypter si tout le monde a accès en écriture. Ça suppose que le proprio
+appartienne au groupe (c'est pas absurde). Encore faut-il ne distribuer la clé
+du groupe qu'à ceux qui sont dans le groupe et ne pas la divulguer. Ça peut
+s'imaginer disons, en déposant dans le home d'un utilisateur un fichier qui
+contient la clé du groupe cryptée avec la clé publique de l'utilisateur qu'on
+veut ajouter au groupe. On retombe sur le problème des clés publiques parce
+que si je la mets sur le FS, elle doit être en clair pour que tout le monde
+puisse m'ajouter à un groupe et donc, Juan peut m'usurper. Du coup, il faut
+distribuer les clés publiques par l'extérieur du FS (via HTTP par exemple) et
+là, on peut croire qu'on est bon. Encore faut-il supposer qu'on ne peut pas
+changer les proprio et groupe d'un fichier (parce qu'on ne peut pas re-crypter
+sans la clé privée) et qu'ils sont donc fixés à la création et immuables. Ne
+parlons pas du cas où on souhaiterait exclure un utilisateur d'un groupe : la
+clé lui a déjà été divulguée et donc, il faudrait ré-encoder tous les fichiers
+(plusieurs Go ?) de ce groupe avec une nouvelle clé...
+
+On a donc réussi à faire un système qui permet à un utilisateur d'écrire ses
+fichiers et de les lire sans que personnes d'autres ne puissent les lire. C'est
+intéressant mais parfaitement inutile dans le cas de Diswork vu que tous les
+fichiers doivent être partagés. Autre possibilité, y'a qu'à les mettre dans le
+groupe "diswork", sauf qu'il faudrait savoir comment un noeud honnête peut
+rejoindre se groupe ou pourquoi Juan, lui, ne pourrait pas en se faisant passer
+pour honnête (voire faire quelques jobs bien), puis trahir plus tard. Donc le
+groupe, ça marche pas vraiment, donc autant tout mettre en clair. Donc retour
+à la case départ.
+
+Mais, y'a pire ! Là, au niveau du FS, on a vu qu'on pouvait embêter Juan s'il
+voulait faire un get() en lui rendant la valeur lue incompréhensible. Peut-être,
+mais ça n'empêchera pas Juan de faire un remove() d'une clé, ou un put() avec
+des données vides voire des grossièretés. Donc de toute façon, on peut peut-être
+l'empêcher de lire, il reste toujours à Juan la possibilité de supprimer nos
+données.
+
+C'est ce qui m'amène à penser que, finalement, le problème, c'est soit la DHT
+soit son utilisation.
+
+Suivons la première hypothèse, la seule échappatoire que je vois, c'est
+d'utiliser une DHT qui gère les droits au niveaux des clés.
+Je ne connais aucune DHT qui permet cela.
+
+On peut repenser à l'époque où il était très facile d'écrire des malwares.
+Il suffisait de faire un peu de C ou de tout langage bas niveau, on pouvait
+aller taper tout simplement dans la mémoire vive, faire un malloc sur un tableau
+et écrire au delà de l'espace alloué et, du coup, écrire sur le reste dans la
+mémoire : en allant assez loin, on écrit sur la mémoire utilisée par les autres
+processus voire sur celle utilisée par l'OS. Pareil pour détruire des système
+de fichiers, on court-circuite le système de droit ou la possibilité de
+parcourir le FS en écrivant direct des I/O sur le disque dur, on arrivera bien à
+abîmer quelque-chose...
+
+Ce temps est aujourd'hui révolu. Aujourd'hui les programmes n'ont accès qu'à la
+mémoire qui leur est allouée par l'OS. Ça clos le problème.
+
+On peut faire une analogie avec notre utilisation de la DHT. Notre DHT est
+mémoire partagée et cela pose le même problème que précédemment. N'importe qui
+peut écrire n'importe-quoi. Qu'il s'agisse de gérer la mémoire vive d'un ordinateur
+(mémoire partagée entre différents processus locaux),
+ou d'une DHT (mémoire partagée entre des processus distants), les probèmes sont
+les même et la solution du premier pourrait amener une solution au deuxième.
+
+Seconde hypothèse, on a pas compris le principe (et on est pas les seuls à
+s'être planté, Pastis est un exemple) et pour faire un système de fichier P2P,
+on a pas la bonne approche. Peut-être qu'il faut utiliser la DHT autrement,
+voire ne pas utiliser une DHT mais pour l'instant je ne vois pas de meilleure
+solution que l'actuelle, étant donné le CdC.
+
+Le problème est intrinsèque à la DHT qui ne gère pas les droits. Je ne connais
+pas de DHT qui le fasse mais ça semble envisageable. Dans le cas de la gestion
+de la mémoire vive, un code intermédiaire (l'OS) fait les contrôles adéquats
+pour éviter qu'un programme fasse des I/O indésirables. On pourrait faire pareil
+dans le DHT, en empêchant chaque nœud de faire les opérations lui-même et en
+devant systématiquement les déléguées à un autre qui vérifiera les droits.
+L'intermédiaire ne doit pas être choisi mais imposé et doit se charger simplement
+de vérifier le droit avant que les opérations soit réellement menées, en instaurant
+la méfiance entre l' nœud qui fait la requête, le nœud intermédiaire et le nœud
+responsable, on multiplie les intervenants et on se base sur le principe que les
+nœuds bienveillants sont majoritaires. Les solutions apportées au problème des
+généraux byzantins devraient être utiles.
+
+En l'état actuel, le plus sage reste la solution de placer la sécurité à la
+périphérie, et de veiller à ce que seuls des nœuds de confiance se connectent
+au système global. Ainsi, on cloisonne le système, c'est pas absurde si les
+noeuds peuvent se trouver dans un même labo comme c'est le cas pour Isis.
+
+Ou alors... il faut tout remettre à plat, et envisager pour une prochaine
+version de Diswork, de s'y prendre autrement, avec une DHT utilisée autrement
+ou sans DHT. Mais là, je sèche parce que vu les contraintes exprimées, il y
+avait pas tellement possibilité de faire autrement...
+
+Pistes pour la version 0.2
+==========================
+
Modified: trunk/src/site/rst/diswork-fs/devel.rst
===================================================================
--- trunk/src/site/rst/diswork-fs/devel.rst 2010-07-27 13:01:35 UTC (rev 113)
+++ trunk/src/site/rst/diswork-fs/devel.rst 2010-07-28 12:22:28 UTC (rev 114)
@@ -208,205 +208,4 @@
since it can be replaced by a malicious node.
Public keys for each nodes should be made available by another means. It may
-be a read-only public key store available through HTTP for example.
-
-Sécurité dans Diswork (French only)
------------------------------------
-
-Les systèmes distribués en général et P2P en particulier comme Diswork sont
-réputés pour être difficiles à concevoir de façon sûre.
-
-Commençons la réflexion par un rappel des faits :
-
-* Diswork daemon est un petit logiciel qui tourne sur une machine et qui propose
- à Isis de lui soumettre des jobs.
-
-* Diswork File System est un système de fichiers utilisé comme sous-couche du
- démon. Le truc, c'est que tous les daemon utilisent tous le même système de
- fichiers : c'est ce qui les relie entre eux. Lorsqu'un démon reçoit une
- soumission de job, en fait, il écrit le job sur le FS, et comme tous les
- démons ont accès au FS, il suffit d'aller lire ce qui se trouve sur le FS
- pour trouver de jobs.
-
-* Pour assurer la distribution du système de fichiers sur tous les noeuds.
- Diswork FS écrit toutes les données du système dans une seule Map (telle que
- java.util.Map). C'est cette Map qui est distribuée entre toutes les machines,
- et comme toutes les machines ont accès à la même Map, le système de fichier se
- trouve être distribué. Cette Map distribuée, c'est la fameuse DHT, c'est sur
- elle que repose tout le système.
-
-Jusqu'ici tout va bien, le système global fonctionne à mon avis si on omet
-l'implémentation de la DHT qui est erratique.
-
-Le problème qui se pose qui nous intéresse ici est le suivant : que se passe-t-il
-si on imagine qu'un individu mal intentionné (au hasard, appelons-le Juan)
-décide de nuire au système.
-
-Juan a de nombreuses possibilités :
-
-* au niveau du démon on peut déjà soumettre toutes les seconds des jobs qui ne
- finissent jamais. Des jobs qui, en fait, envoient du spam ou font crasher la
- machine qui les lances (fork bombs) ou encore envoyer des tas de requêtes HTTP
- vers un serveur cible ce qui aurait pour effet (en soumettant ce job plusieurs)
- de faire participer tous les noeuds diswork à un DDoS. On peut modifier le
- code du démon pour réserver un job comme si on allait le faire, puis, en fait,
- ne jamais le faire.
-
-* au niveau du File System, c'est simple, les droits ne sont pas gérés
- (et pour cause, voir la suite). Tout est accessible en lecture/écriture.
- Juan peut donc faire un petit « rm -rf / ».
-
-* au niveau de la DHT, nous avons vu que c'est une Map. C'est donc une mémoire
- partagée entre tous les nœuds du réseau : et ça, c'est bon pour Juan. Les DHT
- ont pour particularité de ne pas permettre, contrairement à toutes les Map
- habituelles, de pouvoir parcourir l'ensemble des clés (espace trop grand).
- Toutefois, en se documentant un peu (oui, j'ai fait de la doc.) Juan pourra
- vite trouver un moyen de trouver tout un tas de clés utilisées dans la Map et
- pourra, à loisirs, faire des map.remove() dessus. Je vais pas m'attarder
- m'attarde pas sur les attaques possibles qui sont intrinsèques à l'algorithme
- et/ou à l'implémentation de la DHT utilisée mais si on parle de l'algo
- Kademlia, on peut parler d'attaque Sybil (ou Spartacus)
-
-Comme on peut le voir, il y a trop de problèmes à trop de niveaux pour espérer
-tout réglé mais on va quand même essayé.
-
-Tentons de régler les problèmes, niveaux par niveaux :
-
-Commençons par le démon. Envisageons de filtrer les jobs pour ne faire que des
-jobs qui sont "gentils" : sur quel critère se baser pour dire que tel ou tel de
-job est mauvais ?
-
-* L'application utilisée ? On peut créer des jobs qui dépendent de Isis (isis
- sera téléchargé) mais préciser une ligne de commande pour ce job qui n'a rien
- à voir (fork bomb)
-
-* Le nœud qui a soumis le job ou les résultats d'un job ? Comment savoir quel
- nœud a posé ce job sur le FS. Vu que le FS est accessible en écriture pour
- Juan, Juan pourrait changer les informations concernant le propriétaire du job
- et donc poser un job vicieux et dire qu'il est à Éric (qui est un ange, comme
- chacun sait). Même si ce n'était pas le cas, comme savoir que Éric est gentil
- et Juan méchant ? Pas moyen. Pour s'assurer de l'origine d'un job, on pense
- tout de suite à signer les jobs avec un système de clés asymétriques. Ça ne
- change rien, Juan peut signer des jobs et des résultats aussi. Vient alors
- encore une idée, on a qu'à faire faire le job par 4 machines différentes,
- comparer les quatre résultats et voir si les résultats sont différent. Si un
- résultat diffère des trois autres, on considère qu'il a été mal fait par une
- machine contrôlée par Juan et on exclue ce résultat pour se baser sur les
- trois restants, supposés fiables. Sauf que, comme dit, les jobs ne sont pas
- poussés vers ceux qui les font mais posés sur le file-system, d'autres nœud,
- en parcourant le FS les trouve. Du coup, Juan peut facilement lancer quatre
- nœud (voire un seul nœud), réserver les quatre jobs, calculer (une fois) de
- faux résultats, les signer avec des clés différentes et les publier 4 fois
- comme 4 résultats faits par des machines différentes (avec un pti délai entre
- chaque dépôt pour pas qu'on voit que tout a été fait en même temps...). Juan
- est vraiment vicieux. En plus, ça impliquerait de mettre en place un système
- pour échanger les clés publiques, il ne faut surtout pas les mettre sur le FS,
- Juan pourrait remplacer celle d'Éric par la sienne. On peut imaginer les
- mettre toutes sur un serveur à côté, où les clés sont publiées une fois pour
- toutes mais comment éviter que Juan y publie ses propres clés ?
-
-Passons au système de fichier. Pour résoudre les problèmes évoqués ci dessus, on
-pourrait souhaiter des droits de le forme UNIX pour le FS distribué (des
-utilisateurs, des groupes et des droits lectures/écritures par fichier pour le
-propriétaire, le groupe et les autres). Il faudrait stocker ces nouvelles
-données dans la Map, c'est pas un problème. Cependant, comme, de toute façon,
-c'est Juan qui choisit d'interpréter les données qu'il peut lire dans la Map,
-il pourra lire les droits, les ignorer, et lire le fichier quand même : il
-suffit de faire des get().
-
-Et si on crypte ? Et bien Juan n'arrivera pas à lire les données, c'est déjà ça
-de pris. Encore faut-il savoir avec quelle clé crypter. Celle du propriétaire ?
-Non, le membres du groupe ne pourrait pas lire. Celle du groupe alors ? Oui,
-c'est déjà mieux. En fait, il faut choisir le clé en fonction des droits. Quand
-on écrit le fichier, il faut crypter avec la clé du groupe si le groupe a accès
-en lecture, celle du proprio si le groupe n'a pas accès en lecture et ne pas
-crypter si tout le monde a accès en écriture. Ça suppose que le proprio
-appartienne au groupe (c'est pas absurde). Encore faut-il ne distribuer la clé
-du groupe qu'à ceux qui sont dans le groupe et ne pas la divulguer. Ça peut
-s'imaginer disons, en déposant dans le home d'un utilisateur un fichier qui
-contient la clé du groupe cryptée avec la clé publique de l'utilisateur qu'on
-veut ajouter au groupe. On retombe sur le problème des clés publiques parce
-que si je la mets sur le FS, elle doit être en clair pour que tout le monde
-puisse m'ajouter à un groupe et donc, Juan peut m'usurper. Du coup, il faut
-distribuer les clés publiques par l'extérieur du FS (via HTTP par exemple) et
-là, on peut croire qu'on est bon. Encore faut-il supposer qu'on ne peut pas
-changer les proprio et groupe d'un fichier (parce qu'on ne peut pas re-crypter
-sans la clé privée) et qu'ils sont donc fixés à la création et immuables. Ne
-parlons pas du cas où on souhaiterait exclure un utilisateur d'un groupe : la
-clé lui a déjà été divulguée et donc, il faudrait ré-encoder tous les fichiers
-(plusieurs Go ?) de ce groupe avec une nouvelle clé...
-
-On a donc réussi à faire un système qui permet à un utilisateur d'écrire ses
-fichiers et de les lire sans que personnes d'autres ne puissent les lire. C'est
-intéressant mais parfaitement inutile dans le cas de Diswork vu que tous les
-fichiers doivent être partagés. Autre possibilité, y'a qu'à les mettre dans le
-groupe "diswork", sauf qu'il faudrait savoir comment un noeud honnête peut
-rejoindre se groupe ou pourquoi Juan, lui, ne pourrait pas en se faisant passer
-pour honnête (voire faire quelques jobs bien), puis trahir plus tard. Donc le
-groupe, ça marche pas vraiment, donc autant tout mettre en clair. Donc retour
-à la case départ.
-
-Mais, y'a pire ! Là, au niveau du FS, on a vu qu'on pouvait embêter Juan s'il
-voulait faire un get() en lui rendant la valeur lue incompréhensible. Peut-être,
-mais ça n'empêchera pas Juan de faire un remove() d'une clé, ou un put() avec
-des données vides voire des grossièretés. Donc de toute façon, on peut peut-être
-l'empêcher de lire, il reste toujours à Juan la possibilité de supprimer nos
-données.
-
-C'est ce qui m'amène à penser que, finalement, le problème, c'est soit la DHT
-soit son utilisation.
-
-Suivons la première hypothèse, la seule échappatoire que je vois, c'est
-d'utiliser une DHT qui gère les droits au niveaux des clés.
-Je ne connais aucune DHT qui permet cela.
-
-On peut repenser à l'époque où il était très facile d'écrire des malwares.
-Il suffisait de faire un peu de C ou de tout langage bas niveau, on pouvait
-aller taper tout simplement dans la mémoire vive, faire un malloc sur un tableau
-et écrire au delà de l'espace alloué et, du coup, écrire sur le reste dans la
-mémoire : en allant assez loin, on écrit sur la mémoire utilisée par les autres
-processus voire sur celle utilisée par l'OS. Pareil pour détruire des système
-de fichiers, on court-circuite le système de droit ou la possibilité de
-parcourir le FS en écrivant direct des I/O sur le disque dur, on arrivera bien à
-abîmer quelque-chose...
-
-Ce temps est aujourd'hui révolu. Aujourd'hui les programmes n'ont accès qu'à la
-mémoire qui leur est allouée par l'OS. Ça clos le problème.
-
-On peut faire une analogie avec notre utilisation de la DHT. Notre DHT est
-mémoire partagée et cela pose le même problème que précédemment. N'importe qui
-peut écrire n'importe-quoi. Qu'il s'agisse de gérer la mémoire vive d'un ordinateur
-(mémoire partagée entre différents processus locaux),
-ou d'une DHT (mémoire partagée entre des processus distants), les probèmes sont
-les même et la solution du premier pourrait amener une solution au deuxième.
-
-Seconde hypothèse, on a pas compris le principe (et on est pas les seuls à
-s'être planté, Pastis est un exemple) et pour faire un système de fichier P2P,
-on a pas la bonne approche. Peut-être qu'il faut utiliser la DHT autrement,
-voire ne pas utiliser une DHT mais pour l'instant je ne vois pas de meilleure
-solution que l'actuelle, étant donné le CdC.
-
-Le problème est intrinsèque à la DHT qui ne gère pas les droits. Je ne connais
-pas de DHT qui le fasse mais ça semble envisageable. Dans le cas de la gestion
-de la mémoire vive, un code intermédiaire (l'OS) fait les contrôles adéquats
-pour éviter qu'un programme fasse des I/O indésirables. On pourrait faire pareil
-dans le DHT, en empêchant chaque nœud de faire les opérations lui-même et en
-devant systématiquement les déléguées à un autre qui vérifiera les droits.
-L'intermédiaire ne doit pas être choisi mais imposé et doit se charger simplement
-de vérifier le droit avant que les opérations soit réellement menées, en instaurant
-la méfiance entre l' nœud qui fait la requête, le nœud intermédiaire et le nœud
-responsable, on multiplie les intervenants et on se base sur le principe que les
-nœuds bienveillants sont majoritaires. Les solutions apportées au problème des
-généraux byzantins devraient être utiles.
-
-En l'état actuel, le plus sage reste la solution de placer la sécurité à la
-périphérie, et de veiller à ce que seuls des nœuds de confiance se connectent
-au système global. Ainsi, on cloisonne le système, c'est pas absurde si les
-noeuds peuvent se trouver dans un même labo comme c'est le cas pour Isis.
-
-Ou alors... il faut tout remettre à plat, et envisager pour une prochaine
-version de Diswork, de s'y prendre autrement, avec une DHT utilisée autrement
-ou sans DHT. Mais là, je sèche parce que vu les contraintes exprimées, il y
-avait pas tellement possibilité de faire autrement...
-
-26/07/2010
\ No newline at end of file
+be a read-only public key store available through HTTP for example.
\ No newline at end of file
Modified: trunk/src/site/site_en.xml
===================================================================
--- trunk/src/site/site_en.xml 2010-07-27 13:01:35 UTC (rev 113)
+++ trunk/src/site/site_en.xml 2010-07-28 12:22:28 UTC (rev 114)
@@ -31,6 +31,10 @@
<item href="diswork-fs/devel.html" name="For developers"/>
</menu>
+ <menu name="Devel">
+ <item href="devel-draft-0.2.html" name="Draft for diswork 0.2"/>
+ </menu>
+
<menu ref="reports"/>
</body>
1
0
r113 - in trunk: diswork-daemon/src/main/java/org/nuiton/diswork/daemon src/site/rst/diswork-fs
by bleny@users.nuiton.org 27 Jul '10
by bleny@users.nuiton.org 27 Jul '10
27 Jul '10
Author: bleny
Date: 2010-07-27 15:01:35 +0200 (Tue, 27 Jul 2010)
New Revision: 113
Url: http://nuiton.org/repositories/revision/diswork/113
Log:
m?\195?\160j doc ; qualite du code
Modified:
trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkConfig.java
trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/WorkersManager.java
trunk/src/site/rst/diswork-fs/devel.rst
Modified: trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkConfig.java
===================================================================
--- trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkConfig.java 2010-07-26 15:02:18 UTC (rev 112)
+++ trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkConfig.java 2010-07-27 13:01:35 UTC (rev 113)
@@ -40,6 +40,7 @@
import java.util.Map;
import java.util.Properties;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -183,8 +184,9 @@
File tokensFile = getTokensFile();
if (tokensFile != null) {
+ InputStream tokensStream = null;
try {
- InputStream tokensStream = new FileInputStream(tokensFile);
+ tokensStream = new FileInputStream(tokensFile);
Properties userTokens = new Properties();
userTokens.load(tokensStream);
for (String token : userTokens.stringPropertyNames()) {
@@ -203,6 +205,8 @@
} catch (IOException e) {
log.error("can't read tokens file", e);
throw new LocalFileException("can't read tokens file", e);
+ } finally {
+ IOUtils.closeQuietly(tokensStream);
}
}
}
@@ -255,9 +259,10 @@
if (path != null) {
File file = new File(path);
schedule = new ArrayList<CronExpression>();
+ BufferedReader in = null;
try {
Reader reader = new FileReader(file);
- BufferedReader in = new BufferedReader(reader);
+ in = new BufferedReader(reader);
String line;
while ((line = in.readLine()) != null) {
if (!line.startsWith("#") && !"".equals(line)) {
@@ -274,6 +279,8 @@
} catch (IOException e) {
log.error(e);
throw new LocalFileException("can't read schedule file", e);
+ } finally {
+ IOUtils.closeQuietly(in);
}
} else {
throw new BadConfigurationException("schedule file has not been specified");
Modified: trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/WorkersManager.java
===================================================================
--- trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/WorkersManager.java 2010-07-26 15:02:18 UTC (rev 112)
+++ trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/WorkersManager.java 2010-07-27 13:01:35 UTC (rev 113)
@@ -48,6 +48,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.diswork.daemon.ActivityStrategy.ActivityStrategies;
+import org.nuiton.diswork.daemon.WorkersManager.Worker;
import org.nuiton.diswork.fs.DisworkFileSystem;
import org.nuiton.diswork.fs.DisworkFileSystemException;
import org.nuiton.util.FileUtil;
@@ -444,7 +445,7 @@
outputFileStream);
log.info("starting job now");
outputReader.start();
-
+
// plugging a file on the standard input
String standardInputFileName = currentJob.getStandardInput();
if (standardInputFileName != null) {
@@ -575,7 +576,7 @@
// wait for the process to return
log.info("waiting for the end of the process");
int returnValue = currentProcess.waitFor();
- log.info("process ended");
+ log.info("process ended (return " + returnValue + ")");
if (shouldStop) {
// process has returned because stop() called Process.destroy()
Modified: trunk/src/site/rst/diswork-fs/devel.rst
===================================================================
--- trunk/src/site/rst/diswork-fs/devel.rst 2010-07-26 15:02:18 UTC (rev 112)
+++ trunk/src/site/rst/diswork-fs/devel.rst 2010-07-27 13:01:35 UTC (rev 113)
@@ -360,8 +360,7 @@
d'utiliser une DHT qui gère les droits au niveaux des clés.
Je ne connais aucune DHT qui permet cela.
-Maintenant, faisons un peu d'histoire.
-Rappelez vous l'époque où il était très facile d'écrire des malwares.
+On peut repenser à l'époque où il était très facile d'écrire des malwares.
Il suffisait de faire un peu de C ou de tout langage bas niveau, on pouvait
aller taper tout simplement dans la mémoire vive, faire un malloc sur un tableau
et écrire au delà de l'espace alloué et, du coup, écrire sur le reste dans la
@@ -374,12 +373,12 @@
Ce temps est aujourd'hui révolu. Aujourd'hui les programmes n'ont accès qu'à la
mémoire qui leur est allouée par l'OS. Ça clos le problème.
-J'y vois une analogie avec notre DHT. Notre DHT, c'est notre mémoire partagée et
-on en est au même point. N'importe qui peut écrire n'importe-quoi. Qu'il s'agisse
-de la gestion de la RAM (mémoire partagée entre différents processus locaux),
-ou d'une DHT (mémoire partagée entre des processus distants), on a la même
-problématique, peut-être que la solution de l'une peut solutionner l'autre.
-C'est la réflexion que je suis en train de mener et j'ai une piste.
+On peut faire une analogie avec notre utilisation de la DHT. Notre DHT est
+mémoire partagée et cela pose le même problème que précédemment. N'importe qui
+peut écrire n'importe-quoi. Qu'il s'agisse de gérer la mémoire vive d'un ordinateur
+(mémoire partagée entre différents processus locaux),
+ou d'une DHT (mémoire partagée entre des processus distants), les probèmes sont
+les même et la solution du premier pourrait amener une solution au deuxième.
Seconde hypothèse, on a pas compris le principe (et on est pas les seuls à
s'être planté, Pastis est un exemple) et pour faire un système de fichier P2P,
@@ -387,20 +386,23 @@
voire ne pas utiliser une DHT mais pour l'instant je ne vois pas de meilleure
solution que l'actuelle, étant donné le CdC.
-Finalement, utiliser de la cryptographie asymétrique, que ce soit pour crypter
-ou signer, ça fera joli mais c'est jamais que répondre à côté de notre
-problématique. Y'a un côté pavlovien "sécurité = crypto".
-
Le problème est intrinsèque à la DHT qui ne gère pas les droits. Je ne connais
-pas de DHT qui le fasse mais j'ai, pendant mes insomnies régulières, des idées
-qui surgissent sur la question, j'en ferai part si je sens que ça peut aboutir,
-encore quelques nuits...
+pas de DHT qui le fasse mais ça semble envisageable. Dans le cas de la gestion
+de la mémoire vive, un code intermédiaire (l'OS) fait les contrôles adéquats
+pour éviter qu'un programme fasse des I/O indésirables. On pourrait faire pareil
+dans le DHT, en empêchant chaque nœud de faire les opérations lui-même et en
+devant systématiquement les déléguées à un autre qui vérifiera les droits.
+L'intermédiaire ne doit pas être choisi mais imposé et doit se charger simplement
+de vérifier le droit avant que les opérations soit réellement menées, en instaurant
+la méfiance entre l' nœud qui fait la requête, le nœud intermédiaire et le nœud
+responsable, on multiplie les intervenants et on se base sur le principe que les
+nœuds bienveillants sont majoritaires. Les solutions apportées au problème des
+généraux byzantins devraient être utiles.
-Tel que je vois la conception actuelle de Diswork, je pense que le plus sage
-pour l'instant est la solution de placer la sécurité à la périphérie, et de
-veiller à ce que seuls des nœuds de confiance se connectent au système global.
-Ainsi, on cloisonne le système, c'est pas absurde si les noeuds peuvent se
-trouver dans un même labo comme c'est le cas pour Isis.
+En l'état actuel, le plus sage reste la solution de placer la sécurité à la
+périphérie, et de veiller à ce que seuls des nœuds de confiance se connectent
+au système global. Ainsi, on cloisonne le système, c'est pas absurde si les
+noeuds peuvent se trouver dans un même labo comme c'est le cas pour Isis.
Ou alors... il faut tout remettre à plat, et envisager pour une prochaine
version de Diswork, de s'y prendre autrement, avec une DHT utilisée autrement
1
0
Author: bleny
Date: 2010-07-26 17:02:18 +0200 (Mon, 26 Jul 2010)
New Revision: 112
Url: http://nuiton.org/repositories/revision/diswork/112
Log:
r?\195?\169flexion sur la s?\195?\169cu dans diswork
Modified:
trunk/src/site/rst/diswork-fs/devel.rst
Modified: trunk/src/site/rst/diswork-fs/devel.rst
===================================================================
--- trunk/src/site/rst/diswork-fs/devel.rst 2010-07-26 09:32:54 UTC (rev 111)
+++ trunk/src/site/rst/diswork-fs/devel.rst 2010-07-26 15:02:18 UTC (rev 112)
@@ -208,4 +208,203 @@
since it can be replaced by a malicious node.
Public keys for each nodes should be made available by another means. It may
-be a read-only public key store available through HTTP for example.
\ No newline at end of file
+be a read-only public key store available through HTTP for example.
+
+Sécurité dans Diswork (French only)
+-----------------------------------
+
+Les systèmes distribués en général et P2P en particulier comme Diswork sont
+réputés pour être difficiles à concevoir de façon sûre.
+
+Commençons la réflexion par un rappel des faits :
+
+* Diswork daemon est un petit logiciel qui tourne sur une machine et qui propose
+ à Isis de lui soumettre des jobs.
+
+* Diswork File System est un système de fichiers utilisé comme sous-couche du
+ démon. Le truc, c'est que tous les daemon utilisent tous le même système de
+ fichiers : c'est ce qui les relie entre eux. Lorsqu'un démon reçoit une
+ soumission de job, en fait, il écrit le job sur le FS, et comme tous les
+ démons ont accès au FS, il suffit d'aller lire ce qui se trouve sur le FS
+ pour trouver de jobs.
+
+* Pour assurer la distribution du système de fichiers sur tous les noeuds.
+ Diswork FS écrit toutes les données du système dans une seule Map (telle que
+ java.util.Map). C'est cette Map qui est distribuée entre toutes les machines,
+ et comme toutes les machines ont accès à la même Map, le système de fichier se
+ trouve être distribué. Cette Map distribuée, c'est la fameuse DHT, c'est sur
+ elle que repose tout le système.
+
+Jusqu'ici tout va bien, le système global fonctionne à mon avis si on omet
+l'implémentation de la DHT qui est erratique.
+
+Le problème qui se pose qui nous intéresse ici est le suivant : que se passe-t-il
+si on imagine qu'un individu mal intentionné (au hasard, appelons-le Juan)
+décide de nuire au système.
+
+Juan a de nombreuses possibilités :
+
+* au niveau du démon on peut déjà soumettre toutes les seconds des jobs qui ne
+ finissent jamais. Des jobs qui, en fait, envoient du spam ou font crasher la
+ machine qui les lances (fork bombs) ou encore envoyer des tas de requêtes HTTP
+ vers un serveur cible ce qui aurait pour effet (en soumettant ce job plusieurs)
+ de faire participer tous les noeuds diswork à un DDoS. On peut modifier le
+ code du démon pour réserver un job comme si on allait le faire, puis, en fait,
+ ne jamais le faire.
+
+* au niveau du File System, c'est simple, les droits ne sont pas gérés
+ (et pour cause, voir la suite). Tout est accessible en lecture/écriture.
+ Juan peut donc faire un petit « rm -rf / ».
+
+* au niveau de la DHT, nous avons vu que c'est une Map. C'est donc une mémoire
+ partagée entre tous les nœuds du réseau : et ça, c'est bon pour Juan. Les DHT
+ ont pour particularité de ne pas permettre, contrairement à toutes les Map
+ habituelles, de pouvoir parcourir l'ensemble des clés (espace trop grand).
+ Toutefois, en se documentant un peu (oui, j'ai fait de la doc.) Juan pourra
+ vite trouver un moyen de trouver tout un tas de clés utilisées dans la Map et
+ pourra, à loisirs, faire des map.remove() dessus. Je vais pas m'attarder
+ m'attarde pas sur les attaques possibles qui sont intrinsèques à l'algorithme
+ et/ou à l'implémentation de la DHT utilisée mais si on parle de l'algo
+ Kademlia, on peut parler d'attaque Sybil (ou Spartacus)
+
+Comme on peut le voir, il y a trop de problèmes à trop de niveaux pour espérer
+tout réglé mais on va quand même essayé.
+
+Tentons de régler les problèmes, niveaux par niveaux :
+
+Commençons par le démon. Envisageons de filtrer les jobs pour ne faire que des
+jobs qui sont "gentils" : sur quel critère se baser pour dire que tel ou tel de
+job est mauvais ?
+
+* L'application utilisée ? On peut créer des jobs qui dépendent de Isis (isis
+ sera téléchargé) mais préciser une ligne de commande pour ce job qui n'a rien
+ à voir (fork bomb)
+
+* Le nœud qui a soumis le job ou les résultats d'un job ? Comment savoir quel
+ nœud a posé ce job sur le FS. Vu que le FS est accessible en écriture pour
+ Juan, Juan pourrait changer les informations concernant le propriétaire du job
+ et donc poser un job vicieux et dire qu'il est à Éric (qui est un ange, comme
+ chacun sait). Même si ce n'était pas le cas, comme savoir que Éric est gentil
+ et Juan méchant ? Pas moyen. Pour s'assurer de l'origine d'un job, on pense
+ tout de suite à signer les jobs avec un système de clés asymétriques. Ça ne
+ change rien, Juan peut signer des jobs et des résultats aussi. Vient alors
+ encore une idée, on a qu'à faire faire le job par 4 machines différentes,
+ comparer les quatre résultats et voir si les résultats sont différent. Si un
+ résultat diffère des trois autres, on considère qu'il a été mal fait par une
+ machine contrôlée par Juan et on exclue ce résultat pour se baser sur les
+ trois restants, supposés fiables. Sauf que, comme dit, les jobs ne sont pas
+ poussés vers ceux qui les font mais posés sur le file-system, d'autres nœud,
+ en parcourant le FS les trouve. Du coup, Juan peut facilement lancer quatre
+ nœud (voire un seul nœud), réserver les quatre jobs, calculer (une fois) de
+ faux résultats, les signer avec des clés différentes et les publier 4 fois
+ comme 4 résultats faits par des machines différentes (avec un pti délai entre
+ chaque dépôt pour pas qu'on voit que tout a été fait en même temps...). Juan
+ est vraiment vicieux. En plus, ça impliquerait de mettre en place un système
+ pour échanger les clés publiques, il ne faut surtout pas les mettre sur le FS,
+ Juan pourrait remplacer celle d'Éric par la sienne. On peut imaginer les
+ mettre toutes sur un serveur à côté, où les clés sont publiées une fois pour
+ toutes mais comment éviter que Juan y publie ses propres clés ?
+
+Passons au système de fichier. Pour résoudre les problèmes évoqués ci dessus, on
+pourrait souhaiter des droits de le forme UNIX pour le FS distribué (des
+utilisateurs, des groupes et des droits lectures/écritures par fichier pour le
+propriétaire, le groupe et les autres). Il faudrait stocker ces nouvelles
+données dans la Map, c'est pas un problème. Cependant, comme, de toute façon,
+c'est Juan qui choisit d'interpréter les données qu'il peut lire dans la Map,
+il pourra lire les droits, les ignorer, et lire le fichier quand même : il
+suffit de faire des get().
+
+Et si on crypte ? Et bien Juan n'arrivera pas à lire les données, c'est déjà ça
+de pris. Encore faut-il savoir avec quelle clé crypter. Celle du propriétaire ?
+Non, le membres du groupe ne pourrait pas lire. Celle du groupe alors ? Oui,
+c'est déjà mieux. En fait, il faut choisir le clé en fonction des droits. Quand
+on écrit le fichier, il faut crypter avec la clé du groupe si le groupe a accès
+en lecture, celle du proprio si le groupe n'a pas accès en lecture et ne pas
+crypter si tout le monde a accès en écriture. Ça suppose que le proprio
+appartienne au groupe (c'est pas absurde). Encore faut-il ne distribuer la clé
+du groupe qu'à ceux qui sont dans le groupe et ne pas la divulguer. Ça peut
+s'imaginer disons, en déposant dans le home d'un utilisateur un fichier qui
+contient la clé du groupe cryptée avec la clé publique de l'utilisateur qu'on
+veut ajouter au groupe. On retombe sur le problème des clés publiques parce
+que si je la mets sur le FS, elle doit être en clair pour que tout le monde
+puisse m'ajouter à un groupe et donc, Juan peut m'usurper. Du coup, il faut
+distribuer les clés publiques par l'extérieur du FS (via HTTP par exemple) et
+là, on peut croire qu'on est bon. Encore faut-il supposer qu'on ne peut pas
+changer les proprio et groupe d'un fichier (parce qu'on ne peut pas re-crypter
+sans la clé privée) et qu'ils sont donc fixés à la création et immuables. Ne
+parlons pas du cas où on souhaiterait exclure un utilisateur d'un groupe : la
+clé lui a déjà été divulguée et donc, il faudrait ré-encoder tous les fichiers
+(plusieurs Go ?) de ce groupe avec une nouvelle clé...
+
+On a donc réussi à faire un système qui permet à un utilisateur d'écrire ses
+fichiers et de les lire sans que personnes d'autres ne puissent les lire. C'est
+intéressant mais parfaitement inutile dans le cas de Diswork vu que tous les
+fichiers doivent être partagés. Autre possibilité, y'a qu'à les mettre dans le
+groupe "diswork", sauf qu'il faudrait savoir comment un noeud honnête peut
+rejoindre se groupe ou pourquoi Juan, lui, ne pourrait pas en se faisant passer
+pour honnête (voire faire quelques jobs bien), puis trahir plus tard. Donc le
+groupe, ça marche pas vraiment, donc autant tout mettre en clair. Donc retour
+à la case départ.
+
+Mais, y'a pire ! Là, au niveau du FS, on a vu qu'on pouvait embêter Juan s'il
+voulait faire un get() en lui rendant la valeur lue incompréhensible. Peut-être,
+mais ça n'empêchera pas Juan de faire un remove() d'une clé, ou un put() avec
+des données vides voire des grossièretés. Donc de toute façon, on peut peut-être
+l'empêcher de lire, il reste toujours à Juan la possibilité de supprimer nos
+données.
+
+C'est ce qui m'amène à penser que, finalement, le problème, c'est soit la DHT
+soit son utilisation.
+
+Suivons la première hypothèse, la seule échappatoire que je vois, c'est
+d'utiliser une DHT qui gère les droits au niveaux des clés.
+Je ne connais aucune DHT qui permet cela.
+
+Maintenant, faisons un peu d'histoire.
+Rappelez vous l'époque où il était très facile d'écrire des malwares.
+Il suffisait de faire un peu de C ou de tout langage bas niveau, on pouvait
+aller taper tout simplement dans la mémoire vive, faire un malloc sur un tableau
+et écrire au delà de l'espace alloué et, du coup, écrire sur le reste dans la
+mémoire : en allant assez loin, on écrit sur la mémoire utilisée par les autres
+processus voire sur celle utilisée par l'OS. Pareil pour détruire des système
+de fichiers, on court-circuite le système de droit ou la possibilité de
+parcourir le FS en écrivant direct des I/O sur le disque dur, on arrivera bien à
+abîmer quelque-chose...
+
+Ce temps est aujourd'hui révolu. Aujourd'hui les programmes n'ont accès qu'à la
+mémoire qui leur est allouée par l'OS. Ça clos le problème.
+
+J'y vois une analogie avec notre DHT. Notre DHT, c'est notre mémoire partagée et
+on en est au même point. N'importe qui peut écrire n'importe-quoi. Qu'il s'agisse
+de la gestion de la RAM (mémoire partagée entre différents processus locaux),
+ou d'une DHT (mémoire partagée entre des processus distants), on a la même
+problématique, peut-être que la solution de l'une peut solutionner l'autre.
+C'est la réflexion que je suis en train de mener et j'ai une piste.
+
+Seconde hypothèse, on a pas compris le principe (et on est pas les seuls à
+s'être planté, Pastis est un exemple) et pour faire un système de fichier P2P,
+on a pas la bonne approche. Peut-être qu'il faut utiliser la DHT autrement,
+voire ne pas utiliser une DHT mais pour l'instant je ne vois pas de meilleure
+solution que l'actuelle, étant donné le CdC.
+
+Finalement, utiliser de la cryptographie asymétrique, que ce soit pour crypter
+ou signer, ça fera joli mais c'est jamais que répondre à côté de notre
+problématique. Y'a un côté pavlovien "sécurité = crypto".
+
+Le problème est intrinsèque à la DHT qui ne gère pas les droits. Je ne connais
+pas de DHT qui le fasse mais j'ai, pendant mes insomnies régulières, des idées
+qui surgissent sur la question, j'en ferai part si je sens que ça peut aboutir,
+encore quelques nuits...
+
+Tel que je vois la conception actuelle de Diswork, je pense que le plus sage
+pour l'instant est la solution de placer la sécurité à la périphérie, et de
+veiller à ce que seuls des nœuds de confiance se connectent au système global.
+Ainsi, on cloisonne le système, c'est pas absurde si les noeuds peuvent se
+trouver dans un même labo comme c'est le cas pour Isis.
+
+Ou alors... il faut tout remettre à plat, et envisager pour une prochaine
+version de Diswork, de s'y prendre autrement, avec une DHT utilisée autrement
+ou sans DHT. Mais là, je sèche parce que vu les contraintes exprimées, il y
+avait pas tellement possibilité de faire autrement...
+
+26/07/2010
\ No newline at end of file
1
0
r111 - trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon
by bleny@users.nuiton.org 26 Jul '10
by bleny@users.nuiton.org 26 Jul '10
26 Jul '10
Author: bleny
Date: 2010-07-26 11:32:54 +0200 (Mon, 26 Jul 2010)
New Revision: 111
Url: http://nuiton.org/repositories/revision/diswork/111
Log:
bugfix, doc
Modified:
trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkDaemon.java
Modified: trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkDaemon.java
===================================================================
--- trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkDaemon.java 2010-07-23 15:36:32 UTC (rev 110)
+++ trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkDaemon.java 2010-07-26 09:32:54 UTC (rev 111)
@@ -491,7 +491,7 @@
getPathForJob(jobId) + "/" + JSDL_PATH));
JobDescription jobDescription = JobDescription.parseJSDL(jsdl);
if (applicationName == null // don't filter application
- || jobDescription.getApplicationName().equals(applicationName)) {
+ || applicationName.equals(jobDescription.getApplicationName())) {
jobDescription.setJobId(jobId);
result.add(jobDescription);
}
1
0
Author: bleny
Date: 2010-07-23 17:36:32 +0200 (Fri, 23 Jul 2010)
New Revision: 110
Url: http://nuiton.org/repositories/revision/diswork/110
Log:
doc secu dans diswork FS
Modified:
trunk/src/site/rst/diswork-fs/devel.rst
Modified: trunk/src/site/rst/diswork-fs/devel.rst
===================================================================
--- trunk/src/site/rst/diswork-fs/devel.rst 2010-07-23 13:22:40 UTC (rev 109)
+++ trunk/src/site/rst/diswork-fs/devel.rst 2010-07-23 15:36:32 UTC (rev 110)
@@ -3,14 +3,14 @@
=============================
Abstract
---------
+========
This document is for people who want to develop Diswork File System. It is not
an interesting reading for people who write to write code that use Diswork
FS.
Diswork File System uses a map to store every data
---------------------------------------------------
+==================================================
Diswork File System uses a map to store data persistently.
@@ -138,11 +138,74 @@
The map is distributed
----------------------
-The map described above is distributed over all nodes through a DHT.
+The map described above is distributed over all nodes through a DHT.
Diswork File System manage concurrency
--------------------------------------
DFS uses copy-on-write to deal with concurrency. Nothing is overridden, when
a file is replaced, the new file is written on the FS without removing the
-old file. The old file data is kept and actually removed later.
\ No newline at end of file
+old file. The old file data is kept and actually removed later.
+
+User rights management and security issues
+==========================================
+
+Peer-to-peer applications are subject to malicious attacks. Introduction of one
+or few malicious node in such a network can cause many problems.
+
+At the File System level, since there is no user-rights management, a malicious
+node can connect and remove recursively root directory or replace any file
+with any bits.
+
+At the DHT level, any malicious node introduce multiple threats :
+
+* a distributed denial of service attack (multiple nodes always asking for the
+ same key)
+
+* various DHT-specific attacks like joining the DHT with a chosen ID allowing
+ to become responsible of a target key that will no longer be avaible due to
+ a malicious peer that do not respond.
+
+* low-level attacks : by sniffing network traffic, key and values that pass
+ through the target connection may be revealed and data privacy corrupted
+
+DHT implementation may provides means to prevent DHT-level threats but we still
+need some ways to prevent File-System level threads. The main problems here is
+that DHT is readable/writable shared memory for each of the nodes connected to
+the network. Thus, a single node can write any bad data.
+
+Those issues lead to the need to implements consider user-rights on the
+File-System. This is not possible because all nodes are self-responsible to
+what they do on the DHT. Thus, the nodes that do the operation on the DHT will
+will be responsible to check it has the right to do so. It's easy to imagine
+a malicious node, allowing itself all operations by badly implementing rights
+checks.
+
+To make user-rights management possible, DHT should give make all operation
+of a node controlled by another one. Just like a given program, running in
+an operating system, can't do any I/O on local file system, the underlying
+file-system is another piece of code that manage the program rights. Here,
+we don't have this intermediate code, so another node should do this job and
+system will become reliable if it's not possible for a malicious node to choose
+itself as intermediate node or any node cooperating with the malicious one.
+
+However, this is a DHT consideration and we can't deal with malicious nodes
+at the File System level.
+
+But we can provide a security layer on top of the file-system. This layer
+should permit to crypt and sign data one writes in order for others to check
+data integrity. Those operations can be done using asymetric key encryption.
+
+When reading/writing a file or directory, keys will permit to be sure that
+a given file or directory content has been written by a given user.
+
+That's not sufficient, malicious nodes can crypt and sign datas too. So
+top level application, that use the File system should make is own
+business-oriented checks before considering a data.
+
+Nodes can write and then read encrypted data if it checks the
+file integrity. Public keys should not be made available through Diswork FS
+since it can be replaced by a malicious node.
+
+Public keys for each nodes should be made available by another means. It may
+be a read-only public key store available through HTTP for example.
\ No newline at end of file
1
0
r109 - in trunk/diswork-daemon/src: main/java/org/nuiton/diswork/daemon test/java/org/nuiton/diswork/daemon
by bleny@users.nuiton.org 23 Jul '10
by bleny@users.nuiton.org 23 Jul '10
23 Jul '10
Author: bleny
Date: 2010-07-23 15:22:40 +0200 (Fri, 23 Jul 2010)
New Revision: 109
Url: http://nuiton.org/repositories/revision/diswork/109
Log:
ajout isApplicationAvailable ?\195?\160 l'API + test
Modified:
trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkDaemon.java
trunk/diswork-daemon/src/test/java/org/nuiton/diswork/daemon/DisworkDaemonTest.java
Modified: trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkDaemon.java
===================================================================
--- trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkDaemon.java 2010-07-23 09:10:52 UTC (rev 108)
+++ trunk/diswork-daemon/src/main/java/org/nuiton/diswork/daemon/DisworkDaemon.java 2010-07-23 13:22:40 UTC (rev 109)
@@ -401,6 +401,28 @@
/* ** public methods for use of the daemon */
+ /** true if a node already submitted this application on diswork */
+ public boolean isApplicationAvailable(String applicationName,
+ String applicationVersion)
+ throws DisworkException {
+ if (applicationName == null) {
+ throw new NullPointerException("application name is null");
+ }
+ if (applicationVersion == null) {
+ throw new NullPointerException("application version can't be null");
+ }
+
+ String path = getPathForDependency(applicationName, applicationVersion);
+
+ Boolean result = null;
+ try {
+ result = fileSystem.exists(path);
+ } catch (DisworkFileSystemException e) {
+ throw new DisworkException("unable to access file-system", e);
+ }
+ return result;
+ }
+
/**
* Provide an application to all nodes. Once provided, all nodes will be
* able to perform a job with this application.
@@ -524,7 +546,19 @@
throw new NullPointerException("job is null");
}
-
+ // if an application is declared is used, check it is available
+ if (jobDescription.getApplicationName() != null) {
+ if ( ! isApplicationAvailable(jobDescription.getApplicationName(),
+ jobDescription.getApplicationVersion())) {
+ throw new DisworkException("job require a dependency " +
+ jobDescription.getApplicationName() + "-" +
+ jobDescription.getApplicationVersion()
+ + " that is not available");
+ }
+ } else {
+ log.debug("no dependency specified for " + jobDescription);
+ }
+
// check all dependencies are provided
for (String name : jobDescription.getInput()) {
if (!jobDescription.getInputData().containsKey(name) &&
@@ -550,22 +584,6 @@
// create both job path and sub-directory .diswork
fileSystem.createDirectories(
getPathForJob(jobDescription) + "/" + ".diswork");
-
- if (jobDescription.applicationName != null) {
- String dependencyPath = getPathForDependency(
- jobDescription.getApplicationName(),
- jobDescription.getApplicationVersion());
- log.info("looking for " + dependencyPath);
-
- if (!fileSystem.exists(dependencyPath)) {
- throw new DisworkException("job require a dependency " +
- jobDescription.getApplicationName() + "-" +
- jobDescription.getApplicationVersion()
- + " that is not available");
- }
- } else {
- log.debug("no dependency specified for " + jobDescription);
- }
String jobDir = getPathForJob(jobDescription);
@@ -807,7 +825,7 @@
String line;
while ((line = in.readLine()) != null) {
if (!line.equals("")) {
- log.debug("reading line" + line);
+ log.debug("reading line " + line);
String[] keyValue = line.split("\t");
String key = keyValue[0];
Long value = Long.parseLong(keyValue[1]);
Modified: trunk/diswork-daemon/src/test/java/org/nuiton/diswork/daemon/DisworkDaemonTest.java
===================================================================
--- trunk/diswork-daemon/src/test/java/org/nuiton/diswork/daemon/DisworkDaemonTest.java 2010-07-23 09:10:52 UTC (rev 108)
+++ trunk/diswork-daemon/src/test/java/org/nuiton/diswork/daemon/DisworkDaemonTest.java 2010-07-23 13:22:40 UTC (rev 109)
@@ -24,18 +24,19 @@
*/
package org.nuiton.diswork.daemon;
-import org.apache.commons.io.IOUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
import java.util.Map;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import org.apache.commons.io.IOUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
public class DisworkDaemonTest {
@@ -89,6 +90,16 @@
// close raise errors due to DHT doesn't manage peer leaving
}
}
+
+ @Test
+ public void applicationManagement() throws Exception {
+ // this application has been submitted
+ assertTrue(daemon.isApplicationAvailable("fake-app", "1.0"));
+
+ // those have not been submitted
+ assertFalse(daemon.isApplicationAvailable("unknow_app", "1.0"));
+ assertFalse(daemon.isApplicationAvailable("fake-app", "1.1"));
+ }
@Test
public void simpleSubmit() throws Exception {
1
0
r108 - trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage
by bleny@users.nuiton.org 23 Jul '10
by bleny@users.nuiton.org 23 Jul '10
23 Jul '10
Author: bleny
Date: 2010-07-23 11:10:52 +0200 (Fri, 23 Jul 2010)
New Revision: 108
Url: http://nuiton.org/repositories/revision/diswork/108
Log:
- log trop lourd qui provoque des java heap space error
Modified:
trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/InMemoryDisworkMap.java
Modified: trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/InMemoryDisworkMap.java
===================================================================
--- trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/InMemoryDisworkMap.java 2010-07-22 12:45:54 UTC (rev 107)
+++ trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/InMemoryDisworkMap.java 2010-07-23 09:10:52 UTC (rev 108)
@@ -39,15 +39,17 @@
public class InMemoryDisworkMap extends HashMap<String, byte[]>
implements DisworkMap {
- private static final long serialVersionUID = 2467699175129909832L;
+ private static final long serialVersionUID = 1L;
private final Log log = LogFactory.getLog(InMemoryDisworkMap.class);
@Override
public byte[] put(String key, byte[] value) {
- log.info("put(\"" + key + "\"," + Arrays.toString(value) + ")");
byte[] valueCopy = value.clone();
- log.info("putting " + valueCopy.length + " bytes");
+ if (log.isTraceEnabled()) {
+ log.trace("put(\"" + key + "\"," + Arrays.toString(value) + ") " +
+ valueCopy.length);
+ }
return super.put(key, valueCopy);
}
1
0