diff --git a/data/grid5000/grid5000.json b/data/grid5000/grid5000.json
new file mode 100644
index 0000000000000000000000000000000000000000..6573a6a97c5b6f50f395ac93b78f7a4434e926bd
--- /dev/null
+++ b/data/grid5000/grid5000.json
@@ -0,0 +1,4 @@
+{
+  "type": "grid",
+  "uid": "grid5000"
+}
\ No newline at end of file
diff --git a/generators/grid5000.rb b/generators/grid5000.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dfa209e647430a9db01fad6079f87d4dd5394452
--- /dev/null
+++ b/generators/grid5000.rb
@@ -0,0 +1,31 @@
+require 'pp'
+require 'rubygems'
+require 'fileutils'
+require 'json'
+require 'time'
+require File.dirname(__FILE__)+'/lib/core_extensions'
+require File.dirname(__FILE__)+'/lib/g5k_generator'
+
+usage = %{ 
+  A tool to generate the Grid5000 reference data.
+  
+  Usage:
+    ruby grid5000.rb [input files] [options]
+  Options:
+    -s : simulation mode
+    
+}
+# true if we want to simulate, else false.
+simulation_mode = !$*.delete("-s").nil?
+if $*.empty?
+  puts usage
+elsif ($*.map{|file| File.exists?(file) && File.extname(file) == ".rb"}.include? false)
+  puts "Error: your input files do not exist or are not ruby files (.rb extension)."
+else
+  description_files = $*
+  puts "[Input files:\t\t #{description_files.join(", ")}]"
+  puts "[Simulation mode:\t #{simulation_mode}]"
+  generator = G5K::ReferenceGenerator.new({:uid => "grid5000", :type => "grid"}, *description_files)
+  data = generator.generate
+  generator.write('../data', :simulate => simulation_mode)
+end
\ No newline at end of file
diff --git a/generators/input/environments.rb b/generators/input/environments.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d6c0c751e6637f92cc8136cfdf41560172aca48f
--- /dev/null
+++ b/generators/input/environments.rb
@@ -0,0 +1,15 @@
+# SITES = %{bordeaux grenoble lille lyon nancy orsay rennes sophia toulouse}
+environment 'sid-x64-base-1.0' do
+  state "stable"
+  file({:path => "/home/nancy/xdelaruelle/images/sid-x64-base-1.0.tgz", :md5 => "e39be32c087f0c9777fd0b0ad7d12050"})
+  valid_on "Dell PE1855, Dell PE1950, HP DL140G3, HP DL145G2, IBM e325, IBM e326, IBM e326m, Sun V20z, Sun X2200 M2, Sun X4100".split(", ")
+  kernel "2.6.18-8"
+  based_on "Debian version sid for amd64"
+  consoles [{:port => "ttyS0", :bps => 34800}]
+  services []
+  accounts [{:login => "root", :password => "grid5000"}, {:login => "g5k", :password => "grid5000"}]
+  applications "Vim, XEmacs, JED, nano, JOE, Perl, Python, Ruby".split(", ")
+  x11_forwarding true
+  max_open_files 8192
+  tcp_bandwidth 1.giga
+end
\ No newline at end of file
diff --git a/generators/input/grenoble.rb b/generators/input/grenoble.rb
new file mode 100644
index 0000000000000000000000000000000000000000..26bcb3c9207b34fb5f680cd589e103b03abd160c
--- /dev/null
+++ b/generators/input/grenoble.rb
@@ -0,0 +1,54 @@
+site :grenoble do
+  name "Grenoble"
+  location "Grenoble, France"
+  web
+  description ""
+  latitude
+  longitude
+  email_contact
+  sys_admin_contact
+  security_contact
+  user_support_contact
+  %w{sid-x64-base-1.0}.each{|env_uid| environment env_uid, :refer_to => "grid5000/environments/#{env_uid}"}
+
+  cluster :genepi do
+    model "Bull R422-E1"
+    date_of_arrival Time.parse("2008-10-01").to_i
+    
+    34.times do |i|
+      node "genepi-#{i+1}" do
+        architecture({
+          :smp_size => 2, 
+          :smt_size => 8,
+          :platform_type => "x86_64"
+          })
+        processor({
+          :vendor => "Intel",
+          :model => "Intel Xeon",
+          :version => "E5420 QC",
+          :clock_speed => 2.5.giga,
+          :instruction_set => "",
+          :other_description => "",
+          :cache_l1 => nil,
+          :cache_l1i => nil,
+          :cache_l1d => nil,
+          :cache_l2 => nil
+        })
+        main_memory({
+          :ram_size => 8.GB(true), # bytes
+          :virtual_size => nil
+        })
+        operating_system({
+          :name => nil,
+          :release => nil,
+          :version => nil
+        })
+        storage_devices [
+          {:interface => 'SATA', :size => 160.GB(false), :driver => nil}
+          ]
+        network_adapters [
+          ]  
+      end      
+    end
+  end
+end
\ No newline at end of file
diff --git a/generators/input/orsay.rb b/generators/input/orsay.rb
new file mode 100644
index 0000000000000000000000000000000000000000..eae7531536c063580e3d1cfe95a2fd528bbe8951
--- /dev/null
+++ b/generators/input/orsay.rb
@@ -0,0 +1,114 @@
+site :orsay do
+  name "Orsay"
+  location "Orsay, France"
+  web
+  description ""
+  latitude
+  longitude
+  email_contact
+  sys_admin_contact
+  security_contact
+  user_support_contact
+  %w{sid-x64-base-1.0}.each{|env_uid| environment env_uid, :refer_to => "grid5000/environments/#{env_uid}"}
+
+  cluster :netgdx do
+    model "IBM eServer 326m"
+    date_of_arrival nil
+    misc "bios:1.28/bcm:1.20.17/bmc:1.10/rsaII:1.00"
+    30.times do |i|
+      node "netgdx-#{i+1}" do
+        architecture({
+          :smp_size => 2, 
+          :smt_size => 2,
+          :platform_type => "x86_64"
+          })
+        processor({
+          :vendor => "AMD",
+          :model => "AMD Opteron",
+          :version => "246",
+          :clock_speed => 2.giga,
+          :instruction_set => "",
+          :other_description => "",
+          :cache_l1 => 1.MB,
+          :cache_l1i => nil,
+          :cache_l1d => nil,
+          :cache_l2 => nil
+        })
+        main_memory({
+          :ram_size => 2.GB(true), # bytes
+          :virtual_size => nil
+        })
+        operating_system({
+          :name => nil,
+          :release => nil,
+          :version => nil
+        })
+        storage_devices [
+          {:interface => 'SATA', :size => 80.GB(false), :driver => nil}
+          ]
+        network_adapters [
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => true, :driver => nil},          
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => true, :driver => nil},
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => true, :driver => nil}
+          ]  
+      end      
+    end
+  end # cluster net-gdx
+  
+  cluster :gdx do
+    model "IBM eServer 326m"
+    date_of_arrival nil
+    misc "bios:1.28/bcm:1.20.17/bmc:1.10/rsaII:1.00"
+    
+    (186+126).times do |i|
+      node "gdx-#{i+1}" do
+        architecture({
+          :smp_size => 2, 
+          :smt_size => 2,
+          :platform_type => "x86_64"
+          })
+        processor({
+          :vendor => "AMD",
+          :model => "AMD Opteron",
+          :version => "246",
+          :clock_speed => 2.giga,
+          :instruction_set => "",
+          :other_description => "",
+          :cache_l1 => 1.MB,
+          :cache_l1i => nil,
+          :cache_l1d => nil,
+          :cache_l2 => nil
+        })
+        main_memory({
+          :ram_size => 2.GB(true), # bytes
+          :virtual_size => nil
+        })
+        operating_system({
+          :name => nil,
+          :release => nil,
+          :version => nil
+        })
+        storage_devices [
+          {:interface => 'SATA', :size => 80.GB(false), :driver => nil}
+          ]
+        network_adapters [
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => true},
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => false},
+          {:interface => 'Myri-10G', :rate => 10.giga, :enabled => true, :vendor => "Myrinet", :version => "10G-PCIE-8A-C"}
+          ]
+      end        
+    end
+    
+    # extension specifics, starting at node 187
+    126.times do |i|
+      node "gdx-#{186+i+1}" do
+        processor({
+          :version => "250",
+          :clock_speed => 2.4.giga
+        })
+      end
+    end
+    
+  end # cluster gdx
+  
+end
\ No newline at end of file
diff --git a/generators/input/rennes.rb b/generators/input/rennes.rb
new file mode 100644
index 0000000000000000000000000000000000000000..977e72ef3dc9817455bcb5dea827235eae57d3ba
--- /dev/null
+++ b/generators/input/rennes.rb
@@ -0,0 +1,147 @@
+site :rennes do
+  name "Rennes"
+  location "Rennes, France"
+  web "http://www.irisa.fr"
+  description ""
+  latitude 48.114722
+  longitude -1.679444
+  email_contact
+  sys_admin_contact
+  security_contact
+  user_support_contact
+  %w{sid-x64-base-1.0}.each do |env_id|
+    environment env_id, :refer_to => "grid5000/environments/#{env_id}"
+  end
+  
+  cluster :paravent do
+    model "HP ProLiant DL145G2"
+    created_at nil
+    99.times do |i|
+      node "paravent-#{i+1}" do
+        architecture({
+          :smp_size => 2,
+          :smt_size => 2,
+          :platform_type => "x86_64"
+        })
+        processor({
+          :vendor => "AMD",
+          :model => "AMD Opteron",
+          :version => "246",
+          :clock_speed => 2.giga,
+          :instruction_set => "",
+          :other_description => "",
+          :cache_l1 => nil,
+          :cache_l1i => nil,
+          :cache_l1d => nil,
+          :cache_l2 => nil          
+        })
+        main_memory({
+          :ram_size => 2.GB(true), # bytes
+          :virtual_size => nil
+        })
+        operating_system({
+          :name => nil,
+          :release => nil,
+          :version => nil
+        })
+        storage_devices [
+          {:interface => 'SATA', :size => 80.GB(false), :driver => "sata_nv"}
+          ]
+        network_adapters [
+          {:interface => 'InfiniBand 10G', :rate => 10.giga, :vendor => "InfiniHost", :version => "MT23108", :enabled => true},
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => true},
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => false}
+          ]        
+      end
+    end
+  end
+  
+  cluster :paramount do
+    model "Dell PowerEdge 1950"
+    created_at Time.parse("2007-09-01").to_i
+    33.times do |i|
+      node "paramount-#{i+1}" do
+        architecture({
+          :smp_size => 2,
+          :smt_size => 4,
+          :platform_type => "x86_64"
+        })
+        
+        processor({
+          :vendor => "Intel",
+          :model => "Intel Xeon",
+          :version => "5148 LV",
+          :clock_speed => 2.33.giga,
+          :instruction_set => "",
+          :other_description => "",
+          :cache_l1 => nil,
+          :cache_l1i => nil,
+          :cache_l1d => nil,
+          :cache_l2 => nil          
+        })
+        main_memory({
+          :ram_size => 8.GB(true), # bytes
+          :virtual_size => nil
+        })
+        operating_system({
+          :name => nil,
+          :release => nil,
+          :version => nil
+        })
+        storage_devices [
+          {:interface => 'SATA', :size => 300.GB(false), :driver => "megaraid_sas", :raid => "0"},
+          {:interface => 'SATA', :size => 300.GB(false), :driver => "megaraid_sas", :raid => "0"}
+          ]
+        network_adapters [
+          {:interface => 'Myri-10G', :rate => 10.giga, :vendor => 'Myrinet', :version => "10G-PCIE-8A-C", :enabled => true},
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => true},
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => false}
+          ]
+      end
+    end
+  end
+  
+  cluster(:paraquad) do
+    model "Dell PowerEdge 1950"
+    created_at Time.parse("2006-12-01").to_i
+    
+    64.times do |i|
+      node "paraquad-#{i+1}" do
+        architecture({
+          :smp_size => 2, 
+          :smt_size => 4,
+          :platform_type => "x86_64"
+          })
+        processor({
+          :vendor => "Intel",
+          :model => "Intel Xeon",
+          :version => "5148 LV",
+          :clock_speed => 2.33.giga,
+          :instruction_set => "",
+          :other_description => "",
+          :cache_l1 => nil,
+          :cache_l1i => nil,
+          :cache_l1d => nil,
+          :cache_l2 => nil
+        })
+        main_memory({
+          :ram_size => 4.GB(true), # bytes
+          :virtual_size => nil
+        })
+        operating_system({
+          :name => nil,
+          :release => nil,
+          :version => nil
+        })
+        storage_devices [
+          {:interface => 'SATA', :size => 160.GB(false), :driver => "mptsas"}
+          ]
+        network_adapters [
+            {:interface => 'Myri-10G', :rate => 10.giga, :vendor => 'Myrinet', :version => "10G-PCIE-8A-C", :enabled => true},
+            {:interface => 'Ethernet', :rate => 1.giga, :enabled => true},
+            {:interface => 'Ethernet', :rate => 1.giga, :enabled => false}
+          ]        
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/generators/input/sophia.rb b/generators/input/sophia.rb
new file mode 100644
index 0000000000000000000000000000000000000000..89f230640280331f341988175388d856dfe1f0a0
--- /dev/null
+++ b/generators/input/sophia.rb
@@ -0,0 +1,181 @@
+site :sophia do
+  name "Sophia-Antipolis"
+  location "Sophia-Antipolis, France"
+  web
+  description ""
+  latitude
+  longitude
+  email_contact
+  sys_admin_contact
+  security_contact
+  user_support_contact
+  %w{sid-x64-base-1.0}.each do |env_id|
+    environment env_id, :refer_to => "grid5000/environments/#{env_id}"
+  end
+  
+  cluster :azur do
+    model "IBM eServer 325"
+    created_at Time.parse("2005-02-18").to_i
+    72.times do |i|
+      node "azur-#{i+1}" do
+        architecture({
+          :smp_size => 2,
+          :smt_size => 2,
+          :platform_type => "x86_64"
+        })
+        processor({
+          :vendor => "AMD",
+          :model => "AMD Opteron",
+          :version => "246",
+          :clock_speed => 2.giga,
+          :instruction_set => "",
+          :other_description => "",
+          :cache_l1 => 1.MB,
+          :cache_l1i => nil,
+          :cache_l1d => nil,
+          :cache_l2 => nil          
+        })
+        main_memory({
+          :ram_size => 2.GB(true), # bytes
+          :virtual_size => nil
+        })
+        operating_system({
+          :name => nil,
+          :release => nil,
+          :version => nil
+        })
+        storage_devices [
+          {:interface => 'IDE', :size => 80.GB(false), :driver => "amd74xx"}
+          ]
+        network_adapters []        
+      end
+    end
+  end
+    
+  cluster :helios do
+    model "Sun Fire X4100"
+    created_at Time.parse("2006-06-02").to_i
+    56.times do |i|
+      node "helios-#{i+1}" do
+        architecture({
+          :smp_size => 2,
+          :smt_size => 4,
+          :platform_type => "x86_64"
+        })
+        processor({
+          :vendor => "AMD",
+          :model => "AMD Opteron",
+          :version => "275",
+          :clock_speed => 2.2.giga,
+          :instruction_set => "",
+          :other_description => "",
+          :cache_l1 => 1.MB,
+          :cache_l1i => nil,
+          :cache_l1d => nil,
+          :cache_l2 => nil          
+        })
+        main_memory({
+          :ram_size => 4.GB(true), # bytes
+          :virtual_size => nil
+        })
+        operating_system({
+          :name => nil,
+          :release => nil,
+          :version => nil
+        })
+        storage_devices [
+          {:interface => 'SAS', :size => 73.GB(false), :driver => "mptsas", :raid => "0"},
+          {:interface => 'SAS', :size => 73.GB(false), :driver => "mptsas", :raid => "0"}
+          ]
+        network_adapters []          
+      end
+    end
+  end
+    
+  cluster :sol do
+    model "Sun Fire X2200 M2"
+    created_at Time.parse("2007-02-23").to_i
+    50.times do |i|
+      node "sol-#{i+1}" do
+        architecture({
+          :smp_size => 2,
+          :smt_size => 4,
+          :platform_type => "x86_64"
+        })
+        processor({
+          :vendor => "AMD",
+          :model => "AMD Opteron",
+          :version => "2218",
+          :clock_speed => 2.6.giga,
+          :instruction_set => "",
+          :other_description => "",
+          :cache_l1 => 1.MB,
+          :cache_l1i => nil,
+          :cache_l1d => nil,
+          :cache_l2 => nil          
+        })
+        main_memory({
+          :ram_size => 4.GB(true), # bytes
+          :virtual_size => nil
+        })
+        operating_system({
+          :name => nil,
+          :release => nil,
+          :version => nil
+        })
+        storage_devices [
+          {:interface => 'SATA', :size => 250.GB(false), :driver => "sata_nv"}
+          ]
+        network_adapters [
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => true, :vendor => "NVIDIA", :version => "MCP55 Pro"},
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => true, :vendor => "NVIDIA", :version => "MCP55 Pro"},
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => false, :vendor => "Broadcom", :version => "BCM5715c"},
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => false, :vendor => "Broadcom", :version => "BCM5715c"}            
+          ]          
+      end
+    end
+  end
+  #   
+  # cluster :storage do
+  #   model "Sun X4100"
+  #   node "storage-1" do
+  #     architecture({
+  #       :smp_size => 2,
+  #       :smt_size => 2,
+  #       :platform_type => ""
+  #     })
+  #     processor({
+  #       :vendor => "AMD",
+  #       :model => "AMD Opteron",
+  #       :version => "275",
+  #       :clock_speed => 2.2.giga,
+  #       :instruction_set => "",
+  #       :other_description => "",
+  #       :cache_l1 => nil,
+  #       :cache_l1i => nil,
+  #       :cache_l1d => nil,
+  #       :cache_l2 => nil          
+  #     })
+  #     main_memory({
+  #       :ram_size => 4.GB(true), # bytes
+  #       :virtual_size => nil
+  #     })
+  #     operating_system({
+  #       :name => nil,
+  #       :release => nil,
+  #       :version => nil
+  #     })
+  #     storage_devices [
+  #       {:interface => 'SAS', :size => 73.GB(false), :rpm => 10_000, :raid => "1 'Mirroring'"},
+  #       {:interface => 'SATA II', :size => 2.TB(false), :raid => "5", :name => "Sun StorEdge 3511 FC Array"}
+  #       ]
+  #     network_adapters [
+  #       {:interface => 'Ethernet', :rate => 1.giga, :enabled => true, :vendor => "Intel", :version => "e1000"},
+  #       {:interface => 'Ethernet', :rate => 1.giga, :enabled => true, :vendor => "Intel", :version => "e1000"},
+  #       {:interface => 'Ethernet', :rate => 1.giga, :enabled => true, :vendor => "Intel", :version => "e1000"},
+  #       {:interface => 'Ethernet', :rate => 1.giga, :enabled => true, :vendor => "Intel", :version => "e1000"},
+  #       {:interface => 'Fibre Channel', :rate => 2.giga, :enabled => true, :vendor => "QLogic", :version => "QLA2342"}           
+  #       ]        
+  #   end
+  # end
+end
\ No newline at end of file
diff --git a/generators/input/toulouse.rb b/generators/input/toulouse.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7eb5b0d4eface7b3a713e373f83b9931e46888ce
--- /dev/null
+++ b/generators/input/toulouse.rb
@@ -0,0 +1,102 @@
+site :toulouse do
+  name "Toulouse"
+  location "Toulouse, France"
+  web
+  description ""
+  latitude
+  longitude
+  email_contact
+  sys_admin_contact
+  security_contact
+  user_support_contact
+  %w{sid-x64-base-1.0}.each{|env_uid| environment env_uid, :refer_to => "grid5000/environments/#{env_uid}"}
+
+  cluster :violette do
+    model "Sun Fire V20z"
+    date_of_arrival Time.parse("2004-09-01").to_i
+    
+    57.times do |i|
+      node "violette-#{i+1}" do
+        architecture({
+          :smp_size => 2, 
+          :smt_size => 2,
+          :platform_type => "x86_64"
+          })
+        processor({
+          :vendor => "AMD",
+          :model => "AMD Opteron",
+          :version => "248",
+          :clock_speed => 2.2.giga,
+          :instruction_set => "",
+          :other_description => "",
+          :cache_l1 => nil,
+          :cache_l1i => nil,
+          :cache_l1d => nil,
+          :cache_l2 => nil
+        })
+        main_memory({
+          :ram_size => 2.GB(true), # bytes
+          :virtual_size => nil
+        })
+        operating_system({
+          :name => nil,
+          :release => nil,
+          :version => nil
+        })
+        storage_devices [
+          {:interface => 'SCSI', :size => 73.GB(false), :driver => "mptspi"}
+          ]
+        network_adapters [
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => true, :driver => "tg3"},
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => false, :driver => "tg3"}
+          ]  
+      end      
+    end
+  end
+  
+  cluster :pastel do
+    model "Sun Fire X2200 M2"
+    date_of_arrival Time.parse("2007-11-29").to_i
+    
+    80.times do |i|
+      node "pastel-#{i+1}" do
+        architecture({
+          :smp_size => 2, 
+          :smt_size => 4,
+          :platform_type => "x86_64"
+          })
+        processor({
+          :vendor => "AMD",
+          :model => "AMD Opteron",
+          :version => "2218",
+          :clock_speed => 2.6.giga,
+          :instruction_set => "",
+          :other_description => "",
+          :cache_l1 => 1.MB,
+          :cache_l1i => nil,
+          :cache_l1d => nil,
+          :cache_l2 => nil
+        })
+        main_memory({
+          :ram_size => 8.GB(true), # bytes
+          :virtual_size => nil
+        })
+        operating_system({
+          :name => nil,
+          :release => nil,
+          :version => nil
+        })
+        storage_devices [
+          {:interface => 'SATA', :size => 250.GB(false), :driver => "sata_nv"}
+          ]
+        network_adapters [
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => true, :vendor => "NVIDIA", :version => "MCP55 Pro", :driver => "forcedeth"},
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => false, :vendor => "NVIDIA", :version => "MCP55 Pro", :driver => "forcedeth"},
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => false, :vendor => "Broadcom", :version => "BCM5715c", :driver => "tg3"},
+          {:interface => 'Ethernet', :rate => 1.giga, :enabled => false, :vendor => "Broadcom", :version => "BCM5715c", :driver => "tg3"}
+          ]  
+      end      
+    end
+  end
+  
+end
\ No newline at end of file
diff --git a/generators/lib/core_extensions.rb b/generators/lib/core_extensions.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7d6b90b9d19f4254d5d0e560751461ba4fd00728
--- /dev/null
+++ b/generators/lib/core_extensions.rb
@@ -0,0 +1,34 @@
+
+class Numeric
+
+  def TB(correct = true)
+    if correct then self*1024**4; else self.tera/(1024**4); end
+  end
+  # Returns the number of bytes.
+  #
+  # If you know that the provided number is not correct (in the case of hard drive capacities for example),
+  # setting +correct+ to +false+ will return the "real" number of bytes (e.g. HD 160GB has in reality 149011611938.477 bytes).
+  def GB(correct = true)
+    if correct then self*1024**3; else self.giga/(1.024**3); end
+  end
+  def MB(correct = true)
+    if correct then self*1024**2; else self.mega/(1024**2); end
+  end
+  def mega; self*1_000_000; end
+  def giga; self*1_000_000_000; end
+  def tera; self*1_000_000_000_000; end
+end
+
+class String
+  # Really naive pluralization.
+  # TODO: see if it's possible to include a better one (from rails or sthg else)
+  def pluralize
+    self+"s"
+  end
+end
+
+class Hash
+  def recursive_merge!(h)
+    self.merge!(h) {|key, _old, _new| if _old.class == Hash then _old.recursive_merge!(_new) else _new end  }
+  end  
+end
\ No newline at end of file
diff --git a/generators/lib/g5k_generator.rb b/generators/lib/g5k_generator.rb
new file mode 100644
index 0000000000000000000000000000000000000000..857f862e969508f8d6de4678f1ef97556a6aa5aa
--- /dev/null
+++ b/generators/lib/g5k_generator.rb
@@ -0,0 +1,131 @@
+module G5K
+  class Tree < Hash
+    attr_reader :contents, :path
+    def write(repository, &block)
+      self[:uid] ||= ""
+      @contents = {}
+      @path = File.join(repository, self[:uid]+".json")
+      self.each do |key, value|
+        if value.is_a? Folder
+          value.write(File.join(repository, self[:uid], key.to_s), &block)
+          @path = File.join(repository, self[:uid], self[:uid]+".json")
+        else
+          @contents.merge!(key => value)
+        end
+      end
+      if !@contents.empty? && !@contents[:uid].empty?
+        yield self
+      end
+    end
+    
+    def valid?
+      true
+      # we could do sthg like: Load(type.class).new(hash_values).valid?
+    end
+  end
+  class Folder < Array
+    attr_reader :path
+    def write(repository, &block)
+      @path = repository
+      self.each do |v| 
+        v.write(repository, &block)
+      end
+      yield self
+    end
+    def valid?
+      true
+    end
+  end
+  class Link < Struct.new(:uid, :refer_to)
+    attr_reader :from, :path
+  
+    def write(repository)
+      @from, @path = [refer_to, File.join(repository, "#{uid}.json")]
+      yield self
+    end
+    def valid?
+      true
+    end
+  end
+
+class ReferenceGenerator
+  attr_reader :data
+  
+  def method_missing(method, *args)
+    @context.recursive_merge!(method.to_sym => args.first)
+  end
+  
+  %w{site cluster environment node}.each do |method|
+    define_method(method) do |uid, *options, &block|
+      key = method.pluralize.to_sym
+      uid = uid.to_s
+      options = options.first || Hash.new
+      old_context = @context
+      @context[key] ||= G5K::Folder.new
+      if options.has_key? :refer_to
+        @context[key] << G5K::Link.new(uid, options[:refer_to])
+      else    
+        # if the same object already exists, we return it for completion/modification
+        if (same_trees = @context[key].select{|tree| tree[:uid] == uid}).size > 0
+          @context = same_trees.first
+        else
+          @context[key] << G5K::Tree.new.replace({:uid => uid, :type => method})
+          @context = @context[key].last
+        end
+        block.call if block
+      end
+      @context = old_context
+    end
+  end
+  
+  # Initializes a new generator that will generates data files in a hierachical way. 
+  # The root of the tree will be named with the value of <tt>data_description[:uid]</tt>.
+  def initialize(data_description = {:uid => ""}, *files)
+    @files = files
+    @data = G5K::Tree.new.replace(data_description)
+    @context = @data
+  end
+  
+  def generate
+    @files.each do |file|
+      File.open(file, 'r') do |f|
+        eval(f.read)
+      end
+    end
+    @data
+  end
+  
+  def write(repository, options = {:simulate => false})
+    things_to_create = []
+    @data.write("/") do |thing_to_create|
+      things_to_create << thing_to_create if thing_to_create.valid?
+    end
+    groups = things_to_create.group_by{|thing| thing.class}
+    groups.has_key?(G5K::Folder) and groups[G5K::Folder].each do |folder|
+      full_path = File.join(repository, folder.path)
+      unless File.exists?(full_path)
+        puts "Directory to be written = \t#{full_path}"
+        FileUtils.mkdir_p(full_path) unless options[:simulate]
+      end
+    end
+    groups.has_key?(G5K::Tree) and groups[G5K::Tree].each do |file|
+      full_path = File.join(repository, file.path)
+      new_content = JSON.pretty_generate(file.contents.rehash)
+      existing_content = File.exists?(full_path) ? File.open(full_path, "r").read : ""
+      if new_content.hash != existing_content.hash
+        puts "File to be written      = \t#{full_path}"
+        File.open(full_path, "w+"){ |f| f << new_content  } unless options[:simulate]
+      end
+    end
+    groups.has_key?(G5K::Link) and groups[G5K::Link].each do |link|      
+      from = File.join(repository, "#{link.from}.json")
+      to = File.join(repository, link.path)
+      # Hard links will always be regenerated
+      # TODO: find a way to detect if a link has to be regenerated
+      puts "Hard link to be written = \t#{to} -> #{from}"
+      FileUtils.link(from, to, :force => true) unless options[:simulate]
+    end  
+  end
+  
+end
+end
\ No newline at end of file