deltacloud-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mfoj...@redhat.com
Subject [PATCH core] Core: Revamped Deltacloud API to be a Sinatra modular application
Date Mon, 16 Apr 2012 13:10:23 GMT
From: Michal Fojtik <mfojtik@redhat.com>

* Collections are now placed in lib/deltacloud/collections directory
* CIMI has own separate directory in lib/cimi
* Switched to the upstream Rabbit DSL (https://github.com/mifo/sinatra-rabbit)
* Added new MiniTest tests (rake test:api)
* Library code added (Deltacloud can be now required as a library)

Signed-off-by: Michal fojtik <mfojtik@redhat.com>
---
 server/Rakefile                                    |   70 ++
 server/config.ru                                   |   44 +-
 server/deltacloud-core.gemspec                     |    1 +
 server/lib/cimi/collections.rb                     |   58 +
 server/lib/cimi/collections/address_templates.rb   |   49 +
 server/lib/cimi/collections/addresses.rb           |   74 ++
 server/lib/cimi/collections/cloud_entry_point.rb   |   32 +
 server/lib/cimi/collections/entity_metadata.rb     |   48 +
 server/lib/cimi/collections/machine_admins.rb      |   74 ++
 .../lib/cimi/collections/machine_configurations.rb |   49 +
 server/lib/cimi/collections/machine_images.rb      |   50 +
 server/lib/cimi/collections/machines.rb            |  157 +++
 .../lib/cimi/collections/network_configurations.rb |   47 +
 server/lib/cimi/collections/network_templates.rb   |   48 +
 server/lib/cimi/collections/networks.rb            |  125 ++
 .../cimi/collections/routing_group_templates.rb    |   47 +
 server/lib/cimi/collections/routing_groups.rb      |   48 +
 .../lib/cimi/collections/volume_configurations.rb  |   48 +
 server/lib/cimi/collections/volume_images.rb       |   50 +
 server/lib/cimi/collections/volumes.rb             |   80 ++
 server/lib/cimi/collections/vsp_configurations.rb  |   48 +
 server/lib/cimi/collections/vsp_templates.rb       |   50 +
 server/lib/cimi/collections/vsps.rb                |  108 ++
 server/lib/cimi/helpers.rb                         |  104 ++
 server/lib/cimi/helpers/cimi_helper.rb             |    2 -
 server/lib/cimi/model.rb                           |   67 -
 server/lib/cimi/model/action.rb                    |   24 -
 server/lib/cimi/model/address.rb                   |   72 --
 server/lib/cimi/model/address_collection.rb        |   34 -
 server/lib/cimi/model/address_template.rb          |   54 -
 .../lib/cimi/model/address_template_collection.rb  |   34 -
 server/lib/cimi/model/base.rb                      |  249 ----
 server/lib/cimi/model/cloud_entry_point.rb         |   48 -
 server/lib/cimi/model/entity_metadata.rb           |   83 --
 .../lib/cimi/model/entity_metadata_collection.rb   |   31 -
 server/lib/cimi/model/errors.rb                    |   48 -
 server/lib/cimi/model/machine.rb                   |  229 ----
 server/lib/cimi/model/machine_admin.rb             |   59 -
 server/lib/cimi/model/machine_admin_collection.rb  |   34 -
 server/lib/cimi/model/machine_collection.rb        |   34 -
 server/lib/cimi/model/machine_configuration.rb     |   70 --
 .../cimi/model/machine_configuration_collection.rb |   34 -
 server/lib/cimi/model/machine_image.rb             |   46 -
 server/lib/cimi/model/machine_image_collection.rb  |   34 -
 server/lib/cimi/model/machine_template.rb          |   41 -
 .../lib/cimi/model/machine_template_collection.rb  |   34 -
 server/lib/cimi/model/network.rb                   |  106 --
 server/lib/cimi/model/network_collection.rb        |   34 -
 server/lib/cimi/model/network_configuration.rb     |   49 -
 .../cimi/model/network_configuration_collection.rb |   34 -
 server/lib/cimi/model/network_template.rb          |   36 -
 .../lib/cimi/model/network_template_collection.rb  |   35 -
 server/lib/cimi/model/routing_group.rb             |   34 -
 server/lib/cimi/model/routing_group_collection.rb  |   34 -
 server/lib/cimi/model/routing_group_template.rb    |   34 -
 .../model/routing_group_template_collection.rb     |   35 -
 server/lib/cimi/model/schema.rb                    |  277 -----
 server/lib/cimi/model/volume.rb                    |  103 --
 server/lib/cimi/model/volume_collection.rb         |   34 -
 server/lib/cimi/model/volume_configuration.rb      |   60 -
 .../cimi/model/volume_configuration_collection.rb  |   34 -
 server/lib/cimi/model/volume_image.rb              |   49 -
 server/lib/cimi/model/volume_image_collection.rb   |   34 -
 server/lib/cimi/model/volume_template.rb           |   23 -
 .../lib/cimi/model/volume_template_collection.rb   |   34 -
 server/lib/cimi/model/vsp.rb                       |  102 --
 server/lib/cimi/model/vsp_collection.rb            |   34 -
 server/lib/cimi/model/vsp_configuration.rb         |   40 -
 .../lib/cimi/model/vsp_configuration_collection.rb |   34 -
 server/lib/cimi/model/vsp_template.rb              |   34 -
 server/lib/cimi/model/vsp_template_collection.rb   |   34 -
 server/lib/cimi/models.rb                          |   75 ++
 server/lib/cimi/models/action.rb                   |   24 +
 server/lib/cimi/models/address.rb                  |   72 ++
 server/lib/cimi/models/address_collection.rb       |   34 +
 server/lib/cimi/models/address_template.rb         |   54 +
 .../lib/cimi/models/address_template_collection.rb |   34 +
 server/lib/cimi/models/base.rb                     |  249 ++++
 server/lib/cimi/models/cloud_entry_point.rb        |   46 +
 server/lib/cimi/models/entity_metadata.rb          |   84 ++
 .../lib/cimi/models/entity_metadata_collection.rb  |   31 +
 server/lib/cimi/models/errors.rb                   |   48 +
 server/lib/cimi/models/machine.rb                  |  227 ++++
 server/lib/cimi/models/machine_admin.rb            |   59 +
 server/lib/cimi/models/machine_admin_collection.rb |   34 +
 server/lib/cimi/models/machine_collection.rb       |   34 +
 server/lib/cimi/models/machine_configuration.rb    |   70 ++
 .../models/machine_configuration_collection.rb     |   34 +
 server/lib/cimi/models/machine_image.rb            |   46 +
 server/lib/cimi/models/machine_image_collection.rb |   34 +
 server/lib/cimi/models/machine_template.rb         |   41 +
 .../lib/cimi/models/machine_template_collection.rb |   34 +
 server/lib/cimi/models/network.rb                  |  109 ++
 server/lib/cimi/models/network_collection.rb       |   34 +
 server/lib/cimi/models/network_configuration.rb    |   49 +
 .../models/network_configuration_collection.rb     |   34 +
 server/lib/cimi/models/network_template.rb         |   36 +
 .../lib/cimi/models/network_template_collection.rb |   35 +
 server/lib/cimi/models/routing_group.rb            |   34 +
 server/lib/cimi/models/routing_group_collection.rb |   34 +
 server/lib/cimi/models/routing_group_template.rb   |   34 +
 .../models/routing_group_template_collection.rb    |   35 +
 server/lib/cimi/models/schema.rb                   |  277 +++++
 server/lib/cimi/models/volume.rb                   |  103 ++
 server/lib/cimi/models/volume_collection.rb        |   34 +
 server/lib/cimi/models/volume_configuration.rb     |   60 +
 .../cimi/models/volume_configuration_collection.rb |   34 +
 server/lib/cimi/models/volume_image.rb             |   49 +
 server/lib/cimi/models/volume_image_collection.rb  |   34 +
 server/lib/cimi/models/volume_template.rb          |   23 +
 .../lib/cimi/models/volume_template_collection.rb  |   34 +
 server/lib/cimi/models/vsp.rb                      |  102 ++
 server/lib/cimi/models/vsp_collection.rb           |   34 +
 server/lib/cimi/models/vsp_configuration.rb        |   40 +
 .../cimi/models/vsp_configuration_collection.rb    |   34 +
 server/lib/cimi/models/vsp_template.rb             |   34 +
 server/lib/cimi/models/vsp_template_collection.rb  |   34 +
 server/lib/cimi/server.rb                          |  959 +--------------
 server/lib/deltacloud.rb                           |   64 +-
 server/lib/deltacloud/backend_capability.rb        |   42 -
 server/lib/deltacloud/base_driver.rb               |   18 -
 server/lib/deltacloud/base_driver/base_driver.rb   |  250 ----
 server/lib/deltacloud/base_driver/exceptions.rb    |  191 ---
 server/lib/deltacloud/base_driver/features.rb      |  276 -----
 server/lib/deltacloud/base_driver/mock_driver.rb   |   78 --
 server/lib/deltacloud/collections.rb               |   54 +
 server/lib/deltacloud/collections/addresses.rb     |   83 ++
 server/lib/deltacloud/collections/buckets.rb       |  215 ++++
 server/lib/deltacloud/collections/drivers.rb       |   51 +
 server/lib/deltacloud/collections/firewalls.rb     |  116 ++
 .../deltacloud/collections/hardware_profiles.rb    |   27 +
 server/lib/deltacloud/collections/images.rb        |   70 ++
 .../lib/deltacloud/collections/instance_states.rb  |   57 +
 server/lib/deltacloud/collections/instances.rb     |  103 ++
 server/lib/deltacloud/collections/keys.rb          |   61 +
 .../lib/deltacloud/collections/load_balancers.rb   |   85 ++
 server/lib/deltacloud/collections/realms.rb        |   27 +
 .../deltacloud/collections/storage_snapshots.rb    |   51 +
 .../lib/deltacloud/collections/storage_volumes.rb  |   99 ++
 server/lib/deltacloud/core_ext.rb                  |   21 -
 server/lib/deltacloud/drivers.rb                   |   48 +-
 .../lib/deltacloud/drivers/azure/azure_driver.rb   |    4 -
 server/lib/deltacloud/drivers/base_driver.rb       |  265 ++++
 .../lib/deltacloud/drivers/condor/condor_driver.rb |    9 +-
 server/lib/deltacloud/drivers/ec2/ec2_driver.rb    |   18 +-
 .../lib/deltacloud/drivers/ec2/ec2_mock_driver.rb  |  186 ---
 .../drivers/eucalyptus/eucalyptus_driver.rb        |    4 -
 server/lib/deltacloud/drivers/exceptions.rb        |  191 +++
 server/lib/deltacloud/drivers/features.rb          |  111 ++
 .../lib/deltacloud/drivers/gogrid/gogrid_driver.rb |    6 -
 .../lib/deltacloud/drivers/google/google_driver.rb |    3 -
 server/lib/deltacloud/drivers/mock/mock_client.rb  |   11 -
 server/lib/deltacloud/drivers/mock/mock_driver.rb  |   21 +-
 .../drivers/mock/mock_driver_cimi_methods.rb       |  139 ---
 .../drivers/opennebula/opennebula_driver.rb        |    8 +-
 .../drivers/openstack/openstack_driver.rb          |   12 +-
 .../drivers/rackspace/rackspace_driver.rb          |    9 +-
 .../lib/deltacloud/drivers/rhevm/rhevm_driver.rb   |   17 +-
 .../drivers/rimuhosting/rimuhosting_client.rb      |   17 +-
 .../drivers/rimuhosting/rimuhosting_driver.rb      |   11 +-
 .../drivers/terremark/terremark_driver.rb          |    7 +-
 .../deltacloud/drivers/vsphere/vsphere_driver.rb   |   15 +-
 server/lib/deltacloud/hardware_profile.rb          |  192 ---
 server/lib/deltacloud/helpers.rb                   |   86 +-
 .../lib/deltacloud/helpers/application_helper.rb   |  238 ----
 server/lib/deltacloud/helpers/assets_helper.rb     |   96 ++
 server/lib/deltacloud/helpers/auth_helper.rb       |   73 ++
 server/lib/deltacloud/helpers/blob_stream.rb       |  213 ----
 server/lib/deltacloud/helpers/conversion_helper.rb |   43 -
 server/lib/deltacloud/helpers/deltacloud_helper.rb |  273 +++++
 server/lib/deltacloud/helpers/driver_helper.rb     |   57 +
 .../deltacloud/helpers/hardware_profiles_helper.rb |   50 -
 server/lib/deltacloud/helpers/json_helper.rb       |   31 -
 server/lib/deltacloud/helpers/rabbit_helper.rb     |   34 +
 server/lib/deltacloud/helpers/url_helper.rb        |  112 ++
 server/lib/deltacloud/method_serializer.rb         |   83 --
 server/lib/deltacloud/models.rb                    |   25 +-
 server/lib/deltacloud/models/hardware_profile.rb   |  194 +++
 server/lib/deltacloud/models/instance.rb           |    2 -
 server/lib/deltacloud/models/key.rb                |    4 +
 server/lib/deltacloud/models/state_machine.rb      |   99 ++
 server/lib/deltacloud/runner.rb                    |  132 --
 server/lib/deltacloud/server.rb                    | 1278 +-------------------
 server/lib/deltacloud/state_machine.rb             |  115 --
 server/lib/deltacloud/validation.rb                |  100 --
 server/lib/sinatra.rb                              |   21 +
 server/lib/sinatra/lazy_auth.rb                    |   75 --
 server/lib/sinatra/rabbit.rb                       |  441 -------
 server/lib/sinatra/rack_accept.rb                  |    4 -
 server/lib/sinatra/rack_cimi.rb                    |   33 -
 server/lib/sinatra/rack_matrix_params.rb           |    4 +-
 server/lib/sinatra/rack_runtime.rb                 |   47 -
 server/lib/sinatra/rack_syslog.rb                  |   93 --
 server/lib/sinatra/sinatra_verbose.rb              |   73 --
 server/lib/sinatra/static_assets.rb                |   99 --
 server/lib/sinatra/url_for.rb                      |   93 --
 server/tests/drivers/api/api_test.rb               |  115 ++
 server/tests/drivers/api/buckets_test.rb           |  194 +++
 server/tests/drivers/api/common.rb                 |   58 +
 server/tests/drivers/api/drivers_test.rb           |  120 ++
 server/tests/drivers/api/hardware_profiles_test.rb |  221 ++++
 server/tests/drivers/api/images_test.rb            |  194 +++
 server/tests/drivers/api/instances_test.rb         |  340 ++++++
 server/tests/drivers/api/keys_test.rb              |  158 +++
 server/tests/drivers/api/realms_test.rb            |  129 ++
 server/tests/drivers/api/storage_snapshots_test.rb |  111 ++
 server/tests/drivers/api/storage_volumes_test.rb   |  119 ++
 server/views/api/show.html.haml                    |    7 +-
 server/views/api/show.xml.haml                     |   13 +-
 server/views/blobs/show.xml.haml                   |   11 +-
 server/views/hardware_profiles/index.html.haml     |    2 +-
 server/views/hardware_profiles/index.xml.haml      |    4 +-
 server/views/hardware_profiles/show.html.haml      |    6 +-
 server/views/hardware_profiles/show.xml.haml       |    6 +-
 server/views/instances/new.html.haml               |   50 +-
 server/views/instances/show.xml.haml               |   12 -
 server/views/keys/show.xml.haml                    |    1 +
 server/views/storage_snapshots/show.xml.haml       |    4 +-
 server/views/storage_volumes/show.html.haml        |    1 +
 server/views/storage_volumes/show.xml.haml         |    5 +-
 220 files changed, 8898 insertions(+), 8557 deletions(-)
 create mode 100644 server/lib/cimi/collections.rb
 create mode 100644 server/lib/cimi/collections/address_templates.rb
 create mode 100644 server/lib/cimi/collections/addresses.rb
 create mode 100644 server/lib/cimi/collections/cloud_entry_point.rb
 create mode 100644 server/lib/cimi/collections/entity_metadata.rb
 create mode 100644 server/lib/cimi/collections/machine_admins.rb
 create mode 100644 server/lib/cimi/collections/machine_configurations.rb
 create mode 100644 server/lib/cimi/collections/machine_images.rb
 create mode 100644 server/lib/cimi/collections/machines.rb
 create mode 100644 server/lib/cimi/collections/network_configurations.rb
 create mode 100644 server/lib/cimi/collections/network_templates.rb
 create mode 100644 server/lib/cimi/collections/networks.rb
 create mode 100644 server/lib/cimi/collections/routing_group_templates.rb
 create mode 100644 server/lib/cimi/collections/routing_groups.rb
 create mode 100644 server/lib/cimi/collections/volume_configurations.rb
 create mode 100644 server/lib/cimi/collections/volume_images.rb
 create mode 100644 server/lib/cimi/collections/volumes.rb
 create mode 100644 server/lib/cimi/collections/vsp_configurations.rb
 create mode 100644 server/lib/cimi/collections/vsp_templates.rb
 create mode 100644 server/lib/cimi/collections/vsps.rb
 create mode 100644 server/lib/cimi/helpers.rb
 delete mode 100644 server/lib/cimi/model.rb
 delete mode 100644 server/lib/cimi/model/action.rb
 delete mode 100644 server/lib/cimi/model/address.rb
 delete mode 100644 server/lib/cimi/model/address_collection.rb
 delete mode 100644 server/lib/cimi/model/address_template.rb
 delete mode 100644 server/lib/cimi/model/address_template_collection.rb
 delete mode 100644 server/lib/cimi/model/base.rb
 delete mode 100644 server/lib/cimi/model/cloud_entry_point.rb
 delete mode 100644 server/lib/cimi/model/entity_metadata.rb
 delete mode 100644 server/lib/cimi/model/entity_metadata_collection.rb
 delete mode 100644 server/lib/cimi/model/errors.rb
 delete mode 100644 server/lib/cimi/model/machine.rb
 delete mode 100644 server/lib/cimi/model/machine_admin.rb
 delete mode 100644 server/lib/cimi/model/machine_admin_collection.rb
 delete mode 100644 server/lib/cimi/model/machine_collection.rb
 delete mode 100644 server/lib/cimi/model/machine_configuration.rb
 delete mode 100644 server/lib/cimi/model/machine_configuration_collection.rb
 delete mode 100644 server/lib/cimi/model/machine_image.rb
 delete mode 100644 server/lib/cimi/model/machine_image_collection.rb
 delete mode 100644 server/lib/cimi/model/machine_template.rb
 delete mode 100644 server/lib/cimi/model/machine_template_collection.rb
 delete mode 100644 server/lib/cimi/model/network.rb
 delete mode 100644 server/lib/cimi/model/network_collection.rb
 delete mode 100644 server/lib/cimi/model/network_configuration.rb
 delete mode 100644 server/lib/cimi/model/network_configuration_collection.rb
 delete mode 100644 server/lib/cimi/model/network_template.rb
 delete mode 100644 server/lib/cimi/model/network_template_collection.rb
 delete mode 100644 server/lib/cimi/model/routing_group.rb
 delete mode 100644 server/lib/cimi/model/routing_group_collection.rb
 delete mode 100644 server/lib/cimi/model/routing_group_template.rb
 delete mode 100644 server/lib/cimi/model/routing_group_template_collection.rb
 delete mode 100644 server/lib/cimi/model/schema.rb
 delete mode 100644 server/lib/cimi/model/volume.rb
 delete mode 100644 server/lib/cimi/model/volume_collection.rb
 delete mode 100644 server/lib/cimi/model/volume_configuration.rb
 delete mode 100644 server/lib/cimi/model/volume_configuration_collection.rb
 delete mode 100644 server/lib/cimi/model/volume_image.rb
 delete mode 100644 server/lib/cimi/model/volume_image_collection.rb
 delete mode 100644 server/lib/cimi/model/volume_template.rb
 delete mode 100644 server/lib/cimi/model/volume_template_collection.rb
 delete mode 100644 server/lib/cimi/model/vsp.rb
 delete mode 100644 server/lib/cimi/model/vsp_collection.rb
 delete mode 100644 server/lib/cimi/model/vsp_configuration.rb
 delete mode 100644 server/lib/cimi/model/vsp_configuration_collection.rb
 delete mode 100644 server/lib/cimi/model/vsp_template.rb
 delete mode 100644 server/lib/cimi/model/vsp_template_collection.rb
 create mode 100644 server/lib/cimi/models.rb
 create mode 100644 server/lib/cimi/models/action.rb
 create mode 100644 server/lib/cimi/models/address.rb
 create mode 100644 server/lib/cimi/models/address_collection.rb
 create mode 100644 server/lib/cimi/models/address_template.rb
 create mode 100644 server/lib/cimi/models/address_template_collection.rb
 create mode 100644 server/lib/cimi/models/base.rb
 create mode 100644 server/lib/cimi/models/cloud_entry_point.rb
 create mode 100644 server/lib/cimi/models/entity_metadata.rb
 create mode 100644 server/lib/cimi/models/entity_metadata_collection.rb
 create mode 100644 server/lib/cimi/models/errors.rb
 create mode 100644 server/lib/cimi/models/machine.rb
 create mode 100644 server/lib/cimi/models/machine_admin.rb
 create mode 100644 server/lib/cimi/models/machine_admin_collection.rb
 create mode 100644 server/lib/cimi/models/machine_collection.rb
 create mode 100644 server/lib/cimi/models/machine_configuration.rb
 create mode 100644 server/lib/cimi/models/machine_configuration_collection.rb
 create mode 100644 server/lib/cimi/models/machine_image.rb
 create mode 100644 server/lib/cimi/models/machine_image_collection.rb
 create mode 100644 server/lib/cimi/models/machine_template.rb
 create mode 100644 server/lib/cimi/models/machine_template_collection.rb
 create mode 100644 server/lib/cimi/models/network.rb
 create mode 100644 server/lib/cimi/models/network_collection.rb
 create mode 100644 server/lib/cimi/models/network_configuration.rb
 create mode 100644 server/lib/cimi/models/network_configuration_collection.rb
 create mode 100644 server/lib/cimi/models/network_template.rb
 create mode 100644 server/lib/cimi/models/network_template_collection.rb
 create mode 100644 server/lib/cimi/models/routing_group.rb
 create mode 100644 server/lib/cimi/models/routing_group_collection.rb
 create mode 100644 server/lib/cimi/models/routing_group_template.rb
 create mode 100644 server/lib/cimi/models/routing_group_template_collection.rb
 create mode 100644 server/lib/cimi/models/schema.rb
 create mode 100644 server/lib/cimi/models/volume.rb
 create mode 100644 server/lib/cimi/models/volume_collection.rb
 create mode 100644 server/lib/cimi/models/volume_configuration.rb
 create mode 100644 server/lib/cimi/models/volume_configuration_collection.rb
 create mode 100644 server/lib/cimi/models/volume_image.rb
 create mode 100644 server/lib/cimi/models/volume_image_collection.rb
 create mode 100644 server/lib/cimi/models/volume_template.rb
 create mode 100644 server/lib/cimi/models/volume_template_collection.rb
 create mode 100644 server/lib/cimi/models/vsp.rb
 create mode 100644 server/lib/cimi/models/vsp_collection.rb
 create mode 100644 server/lib/cimi/models/vsp_configuration.rb
 create mode 100644 server/lib/cimi/models/vsp_configuration_collection.rb
 create mode 100644 server/lib/cimi/models/vsp_template.rb
 create mode 100644 server/lib/cimi/models/vsp_template_collection.rb
 delete mode 100644 server/lib/deltacloud/backend_capability.rb
 delete mode 100644 server/lib/deltacloud/base_driver.rb
 delete mode 100644 server/lib/deltacloud/base_driver/base_driver.rb
 delete mode 100644 server/lib/deltacloud/base_driver/exceptions.rb
 delete mode 100644 server/lib/deltacloud/base_driver/features.rb
 delete mode 100644 server/lib/deltacloud/base_driver/mock_driver.rb
 create mode 100644 server/lib/deltacloud/collections.rb
 create mode 100644 server/lib/deltacloud/collections/addresses.rb
 create mode 100644 server/lib/deltacloud/collections/buckets.rb
 create mode 100644 server/lib/deltacloud/collections/drivers.rb
 create mode 100644 server/lib/deltacloud/collections/firewalls.rb
 create mode 100644 server/lib/deltacloud/collections/hardware_profiles.rb
 create mode 100644 server/lib/deltacloud/collections/images.rb
 create mode 100644 server/lib/deltacloud/collections/instance_states.rb
 create mode 100644 server/lib/deltacloud/collections/instances.rb
 create mode 100644 server/lib/deltacloud/collections/keys.rb
 create mode 100644 server/lib/deltacloud/collections/load_balancers.rb
 create mode 100644 server/lib/deltacloud/collections/realms.rb
 create mode 100644 server/lib/deltacloud/collections/storage_snapshots.rb
 create mode 100644 server/lib/deltacloud/collections/storage_volumes.rb
 delete mode 100644 server/lib/deltacloud/core_ext.rb
 create mode 100644 server/lib/deltacloud/drivers/base_driver.rb
 delete mode 100644 server/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb
 create mode 100644 server/lib/deltacloud/drivers/exceptions.rb
 create mode 100644 server/lib/deltacloud/drivers/features.rb
 delete mode 100644 server/lib/deltacloud/hardware_profile.rb
 delete mode 100644 server/lib/deltacloud/helpers/application_helper.rb
 create mode 100644 server/lib/deltacloud/helpers/assets_helper.rb
 create mode 100644 server/lib/deltacloud/helpers/auth_helper.rb
 delete mode 100644 server/lib/deltacloud/helpers/blob_stream.rb
 delete mode 100644 server/lib/deltacloud/helpers/conversion_helper.rb
 create mode 100644 server/lib/deltacloud/helpers/deltacloud_helper.rb
 create mode 100644 server/lib/deltacloud/helpers/driver_helper.rb
 delete mode 100644 server/lib/deltacloud/helpers/hardware_profiles_helper.rb
 delete mode 100644 server/lib/deltacloud/helpers/json_helper.rb
 create mode 100644 server/lib/deltacloud/helpers/rabbit_helper.rb
 create mode 100644 server/lib/deltacloud/helpers/url_helper.rb
 delete mode 100644 server/lib/deltacloud/method_serializer.rb
 create mode 100644 server/lib/deltacloud/models/hardware_profile.rb
 create mode 100644 server/lib/deltacloud/models/state_machine.rb
 delete mode 100644 server/lib/deltacloud/runner.rb
 delete mode 100644 server/lib/deltacloud/state_machine.rb
 delete mode 100644 server/lib/deltacloud/validation.rb
 create mode 100644 server/lib/sinatra.rb
 delete mode 100644 server/lib/sinatra/lazy_auth.rb
 delete mode 100644 server/lib/sinatra/rabbit.rb
 delete mode 100644 server/lib/sinatra/rack_cimi.rb
 delete mode 100644 server/lib/sinatra/rack_runtime.rb
 delete mode 100644 server/lib/sinatra/rack_syslog.rb
 delete mode 100644 server/lib/sinatra/sinatra_verbose.rb
 delete mode 100644 server/lib/sinatra/static_assets.rb
 delete mode 100644 server/lib/sinatra/url_for.rb
 create mode 100644 server/tests/drivers/api/api_test.rb
 create mode 100644 server/tests/drivers/api/buckets_test.rb
 create mode 100644 server/tests/drivers/api/common.rb
 create mode 100644 server/tests/drivers/api/drivers_test.rb
 create mode 100644 server/tests/drivers/api/hardware_profiles_test.rb
 create mode 100644 server/tests/drivers/api/images_test.rb
 create mode 100644 server/tests/drivers/api/instances_test.rb
 create mode 100644 server/tests/drivers/api/keys_test.rb
 create mode 100644 server/tests/drivers/api/realms_test.rb
 create mode 100644 server/tests/drivers/api/storage_snapshots_test.rb
 create mode 100644 server/tests/drivers/api/storage_volumes_test.rb

diff --git a/server/Rakefile b/server/Rakefile
index 8543285..2a765b7 100644
--- a/server/Rakefile
+++ b/server/Rakefile
@@ -193,3 +193,73 @@ namespace :mock do
 
   end
 end
+
+namespace :rabbit do
+  load File.join(File.dirname(__FILE__), 'config.ru')
+
+  desc "List the routes defined by Rabbit"
+  task :routes do
+    Deltacloud.collections.each do |c|
+      puts "\033[1;32;m#{c.name}\33[0m"
+      c.operations.each do |o|
+        puts "\033[1;37m%6s\033[0m :%-10s %-30s (%s)" % [
+          o.http_method.to_s.upcase,
+          o.operation_name,
+          o.full_path,
+          o.description[0..100]
+        ]
+      end
+      unless c.collections.empty?
+        puts
+        c.collections.each do |s|
+          puts "\033[1;32;m#{s.name}\33[0m"
+          s.operations.each do |o|
+            puts "\033[1;37m%6s\033[0m :%-10s %-30s (%s)" % [
+              o.http_method.to_s.upcase,
+              o.operation_name,
+              o.full_path,
+              o.description[0..100]
+            ]
+          end
+        end
+      end
+      puts
+    end
+  end
+
+  Deltacloud.collections.each do |c|
+    desc "Show details for #{c.collection_name} collection"
+    task :"#{c.collection_name}" do
+      puts "\033[1;32;m#{c.name} -> #{c.collection_name}\33[0m"
+      puts
+      puts c.description
+      puts
+      puts "Features:\n\n"
+      c.features.each do |f|
+        puts "\033[1;36;m:%-12s \33[0m%s\33[0m" % [
+          f.name,
+          f.description
+        ]
+      end
+      puts
+    end
+    c.operations.each do |o|
+      desc "Show details for #{o.operation_name} operation on #{c.collection_name} collection"
+      task :"#{c.collection_name}:#{o.operation_name}" do
+        puts "\033[1;32;m#{o.name} -> #{o.full_path}\33[0m"
+        puts
+        puts "Parameters:\n\n"
+        o.params.each do |p|
+          puts "\033[1;36;m:%-12s\33[1;33;m %-12s \33[0m%s\33[0m" % [
+            p.name,
+            p.klass.to_s.capitalize + (p.required? ? "\33[1;31m*\33[0m\t  " : ''),
+            p.description
+         ]
+        end
+        puts
+      end
+    end
+  end
+
+end
+
diff --git a/server/config.ru b/server/config.ru
index a1f9efd..f17de43 100644
--- a/server/config.ru
+++ b/server/config.ru
@@ -14,14 +14,46 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-require 'rubygems'
+# The default URL prefix (where to mount Deltacloud API)
 
-$top_srcdir ||= File::expand_path(File.dirname(__FILE__))
+# The default driver is 'mock'
+ENV['API_DRIVER'] ||= 'mock'
 
-$:.unshift File.join($top_srcdir, 'lib')
+# Set the API frontend use ('cimi' or 'deltacloud', default is 'deltacloud')
+ENV['API_FRONTEND'] ||= 'deltacloud'
 
-server_dir = ENV['API_FRONTEND'] == 'cimi' ? 'cimi' : 'deltacloud'
+# We need to set different API version and entrypoint location
+if ENV['API_FRONTEND'] == 'deltacloud'
+  API_VERSION = "9.9.9"
+  API_ROOT_URL = "/api"
+elsif ENV['API_FRONTEND'] == 'cimi'
+  API_VERSION = "1.0.0"
+  API_ROOT_URL = "/cloudEntryPoint"
+end
 
-load File.join($top_srcdir, 'lib', server_dir, 'server.rb')
+#begin
+  require File.join(File.dirname(__FILE__), 'lib', ENV['API_FRONTEND'], 'server.rb')
+#rescue LoadError => e
+#  puts "[ERROR] The specified frontend (#{ENV['API_FRONTEND']}) not supported (#{e.message})"
+#  exit 1
+#end
 
-run Sinatra::Application
+if self.respond_to? :map
+  map "/" do
+    class IndexEntrypoint < Sinatra::Base
+      get "/" do
+        redirect API_ROOT_URL, 301
+      end
+    end
+    run IndexEntrypoint
+  end
+
+  map API_ROOT_URL do
+    use Rack::Static, :urls => ["/stylesheets", "/javascripts"], :root => "public"
+    use Rack::Session::Cookie
+    case ENV['API_FRONTEND']
+      when 'deltacloud' then run Rack::Cascade.new([Deltacloud::API])
+      when 'cimi' then run Rack::Cascade.new([CIMI::API])
+    end
+  end
+end
diff --git a/server/deltacloud-core.gemspec b/server/deltacloud-core.gemspec
index 55aa182..54d88cc 100644
--- a/server/deltacloud-core.gemspec
+++ b/server/deltacloud-core.gemspec
@@ -68,6 +68,7 @@ Gem::Specification.new do |s|
   s.add_dependency('rake', '>= 0.8.7')
   s.add_dependency('haml', '>= 2.2.17')
   s.add_dependency('sinatra', '>= 0.9.4')
+  s.add_dependency('sinatra-rabbit', '>= 1.0.5')
   s.add_dependency('rack', '>= 1.0.0')
   s.add_dependency('rack-accept')
   s.add_dependency('json', '>= 1.1.9')
diff --git a/server/lib/cimi/collections.rb b/server/lib/cimi/collections.rb
new file mode 100644
index 0000000..b675fc4
--- /dev/null
+++ b/server/lib/cimi/collections.rb
@@ -0,0 +1,58 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI
+
+  def self.collection_names
+    @collections.map { |c| c.collection_name }
+  end
+
+  def self.collections
+    @collections ||= []
+  end
+
+  module Collections
+
+    def self.collection(name)
+      CIMI.collections.find { |c| c.collection_name == name }
+    end
+
+    def self.cimi_modules
+      @cimi_modules ||= []
+    end
+
+    Dir[File.join(File::dirname(__FILE__), "collections", "*.rb")].each do |collection|
+      require collection
+      base_collection_name = File.basename(collection).gsub('.rb', '')
+      cimi_module_class = CIMI::Collections.const_get(base_collection_name.camelize)
+      cimi_modules << cimi_module_class
+      unless cimi_module_class.collections.nil?
+        cimi_module_class.collections.each do |c|
+          CIMI.collections << c
+        end
+      else
+        warn "WARNING: File %s placed in collections directory but does not have any collections defined" % base_collection_name
+      end
+    end
+
+    def self.included(klass)
+      klass.class_eval do
+        CIMI::Collections.cimi_modules.each { |c| use c }
+      end
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/address_templates.rb b/server/lib/cimi/collections/address_templates.rb
new file mode 100644
index 0000000..db59507
--- /dev/null
+++ b/server/lib/cimi/collections/address_templates.rb
@@ -0,0 +1,49 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class AddressTemplates < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+
+    collection :address_templates do
+
+      operation :index do
+        description 'List all AddressTemplates in the AddressTemplateCollection'
+        param :CIMISelect, :string, :optional
+        control do
+          address_templates = AddressTemplateCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml {address_templates.to_xml}
+            format.json {address_templates.to_json}
+          end
+        end
+      end
+
+      operation :show do
+        description 'Show a specific AddressTemplate'
+        control do
+          address_template = CIMI::Model::AddressTemplate.find(params[:id], self)
+          respond_to do |format|
+            format.xml {address_template.to_xml}
+            format.json {address_template.to_json}
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/addresses.rb b/server/lib/cimi/collections/addresses.rb
new file mode 100644
index 0000000..96871c1
--- /dev/null
+++ b/server/lib/cimi/collections/addresses.rb
@@ -0,0 +1,74 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class Addresses < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    collection :addresses do
+
+      description 'An Address represents an IP address, and its associated metdata, for a particular Network.'
+
+      operation :index do
+        description 'List all Addresses in the AddressCollection'
+        param :CIMISelect, :string, :optional
+        control do
+          addresses = AddressCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml {addresses.to_xml}
+            format.json {addresses.to_json}
+          end
+        end
+      end
+
+      operation :show do
+        description 'Show a specific Address'
+        control do
+          address = CIMI::Model::Address.find(params[:id], self)
+          respond_to do |format|
+            format.xml {address.to_xml}
+            format.json {address.to_json}
+          end
+        end
+      end
+
+      operation :create do
+        description "Create a new Address"
+        control do
+          if request.content_type.end_with?("json")
+            address = CIMI::Model::Address.create(request.body.read, self, :json)
+          else
+            address = CIMI::Model::Address.create(request.body.read, self, :xml)
+          end
+          respond_to do |format|
+            format.xml { address.to_xml }
+            format.json { address.to_json }
+          end
+        end
+      end
+
+      operation :destroy do
+        description "Delete a specified Address"
+        param :id, :string, :required
+        control do
+          CIMI::Model::Address.delete!(params[:id], self)
+          no_content_with_status(200)
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/cloud_entry_point.rb b/server/lib/cimi/collections/cloud_entry_point.rb
new file mode 100644
index 0000000..79454f3
--- /dev/null
+++ b/server/lib/cimi/collections/cloud_entry_point.rb
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class CloudEntryPoint < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+
+    collection  :cloudEntryPoint do
+      description 'Cloud entry point'
+      operation :index do
+        description "list all resources of the cloud"
+        control do
+          redirect API_ROOT_URL
+        end
+      end
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/entity_metadata.rb b/server/lib/cimi/collections/entity_metadata.rb
new file mode 100644
index 0000000..84e1fec
--- /dev/null
+++ b/server/lib/cimi/collections/entity_metadata.rb
@@ -0,0 +1,48 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class EntityMetadata < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+
+    collection :entity_metadata do
+
+      operation :index do
+        description "List all entity metadata defined for this provider"
+        control do
+          entity_metadata = CIMI::Model::EntityMetadataCollection.default(self)
+          respond_to do |format|
+            format.xml{entity_metadata.to_xml}
+            format.json{entity_metadata.to_json}
+          end
+        end
+      end
+
+      operation :show do
+        description "Get the entity metadata for a specific collection"
+        control do
+          entity_metadata = EntityMetadata.find(params[:id], self)
+          respond_to do |format|
+            format.xml{entity_metadata.to_xml}
+            format.json{entity_metadata.to_json}
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/machine_admins.rb b/server/lib/cimi/collections/machine_admins.rb
new file mode 100644
index 0000000..c413cc9
--- /dev/null
+++ b/server/lib/cimi/collections/machine_admins.rb
@@ -0,0 +1,74 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class MachineAdmins < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+
+    collection :machine_admins do
+      description 'Machine Admin entity'
+
+      operation :index do
+        description "List all machine admins"
+        param :CIMISelect,  :string,  :optional
+        control do
+          machine_admins = MachineAdminCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml { machine_admins.to_xml }
+            format.json { machine_admins.to_json }
+          end
+        end
+      end
+
+      operation :show do
+        description "Show specific machine admin"
+        control do
+          machine_admin = MachineAdmin.find(params[:id], self)
+          respond_to do |format|
+            format.xml { machine_admin.to_xml }
+            format.json { machine_admin.to_json }
+          end
+        end
+      end
+
+      operation :create do
+        description "Show specific machine admin"
+        control do
+          if request.content_type.end_with?("+json")
+            new_admin = MachineAdmin.create_from_json(request.body.read, self)
+          else
+            new_admin = MachineAdmin.create_from_xml(request.body.read, self)
+          end
+          status 201 # Created
+          respond_to do |format|
+            format.json { new_admin.to_json }
+            format.xml { new_admin.to_xml }
+          end
+        end
+      end
+
+      operation :delete do
+        description "Delete specified MachineAdmin entity"
+        control do
+          MachineAdmin.delete!(params[:id], self)
+          no_content_with_status(200)
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/machine_configurations.rb b/server/lib/cimi/collections/machine_configurations.rb
new file mode 100644
index 0000000..5b09e6a
--- /dev/null
+++ b/server/lib/cimi/collections/machine_configurations.rb
@@ -0,0 +1,49 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class MachineConfigurations < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+
+    collection :machine_configurations do
+      description 'List all machine configurations'
+
+      operation :index do
+        param :CIMISelect,  :string,  :optional
+        description "List all machine configurations"
+        control do
+          machine_configs = MachineConfigurationCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml { machine_configs.to_xml }
+            format.json { machine_configs.to_json }
+          end
+        end
+      end
+
+      operation :show do
+        control do
+          machine_conf = MachineConfiguration.find(params[:id], self)
+          respond_to do |format|
+            format.xml { machine_conf.to_xml }
+            format.json { machine_conf.to_json }
+          end
+        end
+
+      end
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/machine_images.rb b/server/lib/cimi/collections/machine_images.rb
new file mode 100644
index 0000000..1296279
--- /dev/null
+++ b/server/lib/cimi/collections/machine_images.rb
@@ -0,0 +1,50 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class MachineImages < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+
+    collection :machine_images do
+      description 'List all machine images'
+
+      operation :index do
+        description "List all machine configurations"
+        param :CIMISelect,  :string,  :optional
+        control do
+          machine_images = MachineImageCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml { machine_images.to_xml }
+            format.json { machine_images.to_json }
+          end
+        end
+      end
+
+      operation :show do
+        description "Show specific machine image."
+        control do
+          machine_image = MachineImage.find(params[:id], self)
+          respond_to do |format|
+            format.xml { machine_image.to_xml }
+            format.json { machine_image.to_json }
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/machines.rb b/server/lib/cimi/collections/machines.rb
new file mode 100644
index 0000000..0abf63a
--- /dev/null
+++ b/server/lib/cimi/collections/machines.rb
@@ -0,0 +1,157 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class Machines < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+
+    collection :machines do
+      description 'List all machine'
+
+      operation :index do
+        param :CIMISelect,  :string,  :optional
+        description "List all machines"
+        control do
+          machines = MachineCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml { machines.to_xml }
+            format.json { machines.to_json }
+          end
+        end
+      end
+
+      operation :show do
+        description "Show specific machine."
+        control do
+          machine = Machine.find(params[:id], self)
+          respond_to do |format|
+            format.xml { machine.to_xml }
+            format.json { machine.to_json }
+          end
+        end
+      end
+
+      operation :create do
+        description "Create a new Machine entity."
+        control do
+          if request.content_type.end_with?("+json")
+            new_machine = Machine.create_from_json(request.body.read, self)
+          else
+            new_machine = Machine.create_from_xml(request.body.read, self)
+          end
+          status 201 # Created
+          respond_to do |format|
+            format.json { new_machine.to_json }
+            format.xml { new_machine.to_xml }
+          end
+        end
+      end
+
+      operation :destroy do
+        description "Delete a specified machine."
+        param :id,          :string,    :required
+        control do
+          Machine.delete!(params[:id], self)
+          no_content_with_status(200)
+        end
+      end
+
+      action :stop do
+        description "Stop specific machine."
+        control do
+          machine = Machine.find(params[:id], self)
+          if request.content_type.end_with?("+json")
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          machine.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      operation :restart do
+        description "Start specific machine."
+        control do
+          machine = Machine.find(params[:id], self)
+          if request.content_type.end_with?("+json")
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          machine.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      operation :start do
+        description "Start specific machine."
+        control do
+          machine = Machine.find(params[:id], self)
+          if request.content_type.end_with?("+json")
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          machine.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      #NOTE: The routes for attach/detach used here are NOT as specified by CIMI
+      #will likely move later. CIMI specifies PUT of the whole Machine description
+      #with inclusion/ommission of the volumes you want [att|det]ached
+      action :attach_volume, :http_method => :put do
+        description "Attach CIMI Volume(s) to a machine."
+        control do
+          if request.content_type.end_with?("+json")
+            volumes_to_attach = Volume.find_to_attach_from_json(request.body.read, self)
+          else
+            volumes_to_attach = Volume.find_to_attach_from_xml(request.body.read, self)
+          end
+          machine = Machine.attach_volumes(volumes_to_attach, self)
+          respond_to do |format|
+            format.json{ machine.to_json}
+            format.xml{machine.to_xml}
+          end
+        end
+      end
+
+      action :detach_volume, :http_method => :put do
+        description "Detach CIMI Volume(s) from a machine."
+        control do
+          if request.content_type.end_with?("+json")
+            volumes_to_detach = Volume.find_to_attach_from_json(request.body.read, self)
+          else
+            volumes_to_detach = Volume.find_to_attach_from_xml(request.body.read, self)
+          end
+          machine = Machine.detach_volumes(volumes_to_detach, self)
+          respond_to do |format|
+            format.json{ machine.to_json}
+            format.xml{machine.to_xml}
+          end
+        end
+      end
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/network_configurations.rb b/server/lib/cimi/collections/network_configurations.rb
new file mode 100644
index 0000000..02452a8
--- /dev/null
+++ b/server/lib/cimi/collections/network_configurations.rb
@@ -0,0 +1,47 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class NetworkConfigurations < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    collection :network_configurations do
+
+      operation :index do
+        description 'List all NetworkConfigurations'
+        param :CIMISelect, :string, :optional
+        control do
+          network_configurations = NetworkConfigurationCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml { network_configurations.to_xml  }
+            format.json { network_configurations.to_json }
+          end
+        end
+      end
+
+      operation :show do
+        description 'Show a specific NetworkConfiguration'
+        control do
+          network_config = NetworkConfiguration.find(params[:id], self)
+          respond_to do |format|
+            format.xml { network_config.to_xml }
+            format.json { network_config.to_json }
+          end
+        end
+      end
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/network_templates.rb b/server/lib/cimi/collections/network_templates.rb
new file mode 100644
index 0000000..0ff82b2
--- /dev/null
+++ b/server/lib/cimi/collections/network_templates.rb
@@ -0,0 +1,48 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class NetworkTemplates < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    collection :network_templates do
+
+      operation :index do
+        description 'List all Network Templates in the NetworkTemplateCollection'
+        param :CIMISelect, :string, :optional
+        control do
+          network_templates = NetworkTemplateCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml {network_templates.to_xml}
+            format.json {network_templates.to_json}
+          end
+        end
+      end
+
+      operation :show do
+        description 'Show a specific Network Template'
+        control do
+          network_template = NetworkTemplate.find(params[:id], self)
+          respond_to do |format|
+            format.xml {network_template.to_xml}
+            format.json {network_template.to_json}
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/networks.rb b/server/lib/cimi/collections/networks.rb
new file mode 100644
index 0000000..0aa21e8
--- /dev/null
+++ b/server/lib/cimi/collections/networks.rb
@@ -0,0 +1,125 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class Networks < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+
+    collection :networks do
+      description 'A Network represents an abstraction of a layer 2 broadcast domain'
+
+      operation :index do
+        description "List all Networks"
+        param :CIMISelect,  :string,  :optional
+        control do
+          networks = NetworkCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml { networks.to_xml }
+            format.json { networks.to_json }
+          end
+        end
+      end
+
+      operation :show do
+        description "Show a specific Network"
+        control do
+          network = Network.find(params[:id], self)
+          respond_to do |format|
+            format.xml { network.to_xml }
+            format.json { network.to_json }
+          end
+        end
+      end
+
+      operation :create do
+        description "Create a new Network"
+        control do
+          if request.content_type.end_with?("json")
+            network = Network.create(request.body.read, self, :json)
+          else
+            network = Network.create(request.body.read, self, :xml)
+          end
+          respond_to do |format|
+            format.xml { network.to_xml}
+            format.json { network.to_json }
+          end
+        end
+      end
+
+      operation :destroy do
+        description "Delete a specified Network"
+        param :id, :string, :required
+        control do
+          Network.delete!(params[:id], self)
+          no_content_with_status(200)
+        end
+      end
+
+      action :start do
+        description "Start specific network."
+        control do
+          network = Network.find(params[:id], self)
+          report_error(404) unless network
+          if request.content_type.end_with?("json")
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          network.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      action :stop do
+        description "Stop specific network."
+        control do
+          network = Network.find(params[:id], self)
+          report_error(404) unless network
+          if request.content_type.end_with?("json")
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          network.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      action :suspend do
+        description "Suspend specific network."
+        control do
+          network = Network.find(params[:id], self)
+          report_error(404) unless network
+          if request.content_type.end_with?("json")
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          network.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/routing_group_templates.rb b/server/lib/cimi/collections/routing_group_templates.rb
new file mode 100644
index 0000000..995b1f8
--- /dev/null
+++ b/server/lib/cimi/collections/routing_group_templates.rb
@@ -0,0 +1,47 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class RoutingGroupTemplates < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    collection :routing_group_templates do
+
+      operation :index do
+        description 'List all RoutingGroupTemplates in the RoutingGroupTemplateCollection'
+        param :CIMISelect, :string, :optional
+        control do
+          routing_group_templates = RoutingGroupTemplateCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml {routing_group_templates.to_xml}
+            format.json {routing_group_templates.to_json}
+          end
+        end
+      end
+
+      operation :show do
+        description 'Show a specific RoutingGroupTemplate'
+        control do
+          routing_group_template = RoutingGroupTemplate.find(params[:id], self)
+          respond_to do |format|
+            format.xml {routing_group_template.to_xml}
+            format.json {routing_group_template.to_json}
+          end
+        end
+      end
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/routing_groups.rb b/server/lib/cimi/collections/routing_groups.rb
new file mode 100644
index 0000000..5e7ccc5
--- /dev/null
+++ b/server/lib/cimi/collections/routing_groups.rb
@@ -0,0 +1,48 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class RoutingGroups < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    collection :routing_groups do
+
+      operation :index do
+        description 'List all RoutingGroups in the RoutingGroupsCollection'
+        param :CIMISelect, :string, :optional
+        control do
+          routing_groups = RoutingGroupCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml {routing_groups.to_xml}
+            format.json {routing_groups.to_json}
+          end
+        end
+      end
+
+      operation :show do
+        description 'Show a specific RoutingGroup'
+        control do
+          routing_group = RoutingGroup.find(params[:id], self)
+          respond_to do |format|
+            format.xml {routing_group.to_xml}
+            format.json {routing_group.to_json}
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/volume_configurations.rb b/server/lib/cimi/collections/volume_configurations.rb
new file mode 100644
index 0000000..055e28c
--- /dev/null
+++ b/server/lib/cimi/collections/volume_configurations.rb
@@ -0,0 +1,48 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class VolumeConfigurations < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+
+    collection :volume_configurations do
+
+      operation :index do
+        description "Get list all VolumeConfigurations"
+        param :CIMISelect,  :string,  :optional
+        control do
+          volume_configuration = VolumeConfigurationCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml { volume_configuration.to_xml }
+            format.json { volume_configuration.to_json }
+          end
+        end
+      end
+
+      operation :show do
+        description "Get a specific VolumeConfiguration"
+        control do
+          volume_config = VolumeConfiguration.find(params[:id], self)
+          respond_to do |format|
+            format.xml { volume_config.to_xml }
+            format.json { volume_config.json }
+          end
+        end
+      end
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/volume_images.rb b/server/lib/cimi/collections/volume_images.rb
new file mode 100644
index 0000000..78432b1
--- /dev/null
+++ b/server/lib/cimi/collections/volume_images.rb
@@ -0,0 +1,50 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class VolumeImages < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+
+    collection :volume_images do
+      description 'This entity represents an image that could be place on a pre-loaded volume.'
+
+      operation :index do
+        description "List all volumes images"
+        param :CIMISelect,  :string,  :optional
+        control do
+          volume_images = VolumeImageCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml { volume_images.to_xml }
+            format.json { volume_images.to_json }
+          end
+        end
+      end
+
+      operation :show do
+        description "Show a specific volume image"
+        control do
+          volume_image = VolumeImage.find(params[:id], self)
+          respond_to do |format|
+            format.xml { volume_image.to_xml }
+            format.json { volume_image.to_json }
+          end
+        end
+      end
+    end
+
+
+  end
+end
diff --git a/server/lib/cimi/collections/volumes.rb b/server/lib/cimi/collections/volumes.rb
new file mode 100644
index 0000000..1c45c9e
--- /dev/null
+++ b/server/lib/cimi/collections/volumes.rb
@@ -0,0 +1,80 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class Volumes < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    collection :volumes do
+
+      operation :index do
+        description "List all volumes"
+        param :CIMISelect,  :string,  :optional
+        control do
+          volumes = VolumeCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml { volumes.to_xml }
+            format.json { volumes.to_json }
+          end
+        end
+      end
+
+      operation :show do
+        description "Show specific Volume."
+        control do
+          volume = Volume.find(params[:id], self)
+          if volume
+            respond_to do |format|
+              format.xml  { volume.to_xml  }
+              format.json { volume.to_json }
+            end
+          else
+            report_error(404)
+          end
+        end
+      end
+
+      operation :create do
+        description "Create a new Volume."
+        control do
+          content_type = (request.content_type.end_with?("+json") ? :json  : :xml)
+          #((request.content_type.end_with?("+xml")) ? :xml : report_error(415) ) FIXME
+          case content_type
+          when :json
+            new_volume = Volume.create_from_json(request.body.read, self)
+          when :xml
+            new_volume = Volume.create_from_xml(request.body.read, self)
+          end
+          respond_to do |format|
+            format.json { new_volume.to_json }
+            format.xml { new_volume.to_xml }
+          end
+        end
+      end
+
+      operation :destroy do
+        description "Delete a specified Volume"
+        param :id, :string, :required
+        control do
+          Volume.delete!(params[:id], self)
+          no_content_with_status(200)
+        end
+      end
+
+    end
+
+
+  end
+end
diff --git a/server/lib/cimi/collections/vsp_configurations.rb b/server/lib/cimi/collections/vsp_configurations.rb
new file mode 100644
index 0000000..31acceb
--- /dev/null
+++ b/server/lib/cimi/collections/vsp_configurations.rb
@@ -0,0 +1,48 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class VspConfigurations < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    collection :vsp_configurations do
+
+      operation :index do
+        description 'List all VSPConfigurations in the VSPConfigurationCollection'
+        param :CIMISelect, :string, :optional
+        control do
+          vsp_configs = VSPConfigurationCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml {vsp_configs.to_xml}
+            format.json {vsp_configs.to_json}
+          end
+        end
+      end
+
+      operation :show do
+        description 'Show a specific VSPConfiguration'
+        control do
+          vsp_config = VSPConfiguration.find(params[:id], self)
+          respond_to do |format|
+            format.xml {vsp_config.to_xml}
+            format.json {vsp_config.to_json}
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/vsp_templates.rb b/server/lib/cimi/collections/vsp_templates.rb
new file mode 100644
index 0000000..503de50
--- /dev/null
+++ b/server/lib/cimi/collections/vsp_templates.rb
@@ -0,0 +1,50 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class VspTemplates < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    collection :vsp_templates do
+
+      description 'The VSP Template is a set of Configuration values for realizing a VSP. A VSP Template may be used to create multiple VSPs'
+
+      operation :index do
+        description 'List all VSPTemplates in the VSPTemplateCollection'
+        param :CIMISelect, :string, :optional
+        control do
+          vsp_templates = VSPTemplateCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml {vsp_templates.to_xml}
+            format.json {vsp_templates.to_json}
+          end
+        end
+      end
+
+      operation :show do
+        description 'Show a specific VSPTemplate'
+        control do
+          vsp_template = VSPTemplate.find(params[:id], self)
+          respond_to do |format|
+            format.xml {vsp_template.to_xml}
+            format.json {vsp_template.to_json}
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/vsps.rb b/server/lib/cimi/collections/vsps.rb
new file mode 100644
index 0000000..52b1a5a
--- /dev/null
+++ b/server/lib/cimi/collections/vsps.rb
@@ -0,0 +1,108 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class Vsps < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    collection :vsps do
+
+      description 'A VSP represents the connection parameters of a network port'
+
+      operation :index do
+        description 'List all VSPs in the VSPCollection'
+        param :CIMISelect, :string, :optional
+        control do
+          vsps = VSPCollection.default(self).filter_by(params[:CIMISelect])
+          respond_to do |format|
+            format.xml {vsps.to_xml}
+            format.json {vsps.to_json}
+          end
+        end
+      end
+
+      operation :show do
+        description 'Show a specific VSP'
+        control do
+          vsp = VSP.find(params[:id], self)
+          respond_to do |format|
+            format.xml {vsp.to_xml}
+            format.json {vsp.to_json}
+          end
+        end
+      end
+
+      operation :create do
+        description "Create a new VSP"
+        control do
+          if request.content_type.end_with?("json")
+            vsp = CIMI::Model::VSP.create(request.body.read, self, :json)
+          else
+            vsp = CIMI::Model::VSP.create(request.body.read, self, :xml)
+          end
+          respond_to do |format|
+            format.xml { vsp.to_xml }
+            format.json { vsp.to_json }
+          end
+        end
+      end
+
+      operation :destroy do
+        description "Delete a specified VSP"
+        control do
+          CIMI::Model::VSP.delete!(params[:id], self)
+          no_content_with_status(200)
+        end
+      end
+
+      action :start do
+        description "Start specific VSP."
+        param :id,          :string,    :required
+        control do
+          vsp = VSP.find(params[:id], self)
+          report_error(404) unless vsp
+          if request.content_type.end_with?("json")
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          vsp.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      action :stop do
+        description "Stop specific VSP."
+        control do
+          vsp = VSP.find(params[:id], self)
+          report_error(404) unless vsp
+          if request.content_type.end_with?("json")
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          vsp.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/helpers.rb b/server/lib/cimi/helpers.rb
new file mode 100644
index 0000000..4535c39
--- /dev/null
+++ b/server/lib/cimi/helpers.rb
@@ -0,0 +1,104 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud; end
+module CIMI; end
+
+require_relative '../deltacloud/drivers'
+require_relative '../deltacloud/models'
+require_relative '../deltacloud/helpers/driver_helper'
+require_relative '../deltacloud/helpers/auth_helper'
+require_relative '../deltacloud/helpers/url_helper'
+require_relative '../deltacloud/helpers/assets_helper'
+require_relative '../deltacloud/helpers/deltacloud_helper'
+require_relative '../deltacloud/helpers/rabbit_helper'
+require_relative '../deltacloud/helpers/rabbit_helper'
+require_relative '../deltacloud/core_ext/string'
+require_relative '../deltacloud/core_ext/array'
+require_relative '../deltacloud/core_ext/hash'
+require_relative '../deltacloud/core_ext/integer'
+require_relative '../deltacloud/core_ext/proc'
+require_relative './helpers/cimi_helper'
+require_relative './models'
+
+module CIMI::Collections
+  class Base < Sinatra::Base
+
+    extend Deltacloud::Helpers::Drivers
+    include Sinatra::Rabbit::Features
+    include CIMI::Model
+
+    helpers Deltacloud::Helpers::Drivers
+    helpers Sinatra::AuthHelper
+    helpers Sinatra::UrlForHelper
+    helpers Sinatra::StaticAssets::Helpers
+    helpers Rack::RespondTo::Helpers
+    helpers Deltacloud::Helpers::Application
+
+    register Rack::RespondTo
+
+    enable :xhtml
+    enable :dump_errors
+    enable :show_errors
+    disable :show_exceptions
+
+    set :root_url, API_ROOT_URL
+    set :version, API_VERSION
+    set :root, File.join(File.dirname(__FILE__), '..', '..')
+    set :views, root + '/views/cimi'
+    set :public_folder, root + '/public'
+
+    error do
+      report_error
+    end
+
+    error Deltacloud::ExceptionHandler::ValidationFailure do
+      report_error
+    end
+
+    before do
+      # Respond with 400, If we don't get a http Host header,
+      halt 400, "Unable to find HTTP Host header" if @env['HTTP_HOST'] == nil
+    end
+
+    after do
+      headers 'X-CIMI-Specification-Version' => API_VERSION
+    end
+
+    def self.new_route_for(route, &block)
+      get route_for('/' + route.to_s + '/new') do
+        instance_eval(&block) if block_given?
+        respond_to do |format|
+          format.html do
+            haml :"#{route}/new"
+          end
+        end
+      end
+    end
+
+    def self.check_capability(opts={})
+      Sinatra::Rabbit.set :check_capability, opts[:for]
+    end
+
+    def self.check_features(opts={})
+      Sinatra::Rabbit.set :check_features, opts[:for]
+    end
+
+    def self.route_for(url)
+      "#{settings.root_url}#{url}"
+    end
+
+  end
+end
diff --git a/server/lib/cimi/helpers/cimi_helper.rb b/server/lib/cimi/helpers/cimi_helper.rb
index b3f3493..e48fa8e 100644
--- a/server/lib/cimi/helpers/cimi_helper.rb
+++ b/server/lib/cimi/helpers/cimi_helper.rb
@@ -28,8 +28,6 @@ module CIMIHelper
 
 end
 
-helpers CIMIHelper
-
 class Array
   def to_xml_cimi_collection(_self)
     model_name = first.class.xml_tag_name
diff --git a/server/lib/cimi/model.rb b/server/lib/cimi/model.rb
deleted file mode 100644
index fa3c771..0000000
--- a/server/lib/cimi/model.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-
-# Declare namespace for CIMI model
-#
-module CIMI
-  module Model; end
-end
-
-require 'cimi/model/schema'
-require 'cimi/model/base'
-require 'cimi/model/errors'
-require 'cimi/model/cloud_entry_point'
-require 'cimi/model/machine_template'
-require 'cimi/model/machine_image'
-require 'cimi/model/machine_configuration'
-require 'cimi/model/action'
-require 'cimi/model/machine'
-require 'cimi/model/volume'
-require 'cimi/model/machine_admin'
-require 'cimi/model/volume_configuration'
-require 'cimi/model/volume_image'
-require 'cimi/model/volume_template'
-require 'cimi/model/machine_template_collection'
-require 'cimi/model/machine_image_collection'
-require 'cimi/model/machine_configuration_collection'
-require 'cimi/model/machine_collection'
-require 'cimi/model/volume_collection'
-require 'cimi/model/machine_admin_collection'
-require 'cimi/model/volume_configuration_collection'
-require 'cimi/model/volume_image_collection'
-require 'cimi/model/volume_template_collection'
-require 'cimi/model/entity_metadata'
-require 'cimi/model/entity_metadata_collection'
-require 'cimi/model/network'
-require 'cimi/model/network_collection'
-require 'cimi/model/network_configuration'
-require 'cimi/model/network_configuration_collection'
-require 'cimi/model/network_template'
-require 'cimi/model/network_template_collection'
-require 'cimi/model/routing_group'
-require 'cimi/model/routing_group_collection'
-require 'cimi/model/routing_group_template'
-require 'cimi/model/routing_group_template_collection'
-require 'cimi/model/vsp'
-require 'cimi/model/vsp_collection'
-require 'cimi/model/vsp_configuration'
-require 'cimi/model/vsp_configuration_collection'
-require 'cimi/model/vsp_template'
-require 'cimi/model/vsp_template_collection'
-require 'cimi/model/address'
-require 'cimi/model/address_collection'
-require 'cimi/model/address_template'
-require 'cimi/model/address_template_collection'
diff --git a/server/lib/cimi/model/action.rb b/server/lib/cimi/model/action.rb
deleted file mode 100644
index c1c9908..0000000
--- a/server/lib/cimi/model/action.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::Action < CIMI::Model::Base
-
-  text :action
-
-  def name
-    action.split('/').last.strip.intern
-  end
-
-end
diff --git a/server/lib/cimi/model/address.rb b/server/lib/cimi/model/address.rb
deleted file mode 100644
index 8838331..0000000
--- a/server/lib/cimi/model/address.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::Address < CIMI::Model::Base
-
-  text :ip
-
-  text :hostname
-
-  text :allocation
-
-  text :default_gateway
-
-  text :dns
-
-  text :mac_address
-
-  text :protocol
-
-  text :mask
-
-  href :network
-
-  href :resource
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    if id==:all
-      context.driver.addresses(context.credentials, {:env=>context})
-    else
-      context.driver.addresses(context.credentials, {:id=>id, :env=>context})
-    end
-  end
-
-  def self.create(request_body, context, type)
-    input = (type == :xml)? XmlSimple.xml_in(request_body, {"ForceArray"=>false, "NormaliseSpace"=>2}) : JSON.parse(request_body)
-    if input["addressTemplate"]["href"] #by reference
-      address_template = AddressTemplate.find(context.href_id(input["addressTemplate"]["href"], :address_templates), context)
-    else
-      case type
-        when :json
-          address_template = AddressTemplate.from_json(JSON.generate(input["addressTemplate"]))
-        when :xml
-          xml = XmlSimple.xml_in(request_body, {"NormaliseSpace"=>2})
-          address_template = AddressTemplate.from_xml(XmlSimple.xml_out(xml["addressTemplate"][0]))
-      end
-    end
-    params = {:name=>input["name"], :description=>input["description"], :address_template=>address_template, :env=>context }
-    raise CIMI::Model::BadRequest.new("Bad request - missing required parameters. Client sent: #{request_body} which produced #{params.inspect}")  if params.has_value?(nil)
-    context.driver.create_address(context.credentials, params)
-  end
-
-  def self.delete!(id, context)
-    context.driver.delete_address(context.credentials, id)
-  end
-
-end
diff --git a/server/lib/cimi/model/address_collection.rb b/server/lib/cimi/model/address_collection.rb
deleted file mode 100644
index eef6c51..0000000
--- a/server/lib/cimi/model/address_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::AddressCollection < CIMI::Model::Base
-
-  act_as_root_entity :address
-
-  array :addresses do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.addresses_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} AddressCollection",
-      :addresses => CIMI::Model::Address.all(context).map { |addr| { :href => addr.id } }
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/address_template.rb b/server/lib/cimi/model/address_template.rb
deleted file mode 100644
index 9d2c409..0000000
--- a/server/lib/cimi/model/address_template.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::AddressTemplate < CIMI::Model::Base
-
-  text :ip
-
-  text :hostname
-
-  text :allocation
-
-  text :default_gateway
-
-  text :dns
-
-  text :mac_address
-
-  text :protocol
-
-  text :mask
-
-  href :network
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    if id==:all
-      context.driver.address_templates(context.credentials, {:env=>context})
-    else
-      context.driver.address_templates(context.credentials, {:id=>id, :env=>context})
-    end
-  end
-
-  def self.create(request_body, context, type)
-  end
-
-  def self.delete!(id, context)
-  end
-
-end
diff --git a/server/lib/cimi/model/address_template_collection.rb b/server/lib/cimi/model/address_template_collection.rb
deleted file mode 100644
index e973252..0000000
--- a/server/lib/cimi/model/address_template_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::AddressTemplateCollection < CIMI::Model::Base
-
-  act_as_root_entity :address_template
-
-  array :address_templates do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.address_templates_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} AddressTemplateCollection",
-      :address_templates => AddressTemplate.all(context).map { |addr| { :href => addr.id } }
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/base.rb b/server/lib/cimi/model/base.rb
deleted file mode 100644
index 16812ac..0000000
--- a/server/lib/cimi/model/base.rb
+++ /dev/null
@@ -1,249 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'xmlsimple'
-require 'json'
-
-# The base class for any CIMI object that we either read from a request or
-# write as a response. This class handles serializing/deserializing XML and
-# JSON into a common form.
-#
-# == Defining the schema
-#
-# The conversion of XML and JSON into internal objects is based on a schema
-# that is defined through a DSL:
-#
-#   class Machine < CIMI::Model::Base
-#     text :status
-#     href :meter
-#     array :volumes do
-#       scalar :href, :attachment_point, :protocol
-#     end
-#   end
-#
-# The DSL automatically takes care of converting identifiers from their
-# underscored form to the camel-cased form used by CIMI. The above class
-# can be used in the following way:
-#
-#   machine = Machine.from_xml(some_xml)
-#   if machine.status == "UP"
-#     ...
-#   end
-#   sda = machine.volumes.find { |v| v.attachment_point == "/dev/sda" }
-#   handle_meter(machine.meter.href)
-#
-# The keywords for the DSL are
-#   [scalar(names, ...)]
-#     Define a scalar attribute; in JSON, this is represented as a string
-#     property. In XML, this can be represented in a number of ways,
-#     depending on whether the option :text is set:
-#       * :text not set: attribute on the enclosing element
-#       * :text == :direct: the text content of the enclosing element
-#       * :text == :nested: the text content of an element +<name>...</name>+
-#   [text(names)]
-#     A shorthand for +scalar(names, :text => :nested)+, i.e., for
-#     attributes that in XML are represented by their own tags
-#   [href(name)]
-#     A shorthand for +struct name { scalar :href }+; in JSON, this is
-#     represented as +{ name: { "href": string } }+, and in XML as +<name
-#     href="..."/>+
-#   [struct(name, opts, &block)]
-#     A structured subobject; the block defines the schema of the
-#     subobject. The +:content+ option can be used to specify the attribute
-#     that should receive the content of hte corresponding XML element
-#   [array(name, opts, &block)]
-#     An array of structured subobjects; the block defines the schema of
-#     the subobjects.
-
-module CIMI::Model
-
-  def self.register_as_root_entity!(name)
-    @root_entities ||= []
-    @root_entities << name
-    unless CIMI::Model::CloudEntryPoint.href_defined?(name)
-      CIMI::Model::CloudEntryPoint.send(:href, name.underscore)
-    end
-  end
-
-  def self.root_entities
-    @root_entities || []
-  end
-
-end
-
-class CIMI::Model::Base
-
-  #
-  # We keep the values of the attributes in a hash
-  #
-  attr_reader :attribute_values
-
-  # Keep the list of all attributes in an array +attributes+; for each
-  # attribute, we also define a getter and a setter to access/change the
-  # value for that attribute
-  class << self
-    def base_schema
-      @schema ||= CIMI::Model::Schema.new
-    end
-
-    def clone_base_schema
-      @schema_duped = true
-      @schema = Marshal::load(Marshal.dump(superclass.base_schema))
-    end
-
-    def base_schema_cloned?
-      @schema_duped
-    end
-
-    private :'clone_base_schema', :'base_schema_cloned?'
-
-    def inherited(child)
-      child.instance_eval do
-        def schema
-          base_schema_cloned? ? @schema : clone_base_schema
-        end
-      end
-    end
-
-    def add_attributes!(names, attr_klass, &block)
-      if self.respond_to? :schema
-        schema.add_attributes!(names, attr_klass, &block)
-      else
-        base_schema.add_attributes!(names, attr_klass, &block)
-      end
-      names.each do |name|
-        define_method(name) { @attribute_values[name] }
-        define_method(:"#{name}=") { |newval| @attribute_values[name] = newval }
-      end
-    end
-
-    # Return Array of links to current CIMI object
-    def all_uri(context)
-      self.all(context).map { |e| { :href => e.id } }
-    end
-  end
-
-  extend CIMI::Model::Schema::DSL
-
-  def [](a)
-    @attribute_values[a]
-  end
-
-  def []=(a, v)
-    @attribute_values[a] = v
-  end
-
-  #
-  # Factory methods
-  #
-  def initialize(values = {})
-    @attribute_values = values
-  end
-
-  # Construct a new object from the XML representation +xml+
-  def self.from_xml(text)
-    xml = XmlSimple.xml_in(text, :force_content => true)
-    model = self.new
-    @schema.from_xml(xml, model)
-    model
-  end
-
-  # Construct a new object
-  def self.from_json(text)
-    json = JSON::parse(text)
-    model = self.new
-    @schema.from_json(json, model)
-    model
-  end
-
-  #
-  # Serialize
-  #
-
-  def self.xml_tag_name
-    self.name.split("::").last
-  end
-
-  def self.to_json(model)
-    JSON::unparse(@schema.to_json(model))
-  end
-
-  def self.to_xml(model)
-    xml = @schema.to_xml(model)
-    xml["xmlns"] = "http://www.dmtf.org/cimi"
-    XmlSimple.xml_out(xml, :root_name => xml_tag_name)
-  end
-
-  def to_json
-    self.class.to_json(self)
-  end
-
-  def to_xml
-    self.class.to_xml(self)
-  end
-
-  #
-  # Common attributes for all resources
-  #
-  text :id, :name, :description, :created
-
-  # FIXME: this doesn't match with JSON
-  hash :property, :content => :value do
-    scalar :name
-  end
-
-  def self.act_as_root_entity(name=nil)
-    if name
-      name = name.to_s.camelize.pluralize
-    else
-      name = xml_tag_name.pluralize.uncapitalize
-    end
-    CIMI::Model.register_as_root_entity! name
-  end
-
-  def self.all(_self); find(:all, _self); end
-
-  def filter_by(filter_opts)
-    return self if filter_opts.nil?
-    return filter_attributes(filter_opts.split(',').map{ |a| a.intern }) if filter_opts.include? ','
-    case filter_opts
-      when /^([\w\_]+)$/ then filter_attributes([$1.intern])
-      when /^([\w\_]+)\[(\d+\-\d+)\]$/ then filter_by_arr_range($1.intern, $2)
-      when /^([\w\_]+)\[(\d+)\]$/ then filter_by_arr_index($1.intern, $2)
-      else self
-    end
-  end
-
-  private
-
-  def filter_attributes(attr_list)
-    attrs = attr_list.inject({}) do |result, attr|
-      result[attr] = self.send(attr) if self.respond_to?(attr)
-      result
-    end
-    self.class.new(attrs)
-  end
-
-  def filter_by_arr_index(attr, filter)
-    return self unless self.respond_to?(attr)
-    self.class.new(attr => [self.send(attr)[filter.to_i]])
-  end
-
-  def filter_by_arr_range(attr, filter)
-    return self unless self.respond_to?(attr)
-    filter = filter.split('-').inject { |s,e| s.to_i..e.to_i }
-    self.class.new(attr => self.send(attr)[filter])
-  end
-end
diff --git a/server/lib/cimi/model/cloud_entry_point.rb b/server/lib/cimi/model/cloud_entry_point.rb
deleted file mode 100644
index 5db94df..0000000
--- a/server/lib/cimi/model/cloud_entry_point.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::CloudEntryPoint < CIMI::Model::Base
-
-  array :entity_metadata do
-    scalar :href
-  end
-
-  def self.create(context)
-    self.new(entities(context).merge({
-      :name => context.driver.name,
-      :description => "Cloud Entry Point for the Deltacloud #{context.driver.name} driver",
-      :id => context.cloudEntryPoint_url,
-      :created => Time.now,
-      :entity_metadata => EntityMetadata.all_uri(context)
-    }))
-  end
-
-  # Return an Hash of the CIMI root entities used in CloudEntryPoint
-  def self.entities(context)
-    CIMI::Model.root_entities.inject({}) do |result, entity|
-      if context.respond_to? :"#{entity.underscore}_url"
-        result[entity.underscore] = { :href => context.send(:"#{entity.underscore}_url") }
-      end
-      result
-    end
-  end
-
-  private
-
-  def self.href_defined?(entity)
-    true if schema.attribute_names.include? entity.underscore
-  end
-
-end
diff --git a/server/lib/cimi/model/entity_metadata.rb b/server/lib/cimi/model/entity_metadata.rb
deleted file mode 100644
index bc20ff3..0000000
--- a/server/lib/cimi/model/entity_metadata.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-
-class CIMI::Model::EntityMetadata < CIMI::Model::Base
-
-text :type_uri
-
-  array :attributes do
-    scalar :name
-    scalar :namespace
-    scalar :type
-    scalar :required
-    scalar :constraints
-  end
-
-  array :operations do
-    scalar :name
-    scalar :uri
-    scalar :description
-    scalar :method
-    scalar :input_message
-    scalar :output_message
-  end
-
-  def self.find(id, context)
-    entity_metadata = []
-    if id == :all
-      CIMI::Model.root_entities.each do |entity|
-        entity_class = CIMI::Model.const_get("#{entity.singularize}")
-        entity_metadata << entity_class.create_entity_metadata(context) if entity_class.respond_to?(:create_entity_metadata)
-      end
-      return entity_metadata
-    else
-      entity_class = CIMI::Model.const_get("#{id.camelize}")
-      if entity_class.respond_to?(:create_entity_metadata)
-        entity_class.create_entity_metadata(context)
-      end
-    end
-  end
-
-  def self.metadata_from_deltacloud_features(cimi_entity, dcloud_entity, context)
-    deltacloud_features = context.driver.features(dcloud_entity)
-    metadata_attributes = deltacloud_features.map{|f| attributes_from_feature(f)}
-    from_feature(cimi_entity, context, metadata_attributes.flatten!)
-  end
-
-  def includes_attribute?(attribute)
-    self.attributes.any?{|attr| attr[:name] == attribute}
-  end
-
-  private
-
-  def self.attributes_from_feature(feature)
-    feature.operations.first.params.inject([]) do |result, param|
-      result << {
-        :name=>(feature.name == :user_name ? :name : param[0]),
-        :type=> "xs:string",
-        :required=> (param[1] and param[1].optional?) ? "false" : "true",
-        :constraints=> (feature.constraints.empty? ? (feature.description.nil? ? "" : feature.description): feature.constraints)
-      }
-    end
-  end
-
-  def self.from_feature(cimi_entity, context, metadata_attributes)
-    self.new(:name => cimi_entity, :uri=>"#{context.entity_metadata_url}/#{cimi_entity.underscore}",
-             :type_uri=> context.send("#{cimi_entity.pluralize.underscore}_url"),
-             :attributes => metadata_attributes)
-  end
-
-end
diff --git a/server/lib/cimi/model/entity_metadata_collection.rb b/server/lib/cimi/model/entity_metadata_collection.rb
deleted file mode 100644
index 63db7f7..0000000
--- a/server/lib/cimi/model/entity_metadata_collection.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::EntityMetadataCollection < CIMI::Model::Base
-
-  array :entity_metadata do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.entity_metadata_url,
-      :name => 'default',
-      :created => Time.now,
-      :entity_metadata => EntityMetadata.all_uri(context)
-   )
-  end
-
-end
diff --git a/server/lib/cimi/model/errors.rb b/server/lib/cimi/model/errors.rb
deleted file mode 100644
index 7c090ed..0000000
--- a/server/lib/cimi/model/errors.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-module CIMI::Model
-
-  class NotFound < StandardError
-    attr_accessor :code
-
-    def initialize
-      super("Requested Entity Not Found")
-      self.code = 404
-    end
-
-  end
-
-  class BadRequest < StandardError
-    attr_accessor :code
-    def initialize(msg="")
-      super(msg)
-      self.code=400
-    end
-  end
-
-  class NotImplemented < StandardError
-    attr_accessor :code
-
-    def initialize
-      super("Requested operation is not implemented by backend provider")
-      self.code = 501
-    end
-
-  end
-
-end
-
-
diff --git a/server/lib/cimi/model/machine.rb b/server/lib/cimi/model/machine.rb
deleted file mode 100644
index 939629a..0000000
--- a/server/lib/cimi/model/machine.rb
+++ /dev/null
@@ -1,229 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'deltacloud/models/instance_address'
-
-class CIMI::Model::Machine < CIMI::Model::Base
-
-  text :state
-  text :cpu
-
-  struct :memory do
-    scalar :quantity
-    scalar :units
-  end
-
-  href :event_log
-
-  array :disks do
-    struct :capacity do
-      scalar :quantity
-      scalar :units
-    end
-    scalar :format
-    scalar :attachment_point
-  end
-
-  array :volumes do
-    scalar :href
-    scalar :protocol
-    scalar :attachment_point
-  end
-
-  array :network_interfaces do
-    href :vsp
-    text :hostname, :mac_address, :state, :protocol, :allocation
-    text :address, :default_gateway, :dns, :max_transmission_unit
-  end
-
-  array :meters do
-    scalar :href
-  end
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    instances = []
-    if id == :all
-      instances = context.driver.instances(context.credentials)
-      instances.map { |instance| from_instance(instance, context) }.compact
-    else
-      instance = context.driver.instance(context.credentials, :id => id)
-      raise CIMI::Model::NotFound unless instance
-      from_instance(instance, context)
-    end
-  end
-
-  def self.create_from_json(body, context)
-    json = JSON.parse(body)
-    hardware_profile_id = xml['machineTemplate']['machineConfig']["href"].split('/').last
-    image_id = xml['machineTemplate']['machineImage']["href"].split('/').last
-    instance = context.create_instance(context.credentials, image_id, { :hwp_id => hardware_profile_id })
-    from_instance(instance, context)
-  end
-
-  def self.create_from_xml(body, context)
-    xml = XmlSimple.xml_in(body)
-    machine_template = xml['machineTemplate'][0]
-    hardware_profile_id = machine_template['machineConfig'][0]["href"].split('/').last
-    image_id = machine_template['machineImage'][0]["href"].split('/').last
-    additional_params = {}
-    additional_params[:name] =xml['name'][0] if xml['name']
-    if machine_template.has_key? 'machineAdmin'
-      additional_params[:keyname] = machine_template['machineAdmin'][0]["href"].split('/').last
-    end
-    instance = context.driver.create_instance(context.credentials, image_id, {
-      :hwp_id => hardware_profile_id
-    }.merge(additional_params))
-    from_instance(instance, context)
-  end
-
-  def perform(action, context, &block)
-    begin
-      if context.driver.send(:"#{action.name}_instance", context.credentials, self.name)
-        block.callback :success
-      else
-        raise "Operation failed to execute on given Machine"
-      end
-    rescue => e
-      block.callback :failure, e.message
-    end
-  end
-
-  def self.delete!(id, context)
-    context.driver.destroy_instance(context.credentials, id)
-  end
-
-  def self.create_entity_metadata(context)
-    cimi_entity = self.name.split("::").last
-    metadata = EntityMetadata.metadata_from_deltacloud_features(cimi_entity, :instances, context)
-    unless metadata.includes_attribute?(:name)
-      metadata.attributes << {:name=>"name", :required=>"false",
-                   :constraints=>"Determined by the cloud provider", :type=>"xs:string"}
-    end
-    metadata
-  end
-
-  def self.attach_volumes(volumes, context)
-    volumes.each do |vol|
-      context.driver.attach_storage_volume(context.credentials,
-      {:id=>vol[:volume].name, :instance_id=>context.params[:id], :device=>vol[:attachment_point]})
-    end
-    self.find(context.params[:id], context)
-  end
-
-  def self.detach_volumes(volumes, context)
-    volumes.each do |vol|
-      context.driver.detach_storage_volume(context.credentials, {:id=>vol[:volume].name, :instance_id => context.params[:id]})
-    end
-    self.find(context.params[:id], context)
-  end
-
-  private
-
-  def self.from_instance(instance, context)
-    cpu =  memory = disks = (instance.instance_profile.id == "opaque")? "n/a" : nil
-    self.new(
-      :name => instance.id,
-      :description => instance.name,
-      :created => instance.launch_time,
-      :id => context.machine_url(instance.id),
-      :state => convert_instance_state(instance.state),
-      :cpu => cpu || convert_instance_cpu(instance.instance_profile, context),
-      :memory => memory || convert_instance_memory(instance.instance_profile, context),
-      :disks => disks || convert_instance_storage(instance.instance_profile, context),
-      :network_interfaces => convert_instance_addresses(instance),
-      :operations => convert_instance_actions(instance, context),
-      :volumes=>convert_storage_volumes(instance, context),
-      :property => convert_instance_properties(instance, context)
-    )
-  end
-
-  # FIXME: This will convert 'RUNNING' state to 'STARTED'
-  # which is defined in CIMI (p65)
-  #
-  def self.convert_instance_state(state)
-    ('RUNNING' == state) ? 'STARTED' : state
-  end
-
-  def self.convert_instance_properties(instance, context)
-    properties = []
-    properties << { :name => :machine_image, :value => context.machine_image_url(instance.image_id) }
-    if instance.respond_to? :keyname
-      properties << { :name => :machine_admin, :value => context.machine_admin_url(instance.keyname) }
-    end
-    properties
-  end
-
-  def self.convert_instance_cpu(profile, context)
-    cpu_override = profile.overrides.find { |p, v| p == :cpu }
-    if cpu_override.nil?
-      MachineConfiguration.find(profile.id, context).cpu
-    else
-      cpu_override[1]
-    end
-  end
-
-  def self.convert_instance_memory(profile, context)
-    machine_conf = MachineConfiguration.find(profile.name, context)
-    memory_override = profile.overrides.find { |p, v| p == :memory }
-    {
-      :quantity => memory_override.nil? ? machine_conf.memory[:quantity] : memory_override[1],
-      :units => machine_conf.memory[:units]
-    }
-  end
-
-  def self.convert_instance_storage(profile, context)
-    machine_conf = MachineConfiguration.find(profile.name, context)
-    storage_override = profile.overrides.find { |p, v| p == :storage }
-    [
-      { :capacity => {
-          :quantity => storage_override.nil? ? machine_conf.disks.first[:capacity][:quantity] : storage_override[1],
-          :units => machine_conf.disks.first[:capacity][:units]
-        }
-      }
-    ]
-  end
-
-  def self.convert_instance_addresses(instance)
-    (instance.public_addresses + instance.private_addresses).collect do |address|
-      {
-        :hostname => address.is_hostname? ? address : nil,
-        :mac_address => address.is_mac? ? address : nil,
-        :state => 'Active',
-        :protocol => 'IPv4',
-        :address => address.is_ipv4? ? address : nil,
-        :allocation => 'Static'
-      }
-    end
-  end
-
-  def self.convert_instance_actions(instance, context)
-    instance.actions.collect do |action|
-      action = :destroy if action == :delete # In CIMI destroy operation become delete
-      action = :restart if action == :reboot  # In CIMI reboot operation become restart
-      { :href => context.send(:"#{action}_machine_url", instance.id), :rel => "http://www.dmtf.org/cimi/action/#{action}" }
-    end
-  end
-
-  def self.convert_storage_volumes(instance, context)
-    instance.storage_volumes ||= [] #deal with nilpointers
-    instance.storage_volumes.map{|vol| {:href=>context.volume_url(vol.keys.first),
-                                       :attachment_point=>vol.values.first} }
-  end
-
-end
diff --git a/server/lib/cimi/model/machine_admin.rb b/server/lib/cimi/model/machine_admin.rb
deleted file mode 100644
index fed7c80..0000000
--- a/server/lib/cimi/model/machine_admin.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::MachineAdmin < CIMI::Model::Base
-
-  text :username
-  text :password
-  text :key
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    if id == :all
-      keys = context.driver.keys(context.credentials)
-      keys.map { |key| from_key(key, context) }
-    else
-      key = context.driver.key(context.credentials, :id => id)
-      from_key(key, context)
-    end
-  end
-
-  def self.create_from_xml(body, context)
-    machine_admin = MachineAdmin.from_xml(body)
-    key = context.driver.create_key(context.credentials, :key_name => machine_admin.name)
-    from_key(key, context)
-  end
-
-  def self.delete!(id, context)
-    context.driver.destroy_key(context.credentials, :id => id)
-  end
-
-  private
-
-  def self.from_key(key, context)
-    self.new(
-      :name => key.id,
-      :username => key.username,
-      :password => key.is_password? ? key.password : key.fingerprint,
-      :key => key.is_key? ? key.pem_rsa_key : nil,
-      :id => context.machine_admin_url(key.id),
-      :created => Time.now
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/machine_admin_collection.rb b/server/lib/cimi/model/machine_admin_collection.rb
deleted file mode 100644
index fd76a52..0000000
--- a/server/lib/cimi/model/machine_admin_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::MachineAdminCollection < CIMI::Model::Base
-
-  act_as_root_entity :machine_admin
-
-  array :machine_admins do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.machine_admins_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} MachineAdminCollection",
-      :machine_admins => MachineAdmin.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/machine_collection.rb b/server/lib/cimi/model/machine_collection.rb
deleted file mode 100644
index 27aa61b..0000000
--- a/server/lib/cimi/model/machine_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::MachineCollection < CIMI::Model::Base
-
-  act_as_root_entity :machine
-
-  array :machines do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.machines_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} MachineCollection",
-      :machines => Machine.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/machine_configuration.rb b/server/lib/cimi/model/machine_configuration.rb
deleted file mode 100644
index f9d98f2..0000000
--- a/server/lib/cimi/model/machine_configuration.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::MachineConfiguration < CIMI::Model::Base
-
-  struct :memory do
-    scalar :quantity
-    scalar :units
-  end
-
-  text :cpu
-
-  array :disks do
-    struct :capacity do
-      scalar :quantity
-      scalar :units
-    end
-    scalar :format
-    scalar :attachment_point
-  end
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    profiles = []
-    if id == :all
-      profiles = context.driver.hardware_profiles(context.credentials)
-      profiles.map { |profile| from_hardware_profile(profile, context) }.compact
-    else
-      profile = context.driver.hardware_profile(context.credentials, id)
-      from_hardware_profile(profile, context)
-    end
-  end
-
-  private
-
-  def self.from_hardware_profile(profile, context)
-    # We accept just profiles with all properties set
-    return unless profile.memory or profile.cpu or profile.storage
-    memory = profile.memory.value || profile.memory.default
-    cpu = profile.cpu.value || profile.cpu.default
-    storage = profile.storage.value || profile.storage.default
-    machine_hash = {
-      :name => profile.name,
-      :description => "Machine Configuration with #{memory} #{profile.memory.unit} "+
-        "of memory and #{cpu} CPU",
-      :cpu => cpu,
-      :created => Time.now.to_s,  # FIXME: DC hardware_profile has no mention about created_at
-      :memory => { :quantity => profile.memory.value || profile.memory.default, :units => profile.memory.unit },
-      :disks => [ { :capacity => { :quantity => profile.storage.value || profile.storage.default, :units => profile.storage.unit } } ],
-      :id => context.machine_configuration_url(profile.name)
-    }
-    self.new(machine_hash)
-  end
-
-end
diff --git a/server/lib/cimi/model/machine_configuration_collection.rb b/server/lib/cimi/model/machine_configuration_collection.rb
deleted file mode 100644
index 171acac..0000000
--- a/server/lib/cimi/model/machine_configuration_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::MachineConfigurationCollection < CIMI::Model::Base
-
-  act_as_root_entity :machine_configuration
-
-  array :machine_configurations do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.machine_configurations_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} MachineConfigurationCollection",
-      :machine_configurations => MachineConfiguration.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/machine_image.rb b/server/lib/cimi/model/machine_image.rb
deleted file mode 100644
index 7389475..0000000
--- a/server/lib/cimi/model/machine_image.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::MachineImage < CIMI::Model::Base
-
-  href :image_location
-  text :image_data
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    images = []
-    if id == :all
-      images = context.driver.images(context.credentials)
-      images.map { |image| from_image(image, context) }
-    else
-      image = context.driver.image(context.credentials, :id => id)
-      from_image(image, context)
-    end
-  end
-
-  def self.from_image(image, context)
-    self.new(
-      :name => image.id,
-      :id => context.machine_image_url(image.id),
-      :description => image.description,
-      :created => Time.now.to_s,
-      :image_location => { :href => "#{context.driver.name}://#{image.id}" } # FIXME
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/machine_image_collection.rb b/server/lib/cimi/model/machine_image_collection.rb
deleted file mode 100644
index b02ede7..0000000
--- a/server/lib/cimi/model/machine_image_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::MachineImageCollection < CIMI::Model::Base
-
-  act_as_root_entity :machine_image
-
-  array :machine_images do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.machine_images_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} MachineImageCollection",
-      :machine_images => MachineImage.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/machine_template.rb b/server/lib/cimi/model/machine_template.rb
deleted file mode 100644
index 8a88052..0000000
--- a/server/lib/cimi/model/machine_template.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::MachineTemplate < CIMI::Model::Base
-
-  href :machine_config
-  href :machine_image
-  href :machine_admin
-
-  array :volumes do
-    scalar :href
-    scalar :protocol
-    scalar :attachment_point
-  end
-
-  array :volume_templates do
-    scalar :href, :attachment_point, :protocol
-  end
-
-  array :network_interfaces do
-    href :vsp
-    text :hostname, :mac_address, :state, :protocol, :allocation
-    text :address, :default_gateway, :dns, :max_transmission_unit
-  end
-
-  array :operations do
-    scalar :rel, :href
-  end
-end
diff --git a/server/lib/cimi/model/machine_template_collection.rb b/server/lib/cimi/model/machine_template_collection.rb
deleted file mode 100644
index e1e8d30..0000000
--- a/server/lib/cimi/model/machine_template_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::MachineTemplateCollection < CIMI::Model::Base
-
-  act_as_root_entity :machine_template
-
-  array :machine_templates do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.machine_template_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} MachineTemplateCollection",
-      :machine_templates => MachineTemplate.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/network.rb b/server/lib/cimi/model/network.rb
deleted file mode 100644
index cbfbae0..0000000
--- a/server/lib/cimi/model/network.rb
+++ /dev/null
@@ -1,106 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::Network < CIMI::Model::Base
-
-  text :state
-
-  text :access
-
-  text :bandwidth_limit
-
-  text :traffic_priority
-
-  text :max_traffic_delay
-
-  text :max_traffic_loss
-
-  text :max_traffic_jitter
-
-  href :routing_group
-
-  href :event_log
-
-  array :meters do
-    scalar :href
-  end
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    networks=[]
-    if id==:all
-      networks = context.driver.networks(context.credentials, {:env=>context})
-    else
-      networks = context.driver.networks(context.credentials, {:id=>id, :env=>context})
-    end
-    networks
-  end
-
-  def self.create(request_body, context, type)
-    input = (type == :xml)? XmlSimple.xml_in(request_body, {"ForceArray"=>false,"NormaliseSpace"=>2}) : JSON.parse(request_body)
-    if input["networkTemplate"]["href"] #template by reference
-      network_config, routing_group = get_by_reference(input, context)
-    else
-      if input["networkTemplate"]["networkConfig"]["href"] # configuration by reference
-        network_config = NetworkConfiguration.find(context.href_id(input["networkTemplate"]["networkConfig"]["href"],:network_configurations), context)
-      else #configuration by value
-        network_config = get_by_value(request_body, type)
-      end
-      routing_group = RoutingGroup.find(context.href_id(input["networkTemplate"]["routingGroup"]["href"], :routing_groups), context)
-    end
-    params = {:network_config => network_config, :routing_group => routing_group, :name=>input["name"], :description=>input["description"], :env=>context}
-    raise CIMI::Model::BadRequest.new("Bad request - missing required parameters. Client sent: #{request_body} which produced #{params.inspect}")  if params.has_value?(nil)
-    context.driver.create_network(context.credentials, params)
-  end
-
-  def self.delete!(id, context)
-    context.driver.delete_network(context.credentials, id)
-  end
-
-  def perform(action, context, &block)
-    begin
-      if context.driver.send(:"#{action.name}_network", context.credentials, self.name)
-        block.callback :success
-      else
-        raise "Operation #{action.name} failed to execute on the Network #{self.name} "
-      end
-    rescue => e
-      block.callback :failure, e.message
-    end
-  end
-
-  private
-
-  def self.get_by_reference(input, context)
-    network_template = NetworkTemplate.find(context.href_id(input["networkTemplate"]["href"], :network_templates), context)
-    network_config = NetworkConfiguration.find(context.href_id(network_template.network_config.href, :network_configurations), context)
-    routing_group = RoutingGroup.find(context.href_id(network_template.routing_group.href, :routing_groups), context)
-    return network_config, routing_group
-  end
-
-  def self.get_by_value(request_body, type)
-    if type == :xml
-      xml_arrays = XmlSimple.xml_in(request_body, {"NormaliseSpace"=>2})
-      network_config = NetworkConfiguration.from_xml(XmlSimple.xml_out(xml_arrays["networkTemplate"][0]["networkConfig"][0]))
-    else
-     json = JSON.parse(request_body)
-      network_config = NetworkConfiguration.from_json(JSON.generate(json["networkTemplate"]["networkConfig"]))
-    end
-  end
-
-end
diff --git a/server/lib/cimi/model/network_collection.rb b/server/lib/cimi/model/network_collection.rb
deleted file mode 100644
index 836d8e8..0000000
--- a/server/lib/cimi/model/network_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::NetworkCollection < CIMI::Model::Base
-
-  act_as_root_entity :network
-
-  array :networks do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.networks_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} NetworkCollection",
-      :networks => Network.all(context).map { |c| { :href => c.id } }
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/network_configuration.rb b/server/lib/cimi/model/network_configuration.rb
deleted file mode 100644
index 1b04548..0000000
--- a/server/lib/cimi/model/network_configuration.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::NetworkConfiguration < CIMI::Model::Base
-
-  text :access
-
-  text :bandwidth_limit
-
-  text :traffic_priority
-
-  text :max_traffic_delay
-
-  text :max_traffic_loss
-
-  text :max_traffic_jitter
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    network_configs = []
-    if id==:all
-      network_configs = context.driver.network_configurations(context.credentials, {:env=>context})
-    else
-      network_configs = context.driver.network_configurations(context.credentials, {:env=>context, :id=>id})
-    end
-    network_configs
-  end
-
-  def self.create_from_xml(request_body, context)
-  end
-
-  def self.create_from_json(request_body, context)
-  end
-end
diff --git a/server/lib/cimi/model/network_configuration_collection.rb b/server/lib/cimi/model/network_configuration_collection.rb
deleted file mode 100644
index fd70047..0000000
--- a/server/lib/cimi/model/network_configuration_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::NetworkConfigurationCollection < CIMI::Model::Base
-
-  act_as_root_entity :network_configuration
-
-  array :network_configurations do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.network_configurations_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} NetworkConfigurationCollection",
-      :network_configurations => NetworkConfiguration.all(context).map { |c| { :href => c.id } }
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/network_template.rb b/server/lib/cimi/model/network_template.rb
deleted file mode 100644
index ce3b990..0000000
--- a/server/lib/cimi/model/network_template.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::NetworkTemplate < CIMI::Model::Base
-
-  href :network_config
-
-  href :routing_group
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    network_templates = []
-    if id==:all
-      network_templates = context.driver.network_templates(context.credentials, {:env=>context})
-    else
-      network_templates = context.driver.network_templates(context.credentials, {:env=>context, :id=>id})
-    end
-    network_templates
-  end
-
-end
diff --git a/server/lib/cimi/model/network_template_collection.rb b/server/lib/cimi/model/network_template_collection.rb
deleted file mode 100644
index 6b97b6e..0000000
--- a/server/lib/cimi/model/network_template_collection.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-
-class CIMI::Model::NetworkTemplateCollection < CIMI::Model::Base
-
-  act_as_root_entity :network_template
-
-  array :network_templates do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.network_templates_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} NetworkTemplateCollection",
-      :network_templates => NetworkTemplate.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/routing_group.rb b/server/lib/cimi/model/routing_group.rb
deleted file mode 100644
index d26f4d7..0000000
--- a/server/lib/cimi/model/routing_group.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::RoutingGroup < CIMI::Model::Base
-
-  array :networks do
-    scalar :href
-  end
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    if id==:all
-      context.driver.routing_groups(context.credentials, {:env=>context})
-    else
-      context.driver.routing_groups(context.credentials, {:env=>context, :id=>id})
-    end
-  end
-
-end
diff --git a/server/lib/cimi/model/routing_group_collection.rb b/server/lib/cimi/model/routing_group_collection.rb
deleted file mode 100644
index 1546c80..0000000
--- a/server/lib/cimi/model/routing_group_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::RoutingGroupCollection < CIMI::Model::Base
-
-  act_as_root_entity :routing_group
-
-  array :routing_groups do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.routing_groups_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} RoutingGroupCollection",
-      :routing_groups => RoutingGroup.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/routing_group_template.rb b/server/lib/cimi/model/routing_group_template.rb
deleted file mode 100644
index 204a353..0000000
--- a/server/lib/cimi/model/routing_group_template.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::RoutingGroupTemplate < CIMI::Model::Base
-
-  array :networks do
-    scalar :href
-  end
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    if id==:all
-      context.driver.routing_group_templates(context.credentials, {:env=>context})
-    else
-      context.driver.routing_group_templates(context.credentials, {:env=>context, :id=>id})
-    end
-  end
-
-end
diff --git a/server/lib/cimi/model/routing_group_template_collection.rb b/server/lib/cimi/model/routing_group_template_collection.rb
deleted file mode 100644
index 5e7a9ba..0000000
--- a/server/lib/cimi/model/routing_group_template_collection.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-
-class CIMI::Model::RoutingGroupTemplateCollection < CIMI::Model::Base
-
-  act_as_root_entity :routing_group_template
-
-  array :routing_group_templates do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.routing_group_templates_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} RoutingGroupTemplateCollection",
-      :routing_group_templates => RoutingGroupTemplate.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/schema.rb b/server/lib/cimi/model/schema.rb
deleted file mode 100644
index f301b69..0000000
--- a/server/lib/cimi/model/schema.rb
+++ /dev/null
@@ -1,277 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-
-# The smarts of converting from XML and JSON into internal objects
-class CIMI::Model::Schema
-
-  #
-  # Attributes describe how we extract values from XML/JSON
-  #
-  class Attribute
-    attr_reader :name, :xml_name, :json_name
-
-    def initialize(name, opts = {})
-      @name = name
-      @xml_name = (opts[:xml_name] || name).to_s.camelize(true)
-      @json_name = (opts[:json_name] || name).to_s.camelize(true)
-    end
-
-    def from_xml(xml, model)
-      model[@name] = xml[@xml_name].first if xml.has_key?(@xml_name)
-    end
-
-    def from_json(json, model)
-      model[@name] = json[@json_name]
-    end
-
-    def to_xml(model, xml)
-      xml[@xml_name] = [model[@name]] if model[@name]
-    end
-
-    def to_json(model, json)
-      json[@json_name] = model[@name] if model and model[@name]
-    end
-  end
-
-  class Scalar < Attribute
-    def initialize(name, opts)
-      @text = opts[:text]
-      if ! [nil, :nested, :direct].include?(@text)
-        raise "text option for scalar must be :nested or :direct"
-      end
-      super(name, opts)
-    end
-
-    def text?; @text; end
-
-    def nested_text?; @text == :nested; end
-
-    def from_xml(xml, model)
-      case @text
-        when :nested then model[@name] = xml[@xml_name].first["content"] if xml[@xml_name]
-        when :direct then model[@name] = xml["content"]
-        else model[@name] = xml[@xml_name]
-      end
-    end
-
-    def to_xml(model, xml)
-      return unless model
-      return unless model[@name]
-      case @text
-        when :nested then xml[@xml_name] = [{ "content" => model[@name] }]
-        when :direct then xml["content"] = model[@name]
-        else xml[@xml_name] = model[@name]
-      end
-    end
-  end
-
-  class Struct < Attribute
-    def initialize(name, opts, &block)
-      content = opts[:content]
-      super(name, opts)
-      @schema = CIMI::Model::Schema.new
-      @schema.instance_eval(&block) if block_given?
-      @schema.scalar(content, :text => :direct) if content
-    end
-
-    def from_xml(xml, model)
-      xml = xml.has_key?(xml_name) ? xml[xml_name].first : {}
-      model[name] = convert_from_xml(xml)
-    end
-
-    def from_json(json, model)
-      json = json.has_key?(json_name) ? json[json_name] : {}
-      model[name] = convert_from_json(json)
-    end
-
-    def to_xml(model, xml)
-      conv = convert_to_xml(model[name])
-      xml[xml_name] = [conv] unless conv.empty?
-    end
-
-    def to_json(model, json)
-      conv = convert_to_json(model[name])
-      json[json_name] = conv unless conv.empty?
-    end
-
-    def convert_from_xml(xml)
-      sub = struct.new
-      @schema.from_xml(xml, sub)
-      sub
-    end
-
-    def convert_from_json(json)
-      sub = struct.new
-      @schema.from_json(json, sub)
-      sub
-    end
-
-    def convert_to_xml(model)
-      xml = {}
-      @schema.to_xml(model, xml)
-      xml
-    end
-
-    def convert_to_json(model)
-      json = {}
-      @schema.to_json(model, json)
-      json
-    end
-
-    private
-    def struct
-      cname = "CIMI_#{json_name.upcase_first}"
-      if ::Struct.const_defined?(cname)
-        ::Struct.const_get(cname)
-      else
-        ::Struct.new("CIMI_#{json_name.upcase_first}",
-                     *@schema.attribute_names)
-      end
-    end
-  end
-
-  class Array < Attribute
-    # For an array :things, we collect all <thing/> elements (XmlSimple
-    # actually does the collecting)
-    def initialize(name, opts = {}, &block)
-      opts[:xml_name] = name.to_s.singularize unless opts[:xml_name]
-      super(name, opts)
-      @struct = Struct.new(name, opts, &block)
-    end
-
-    def from_xml(xml, model)
-      model[name] = (xml[xml_name] || []).map { |elt| @struct.convert_from_xml(elt) }
-    end
-
-    def from_json(json, model)
-      model[name] = (json[json_name] || []).map { |elt| @struct.convert_from_json(elt) }
-    end
-
-    def to_xml(model, xml)
-      ary = (model[name] || []).map { |elt| @struct.convert_to_xml(elt) }
-      xml[xml_name] = ary unless ary.empty?
-    end
-
-    def to_json(model, json)
-      ary = (model[name] || []).map { |elt| @struct.convert_to_json(elt) }
-      json[json_name] = ary unless ary.empty?
-    end
-  end
-
-  class Hash < Attribute
-
-    def initialize(name, opts = {}, &block)
-      opts[:json_name] = name.to_s.pluralize unless opts[:json_name]
-      super(name, opts)
-      @struct = Struct.new(name, opts, &block)
-    end
-
-    def from_xml(xml, model)
-      model[name] = (xml[xml_name] || []).map { |elt| @struct.convert_from_xml(elt) }
-    end
-
-    def from_json(json, model)
-      model[name] = (json[json_name] || {}).inject([]) do |result,item|
-        result << @struct.convert_from_json({ 'name' => item[0], 'value' => item[1] })
-      end
-    end
-
-    def to_xml(model, xml)
-      ary = (model[name] || []).map { |elt| @struct.convert_to_xml(elt) }
-      xml[xml_name] = ary unless ary.empty?
-    end
-
-    def to_json(model, json)
-      ary = (model[name] || []).map { |elt| @struct.convert_to_json(elt) }
-      json[json_name] = ary.inject({}) { |result, item| result[item['name']] = item['value']; result } unless ary.empty?
-    end
-  end
-
-  #
-  # The actual Schema class
-  #
-  def initialize
-    @attributes = []
-  end
-
-  def from_xml(xml, model = {})
-    @attributes.freeze
-    @attributes.each { |attr| attr.from_xml(xml, model) }
-    model
-  end
-
-  def from_json(json, model = {})
-    @attributes.freeze
-    @attributes.each { |attr| attr.from_json(json, model) }
-    model
-  end
-
-  def to_xml(model, xml = {})
-    @attributes.freeze
-    @attributes.each { |attr| attr.to_xml(model, xml) }
-    xml
-  end
-
-  def to_json(model, json = {})
-    @attributes.freeze
-    @attributes.each { |attr| attr.to_json(model, json) }
-    json
-  end
-
-  def attribute_names
-    @attributes.map { |a| a.name }
-  end
-
-  #
-  # The DSL
-  #
-  # Requires that the class into which this is included has a
-  # +add_attributes!+ method
-  module DSL
-    def href(*args)
-      args.each { |arg| struct(arg) { scalar :href } }
-    end
-
-    def text(*args)
-      args.expand_opts!(:text => :nested)
-      scalar(*args)
-    end
-
-    def scalar(*args)
-      add_attributes!(args, Scalar)
-    end
-
-    def array(name, opts={}, &block)
-      add_attributes!([name, opts], Array, &block)
-    end
-
-    def struct(name, opts={}, &block)
-      add_attributes!([name, opts], Struct, &block)
-    end
-
-    def hash(name, opts={}, &block)
-      add_attributes!([name, opts], Hash, &block)
-    end
-  end
-
-  include DSL
-
-  def add_attributes!(args, attr_klass, &block)
-    raise "The schema has already been used to convert objects" if @attributes.frozen?
-    opts = args.extract_opts!
-    args.each { |arg| @attributes << attr_klass.new(arg, opts, &block) }
-  end
-end
diff --git a/server/lib/cimi/model/volume.rb b/server/lib/cimi/model/volume.rb
deleted file mode 100644
index 0a232d5..0000000
--- a/server/lib/cimi/model/volume.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::Volume < CIMI::Model::Base
-
-  struct :capacity do
-    scalar :quantity
-    scalar :units
-  end
-  text :bootable
-  text :supports_snapshots
-  array :snapshots do
-    scalar :ref
-  end
-  text :guest_interface
-  array :meters do
-    scalar :ref
-  end
-  href :eventlog
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    volumes = []
-    opts = ( id == :all ) ? {} : { :id => id }
-    volumes = self.driver.storage_volumes(context.credentials, opts)
-    volumes.collect!{ |volume| from_storage_volume(volume, context) }
-    return volumes.first unless volumes.length > 1
-    return volumes
-  end
-
-  def self.all(context); find(:all, context); end
-
-  def self.create_from_json(json_in, context)
-    json = JSON.parse(json_in)
-    volume_config_id = json["volumeTemplate"]["volumeConfig"]["href"].split("/").last
-    volume_image_id = (json["volumeTemplate"].has_key?("volumeImage") ?
-                json["volumeTemplate"]["volumeImage"]["href"].split("/").last  : nil)
-    create_volume({:volume_config_id=>volume_config_id, :volume_image_id=>volume_image_id}, context)
-  end
-
-  def self.create_from_xml(xml_in, context)
-    xml = XmlSimple.xml_in(xml_in)
-    volume_config_id = xml["volumeTemplate"][0]["volumeConfig"][0]["href"].split("/").last
-    volume_image_id = (xml["volumeTemplate"][0].has_key?("volumeImage") ?
-             xml["volumeTemplate"][0]["volumeImage"][0]["href"].split("/").last  : nil)
-    create_volume({:volume_config_id=>volume_config_id, :volume_image_id=>volume_image_id}, context)
-  end
-
-  def self.delete!(id, context)
-    context.driver.destroy_storage_volume(context.credentials, {:id=>id} )
-  end
-
-  def self.find_to_attach_from_json(json_in, context)
-    json = JSON.parse(json_in)
-    volumes = json["volumes"].map{|v| {:volume=>self.find(v["volume"]["href"].split("/volumes/").last, context),
-                                       :attachment_point=>v["attachmentPoint"]  }}
-  end
-
-  def self.find_to_attach_from_xml(xml_in, context)
-    xml = XmlSimple.xml_in(xml_in)
-    volumes = xml["volume"].map{|v| {:volume => self.find(v["href"].split("/volumes/").last, context),
-                                      :attachment_point=>v["attachmentPoint"] }}
-  end
-
-  private
-
-  def self.create_volume(params, context)
-    volume_config = VolumeConfiguration.find(params[:volume_config_id], context)
-    opts = {:capacity=>volume_config.capacity[:quantity], :snapshot_id=>params[:volume_image_id] }
-    storage_volume = self.driver.create_storage_volume(context.credentials, opts)
-    from_storage_volume(storage_volume, context)
-  end
-
-  def self.from_storage_volume(volume, context)
-    self.new( { :name => volume.id,
-                :description => volume.id,
-                :created => volume.created,
-                :id => context.volume_url(volume.id),
-                :capacity => { :quantity=>volume.capacity, :units=>"gibibyte"  }, #FIXME... units will vary
-                :bootable => "false", #fixme ... will vary... ec2 doesn't expose this
-                :supports_snapshots => "true", #fixme, will vary (true for ec2)
-                :snapshots => [], #fixme...
-                :guest_interface => "",
-                :eventlog => {:href=> "http://eventlogs"},#FIXME
-                :meters => []
-            } )
-  end
-
-end
diff --git a/server/lib/cimi/model/volume_collection.rb b/server/lib/cimi/model/volume_collection.rb
deleted file mode 100644
index d5053c7..0000000
--- a/server/lib/cimi/model/volume_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::VolumeCollection < CIMI::Model::Base
-
-  act_as_root_entity :volume
-
-  array :volumes do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.volumes_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} VolumeCollection",
-      :volumes => Volume.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/volume_configuration.rb b/server/lib/cimi/model/volume_configuration.rb
deleted file mode 100644
index 75b37ea..0000000
--- a/server/lib/cimi/model/volume_configuration.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::VolumeConfiguration < CIMI::Model::Base
-
-  text :format
-  struct :capacity do
-    scalar :quantity
-    scalar :units
-  end
-  text :supports_snapshots
-  text :guest_interface
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    volume_configs = []
-    if id == :all
-      #ec2 ebs volumes can 1gb..1tb
-      (1..1000).each do |size|
-        volume_configs << create(size, context)
-      end
-    else
-      volume_configs << create(id, context)
-      return volume_configs.first
-    end
-    return volume_configs
-  end
-
-
-  def self.all(context); find(:all, context); end
-
-  private
-
-  def self.create(size, context)
-    self.new( {
-                :id => context.volume_configuration_url(size),
-                :name => size,
-                :description => "volume configuration with #{size} GiB",
-                :created => Time.now.to_s,
-                :capacity => {:quantity=>size, :units=>"gibibytes"},
-                :supports_snapshots => "true"
-                # FIXME :guest_interface => "NFS"
-            } )
-  end
-
-end
diff --git a/server/lib/cimi/model/volume_configuration_collection.rb b/server/lib/cimi/model/volume_configuration_collection.rb
deleted file mode 100644
index ace31bf..0000000
--- a/server/lib/cimi/model/volume_configuration_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::VolumeConfigurationCollection < CIMI::Model::Base
-
-  act_as_root_entity :volume_configuration
-
-  array :volume_configurations do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.volume_configurations_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} VolumeConfigurationCollection",
-      :volume_configurations => VolumeConfiguration.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/volume_image.rb b/server/lib/cimi/model/volume_image.rb
deleted file mode 100644
index 03cc7fd..0000000
--- a/server/lib/cimi/model/volume_image.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::VolumeImage < CIMI::Model::Base
-
-  href :image_location
-  text :image_data
-  text :bootable
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    storage_snapshots = []
-    opts = ( id==:all  ) ? {}  : { :id=>id }
-    storage_snapshots = self.driver.storage_snapshots(context.credentials, opts)
-    storage_snapshots.collect!{ |snapshot| from_storage_snapshot(snapshot, context) }
-    return storage_snapshots.first unless storage_snapshots.length > 1
-    return storage_snapshots
-  end
-
-  def self.all(context); find(:all, context); end
-
-  private
-
-  def self.from_storage_snapshot(snapshot, context)
-    self.new( {
-               :name => snapshot.id,
-               :description => snapshot.id,
-               :created => snapshot.created,
-               :id => context.volume_image_url(snapshot.id),
-               :image_location => {:href=>context.volume_url(snapshot.storage_volume_id)},
-               :bootable => "false"  #FIXME
-            } )
-  end
-
-end
diff --git a/server/lib/cimi/model/volume_image_collection.rb b/server/lib/cimi/model/volume_image_collection.rb
deleted file mode 100644
index 0172c04..0000000
--- a/server/lib/cimi/model/volume_image_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::VolumeImageCollection < CIMI::Model::Base
-
-  act_as_root_entity :volume_image
-
-  array :volume_images do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.volume_images_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} VolumeImageCollection",
-      :volume_images => VolumeImage.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/volume_template.rb b/server/lib/cimi/model/volume_template.rb
deleted file mode 100644
index b9c82db..0000000
--- a/server/lib/cimi/model/volume_template.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::VolumeTemplate < CIMI::Model::Base
-
-  href :volume_config
-  href :volume_image
-  array :operations do
-    scalar :rel, :href
-  end
-end
diff --git a/server/lib/cimi/model/volume_template_collection.rb b/server/lib/cimi/model/volume_template_collection.rb
deleted file mode 100644
index 6b6e4ac..0000000
--- a/server/lib/cimi/model/volume_template_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::VolumeTemplateCollection < CIMI::Model::Base
-
-  act_as_root_entity :volume_template
-
-  array :volume_templates do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.volume_template_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} VolumeTemplateCollection",
-      :volume_templates => VolumeTemplate.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/vsp.rb b/server/lib/cimi/model/vsp.rb
deleted file mode 100644
index 40a526f..0000000
--- a/server/lib/cimi/model/vsp.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::VSP < CIMI::Model::Base
-
-  text :state
-
-  href :network
-
-  text :bandwidth_reservation
-
-  text :traffic_priority
-
-  text :max_traffic_delay
-
-  text :max_traffic_loss
-
-  text :max_traffic_jitter
-
-  href :event_log
-
-  array :meters do
-    scalar :href
-  end
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    if id==:all
-      context.driver.vsps(context.credentials, {:env=>context})
-    else
-      context.driver.vsps(context.credentials, {:id=>id, :env=>context})
-    end
-  end
-
-  def self.create(request_body, context, type)
-    input = (type == :xml)? XmlSimple.xml_in(request_body, {"ForceArray"=>false, "NormaliseSpace"=>2}) : JSON.parse(request_body)
-    if input["vspTemplate"]["href"] #template by reference
-      vsp_config, network = get_by_reference(input, context)
-    else
-      if input["vspTemplate"]["vspConfig"]["href"] # configuration by reference
-        vsp_config = VSPConfiguration.find(context.href_id(input["vspTemplate"]["vspConfig"]["href"],:vsp_configurations), context)
-      else #configuration by value
-        vsp_config = get_by_value(request_body, type)
-      end
-      network = Network.find(context.href_id(input["vspTemplate"]["network"]["href"], :networks), context)
-    end
-    params = {:vsp_config => vsp_config, :network => network, :name=>input["name"], :description=>input["description"], :env=>context}
-    raise CIMI::Model::BadRequest.new("Bad request - missing required parameters. Client sent: #{request_body} which produced #{params.inspect}")  if params.has_value?(nil)
-    context.driver.create_vsp(context.credentials, params)
-  end
-
-  def self.delete!(id, context)
-    context.driver.delete_vsp(context.credentials, id)
-  end
-
-  def perform(action, context, &block)
-    begin
-      if context.driver.send(:"#{action.name}_vsp", context.credentials, self.name)
-        block.callback :success
-      else
-        raise "Operation #{action.name} failed to execute on the VSP #{self.name} "
-      end
-    rescue => e
-      block.callback :failure, e.message
-    end
-  end
-
-
-  private
-
-  def self.get_by_reference(input, context)
-    vsp_template = VSPTemplate.find(context.href_id(input["vspTemplate"]["href"], :vsp_templates), context)
-    vsp_config = VSPConfiguration.find(context.href_id(vsp_template.vsp_config.href, :vsp_configurations), context)
-    network = Network.find(context.href_id(vsp_template.network.href, :networks), context)
-    return vsp_config, network
-  end
-
-  def self.get_by_value(request_body, type)
-    if type == :xml
-      xml_arrays = XmlSimple.xml_in(request_body, {"NormaliseSpace"=>2})
-      vsp_config = VSPConfiguration.from_xml(XmlSimple.xml_out(xml_arrays["vspTemplate"][0]["vspConfig"][0]))
-    else
-     json = JSON.parse(request_body)
-      vsp_config = VSPConfiguration.from_json(JSON.generate(json["vspTemplate"]["vspConfig"]))
-    end
-  end
-end
diff --git a/server/lib/cimi/model/vsp_collection.rb b/server/lib/cimi/model/vsp_collection.rb
deleted file mode 100644
index 6f659e1..0000000
--- a/server/lib/cimi/model/vsp_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::VSPCollection < CIMI::Model::Base
-
-  CIMI::Model.register_as_root_entity! "VSPs"
-
-  array :vsps do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.vsps_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} VSPCollection",
-      :vsps => VSP.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/vsp_configuration.rb b/server/lib/cimi/model/vsp_configuration.rb
deleted file mode 100644
index c9a9bf3..0000000
--- a/server/lib/cimi/model/vsp_configuration.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::VSPConfiguration < CIMI::Model::Base
-
-  text :bandwidth_reservation
-
-  text :traffic_priority
-
-  text :max_traffic_delay
-
-  text :max_traffic_loss
-
-  text :max_traffic_jitter
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    if id==:all
-      context.driver.vsp_configurations(context.credentials, {:env=>context})
-    else
-      context.driver.vsp_configurations(context.credentials, {:env=>context, :id=>id})
-    end
-  end
-
-end
diff --git a/server/lib/cimi/model/vsp_configuration_collection.rb b/server/lib/cimi/model/vsp_configuration_collection.rb
deleted file mode 100644
index addff1c..0000000
--- a/server/lib/cimi/model/vsp_configuration_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::VSPConfigurationCollection < CIMI::Model::Base
-
-  CIMI::Model.register_as_root_entity! "VSPConfigurations"
-
-  array :vsp_configurations do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.vsp_configurations_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} VSPConfigurationCollection",
-      :vsp_configurations => VSPConfiguration.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/model/vsp_template.rb b/server/lib/cimi/model/vsp_template.rb
deleted file mode 100644
index f1b8078..0000000
--- a/server/lib/cimi/model/vsp_template.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::VSPTemplate < CIMI::Model::Base
-
-  href :network
-
-  href :vsp_config
-
-  array :operations do
-    scalar :rel, :href
-  end
-
-  def self.find(id, context)
-    if id==:all
-      context.driver.vsp_templates(context.credentials, {:env=>context})
-    else
-      context.driver.vsp_templates(context.credentials, {:env=>context, :id=>id})
-    end
-  end
-
-end
diff --git a/server/lib/cimi/model/vsp_template_collection.rb b/server/lib/cimi/model/vsp_template_collection.rb
deleted file mode 100644
index 4acb74e..0000000
--- a/server/lib/cimi/model/vsp_template_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-class CIMI::Model::VSPTemplateCollection < CIMI::Model::Base
-
-  CIMI::Model.register_as_root_entity! "VSPTemplates"
-
-  array :vsp_templates do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.vsp_templates_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} VSPTemplateCollection",
-      :vsp_templates => VSPTemplate.all_uri(context)
-    )
-  end
-
-end
diff --git a/server/lib/cimi/models.rb b/server/lib/cimi/models.rb
new file mode 100644
index 0000000..b0793ee
--- /dev/null
+++ b/server/lib/cimi/models.rb
@@ -0,0 +1,75 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless require_relatived by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+require_relative '../deltacloud/drivers/features'
+
+# Declare namespace for CIMI models
+#
+
+module CIMI
+  module Model; end
+
+  class FakeCollection
+    extend Sinatra::Rabbit::Features
+    include Deltacloud::InstanceFeatures
+  end
+end
+
+require_relative './models/schema'
+require_relative './models/base'
+require_relative './models/errors'
+require_relative './models/entity_metadata'
+require_relative './models/entity_metadata_collection'
+require_relative './models/cloud_entry_point'
+require_relative './models/machine_template'
+require_relative './models/machine_image'
+require_relative './models/machine_configuration'
+require_relative './models/action'
+require_relative './models/machine'
+require_relative './models/volume'
+require_relative './models/machine_admin'
+require_relative './models/volume_configuration'
+require_relative './models/volume_image'
+require_relative './models/volume_template'
+require_relative './models/machine_template_collection'
+require_relative './models/machine_image_collection'
+require_relative './models/machine_configuration_collection'
+require_relative './models/machine_collection'
+require_relative './models/volume_collection'
+require_relative './models/machine_admin_collection'
+require_relative './models/volume_configuration_collection'
+require_relative './models/volume_image_collection'
+require_relative './models/volume_template_collection'
+require_relative './models/network'
+require_relative './models/network_collection'
+require_relative './models/network_configuration'
+require_relative './models/network_configuration_collection'
+require_relative './models/network_template'
+require_relative './models/network_template_collection'
+require_relative './models/routing_group'
+require_relative './models/routing_group_collection'
+require_relative './models/routing_group_template'
+require_relative './models/routing_group_template_collection'
+require_relative './models/vsp'
+require_relative './models/vsp_collection'
+require_relative './models/vsp_configuration'
+require_relative './models/vsp_configuration_collection'
+require_relative './models/vsp_template'
+require_relative './models/vsp_template_collection'
+require_relative './models/address'
+require_relative './models/address_collection'
+require_relative './models/address_template'
+require_relative './models/address_template_collection'
diff --git a/server/lib/cimi/models/action.rb b/server/lib/cimi/models/action.rb
new file mode 100644
index 0000000..c1c9908
--- /dev/null
+++ b/server/lib/cimi/models/action.rb
@@ -0,0 +1,24 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::Action < CIMI::Model::Base
+
+  text :action
+
+  def name
+    action.split('/').last.strip.intern
+  end
+
+end
diff --git a/server/lib/cimi/models/address.rb b/server/lib/cimi/models/address.rb
new file mode 100644
index 0000000..f9e10a1
--- /dev/null
+++ b/server/lib/cimi/models/address.rb
@@ -0,0 +1,72 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::Address < CIMI::Model::Base
+
+  text :ip
+
+  text :hostname
+
+  text :allocation
+
+  text :default_gateway
+
+  text :dns
+
+  text :mac_address
+
+  text :protocol
+
+  text :mask
+
+  href :network
+
+  href :resource
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.addresses(context.credentials, {:env=>context})
+    else
+      context.driver.addresses(context.credentials, {:id=>id, :env=>context})
+    end
+  end
+
+  def self.create(request_body, context, type)
+    input = (type == :xml)? XmlSimple.xml_in(request_body, {"ForceArray"=>false, "NormaliseSpace"=>2}) : JSON.parse(request_body)
+    if input["addressTemplate"]["href"] #by reference
+      address_template = CIMI::Model::AddressTemplate.find(context.href_id(input["addressTemplate"]["href"], :address_templates), context)
+    else
+      case type
+        when :json
+          address_template = CIMI::Model::AddressTemplate.from_json(JSON.generate(input["addressTemplate"]))
+        when :xml
+          xml = XmlSimple.xml_in(request_body, {"NormaliseSpace"=>2})
+          address_template = CIMI::Model::AddressTemplate.from_xml(XmlSimple.xml_out(xml["addressTemplate"][0]))
+      end
+    end
+    params = {:name=>input["name"], :description=>input["description"], :address_template=>address_template, :env=>context }
+    raise CIMI::Model::BadRequest.new("Bad request - missing required parameters. Client sent: #{request_body} which produced #{params.inspect}")  if params.has_value?(nil)
+    context.driver.create_address(context.credentials, params)
+  end
+
+  def self.delete!(id, context)
+    context.driver.delete_address(context.credentials, id)
+  end
+
+end
diff --git a/server/lib/cimi/models/address_collection.rb b/server/lib/cimi/models/address_collection.rb
new file mode 100644
index 0000000..eef6c51
--- /dev/null
+++ b/server/lib/cimi/models/address_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::AddressCollection < CIMI::Model::Base
+
+  act_as_root_entity :address
+
+  array :addresses do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.addresses_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} AddressCollection",
+      :addresses => CIMI::Model::Address.all(context).map { |addr| { :href => addr.id } }
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/address_template.rb b/server/lib/cimi/models/address_template.rb
new file mode 100644
index 0000000..9d2c409
--- /dev/null
+++ b/server/lib/cimi/models/address_template.rb
@@ -0,0 +1,54 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::AddressTemplate < CIMI::Model::Base
+
+  text :ip
+
+  text :hostname
+
+  text :allocation
+
+  text :default_gateway
+
+  text :dns
+
+  text :mac_address
+
+  text :protocol
+
+  text :mask
+
+  href :network
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.address_templates(context.credentials, {:env=>context})
+    else
+      context.driver.address_templates(context.credentials, {:id=>id, :env=>context})
+    end
+  end
+
+  def self.create(request_body, context, type)
+  end
+
+  def self.delete!(id, context)
+  end
+
+end
diff --git a/server/lib/cimi/models/address_template_collection.rb b/server/lib/cimi/models/address_template_collection.rb
new file mode 100644
index 0000000..3bb95cd
--- /dev/null
+++ b/server/lib/cimi/models/address_template_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::AddressTemplateCollection < CIMI::Model::Base
+
+  act_as_root_entity :address_template
+
+  array :address_templates do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.address_templates_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} AddressTemplateCollection",
+      :address_templates => CIMI::Model::AddressTemplate.all(context).map { |addr| { :href => addr.id } }
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
new file mode 100644
index 0000000..16812ac
--- /dev/null
+++ b/server/lib/cimi/models/base.rb
@@ -0,0 +1,249 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+require 'xmlsimple'
+require 'json'
+
+# The base class for any CIMI object that we either read from a request or
+# write as a response. This class handles serializing/deserializing XML and
+# JSON into a common form.
+#
+# == Defining the schema
+#
+# The conversion of XML and JSON into internal objects is based on a schema
+# that is defined through a DSL:
+#
+#   class Machine < CIMI::Model::Base
+#     text :status
+#     href :meter
+#     array :volumes do
+#       scalar :href, :attachment_point, :protocol
+#     end
+#   end
+#
+# The DSL automatically takes care of converting identifiers from their
+# underscored form to the camel-cased form used by CIMI. The above class
+# can be used in the following way:
+#
+#   machine = Machine.from_xml(some_xml)
+#   if machine.status == "UP"
+#     ...
+#   end
+#   sda = machine.volumes.find { |v| v.attachment_point == "/dev/sda" }
+#   handle_meter(machine.meter.href)
+#
+# The keywords for the DSL are
+#   [scalar(names, ...)]
+#     Define a scalar attribute; in JSON, this is represented as a string
+#     property. In XML, this can be represented in a number of ways,
+#     depending on whether the option :text is set:
+#       * :text not set: attribute on the enclosing element
+#       * :text == :direct: the text content of the enclosing element
+#       * :text == :nested: the text content of an element +<name>...</name>+
+#   [text(names)]
+#     A shorthand for +scalar(names, :text => :nested)+, i.e., for
+#     attributes that in XML are represented by their own tags
+#   [href(name)]
+#     A shorthand for +struct name { scalar :href }+; in JSON, this is
+#     represented as +{ name: { "href": string } }+, and in XML as +<name
+#     href="..."/>+
+#   [struct(name, opts, &block)]
+#     A structured subobject; the block defines the schema of the
+#     subobject. The +:content+ option can be used to specify the attribute
+#     that should receive the content of hte corresponding XML element
+#   [array(name, opts, &block)]
+#     An array of structured subobjects; the block defines the schema of
+#     the subobjects.
+
+module CIMI::Model
+
+  def self.register_as_root_entity!(name)
+    @root_entities ||= []
+    @root_entities << name
+    unless CIMI::Model::CloudEntryPoint.href_defined?(name)
+      CIMI::Model::CloudEntryPoint.send(:href, name.underscore)
+    end
+  end
+
+  def self.root_entities
+    @root_entities || []
+  end
+
+end
+
+class CIMI::Model::Base
+
+  #
+  # We keep the values of the attributes in a hash
+  #
+  attr_reader :attribute_values
+
+  # Keep the list of all attributes in an array +attributes+; for each
+  # attribute, we also define a getter and a setter to access/change the
+  # value for that attribute
+  class << self
+    def base_schema
+      @schema ||= CIMI::Model::Schema.new
+    end
+
+    def clone_base_schema
+      @schema_duped = true
+      @schema = Marshal::load(Marshal.dump(superclass.base_schema))
+    end
+
+    def base_schema_cloned?
+      @schema_duped
+    end
+
+    private :'clone_base_schema', :'base_schema_cloned?'
+
+    def inherited(child)
+      child.instance_eval do
+        def schema
+          base_schema_cloned? ? @schema : clone_base_schema
+        end
+      end
+    end
+
+    def add_attributes!(names, attr_klass, &block)
+      if self.respond_to? :schema
+        schema.add_attributes!(names, attr_klass, &block)
+      else
+        base_schema.add_attributes!(names, attr_klass, &block)
+      end
+      names.each do |name|
+        define_method(name) { @attribute_values[name] }
+        define_method(:"#{name}=") { |newval| @attribute_values[name] = newval }
+      end
+    end
+
+    # Return Array of links to current CIMI object
+    def all_uri(context)
+      self.all(context).map { |e| { :href => e.id } }
+    end
+  end
+
+  extend CIMI::Model::Schema::DSL
+
+  def [](a)
+    @attribute_values[a]
+  end
+
+  def []=(a, v)
+    @attribute_values[a] = v
+  end
+
+  #
+  # Factory methods
+  #
+  def initialize(values = {})
+    @attribute_values = values
+  end
+
+  # Construct a new object from the XML representation +xml+
+  def self.from_xml(text)
+    xml = XmlSimple.xml_in(text, :force_content => true)
+    model = self.new
+    @schema.from_xml(xml, model)
+    model
+  end
+
+  # Construct a new object
+  def self.from_json(text)
+    json = JSON::parse(text)
+    model = self.new
+    @schema.from_json(json, model)
+    model
+  end
+
+  #
+  # Serialize
+  #
+
+  def self.xml_tag_name
+    self.name.split("::").last
+  end
+
+  def self.to_json(model)
+    JSON::unparse(@schema.to_json(model))
+  end
+
+  def self.to_xml(model)
+    xml = @schema.to_xml(model)
+    xml["xmlns"] = "http://www.dmtf.org/cimi"
+    XmlSimple.xml_out(xml, :root_name => xml_tag_name)
+  end
+
+  def to_json
+    self.class.to_json(self)
+  end
+
+  def to_xml
+    self.class.to_xml(self)
+  end
+
+  #
+  # Common attributes for all resources
+  #
+  text :id, :name, :description, :created
+
+  # FIXME: this doesn't match with JSON
+  hash :property, :content => :value do
+    scalar :name
+  end
+
+  def self.act_as_root_entity(name=nil)
+    if name
+      name = name.to_s.camelize.pluralize
+    else
+      name = xml_tag_name.pluralize.uncapitalize
+    end
+    CIMI::Model.register_as_root_entity! name
+  end
+
+  def self.all(_self); find(:all, _self); end
+
+  def filter_by(filter_opts)
+    return self if filter_opts.nil?
+    return filter_attributes(filter_opts.split(',').map{ |a| a.intern }) if filter_opts.include? ','
+    case filter_opts
+      when /^([\w\_]+)$/ then filter_attributes([$1.intern])
+      when /^([\w\_]+)\[(\d+\-\d+)\]$/ then filter_by_arr_range($1.intern, $2)
+      when /^([\w\_]+)\[(\d+)\]$/ then filter_by_arr_index($1.intern, $2)
+      else self
+    end
+  end
+
+  private
+
+  def filter_attributes(attr_list)
+    attrs = attr_list.inject({}) do |result, attr|
+      result[attr] = self.send(attr) if self.respond_to?(attr)
+      result
+    end
+    self.class.new(attrs)
+  end
+
+  def filter_by_arr_index(attr, filter)
+    return self unless self.respond_to?(attr)
+    self.class.new(attr => [self.send(attr)[filter.to_i]])
+  end
+
+  def filter_by_arr_range(attr, filter)
+    return self unless self.respond_to?(attr)
+    filter = filter.split('-').inject { |s,e| s.to_i..e.to_i }
+    self.class.new(attr => self.send(attr)[filter])
+  end
+end
diff --git a/server/lib/cimi/models/cloud_entry_point.rb b/server/lib/cimi/models/cloud_entry_point.rb
new file mode 100644
index 0000000..ffe1ef5
--- /dev/null
+++ b/server/lib/cimi/models/cloud_entry_point.rb
@@ -0,0 +1,46 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::CloudEntryPoint < CIMI::Model::Base
+
+  array :entity_metadata do
+    scalar :href
+  end
+
+  def self.create(context)
+    self.new(entities(context).merge({
+      :name => context.driver.name,
+      :description => "Cloud Entry Point for the Deltacloud #{context.driver.name} driver",
+      :id => context.cloudEntryPoint_url,
+      :created => Time.now,
+      :entity_metadata => CIMI::Model::EntityMetadata.all_uri(context)
+    }))
+  end
+
+  # Return an Hash of the CIMI root entities used in CloudEntryPoint
+  def self.entities(context)
+    CIMI::Model.root_entities.inject({}) do |result, entity|
+      result[entity.underscore] = { :href => context.send(:"#{entity.underscore}_url") }
+      result
+    end
+  end
+
+  private
+
+  def self.href_defined?(entity)
+    true if schema.attribute_names.include? entity.underscore
+  end
+
+end
diff --git a/server/lib/cimi/models/entity_metadata.rb b/server/lib/cimi/models/entity_metadata.rb
new file mode 100644
index 0000000..5455c75
--- /dev/null
+++ b/server/lib/cimi/models/entity_metadata.rb
@@ -0,0 +1,84 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+class CIMI::Model::EntityMetadata < CIMI::Model::Base
+
+  text :type_uri
+
+  array :attributes do
+    scalar :name
+    scalar :namespace
+    scalar :type
+    scalar :required
+    scalar :constraints
+  end
+
+  array :operations do
+    scalar :name
+    scalar :uri
+    scalar :description
+    scalar :method
+    scalar :input_message
+    scalar :output_message
+  end
+
+  def self.find(id, context)
+    entity_metadata = []
+    if id == :all
+      CIMI::Model.root_entities.each do |entity|
+        entity_class = CIMI::Model.const_get("#{entity.singularize}")
+        entity_metadata << entity_class.create_entity_metadata(context) if entity_class.respond_to?(:create_entity_metadata)
+      end
+      return entity_metadata
+    else
+      entity_class = CIMI::Model.const_get("#{id.camelize}")
+      if entity_class.respond_to?(:create_entity_metadata)
+        entity_class.create_entity_metadata(context)
+      end
+    end
+  end
+
+  def self.metadata_from_deltacloud_features(cimi_entity, dcloud_entity, context)
+    deltacloud_features = context.driver.class.features_for(dcloud_entity)
+    metadata_attributes = deltacloud_features.map{|f| attributes_from_feature(f)}
+    from_feature(cimi_entity, context, metadata_attributes.flatten!)
+  end
+
+  def includes_attribute?(attribute)
+    self.attributes.any?{|attr| attr[:name] == attribute}
+  end
+
+  private
+
+  def self.attributes_from_feature(feature)
+    feature = CIMI::FakeCollection.feature(feature)
+    feature.operations.first.params_array.map do |p|
+      {
+        :name=> p.name,
+        :type=> "xs:string",
+        :required=> p.required? ? "true" : "false",
+        :constraints=> (feature.constraints.empty? ? (feature.description.nil? ? "" : feature.description): feature.constraints)
+      }
+    end
+  end
+
+  def self.from_feature(cimi_entity, context, metadata_attributes)
+    self.new(:name => cimi_entity, :uri=>"#{context.entity_metadata_url}/#{cimi_entity.underscore}",
+             :type_uri=> context.send("#{cimi_entity.pluralize.underscore}_url"),
+             :attributes => metadata_attributes)
+  end
+
+end
diff --git a/server/lib/cimi/models/entity_metadata_collection.rb b/server/lib/cimi/models/entity_metadata_collection.rb
new file mode 100644
index 0000000..595b502
--- /dev/null
+++ b/server/lib/cimi/models/entity_metadata_collection.rb
@@ -0,0 +1,31 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::EntityMetadataCollection < CIMI::Model::Base
+
+  array :entity_metadata do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.entity_metadata_url,
+      :name => 'default',
+      :created => Time.now,
+      :entity_metadata => CIMI::Model::EntityMetadata.all_uri(context)
+   )
+  end
+
+end
diff --git a/server/lib/cimi/models/errors.rb b/server/lib/cimi/models/errors.rb
new file mode 100644
index 0000000..7c090ed
--- /dev/null
+++ b/server/lib/cimi/models/errors.rb
@@ -0,0 +1,48 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Model
+
+  class NotFound < StandardError
+    attr_accessor :code
+
+    def initialize
+      super("Requested Entity Not Found")
+      self.code = 404
+    end
+
+  end
+
+  class BadRequest < StandardError
+    attr_accessor :code
+    def initialize(msg="")
+      super(msg)
+      self.code=400
+    end
+  end
+
+  class NotImplemented < StandardError
+    attr_accessor :code
+
+    def initialize
+      super("Requested operation is not implemented by backend provider")
+      self.code = 501
+    end
+
+  end
+
+end
+
+
diff --git a/server/lib/cimi/models/machine.rb b/server/lib/cimi/models/machine.rb
new file mode 100644
index 0000000..0540bd8
--- /dev/null
+++ b/server/lib/cimi/models/machine.rb
@@ -0,0 +1,227 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::Machine < CIMI::Model::Base
+
+  text :state
+  text :cpu
+
+  struct :memory do
+    scalar :quantity
+    scalar :units
+  end
+
+  href :event_log
+
+  array :disks do
+    struct :capacity do
+      scalar :quantity
+      scalar :units
+    end
+    scalar :format
+    scalar :attachment_point
+  end
+
+  array :volumes do
+    scalar :href
+    scalar :protocol
+    scalar :attachment_point
+  end
+
+  array :network_interfaces do
+    href :vsp
+    text :hostname, :mac_address, :state, :protocol, :allocation
+    text :address, :default_gateway, :dns, :max_transmission_unit
+  end
+
+  array :meters do
+    scalar :href
+  end
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    instances = []
+    if id == :all
+      instances = context.driver.instances(context.credentials)
+      instances.map { |instance| from_instance(instance, context) }.compact
+    else
+      instance = context.driver.instance(context.credentials, :id => id)
+      raise CIMI::Model::NotFound unless instance
+      from_instance(instance, context)
+    end
+  end
+
+  def self.create_from_json(body, context)
+    json = JSON.parse(body)
+    hardware_profile_id = xml['machineTemplate']['machineConfig']["href"].split('/').last
+    image_id = xml['machineTemplate']['machineImage']["href"].split('/').last
+    instance = context.create_instance(context.credentials, image_id, { :hwp_id => hardware_profile_id })
+    from_instance(instance, context)
+  end
+
+  def self.create_from_xml(body, context)
+    xml = XmlSimple.xml_in(body)
+    machine_template = xml['machineTemplate'][0]
+    hardware_profile_id = machine_template['machineConfig'][0]["href"].split('/').last
+    image_id = machine_template['machineImage'][0]["href"].split('/').last
+    additional_params = {}
+    additional_params[:name] =xml['name'][0] if xml['name']
+    if machine_template.has_key? 'machineAdmin'
+      additional_params[:keyname] = machine_template['machineAdmin'][0]["href"].split('/').last
+    end
+    instance = context.driver.create_instance(context.credentials, image_id, {
+      :hwp_id => hardware_profile_id
+    }.merge(additional_params))
+    from_instance(instance, context)
+  end
+
+  def perform(action, context, &block)
+    begin
+      if context.driver.send(:"#{action.name}_instance", context.credentials, self.name)
+        block.callback :success
+      else
+        raise "Operation failed to execute on given Machine"
+      end
+    rescue => e
+      block.callback :failure, e.message
+    end
+  end
+
+  def self.delete!(id, context)
+    context.driver.destroy_instance(context.credentials, id)
+  end
+
+  def self.create_entity_metadata(context)
+    cimi_entity = self.name.split("::").last
+    metadata = CIMI::Model::EntityMetadata.metadata_from_deltacloud_features(cimi_entity, :instances, context)
+    unless metadata.includes_attribute?(:name)
+      metadata.attributes << {:name=>"name", :required=>"false",
+                   :constraints=>"Determined by the cloud provider", :type=>"xs:string"}
+    end
+    metadata
+  end
+
+  def self.attach_volumes(volumes, context)
+    volumes.each do |vol|
+      context.driver.attach_storage_volume(context.credentials,
+      {:id=>vol[:volume].name, :instance_id=>context.params[:id], :device=>vol[:attachment_point]})
+    end
+    self.find(context.params[:id], context)
+  end
+
+  def self.detach_volumes(volumes, context)
+    volumes.each do |vol|
+      context.driver.detach_storage_volume(context.credentials, {:id=>vol[:volume].name, :instance_id => context.params[:id]})
+    end
+    self.find(context.params[:id], context)
+  end
+
+  private
+
+  def self.from_instance(instance, context)
+    cpu =  memory = disks = (instance.instance_profile.id == "opaque")? "n/a" : nil
+    self.new(
+      :name => instance.id,
+      :description => instance.name,
+      :created => instance.launch_time,
+      :id => context.machine_url(instance.id),
+      :state => convert_instance_state(instance.state),
+      :cpu => cpu || convert_instance_cpu(instance.instance_profile, context),
+      :memory => memory || convert_instance_memory(instance.instance_profile, context),
+      :disks => disks || convert_instance_storage(instance.instance_profile, context),
+      :network_interfaces => convert_instance_addresses(instance),
+      :operations => convert_instance_actions(instance, context),
+      :volumes=>convert_storage_volumes(instance, context),
+      :property => convert_instance_properties(instance, context)
+    )
+  end
+
+  # FIXME: This will convert 'RUNNING' state to 'STARTED'
+  # which is defined in CIMI (p65)
+  #
+  def self.convert_instance_state(state)
+    ('RUNNING' == state) ? 'STARTED' : state
+  end
+
+  def self.convert_instance_properties(instance, context)
+    properties = []
+    properties << { :name => :machine_image, :value => context.machine_image_url(instance.image_id) }
+    if instance.respond_to? :keyname
+      properties << { :name => :machine_admin, :value => context.machine_admin_url(instance.keyname) }
+    end
+    properties
+  end
+
+  def self.convert_instance_cpu(profile, context)
+    cpu_override = profile.overrides.find { |p, v| p == :cpu }
+    if cpu_override.nil?
+      CIMI::Model::MachineConfiguration.find(profile.id, context).cpu
+    else
+      cpu_override[1]
+    end
+  end
+
+  def self.convert_instance_memory(profile, context)
+    machine_conf = CIMI::Model::MachineConfiguration.find(profile.name, context)
+    memory_override = profile.overrides.find { |p, v| p == :memory }
+    {
+      :quantity => memory_override.nil? ? machine_conf.memory[:quantity] : memory_override[1],
+      :units => machine_conf.memory[:units]
+    }
+  end
+
+  def self.convert_instance_storage(profile, context)
+    machine_conf = CIMI::Model::MachineConfiguration.find(profile.name, context)
+    storage_override = profile.overrides.find { |p, v| p == :storage }
+    [
+      { :capacity => {
+          :quantity => storage_override.nil? ? machine_conf.disks.first[:capacity][:quantity] : storage_override[1],
+          :units => machine_conf.disks.first[:capacity][:units]
+        }
+      }
+    ]
+  end
+
+  def self.convert_instance_addresses(instance)
+    (instance.public_addresses + instance.private_addresses).collect do |address|
+      {
+        :hostname => address.is_hostname? ? address : nil,
+        :mac_address => address.is_mac? ? address : nil,
+        :state => 'Active',
+        :protocol => 'IPv4',
+        :address => address.is_ipv4? ? address : nil,
+        :allocation => 'Static'
+      }
+    end
+  end
+
+  def self.convert_instance_actions(instance, context)
+    instance.actions.collect do |action|
+      action = :destroy if action == :delete # In CIMI destroy operation become delete
+      action = :restart if action == :reboot  # In CIMI reboot operation become restart
+      { :href => context.send(:"#{action}_machine_url", instance.id), :rel => "http://www.dmtf.org/cimi/action/#{action}" }
+    end
+  end
+
+  def self.convert_storage_volumes(instance, context)
+    instance.storage_volumes ||= [] #deal with nilpointers
+    instance.storage_volumes.map{|vol| {:href=>context.volume_url(vol.keys.first),
+                                       :attachment_point=>vol.values.first} }
+  end
+
+end
diff --git a/server/lib/cimi/models/machine_admin.rb b/server/lib/cimi/models/machine_admin.rb
new file mode 100644
index 0000000..fed7c80
--- /dev/null
+++ b/server/lib/cimi/models/machine_admin.rb
@@ -0,0 +1,59 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineAdmin < CIMI::Model::Base
+
+  text :username
+  text :password
+  text :key
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    if id == :all
+      keys = context.driver.keys(context.credentials)
+      keys.map { |key| from_key(key, context) }
+    else
+      key = context.driver.key(context.credentials, :id => id)
+      from_key(key, context)
+    end
+  end
+
+  def self.create_from_xml(body, context)
+    machine_admin = MachineAdmin.from_xml(body)
+    key = context.driver.create_key(context.credentials, :key_name => machine_admin.name)
+    from_key(key, context)
+  end
+
+  def self.delete!(id, context)
+    context.driver.destroy_key(context.credentials, :id => id)
+  end
+
+  private
+
+  def self.from_key(key, context)
+    self.new(
+      :name => key.id,
+      :username => key.username,
+      :password => key.is_password? ? key.password : key.fingerprint,
+      :key => key.is_key? ? key.pem_rsa_key : nil,
+      :id => context.machine_admin_url(key.id),
+      :created => Time.now
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/machine_admin_collection.rb b/server/lib/cimi/models/machine_admin_collection.rb
new file mode 100644
index 0000000..08c1559
--- /dev/null
+++ b/server/lib/cimi/models/machine_admin_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineAdminCollection < CIMI::Model::Base
+
+  act_as_root_entity :machine_admin
+
+  array :machine_admins do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.machine_admins_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} MachineAdminCollection",
+      :machine_admins => CIMI::Model::MachineAdmin.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/machine_collection.rb b/server/lib/cimi/models/machine_collection.rb
new file mode 100644
index 0000000..9154aa9
--- /dev/null
+++ b/server/lib/cimi/models/machine_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineCollection < CIMI::Model::Base
+
+  act_as_root_entity :machine
+
+  array :machines do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.machines_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} MachineCollection",
+      :machines => CIMI::Model::Machine.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/machine_configuration.rb b/server/lib/cimi/models/machine_configuration.rb
new file mode 100644
index 0000000..f9d98f2
--- /dev/null
+++ b/server/lib/cimi/models/machine_configuration.rb
@@ -0,0 +1,70 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineConfiguration < CIMI::Model::Base
+
+  struct :memory do
+    scalar :quantity
+    scalar :units
+  end
+
+  text :cpu
+
+  array :disks do
+    struct :capacity do
+      scalar :quantity
+      scalar :units
+    end
+    scalar :format
+    scalar :attachment_point
+  end
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    profiles = []
+    if id == :all
+      profiles = context.driver.hardware_profiles(context.credentials)
+      profiles.map { |profile| from_hardware_profile(profile, context) }.compact
+    else
+      profile = context.driver.hardware_profile(context.credentials, id)
+      from_hardware_profile(profile, context)
+    end
+  end
+
+  private
+
+  def self.from_hardware_profile(profile, context)
+    # We accept just profiles with all properties set
+    return unless profile.memory or profile.cpu or profile.storage
+    memory = profile.memory.value || profile.memory.default
+    cpu = profile.cpu.value || profile.cpu.default
+    storage = profile.storage.value || profile.storage.default
+    machine_hash = {
+      :name => profile.name,
+      :description => "Machine Configuration with #{memory} #{profile.memory.unit} "+
+        "of memory and #{cpu} CPU",
+      :cpu => cpu,
+      :created => Time.now.to_s,  # FIXME: DC hardware_profile has no mention about created_at
+      :memory => { :quantity => profile.memory.value || profile.memory.default, :units => profile.memory.unit },
+      :disks => [ { :capacity => { :quantity => profile.storage.value || profile.storage.default, :units => profile.storage.unit } } ],
+      :id => context.machine_configuration_url(profile.name)
+    }
+    self.new(machine_hash)
+  end
+
+end
diff --git a/server/lib/cimi/models/machine_configuration_collection.rb b/server/lib/cimi/models/machine_configuration_collection.rb
new file mode 100644
index 0000000..6d7ebad
--- /dev/null
+++ b/server/lib/cimi/models/machine_configuration_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineConfigurationCollection < CIMI::Model::Base
+
+  act_as_root_entity :machine_configuration
+
+  array :machine_configurations do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.machine_configurations_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} MachineConfigurationCollection",
+      :machine_configurations => CIMI::Model::MachineConfiguration.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/machine_image.rb b/server/lib/cimi/models/machine_image.rb
new file mode 100644
index 0000000..7389475
--- /dev/null
+++ b/server/lib/cimi/models/machine_image.rb
@@ -0,0 +1,46 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineImage < CIMI::Model::Base
+
+  href :image_location
+  text :image_data
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    images = []
+    if id == :all
+      images = context.driver.images(context.credentials)
+      images.map { |image| from_image(image, context) }
+    else
+      image = context.driver.image(context.credentials, :id => id)
+      from_image(image, context)
+    end
+  end
+
+  def self.from_image(image, context)
+    self.new(
+      :name => image.id,
+      :id => context.machine_image_url(image.id),
+      :description => image.description,
+      :created => Time.now.to_s,
+      :image_location => { :href => "#{context.driver.name}://#{image.id}" } # FIXME
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/machine_image_collection.rb b/server/lib/cimi/models/machine_image_collection.rb
new file mode 100644
index 0000000..70bdc7b
--- /dev/null
+++ b/server/lib/cimi/models/machine_image_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineImageCollection < CIMI::Model::Base
+
+  act_as_root_entity :machine_image
+
+  array :machine_images do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.machine_images_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} MachineImageCollection",
+      :machine_images => CIMI::Model::MachineImage.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/machine_template.rb b/server/lib/cimi/models/machine_template.rb
new file mode 100644
index 0000000..8a88052
--- /dev/null
+++ b/server/lib/cimi/models/machine_template.rb
@@ -0,0 +1,41 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineTemplate < CIMI::Model::Base
+
+  href :machine_config
+  href :machine_image
+  href :machine_admin
+
+  array :volumes do
+    scalar :href
+    scalar :protocol
+    scalar :attachment_point
+  end
+
+  array :volume_templates do
+    scalar :href, :attachment_point, :protocol
+  end
+
+  array :network_interfaces do
+    href :vsp
+    text :hostname, :mac_address, :state, :protocol, :allocation
+    text :address, :default_gateway, :dns, :max_transmission_unit
+  end
+
+  array :operations do
+    scalar :rel, :href
+  end
+end
diff --git a/server/lib/cimi/models/machine_template_collection.rb b/server/lib/cimi/models/machine_template_collection.rb
new file mode 100644
index 0000000..d2a3f23
--- /dev/null
+++ b/server/lib/cimi/models/machine_template_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineTemplateCollection < CIMI::Model::Base
+
+  act_as_root_entity :machine_template
+
+  array :machine_templates do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.machine_template_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} MachineTemplateCollection",
+      :machine_templates => CIMI::Model::MachineTemplate.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/network.rb b/server/lib/cimi/models/network.rb
new file mode 100644
index 0000000..3d9c7ed
--- /dev/null
+++ b/server/lib/cimi/models/network.rb
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::Network < CIMI::Model::Base
+
+  text :state
+
+  text :access
+
+  text :bandwidth_limit
+
+  text :traffic_priority
+
+  text :max_traffic_delay
+
+  text :max_traffic_loss
+
+  text :max_traffic_jitter
+
+  href :routing_group
+
+  href :event_log
+
+  array :meters do
+    scalar :href
+  end
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    networks=[]
+    if id==:all
+      networks = context.driver.networks(context.credentials, {:env=>context})
+    else
+      networks = context.driver.networks(context.credentials, {:id=>id, :env=>context})
+    end
+    networks
+  end
+
+  def self.create(request_body, context, type)
+    input = (type == :xml)? XmlSimple.xml_in(request_body, {"ForceArray"=>false,"NormaliseSpace"=>2}) : JSON.parse(request_body)
+    if input["networkTemplate"]["href"] #template by reference
+      network_config, routing_group = get_by_reference(input, context)
+    else
+      if input["networkTemplate"]["networkConfig"]["href"] # configuration by reference
+        network_config = CIMI::Model::NetworkConfiguration.find(context.href_id(input["networkTemplate"]["networkConfig"]["href"],
+                                                                                :network_configurations), context)
+      else #configuration by value
+        network_config = get_by_value(request_body, type)
+      end
+      routing_group = CIMI::Model::RoutingGroup.find(context.href_id(input["networkTemplate"]["routingGroup"]["href"],
+                                                                     :routing_groups), context)
+    end
+    params = {:network_config => network_config, :routing_group => routing_group, :name=>input["name"],
+              :description=>input["description"], :env=>context}
+    raise CIMI::Model::BadRequest.new("Bad request - missing required parameters. Client sent: #{request_body} which produced #{params.inspect}")  if params.has_value?(nil)
+    context.driver.create_network(context.credentials, params)
+  end
+
+  def self.delete!(id, context)
+    context.driver.delete_network(context.credentials, id)
+  end
+
+  def perform(action, context, &block)
+    begin
+      if context.driver.send(:"#{action.name}_network", context.credentials, self.name)
+        block.callback :success
+      else
+        raise "Operation #{action.name} failed to execute on the Network #{self.name} "
+      end
+    rescue => e
+      block.callback :failure, e.message
+    end
+  end
+
+  private
+
+  def self.get_by_reference(input, context)
+    network_template = CIMI::Model::NetworkTemplate.find(context.href_id(input["networkTemplate"]["href"], :network_templates), context)
+    network_config = CIMI::Model::NetworkConfiguration.find(context.href_id(network_template.network_config.href, :network_configurations), context)
+    routing_group = CIMI::Model::RoutingGroup.find(context.href_id(network_template.routing_group.href, :routing_groups), context)
+    return network_config, routing_group
+  end
+
+  def self.get_by_value(request_body, type)
+    if type == :xml
+      xml_arrays = XmlSimple.xml_in(request_body, {"NormaliseSpace"=>2})
+      network_config = CIMI::Model::NetworkConfiguration.from_xml(XmlSimple.xml_out(xml_arrays["networkTemplate"][0]["networkConfig"][0]))
+    else
+     json = JSON.parse(request_body)
+      network_config = CIMI::Model::NetworkConfiguration.from_json(JSON.generate(json["networkTemplate"]["networkConfig"]))
+    end
+  end
+
+end
diff --git a/server/lib/cimi/models/network_collection.rb b/server/lib/cimi/models/network_collection.rb
new file mode 100644
index 0000000..d76a3dd
--- /dev/null
+++ b/server/lib/cimi/models/network_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::NetworkCollection < CIMI::Model::Base
+
+  act_as_root_entity :network
+
+  array :networks do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.networks_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} NetworkCollection",
+      :networks => CIMI::Model::Network.all(context).map { |c| { :href => c.id } }
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/network_configuration.rb b/server/lib/cimi/models/network_configuration.rb
new file mode 100644
index 0000000..1b04548
--- /dev/null
+++ b/server/lib/cimi/models/network_configuration.rb
@@ -0,0 +1,49 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::NetworkConfiguration < CIMI::Model::Base
+
+  text :access
+
+  text :bandwidth_limit
+
+  text :traffic_priority
+
+  text :max_traffic_delay
+
+  text :max_traffic_loss
+
+  text :max_traffic_jitter
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    network_configs = []
+    if id==:all
+      network_configs = context.driver.network_configurations(context.credentials, {:env=>context})
+    else
+      network_configs = context.driver.network_configurations(context.credentials, {:env=>context, :id=>id})
+    end
+    network_configs
+  end
+
+  def self.create_from_xml(request_body, context)
+  end
+
+  def self.create_from_json(request_body, context)
+  end
+end
diff --git a/server/lib/cimi/models/network_configuration_collection.rb b/server/lib/cimi/models/network_configuration_collection.rb
new file mode 100644
index 0000000..fc14592
--- /dev/null
+++ b/server/lib/cimi/models/network_configuration_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::NetworkConfigurationCollection < CIMI::Model::Base
+
+  act_as_root_entity :network_configuration
+
+  array :network_configurations do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.network_configurations_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} NetworkConfigurationCollection",
+      :network_configurations => CIMI::Model::NetworkConfiguration.all(context).map { |c| { :href => c.id } }
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/network_template.rb b/server/lib/cimi/models/network_template.rb
new file mode 100644
index 0000000..ce3b990
--- /dev/null
+++ b/server/lib/cimi/models/network_template.rb
@@ -0,0 +1,36 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::NetworkTemplate < CIMI::Model::Base
+
+  href :network_config
+
+  href :routing_group
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    network_templates = []
+    if id==:all
+      network_templates = context.driver.network_templates(context.credentials, {:env=>context})
+    else
+      network_templates = context.driver.network_templates(context.credentials, {:env=>context, :id=>id})
+    end
+    network_templates
+  end
+
+end
diff --git a/server/lib/cimi/models/network_template_collection.rb b/server/lib/cimi/models/network_template_collection.rb
new file mode 100644
index 0000000..b2ac537
--- /dev/null
+++ b/server/lib/cimi/models/network_template_collection.rb
@@ -0,0 +1,35 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+class CIMI::Model::NetworkTemplateCollection < CIMI::Model::Base
+
+  act_as_root_entity :network_template
+
+  array :network_templates do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.network_templates_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} NetworkTemplateCollection",
+      :network_templates => CIMI::Model::NetworkTemplate.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/routing_group.rb b/server/lib/cimi/models/routing_group.rb
new file mode 100644
index 0000000..d26f4d7
--- /dev/null
+++ b/server/lib/cimi/models/routing_group.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::RoutingGroup < CIMI::Model::Base
+
+  array :networks do
+    scalar :href
+  end
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.routing_groups(context.credentials, {:env=>context})
+    else
+      context.driver.routing_groups(context.credentials, {:env=>context, :id=>id})
+    end
+  end
+
+end
diff --git a/server/lib/cimi/models/routing_group_collection.rb b/server/lib/cimi/models/routing_group_collection.rb
new file mode 100644
index 0000000..285e164
--- /dev/null
+++ b/server/lib/cimi/models/routing_group_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::RoutingGroupCollection < CIMI::Model::Base
+
+  act_as_root_entity :routing_group
+
+  array :routing_groups do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.routing_groups_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} RoutingGroupCollection",
+      :routing_groups => CIMI::Model::RoutingGroup.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/routing_group_template.rb b/server/lib/cimi/models/routing_group_template.rb
new file mode 100644
index 0000000..204a353
--- /dev/null
+++ b/server/lib/cimi/models/routing_group_template.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::RoutingGroupTemplate < CIMI::Model::Base
+
+  array :networks do
+    scalar :href
+  end
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.routing_group_templates(context.credentials, {:env=>context})
+    else
+      context.driver.routing_group_templates(context.credentials, {:env=>context, :id=>id})
+    end
+  end
+
+end
diff --git a/server/lib/cimi/models/routing_group_template_collection.rb b/server/lib/cimi/models/routing_group_template_collection.rb
new file mode 100644
index 0000000..61a4a68
--- /dev/null
+++ b/server/lib/cimi/models/routing_group_template_collection.rb
@@ -0,0 +1,35 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+class CIMI::Model::RoutingGroupTemplateCollection < CIMI::Model::Base
+
+  act_as_root_entity :routing_group_template
+
+  array :routing_group_templates do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.routing_group_templates_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} RoutingGroupTemplateCollection",
+      :routing_group_templates => CIMI::Model::RoutingGroupTemplate.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
new file mode 100644
index 0000000..f301b69
--- /dev/null
+++ b/server/lib/cimi/models/schema.rb
@@ -0,0 +1,277 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+# The smarts of converting from XML and JSON into internal objects
+class CIMI::Model::Schema
+
+  #
+  # Attributes describe how we extract values from XML/JSON
+  #
+  class Attribute
+    attr_reader :name, :xml_name, :json_name
+
+    def initialize(name, opts = {})
+      @name = name
+      @xml_name = (opts[:xml_name] || name).to_s.camelize(true)
+      @json_name = (opts[:json_name] || name).to_s.camelize(true)
+    end
+
+    def from_xml(xml, model)
+      model[@name] = xml[@xml_name].first if xml.has_key?(@xml_name)
+    end
+
+    def from_json(json, model)
+      model[@name] = json[@json_name]
+    end
+
+    def to_xml(model, xml)
+      xml[@xml_name] = [model[@name]] if model[@name]
+    end
+
+    def to_json(model, json)
+      json[@json_name] = model[@name] if model and model[@name]
+    end
+  end
+
+  class Scalar < Attribute
+    def initialize(name, opts)
+      @text = opts[:text]
+      if ! [nil, :nested, :direct].include?(@text)
+        raise "text option for scalar must be :nested or :direct"
+      end
+      super(name, opts)
+    end
+
+    def text?; @text; end
+
+    def nested_text?; @text == :nested; end
+
+    def from_xml(xml, model)
+      case @text
+        when :nested then model[@name] = xml[@xml_name].first["content"] if xml[@xml_name]
+        when :direct then model[@name] = xml["content"]
+        else model[@name] = xml[@xml_name]
+      end
+    end
+
+    def to_xml(model, xml)
+      return unless model
+      return unless model[@name]
+      case @text
+        when :nested then xml[@xml_name] = [{ "content" => model[@name] }]
+        when :direct then xml["content"] = model[@name]
+        else xml[@xml_name] = model[@name]
+      end
+    end
+  end
+
+  class Struct < Attribute
+    def initialize(name, opts, &block)
+      content = opts[:content]
+      super(name, opts)
+      @schema = CIMI::Model::Schema.new
+      @schema.instance_eval(&block) if block_given?
+      @schema.scalar(content, :text => :direct) if content
+    end
+
+    def from_xml(xml, model)
+      xml = xml.has_key?(xml_name) ? xml[xml_name].first : {}
+      model[name] = convert_from_xml(xml)
+    end
+
+    def from_json(json, model)
+      json = json.has_key?(json_name) ? json[json_name] : {}
+      model[name] = convert_from_json(json)
+    end
+
+    def to_xml(model, xml)
+      conv = convert_to_xml(model[name])
+      xml[xml_name] = [conv] unless conv.empty?
+    end
+
+    def to_json(model, json)
+      conv = convert_to_json(model[name])
+      json[json_name] = conv unless conv.empty?
+    end
+
+    def convert_from_xml(xml)
+      sub = struct.new
+      @schema.from_xml(xml, sub)
+      sub
+    end
+
+    def convert_from_json(json)
+      sub = struct.new
+      @schema.from_json(json, sub)
+      sub
+    end
+
+    def convert_to_xml(model)
+      xml = {}
+      @schema.to_xml(model, xml)
+      xml
+    end
+
+    def convert_to_json(model)
+      json = {}
+      @schema.to_json(model, json)
+      json
+    end
+
+    private
+    def struct
+      cname = "CIMI_#{json_name.upcase_first}"
+      if ::Struct.const_defined?(cname)
+        ::Struct.const_get(cname)
+      else
+        ::Struct.new("CIMI_#{json_name.upcase_first}",
+                     *@schema.attribute_names)
+      end
+    end
+  end
+
+  class Array < Attribute
+    # For an array :things, we collect all <thing/> elements (XmlSimple
+    # actually does the collecting)
+    def initialize(name, opts = {}, &block)
+      opts[:xml_name] = name.to_s.singularize unless opts[:xml_name]
+      super(name, opts)
+      @struct = Struct.new(name, opts, &block)
+    end
+
+    def from_xml(xml, model)
+      model[name] = (xml[xml_name] || []).map { |elt| @struct.convert_from_xml(elt) }
+    end
+
+    def from_json(json, model)
+      model[name] = (json[json_name] || []).map { |elt| @struct.convert_from_json(elt) }
+    end
+
+    def to_xml(model, xml)
+      ary = (model[name] || []).map { |elt| @struct.convert_to_xml(elt) }
+      xml[xml_name] = ary unless ary.empty?
+    end
+
+    def to_json(model, json)
+      ary = (model[name] || []).map { |elt| @struct.convert_to_json(elt) }
+      json[json_name] = ary unless ary.empty?
+    end
+  end
+
+  class Hash < Attribute
+
+    def initialize(name, opts = {}, &block)
+      opts[:json_name] = name.to_s.pluralize unless opts[:json_name]
+      super(name, opts)
+      @struct = Struct.new(name, opts, &block)
+    end
+
+    def from_xml(xml, model)
+      model[name] = (xml[xml_name] || []).map { |elt| @struct.convert_from_xml(elt) }
+    end
+
+    def from_json(json, model)
+      model[name] = (json[json_name] || {}).inject([]) do |result,item|
+        result << @struct.convert_from_json({ 'name' => item[0], 'value' => item[1] })
+      end
+    end
+
+    def to_xml(model, xml)
+      ary = (model[name] || []).map { |elt| @struct.convert_to_xml(elt) }
+      xml[xml_name] = ary unless ary.empty?
+    end
+
+    def to_json(model, json)
+      ary = (model[name] || []).map { |elt| @struct.convert_to_json(elt) }
+      json[json_name] = ary.inject({}) { |result, item| result[item['name']] = item['value']; result } unless ary.empty?
+    end
+  end
+
+  #
+  # The actual Schema class
+  #
+  def initialize
+    @attributes = []
+  end
+
+  def from_xml(xml, model = {})
+    @attributes.freeze
+    @attributes.each { |attr| attr.from_xml(xml, model) }
+    model
+  end
+
+  def from_json(json, model = {})
+    @attributes.freeze
+    @attributes.each { |attr| attr.from_json(json, model) }
+    model
+  end
+
+  def to_xml(model, xml = {})
+    @attributes.freeze
+    @attributes.each { |attr| attr.to_xml(model, xml) }
+    xml
+  end
+
+  def to_json(model, json = {})
+    @attributes.freeze
+    @attributes.each { |attr| attr.to_json(model, json) }
+    json
+  end
+
+  def attribute_names
+    @attributes.map { |a| a.name }
+  end
+
+  #
+  # The DSL
+  #
+  # Requires that the class into which this is included has a
+  # +add_attributes!+ method
+  module DSL
+    def href(*args)
+      args.each { |arg| struct(arg) { scalar :href } }
+    end
+
+    def text(*args)
+      args.expand_opts!(:text => :nested)
+      scalar(*args)
+    end
+
+    def scalar(*args)
+      add_attributes!(args, Scalar)
+    end
+
+    def array(name, opts={}, &block)
+      add_attributes!([name, opts], Array, &block)
+    end
+
+    def struct(name, opts={}, &block)
+      add_attributes!([name, opts], Struct, &block)
+    end
+
+    def hash(name, opts={}, &block)
+      add_attributes!([name, opts], Hash, &block)
+    end
+  end
+
+  include DSL
+
+  def add_attributes!(args, attr_klass, &block)
+    raise "The schema has already been used to convert objects" if @attributes.frozen?
+    opts = args.extract_opts!
+    args.each { |arg| @attributes << attr_klass.new(arg, opts, &block) }
+  end
+end
diff --git a/server/lib/cimi/models/volume.rb b/server/lib/cimi/models/volume.rb
new file mode 100644
index 0000000..9c106e2
--- /dev/null
+++ b/server/lib/cimi/models/volume.rb
@@ -0,0 +1,103 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::Volume < CIMI::Model::Base
+
+  struct :capacity do
+    scalar :quantity
+    scalar :units
+  end
+  text :bootable
+  text :supports_snapshots
+  array :snapshots do
+    scalar :ref
+  end
+  text :guest_interface
+  array :meters do
+    scalar :ref
+  end
+  href :eventlog
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    volumes = []
+    opts = ( id == :all ) ? {} : { :id => id }
+    volumes = context.driver.storage_volumes(context.credentials, opts)
+    volumes.collect!{ |volume| from_storage_volume(volume, context) }
+    return volumes.first unless volumes.length > 1
+    return volumes
+  end
+
+  def self.all(context); find(:all, context); end
+
+  def self.create_from_json(json_in, context)
+    json = JSON.parse(json_in)
+    volume_config_id = json["volumeTemplate"]["volumeConfig"]["href"].split("/").last
+    volume_image_id = (json["volumeTemplate"].has_key?("volumeImage") ?
+                json["volumeTemplate"]["volumeImage"]["href"].split("/").last  : nil)
+    create_volume({:volume_config_id=>volume_config_id, :volume_image_id=>volume_image_id}, context)
+  end
+
+  def self.create_from_xml(xml_in, context)
+    xml = XmlSimple.xml_in(xml_in)
+    volume_config_id = xml["volumeTemplate"][0]["volumeConfig"][0]["href"].split("/").last
+    volume_image_id = (xml["volumeTemplate"][0].has_key?("volumeImage") ?
+             xml["volumeTemplate"][0]["volumeImage"][0]["href"].split("/").last  : nil)
+    create_volume({:volume_config_id=>volume_config_id, :volume_image_id=>volume_image_id}, context)
+  end
+
+  def self.delete!(id, context)
+    context.driver.destroy_storage_volume(context.credentials, {:id=>id} )
+  end
+
+  def self.find_to_attach_from_json(json_in, context)
+    json = JSON.parse(json_in)
+    volumes = json["volumes"].map{|v| {:volume=>self.find(v["volume"]["href"].split("/volumes/").last, context),
+                                       :attachment_point=>v["attachmentPoint"]  }}
+  end
+
+  def self.find_to_attach_from_xml(xml_in, context)
+    xml = XmlSimple.xml_in(xml_in)
+    volumes = xml["volume"].map{|v| {:volume => self.find(v["href"].split("/volumes/").last, context),
+                                      :attachment_point=>v["attachmentPoint"] }}
+  end
+
+  private
+
+  def self.create_volume(params, context)
+    volume_config = CIMI::Model::VolumeConfiguration.find(params[:volume_config_id], context)
+    opts = {:capacity=>volume_config.capacity[:quantity], :snapshot_id=>params[:volume_image_id] }
+    storage_volume = self.driver.create_storage_volume(context.credentials, opts)
+    from_storage_volume(storage_volume, context)
+  end
+
+  def self.from_storage_volume(volume, context)
+    self.new( { :name => volume.id,
+                :description => volume.id,
+                :created => volume.created,
+                :id => context.volume_url(volume.id),
+                :capacity => { :quantity=>volume.capacity, :units=>"gibibyte"  }, #FIXME... units will vary
+                :bootable => "false", #fixme ... will vary... ec2 doesn't expose this
+                :supports_snapshots => "true", #fixme, will vary (true for ec2)
+                :snapshots => [], #fixme...
+                :guest_interface => "",
+                :eventlog => {:href=> "http://eventlogs"},#FIXME
+                :meters => []
+            } )
+  end
+
+end
diff --git a/server/lib/cimi/models/volume_collection.rb b/server/lib/cimi/models/volume_collection.rb
new file mode 100644
index 0000000..1f4152e
--- /dev/null
+++ b/server/lib/cimi/models/volume_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::VolumeCollection < CIMI::Model::Base
+
+  act_as_root_entity :volume
+
+  array :volumes do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.volumes_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} VolumeCollection",
+      :volumes => CIMI::Model::Volume.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/volume_configuration.rb b/server/lib/cimi/models/volume_configuration.rb
new file mode 100644
index 0000000..75b37ea
--- /dev/null
+++ b/server/lib/cimi/models/volume_configuration.rb
@@ -0,0 +1,60 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::VolumeConfiguration < CIMI::Model::Base
+
+  text :format
+  struct :capacity do
+    scalar :quantity
+    scalar :units
+  end
+  text :supports_snapshots
+  text :guest_interface
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    volume_configs = []
+    if id == :all
+      #ec2 ebs volumes can 1gb..1tb
+      (1..1000).each do |size|
+        volume_configs << create(size, context)
+      end
+    else
+      volume_configs << create(id, context)
+      return volume_configs.first
+    end
+    return volume_configs
+  end
+
+
+  def self.all(context); find(:all, context); end
+
+  private
+
+  def self.create(size, context)
+    self.new( {
+                :id => context.volume_configuration_url(size),
+                :name => size,
+                :description => "volume configuration with #{size} GiB",
+                :created => Time.now.to_s,
+                :capacity => {:quantity=>size, :units=>"gibibytes"},
+                :supports_snapshots => "true"
+                # FIXME :guest_interface => "NFS"
+            } )
+  end
+
+end
diff --git a/server/lib/cimi/models/volume_configuration_collection.rb b/server/lib/cimi/models/volume_configuration_collection.rb
new file mode 100644
index 0000000..2120ae6
--- /dev/null
+++ b/server/lib/cimi/models/volume_configuration_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::VolumeConfigurationCollection < CIMI::Model::Base
+
+  act_as_root_entity :volume_configuration
+
+  array :volume_configurations do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.volume_configurations_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} VolumeConfigurationCollection",
+      :volume_configurations => CIMI::Model::VolumeConfiguration.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/volume_image.rb b/server/lib/cimi/models/volume_image.rb
new file mode 100644
index 0000000..03cc7fd
--- /dev/null
+++ b/server/lib/cimi/models/volume_image.rb
@@ -0,0 +1,49 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::VolumeImage < CIMI::Model::Base
+
+  href :image_location
+  text :image_data
+  text :bootable
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    storage_snapshots = []
+    opts = ( id==:all  ) ? {}  : { :id=>id }
+    storage_snapshots = self.driver.storage_snapshots(context.credentials, opts)
+    storage_snapshots.collect!{ |snapshot| from_storage_snapshot(snapshot, context) }
+    return storage_snapshots.first unless storage_snapshots.length > 1
+    return storage_snapshots
+  end
+
+  def self.all(context); find(:all, context); end
+
+  private
+
+  def self.from_storage_snapshot(snapshot, context)
+    self.new( {
+               :name => snapshot.id,
+               :description => snapshot.id,
+               :created => snapshot.created,
+               :id => context.volume_image_url(snapshot.id),
+               :image_location => {:href=>context.volume_url(snapshot.storage_volume_id)},
+               :bootable => "false"  #FIXME
+            } )
+  end
+
+end
diff --git a/server/lib/cimi/models/volume_image_collection.rb b/server/lib/cimi/models/volume_image_collection.rb
new file mode 100644
index 0000000..f3da877
--- /dev/null
+++ b/server/lib/cimi/models/volume_image_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::VolumeImageCollection < CIMI::Model::Base
+
+  act_as_root_entity :volume_image
+
+  array :volume_images do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.volume_images_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} VolumeImageCollection",
+      :volume_images => CIMI::Model::VolumeImage.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/volume_template.rb b/server/lib/cimi/models/volume_template.rb
new file mode 100644
index 0000000..b9c82db
--- /dev/null
+++ b/server/lib/cimi/models/volume_template.rb
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::VolumeTemplate < CIMI::Model::Base
+
+  href :volume_config
+  href :volume_image
+  array :operations do
+    scalar :rel, :href
+  end
+end
diff --git a/server/lib/cimi/models/volume_template_collection.rb b/server/lib/cimi/models/volume_template_collection.rb
new file mode 100644
index 0000000..f53547c
--- /dev/null
+++ b/server/lib/cimi/models/volume_template_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::VolumeTemplateCollection < CIMI::Model::Base
+
+  act_as_root_entity :volume_template
+
+  array :volume_templates do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.volume_template_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} VolumeTemplateCollection",
+      :volume_templates => CIMI::Model::VolumeTemplate.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/vsp.rb b/server/lib/cimi/models/vsp.rb
new file mode 100644
index 0000000..b8b27f5
--- /dev/null
+++ b/server/lib/cimi/models/vsp.rb
@@ -0,0 +1,102 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::VSP < CIMI::Model::Base
+
+  text :state
+
+  href :network
+
+  text :bandwidth_reservation
+
+  text :traffic_priority
+
+  text :max_traffic_delay
+
+  text :max_traffic_loss
+
+  text :max_traffic_jitter
+
+  href :event_log
+
+  array :meters do
+    scalar :href
+  end
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.vsps(context.credentials, {:env=>context})
+    else
+      context.driver.vsps(context.credentials, {:id=>id, :env=>context})
+    end
+  end
+
+  def self.create(request_body, context, type)
+    input = (type == :xml)? XmlSimple.xml_in(request_body, {"ForceArray"=>false, "NormaliseSpace"=>2}) : JSON.parse(request_body)
+    if input["vspTemplate"]["href"] #template by reference
+      vsp_config, network = get_by_reference(input, context)
+    else
+      if input["vspTemplate"]["vspConfig"]["href"] # configuration by reference
+        vsp_config = CIMI::Model::VSPConfiguration.find(context.href_id(input["vspTemplate"]["vspConfig"]["href"],:vsp_configurations), context)
+      else #configuration by value
+        vsp_config = get_by_value(request_body, type)
+      end
+      network = CIMI::Model::Network.find(context.href_id(input["vspTemplate"]["network"]["href"], :networks), context)
+    end
+    params = {:vsp_config => vsp_config, :network => network, :name=>input["name"], :description=>input["description"], :env=>context}
+    raise CIMI::Model::BadRequest.new("Bad request - missing required parameters. Client sent: #{request_body} which produced #{params.inspect}")  if params.has_value?(nil)
+    context.driver.create_vsp(context.credentials, params)
+  end
+
+  def self.delete!(id, context)
+    context.driver.delete_vsp(context.credentials, id)
+  end
+
+  def perform(action, context, &block)
+    begin
+      if context.driver.send(:"#{action.name}_vsp", context.credentials, self.name)
+        block.callback :success
+      else
+        raise "Operation #{action.name} failed to execute on the VSP #{self.name} "
+      end
+    rescue => e
+      block.callback :failure, e.message
+    end
+  end
+
+
+  private
+
+  def self.get_by_reference(input, context)
+    vsp_template = CIMI::Model::VSPTemplate.find(context.href_id(input["vspTemplate"]["href"], :vsp_templates), context)
+    vsp_config = CIMI::Model::VSPConfiguration.find(context.href_id(vsp_template.vsp_config.href, :vsp_configurations), context)
+    network = CIMI::Model::Network.find(context.href_id(vsp_template.network.href, :networks), context)
+    return vsp_config, network
+  end
+
+  def self.get_by_value(request_body, type)
+    if type == :xml
+      xml_arrays = XmlSimple.xml_in(request_body, {"NormaliseSpace"=>2})
+      vsp_config = CIMI::Model::VSPConfiguration.from_xml(XmlSimple.xml_out(xml_arrays["vspTemplate"][0]["vspConfig"][0]))
+    else
+     json = JSON.parse(request_body)
+      vsp_config = CIMI::Model::VSPConfiguration.from_json(JSON.generate(json["vspTemplate"]["vspConfig"]))
+    end
+  end
+end
diff --git a/server/lib/cimi/models/vsp_collection.rb b/server/lib/cimi/models/vsp_collection.rb
new file mode 100644
index 0000000..fc72024
--- /dev/null
+++ b/server/lib/cimi/models/vsp_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::VSPCollection < CIMI::Model::Base
+
+  CIMI::Model.register_as_root_entity! "VSPs"
+
+  array :vsps do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.vsps_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} VSPCollection",
+      :vsps => CIMI::Model::VSP.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/vsp_configuration.rb b/server/lib/cimi/models/vsp_configuration.rb
new file mode 100644
index 0000000..c9a9bf3
--- /dev/null
+++ b/server/lib/cimi/models/vsp_configuration.rb
@@ -0,0 +1,40 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::VSPConfiguration < CIMI::Model::Base
+
+  text :bandwidth_reservation
+
+  text :traffic_priority
+
+  text :max_traffic_delay
+
+  text :max_traffic_loss
+
+  text :max_traffic_jitter
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.vsp_configurations(context.credentials, {:env=>context})
+    else
+      context.driver.vsp_configurations(context.credentials, {:env=>context, :id=>id})
+    end
+  end
+
+end
diff --git a/server/lib/cimi/models/vsp_configuration_collection.rb b/server/lib/cimi/models/vsp_configuration_collection.rb
new file mode 100644
index 0000000..d4927e7
--- /dev/null
+++ b/server/lib/cimi/models/vsp_configuration_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::VSPConfigurationCollection < CIMI::Model::Base
+
+  CIMI::Model.register_as_root_entity! "VSPConfigurations"
+
+  array :vsp_configurations do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.vsp_configurations_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} VSPConfigurationCollection",
+      :vsp_configurations => CIMI::Model::VSPConfiguration.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/vsp_template.rb b/server/lib/cimi/models/vsp_template.rb
new file mode 100644
index 0000000..f1b8078
--- /dev/null
+++ b/server/lib/cimi/models/vsp_template.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::VSPTemplate < CIMI::Model::Base
+
+  href :network
+
+  href :vsp_config
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.vsp_templates(context.credentials, {:env=>context})
+    else
+      context.driver.vsp_templates(context.credentials, {:env=>context, :id=>id})
+    end
+  end
+
+end
diff --git a/server/lib/cimi/models/vsp_template_collection.rb b/server/lib/cimi/models/vsp_template_collection.rb
new file mode 100644
index 0000000..61d5311
--- /dev/null
+++ b/server/lib/cimi/models/vsp_template_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::VSPTemplateCollection < CIMI::Model::Base
+
+  CIMI::Model.register_as_root_entity! "VSPTemplates"
+
+  array :vsp_templates do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.vsp_templates_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} VSPTemplateCollection",
+      :vsp_templates => CIMI::Model::VSPTemplate.all_uri(context)
+    )
+  end
+
+end
diff --git a/server/lib/cimi/server.rb b/server/lib/cimi/server.rb
index 60f9a3b..a1c7ef9 100644
--- a/server/lib/cimi/server.rb
+++ b/server/lib/cimi/server.rb
@@ -13,947 +13,48 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-require 'cimi/dependencies'
-require 'cimi/helpers/cimi_helper'
-require 'cimi/model'
+require 'rubygems'
+require 'crack'
+require 'json'
+require 'yaml'
+require 'haml'
+require 'sinatra/base'
+require 'sinatra/rabbit'
+require_relative '../sinatra'
 
-set :version, '0.1.0'
+require_relative './helpers'
+require_relative './collections'
 
-include Deltacloud::Drivers
-include CIMI::Model
+CMWG_NAMESPACE = "http://www.dmtf.org/cimi"
 
-set :drivers, Proc.new { driver_config }
+module CIMI
+  class API < Collections::Base
 
-Sinatra::Application.register Rack::RespondTo
+    # Enable logging
+    use Rack::CommonLogger
+    use Rack::Date
+    use Rack::ETag
+    use Rack::MatrixParams
+    use Rack::DriverSelect
+    use Rack::Accept
+    use Rack::MediaType
 
-use Rack::ETag
-use Rack::Runtime
-use Rack::MatrixParams
-use Rack::DriverSelect
-use Rack::MediaType
-use Rack::Date
-use Rack::CIMI
+    helpers CIMIHelper
 
-configure do
-  set :root_url, "/cimi"
-  set :views, File::join($top_srcdir, 'views', 'cimi')
-  set :public_folder, File::join($top_srcdir, 'public')
-  driver
-end
-
-configure :production do
-  use Rack::SyslogLogger
-  disable :logging
-  enable :show_errors
-  set :dump_errors, false
-  $stdout = SyslogFile.new
-  $stderr = $stdout
-end
-
-configure :development do
-  set :raise_errors => false
-  set :show_exceptions, false
-  $stdout.sync = true
-  $stderr.sync = true
-end
-
-# You could use $API_HOST environment variable to change your hostname to
-# whatever you want (eg. if you running API behind NAT)
-HOSTNAME=ENV['API_HOST'] ? ENV['API_HOST'] : nil
-
-error do
-  report_error
-end
-
-get "/" do
-  redirect settings.root_url
-end
-
-get "#{settings.root_url}\/?" do
-  halt 401 if params[:force_auth] and not driver.valid_credentials?(credentials)
-  redirect cloudEntryPoint_url, 301
-end
+    include Deltacloud::Helpers
+    include CIMI::Collections
+    include CIMI::Model
 
-global_collection  :cloudEntryPoint do
-  description 'Cloud entry point'
-  operation :index do
-    description "list all resources of the cloud"
-    control do
-      entry_point = CloudEntryPoint.create(self)
+    get API_ROOT_URL do
+      if params[:force_auth]
+        return [401, 'Authentication failed'] unless driver.valid_credentials?(credentials)
+      end
+      entry_point = CIMI::Model::CloudEntryPoint.create(self)
       respond_to do |format|
         format.xml { entry_point.to_xml }
         format.json { entry_point.to_json }
       end
     end
-  end
-end
-
-global_collection :machine_configurations do
-  description 'List all machine configurations'
-
-  operation :index do
-    param :CIMISelect,  :string,  :optional
-    description "List all machine configurations"
-    control do
-      machine_configs = MachineConfigurationCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml { machine_configs.to_xml }
-        format.json { machine_configs.to_json }
-      end
-    end
-  end
-
-  operation :show do
-
-    description "The Machine Configuration entity represents the set of configuration values "+
-      "that define the (virtual) hardware resources of a to-be-realized Machine Instance.."
-
-    param :id, :string, :required
-
-    control do
-      machine_conf = MachineConfiguration.find(params[:id], self)
-      respond_to do |format|
-        format.xml { machine_conf.to_xml }
-        format.json { machine_conf.to_json }
-      end
-    end
-
-  end
-end
-
-global_collection :machine_images do
-  description 'List all machine images'
-
-  operation :index do
-    description "List all machine configurations"
-    param :CIMISelect,  :string,  :optional
-    control do
-      machine_images = MachineImageCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml { machine_images.to_xml }
-        format.json { machine_images.to_json }
-      end
-    end
-  end
-
-  operation :show do
-    description "Show specific machine image."
-    param :id,          :string,    :required
-    control do
-      machine_image = MachineImage.find(params[:id], self)
-      respond_to do |format|
-        format.xml { machine_image.to_xml }
-        format.json { machine_image.to_json }
-      end
-    end
-  end
-
-end
-
-global_collection :machine_admins do
-  description 'Machine Admin entity'
-
-  operation :index do
-    description "List all machine admins"
-    param :CIMISelect,  :string,  :optional
-    with_capability :keys
-    control do
-      machine_admins = MachineAdminCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml { machine_admins.to_xml }
-        format.json { machine_admins.to_json }
-      end
-    end
-  end
-
-  operation :show do
-    description "Show specific machine admin"
-    param :id,          :string,    :required
-    with_capability :key
-    control do
-      machine_admin = MachineAdmin.find(params[:id], self)
-      respond_to do |format|
-        format.xml { machine_admin.to_xml }
-        format.json { machine_admin.to_json }
-      end
-    end
-  end
-
-  operation :create do
-    description "Show specific machine admin"
-    with_capability :create_key
-    control do
-      if request.content_type.end_with?("+json")
-        new_admin = MachineAdmin.create_from_json(request.body.read, self)
-      else
-        new_admin = MachineAdmin.create_from_xml(request.body.read, self)
-      end
-      status 201 # Created
-      respond_to do |format|
-        format.json { new_admin.to_json }
-        format.xml { new_admin.to_xml }
-      end
-    end
-  end
-
-  operation :delete, :method => :delete, :member => true do
-    description "Delete specified MachineAdmin entity"
-    param :id,          :string,    :required
-    control do
-      MachineAdmin.delete!(params[:id], self)
-      no_content_with_status(200)
-    end
-  end
-
-end
-
-global_collection :machines do
-  description 'List all machine'
-
-  operation :index do
-    param :CIMISelect,  :string,  :optional
-    description "List all machines"
-    control do
-      machines = MachineCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml { machines.to_xml }
-        format.json { machines.to_json }
-      end
-    end
-  end
-
-  operation :show do
-    description "Show specific machine."
-    param :id,          :string,    :required
-    control do
-      machine = Machine.find(params[:id], self)
-      respond_to do |format|
-        format.xml { machine.to_xml }
-        format.json { machine.to_json }
-      end
-    end
-  end
 
-  operation :create do
-    description "Create a new Machine entity."
-    control do
-      if request.content_type.end_with?("+json")
-        new_machine = Machine.create_from_json(request.body.read, self)
-      else
-        new_machine = Machine.create_from_xml(request.body.read, self)
-      end
-      status 201 # Created
-      respond_to do |format|
-        format.json { new_machine.to_json }
-        format.xml { new_machine.to_xml }
-      end
-    end
   end
-
-  operation :destroy do
-    description "Delete a specified machine."
-    param :id,          :string,    :required
-    control do
-      Machine.delete!(params[:id], self)
-      no_content_with_status(200)
-    end
-  end
-
-  operation :stop, :method => :post, :member => true do
-    description "Stop specific machine."
-    param :id,          :string,    :required
-    control do
-      machine = Machine.find(params[:id], self)
-      if request.content_type.end_with?("+json")
-        action = Action.from_json(request.body.read)
-      else
-        action = Action.from_xml(request.body.read)
-      end
-      machine.perform(action, self) do |operation|
-        no_content_with_status(202) if operation.success?
-        # Handle errors using operation.failure?
-      end
-    end
-  end
-
-  operation :restart, :method => :post, :member => true do
-    description "Start specific machine."
-    param :id,          :string,    :required
-    control do
-      machine = Machine.find(params[:id], self)
-      if request.content_type.end_with?("+json")
-        action = Action.from_json(request.body.read)
-      else
-        action = Action.from_xml(request.body.read)
-      end
-      machine.perform(action, self) do |operation|
-        no_content_with_status(202) if operation.success?
-        # Handle errors using operation.failure?
-      end
-    end
-  end
-
-  operation :start, :method => :post, :member => true do
-    description "Start specific machine."
-    param :id,          :string,    :required
-    control do
-      machine = Machine.find(params[:id], self)
-      if request.content_type.end_with?("+json")
-        action = Action.from_json(request.body.read)
-      else
-        action = Action.from_xml(request.body.read)
-      end
-      machine.perform(action, self) do |operation|
-        no_content_with_status(202) if operation.success?
-        # Handle errors using operation.failure?
-      end
-    end
-  end
-
-#NOTE: The routes for attach/detach used here are NOT as specified by CIMI
-#will likely move later. CIMI specifies PUT of the whole Machine description
-#with inclusion/ommission of the volumes you want [att|det]ached
-  operation :attach_volume, :method => :put, :member => true do
-    description "Attach CIMI Volume(s) to a machine."
-    param :id, :string, :required
-    control do
-      if request.content_type.end_with?("+json")
-        volumes_to_attach = Volume.find_to_attach_from_json(request.body.read, self)
-      else
-        volumes_to_attach = Volume.find_to_attach_from_xml(request.body.read, self)
-      end
-      machine = Machine.attach_volumes(volumes_to_attach, self)
-      respond_to do |format|
-        format.json{ machine.to_json}
-        format.xml{machine.to_xml}
-      end
-    end
-  end
-
-  operation :detach_volume, :method => :put, :member => true do
-    description "Detach CIMI Volume(s) from a machine."
-    param :id, :string, :required
-    control do
-      if request.content_type.end_with?("+json")
-        volumes_to_detach = Volume.find_to_attach_from_json(request.body.read, self)
-      else
-        volumes_to_detach = Volume.find_to_attach_from_xml(request.body.read, self)
-      end
-      machine = Machine.detach_volumes(volumes_to_detach, self)
-      respond_to do |format|
-        format.json{ machine.to_json}
-        format.xml{machine.to_xml}
-      end
-    end
-  end
-end
-
-global_collection :volumes do
-  description "Volume represents storage at either the block or file-system level. Volumes can be attached to Machines. Once attached, Volumes can be accessed by processes on that Machine"
-
-  operation :index do
-    description "List all volumes"
-    param :CIMISelect,  :string,  :optional
-    control do
-      volumes = VolumeCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml { volumes.to_xml }
-        format.json { volumes.to_json }
-      end
-    end
-  end
-
-  operation :show do
-    description "Show specific Volume."
-    param :id, :string, :required
-    control do
-      volume = Volume.find(params[:id], self)
-      if volume
-        respond_to do |format|
-          format.xml  { volume.to_xml  }
-          format.json { volume.to_json }
-        end
-      else
-        report_error(404)
-      end
-    end
-  end
-
-  operation :create do
-    description "Create a new Volume."
-    control do
-      content_type = (request.content_type.end_with?("+json") ? :json  : :xml)
-          #((request.content_type.end_with?("+xml")) ? :xml : report_error(415) ) FIXME
-      case content_type
-        when :json
-          new_volume = Volume.create_from_json(request.body.read, self)
-        when :xml
-          new_volume = Volume.create_from_xml(request.body.read, self)
-      end
-      respond_to do |format|
-        format.json { new_volume.to_json }
-        format.xml { new_volume.to_xml }
-      end
-    end
-  end
-
-  operation :destroy do
-    description "Delete a specified Volume"
-    param :id, :string, :required
-    control do
-      Volume.delete!(params[:id], self)
-      no_content_with_status(200)
-    end
-  end
-
-end
-
-global_collection :volume_configurations do
-  description "The Volume Configuration entity represents the set of configuration values needed to create a Volume with certain characteristics. Volume Configurations are created by Providers and MAY, at the Providers discretion, be created by Consumers"
-
-  operation :index do
-    description "Get list all VolumeConfigurations"
-    param :CIMISelect,  :string,  :optional
-    control do
-      volume_configuration = VolumeConfigurationCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml { volume_configuration.to_xml }
-        format.json { volume_configuration.to_json }
-      end
-    end
-  end
-
-  operation :show do
-    description "Get a specific VolumeConfiguration"
-    param :id, :required, :string
-    control do
-      volume_config = VolumeConfiguration.find(params[:id], self)
-      respond_to do |format|
-        format.xml { volume_config.to_xml }
-        format.json { volume_config.json }
-      end
-    end
-  end
-
-global_collection :volume_images do
-  description 'This entity represents an image that could be place on a pre-loaded volume.'
-
-  operation :index do
-    description "List all volumes images"
-    param :CIMISelect,  :string,  :optional
-    control do
-      volume_images = VolumeImageCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml { volume_images.to_xml }
-        format.json { volume_images.to_json }
-      end
-    end
-  end
-
-  operation :show do
-    description "Show a specific volume image"
-    param :id, :string, :required
-    control do
-      volume_image = VolumeImage.find(params[:id], self)
-      respond_to do |format|
-        format.xml { volume_image.to_xml }
-        format.json { volume_image.to_json }
-      end
-    end
-  end
-
-end
-
-
-global_collection :entity_metadata do
-  description 'This allows for the discovery of Provider defined constraints on the CIMI defined attributes as well as discovery of any new extension attributes that the Provider may have defined.'
-
-  operation :index do
-    description "List all entity metadata defined for this provider"
-    control do
-      entity_metadata = EntityMetadataCollection.default(self)
-      respond_to do |format|
-        format.xml{entity_metadata.to_xml}
-        format.json{entity_metadata.to_json}
-      end
-    end
-  end
-
-  operation :show do
-    description "Get the entity metadata for a specific collection"
-    param :id, :required, :string
-    control do
-      entity_metadata = EntityMetadata.find(params[:id], self)
-      respond_to do |format|
-        format.xml{entity_metadata.to_xml}
-        format.json{entity_metadata.to_json}
-      end
-    end
-  end
-
-end
-
-global_collection :networks do
-  description 'A Network represents an abstraction of a layer 2 broadcast domain'
-
-  operation :index do
-    description "List all Networks"
-    param :CIMISelect,  :string,  :optional
-    control do
-      networks = NetworkCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml { networks.to_xml }
-        format.json { networks.to_json }
-      end
-    end
-  end
-
-  operation :show do
-    description "Show a specific Network"
-    param :id, :string, :required
-    control do
-      network = Network.find(params[:id], self)
-      respond_to do |format|
-        format.xml { network.to_xml }
-        format.json { network.to_json }
-      end
-    end
-  end
-
-  operation :create do
-    description "Create a new Network"
-    control do
-      if request.content_type.end_with?("json")
-        network = Network.create(request.body.read, self, :json)
-      else
-        network = Network.create(request.body.read, self, :xml)
-      end
-      respond_to do |format|
-        format.xml { network.to_xml}
-        format.json { network.to_json }
-      end
-    end
-  end
-
-  operation :destroy do
-    description "Delete a specified Network"
-    param :id, :string, :required
-    control do
-      Network.delete!(params[:id], self)
-      no_content_with_status(200)
-    end
-  end
-
-  operation :start, :method => :post, :member => true do
-    description "Start specific network."
-    param :id,          :string,    :required
-    control do
-      network = Network.find(params[:id], self)
-      report_error(404) unless network
-      if request.content_type.end_with?("json")
-        action = Action.from_json(request.body.read)
-      else
-        action = Action.from_xml(request.body.read)
-      end
-      network.perform(action, self) do |operation|
-        no_content_with_status(202) if operation.success?
-        # Handle errors using operation.failure?
-      end
-    end
-  end
-
-  operation :stop, :method => :post, :member => true do
-    description "Stop specific network."
-    param :id,          :string,    :required
-    control do
-      network = Network.find(params[:id], self)
-      report_error(404) unless network
-      if request.content_type.end_with?("json")
-        action = Action.from_json(request.body.read)
-      else
-        action = Action.from_xml(request.body.read)
-      end
-      network.perform(action, self) do |operation|
-        no_content_with_status(202) if operation.success?
-        # Handle errors using operation.failure?
-      end
-    end
-  end
-
-  operation :suspend, :method => :post, :member => true do
-    description "Suspend specific network."
-    param :id,          :string,    :required
-    control do
-      network = Network.find(params[:id], self)
-      report_error(404) unless network
-      if request.content_type.end_with?("json")
-        action = Action.from_json(request.body.read)
-      else
-        action = Action.from_xml(request.body.read)
-      end
-      network.perform(action, self) do |operation|
-        no_content_with_status(202) if operation.success?
-        # Handle errors using operation.failure?
-      end
-    end
-  end
-
-end
-
-global_collection :network_configurations do
-  description 'Network Configurations contain the set of configuration values representing the information needed to create a Network with certain characteristics'
-
-  operation :index do
-    description 'List all NetworkConfigurations'
-    param :CIMISelect, :string, :optional
-    control do
-      network_configurations = NetworkConfigurationCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml { network_configurations.to_xml  }
-        format.json { network_configurations.to_json }
-      end
-    end
-  end
-
-  operation :show do
-    description 'Show a specific NetworkConfiguration'
-    param :id, :string, :required
-    control do
-      network_config = NetworkConfiguration.find(params[:id], self)
-      respond_to do |format|
-        format.xml { network_config.to_xml }
-        format.json { network_config.to_json }
-      end
-    end
-  end
-end
-end
-
-global_collection :network_templates do
-
-  description 'Network Template is a set of configuration values for realizing a Network. An instance of Network Template may be used to create multiple Networks'
-
-  operation :index do
-    description 'List all Network Templates in the NetworkTemplateCollection'
-    param :CIMISelect, :string, :optional
-    control do
-      network_templates = NetworkTemplateCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml {network_templates.to_xml}
-        format.json {network_templates.to_json}
-      end
-    end
-  end
-
-  operation :show do
-    description 'Show a specific Network Template'
-    param :id, :string, :required
-    control do
-      network_template = NetworkTemplate.find(params[:id], self)
-      respond_to do |format|
-        format.xml {network_template.to_xml}
-        format.json {network_template.to_json}
-      end
-    end
-  end
-
-end
-
-
-global_collection :routing_groups do
-
-  description 'Routing Groups represent a collection of Networks that route to each other. Providers shall not allow two Networks to be routable to each other unless they are explicitly connected by being part of a common RoutingGroup.'
-
-  operation :index do
-    description 'List all RoutingGroups in the RoutingGroupsCollection'
-    param :CIMISelect, :string, :optional
-    control do
-      routing_groups = RoutingGroupCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml {routing_groups.to_xml}
-        format.json {routing_groups.to_json}
-      end
-    end
-  end
-
-  operation :show do
-    description 'Show a specific RoutingGroup'
-    param :id, :string, :required
-    control do
-      routing_group = RoutingGroup.find(params[:id], self)
-      respond_to do |format|
-        format.xml {routing_group.to_xml}
-        format.json {routing_group.to_json}
-      end
-    end
-  end
-
-end
-
-
-global_collection :routing_group_templates do
-
-  description 'Routing Groups Templates capture the configuration values for realizing a RoutingGroup. A Routing Group Template may be used to create multiple RoutingGroups'
-
-  operation :index do
-    description 'List all RoutingGroupTemplates in the RoutingGroupTemplateCollection'
-    param :CIMISelect, :string, :optional
-    control do
-      routing_group_templates = RoutingGroupTemplateCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml {routing_group_templates.to_xml}
-        format.json {routing_group_templates.to_json}
-      end
-    end
-  end
-
-  operation :show do
-    description 'Show a specific RoutingGroupTemplate'
-    param :id, :string, :required
-    control do
-      routing_group_template = RoutingGroupTemplate.find(params[:id], self)
-      respond_to do |format|
-        format.xml {routing_group_template.to_xml}
-        format.json {routing_group_template.to_json}
-      end
-    end
-  end
-
-end
-
-
-global_collection :vsps do
-
-  description 'A VSP represents the connection parameters of a network port'
-
-  operation :index do
-    description 'List all VSPs in the VSPCollection'
-    param :CIMISelect, :string, :optional
-    control do
-      vsps = VSPCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml {vsps.to_xml}
-        format.json {vsps.to_json}
-      end
-    end
-  end
-
-  operation :show do
-    description 'Show a specific VSP'
-    param :id, :string, :required
-    control do
-      vsp = VSP.find(params[:id], self)
-      respond_to do |format|
-        format.xml {vsp.to_xml}
-        format.json {vsp.to_json}
-      end
-    end
-  end
-
-  operation :create do
-    description "Create a new VSP"
-    control do
-      if request.content_type.end_with?("json")
-        vsp = CIMI::Model::VSP.create(request.body.read, self, :json)
-      else
-        vsp = CIMI::Model::VSP.create(request.body.read, self, :xml)
-      end
-      respond_to do |format|
-        format.xml { vsp.to_xml }
-        format.json { vsp.to_json }
-      end
-    end
-  end
-
-  operation :destroy do
-    description "Delete a specified VSP"
-    param :id, :string, :required
-    control do
-      CIMI::Model::VSP.delete!(params[:id], self)
-      no_content_with_status(200)
-    end
-  end
-
-  operation :start, :method => :post, :member => true do
-    description "Start specific VSP."
-    param :id,          :string,    :required
-    control do
-      vsp = VSP.find(params[:id], self)
-      report_error(404) unless vsp
-      if request.content_type.end_with?("json")
-        action = Action.from_json(request.body.read)
-      else
-        action = Action.from_xml(request.body.read)
-      end
-      vsp.perform(action, self) do |operation|
-        no_content_with_status(202) if operation.success?
-        # Handle errors using operation.failure?
-      end
-    end
-  end
-
-  operation :stop, :method => :post, :member => true do
-    description "Stop specific VSP."
-    param :id,          :string,    :required
-    control do
-      vsp = VSP.find(params[:id], self)
-      report_error(404) unless vsp
-      if request.content_type.end_with?("json")
-        action = Action.from_json(request.body.read)
-      else
-        action = Action.from_xml(request.body.read)
-      end
-      vsp.perform(action, self) do |operation|
-        no_content_with_status(202) if operation.success?
-        # Handle errors using operation.failure?
-      end
-    end
-  end
-
-end
-
-global_collection :vsp_configurations do
-
-  description 'A VSP Configuration is the set of configuration values representing the information needed to create a VSP with certain characteristics'
-
-  operation :index do
-    description 'List all VSPConfigurations in the VSPConfigurationCollection'
-    param :CIMISelect, :string, :optional
-    control do
-      vsp_configs = VSPConfigurationCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml {vsp_configs.to_xml}
-        format.json {vsp_configs.to_json}
-      end
-    end
-  end
-
-  operation :show do
-    description 'Show a specific VSPConfiguration'
-    param :id, :string, :required
-    control do
-      vsp_config = VSPConfiguration.find(params[:id], self)
-      respond_to do |format|
-        format.xml {vsp_config.to_xml}
-        format.json {vsp_config.to_json}
-      end
-    end
-  end
-
-end
-
-
-global_collection :vsp_templates do
-
-  description 'The VSP Template is a set of Configuration values for realizing a VSP. A VSP Template may be used to create multiple VSPs'
-
-  operation :index do
-    description 'List all VSPTemplates in the VSPTemplateCollection'
-    param :CIMISelect, :string, :optional
-    control do
-      vsp_templates = VSPTemplateCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml {vsp_templates.to_xml}
-        format.json {vsp_templates.to_json}
-      end
-    end
-  end
-
-  operation :show do
-    description 'Show a specific VSPTemplate'
-    param :id, :string, :required
-    control do
-      vsp_template = VSPTemplate.find(params[:id], self)
-      respond_to do |format|
-        format.xml {vsp_template.to_xml}
-        format.json {vsp_template.to_json}
-      end
-    end
-  end
-
-end
-
-global_collection :addresses do
-
-  description 'An Address represents an IP address, and its associated metdata, for a particular Network.'
-
-  operation :index do
-    description 'List all Addresses in the AddressCollection'
-    param :CIMISelect, :string, :optional
-    control do
-      addresses = AddressCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml {addresses.to_xml}
-        format.json {addresses.to_json}
-      end
-    end
-  end
-
-  operation :show do
-    description 'Show a specific Address'
-    param :id, :string, :required
-    control do
-      address = CIMI::Model::Address.find(params[:id], self)
-      respond_to do |format|
-        format.xml {address.to_xml}
-        format.json {address.to_json}
-      end
-    end
-  end
-
-  operation :create do
-    description "Create a new Address"
-    control do
-      if request.content_type.end_with?("json")
-        address = CIMI::Model::Address.create(request.body.read, self, :json)
-      else
-        address = CIMI::Model::Address.create(request.body.read, self, :xml)
-      end
-      respond_to do |format|
-        format.xml { address.to_xml }
-        format.json { address.to_json }
-      end
-    end
-  end
-
-  operation :destroy do
-    description "Delete a specified Address"
-    param :id, :string, :required
-    control do
-      CIMI::Model::Address.delete!(params[:id], self)
-      no_content_with_status(200)
-    end
-  end
-
-end
-
-
-global_collection :address_templates do
-
-  description 'An AddressTemplate captures the configuration values for realizing an Address. An Address Template may be used to create multiple Addresses.'
-
-  operation :index do
-    description 'List all AddressTemplates in the AddressTemplateCollection'
-    param :CIMISelect, :string, :optional
-    control do
-      address_templates = AddressTemplateCollection.default(self).filter_by(params[:CIMISelect])
-      respond_to do |format|
-        format.xml {address_templates.to_xml}
-        format.json {address_templates.to_json}
-      end
-    end
-  end
-
-  operation :show do
-    description 'Show a specific AddressTemplate'
-    param :id, :string, :required
-    control do
-      address_template = CIMI::Model::AddressTemplate.find(params[:id], self)
-      respond_to do |format|
-        format.xml {address_template.to_xml}
-        format.json {address_template.to_json}
-      end
-    end
-  end
-
 end
diff --git a/server/lib/deltacloud.rb b/server/lib/deltacloud.rb
index 6ff547e..d64797d 100644
--- a/server/lib/deltacloud.rb
+++ b/server/lib/deltacloud.rb
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.  The
@@ -14,14 +13,59 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-require 'deltacloud/drivers'
+require 'rubygems'
+
+unless Kernel.respond_to?(:require_relative)
+  module Kernel
+    def require_relative(path)
+      require File.join(File.dirname(caller[0]), path.to_str)
+    end
+  end
+end
+
+require 'ostruct'
+
+require_relative 'deltacloud/core_ext/string'
+require_relative 'deltacloud/core_ext/array'
+require_relative 'deltacloud/core_ext/hash'
+require_relative 'deltacloud/core_ext/integer'
+require_relative 'deltacloud/core_ext/proc'
+require_relative 'deltacloud/models'
+require_relative 'deltacloud/drivers'
+require_relative 'deltacloud/helpers/driver_helper'
+
+module Deltacloud
+
+  def self.drivers
+    Drivers.driver_config
+  end
+
+  class Library
+    include Helpers::Drivers
+    attr_reader :backend, :credentials
+
+    def initialize(driver_name, opts={}, &block)
+      Thread.current[:driver] = driver_name.to_s
+      Thread.current[:provider] = opts[:provider] if opts[:provider]
+      @backend = driver
+      @credentials = OpenStruct.new(:user => opts[:user], :password => opts[:password])
+      yield self if block_given?
+    end
+
+    def method_missing(name, *args)
+      return super unless backend.respond_to? name
+      begin
+        params = ([@credentials] + args).flatten
+        backend.send(name, *params)
+      rescue ArgumentError
+        backend.send(name, *args)
+      end
+    end
+
+  end
 
-require 'deltacloud/core_ext'
+  def self.new(driver_name, opts={}, &block)
+    Library.new(driver_name, opts, &block)
+  end
 
-require 'deltacloud/base_driver'
-require 'deltacloud/hardware_profile'
-require 'deltacloud/state_machine'
-require 'deltacloud/helpers'
-require 'deltacloud/models'
-require 'deltacloud/validation'
-require 'deltacloud/runner'
+end
diff --git a/server/lib/deltacloud/backend_capability.rb b/server/lib/deltacloud/backend_capability.rb
deleted file mode 100644
index 7f19007..0000000
--- a/server/lib/deltacloud/backend_capability.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-module Deltacloud::BackendCapability
-
-  attr_reader :capability
-
-  def with_capability(capability)
-    @capability = capability
-  end
-
-  def has_capability?(backend)
-    !capability or backend.has_capability?(capability)
-  end
-
-  def check_capability(backend)
-    if !has_capability?(backend)
-      raise Deltacloud::ExceptionHandler::NotSupported.new("#{capability} capability not supported by backend #{backend.class.name}")
-    end
-  end
-
-  module Helpers
-    def operations_for_collection(collection)
-      collections[collection].operations.values.select { |op| op.has_capability?(driver) }
-    end
-  end
-
-  helpers Helpers
-end
diff --git a/server/lib/deltacloud/base_driver.rb b/server/lib/deltacloud/base_driver.rb
deleted file mode 100644
index 77cdc84..0000000
--- a/server/lib/deltacloud/base_driver.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'deltacloud/base_driver/base_driver'
-require 'deltacloud/base_driver/features'
diff --git a/server/lib/deltacloud/base_driver/base_driver.rb b/server/lib/deltacloud/base_driver/base_driver.rb
deleted file mode 100644
index 01dd5e7..0000000
--- a/server/lib/deltacloud/base_driver/base_driver.rb
+++ /dev/null
@@ -1,250 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'deltacloud/base_driver/exceptions'
-
-module Deltacloud
-
-  class BaseDriver
-
-    include ExceptionHandler
-
-    STATE_MACHINE_OPTS = {
-      :all_states => [:start, :pending, :running, :stopping, :stopped, :finish],
-      :all_actions => [:create, :reboot, :stop, :start, :destroy]
-    }
-
-    def name
-      self.class.name.split('::').last.gsub('Driver', '').downcase
-    end
-
-    def self.exceptions(&block)
-      ExceptionHandler::exceptions(&block)
-    end
-
-    def self.define_hardware_profile(name,&block)
-      @hardware_profiles ||= []
-      hw_profile = @hardware_profiles.find{|e| e.name == name}
-      return if hw_profile
-      hw_profile = ::Deltacloud::HardwareProfile.new( name, &block )
-      @hardware_profiles << hw_profile
-      hw_params = hw_profile.params
-      unless hw_params.empty?
-        feature :instances, :hardware_profiles do
-          decl.operation(:create) { add_params(hw_params) }
-        end
-      end
-    end
-
-    def self.hardware_profiles
-      @hardware_profiles ||= []
-      @hardware_profiles
-    end
-
-    def hardware_profiles(credentials, opts = nil)
-      results = self.class.hardware_profiles
-      filter_hardware_profiles(results, opts)
-    end
-
-    def hardware_profile(credentials, name)
-      hardware_profiles(credentials, :id => name).first
-    end
-
-    def filter_hardware_profiles(profiles, opts)
-      if opts
-        if v = opts[:architecture]
-          profiles = profiles.select { |hwp| hwp.include?(:architecture, v) }
-        end
-        # As a request param, we call 'name' 'id'
-        if v = opts[:id]
-          profiles = profiles.select { |hwp| hwp.name == v }
-        end
-      end
-      profiles
-    end
-
-    def find_hardware_profile(credentials, name, image_id)
-      hwp = nil
-      if name
-        unless hwp = hardware_profiles(credentials, :id => name).first
-          raise BackendError.new(400, "bad-hardware-profile-name",
-            "Hardware profile '#{name}' does not exist", nil)
-        end
-      else
-        unless image = image(credentials, :id=>image_id)
-          raise BackendError.new(400, "bad-image-id",
-              "Image with ID '#{image_id}' does not exist", nil)
-        end
-        hwp = hardware_profiles(credentials,
-                                :architecture=>image.architecture).first
-      end
-      return hwp
-    end
-
-    def self.define_instance_states(&block)
-      machine = ::Deltacloud::StateMachine.new(STATE_MACHINE_OPTS, &block)
-      @instance_state_machine = machine
-    end
-
-    def self.instance_state_machine
-      @instance_state_machine
-    end
-
-    def instance_state_machine
-      self.class.instance_state_machine
-    end
-
-    def instance_actions_for(state)
-      actions = []
-      state_key = state.downcase.to_sym
-      states = instance_state_machine.states()
-      current_state = states.find{|e| e.name == state.underscore.to_sym }
-      if ( current_state )
-        actions = current_state.transitions.collect{|e|e.action}
-        actions.reject!{|e| e.nil?}
-      end
-      actions
-    end
-
-    ## Capabilities
-    # The rabbit dsl supports declaring a capability that is required
-    # in the backend driver for the call to succeed. A driver can
-    # provide a capability by implementing the method with the same
-    # name as the capability. Below is a list of the capabilities as
-    # the expected method signatures.
-    #
-    # Following the capability list are the resource member show
-    # methods. They each require that the corresponding collection
-    # method be defined
-    #
-    # TODO: standardize all of these to the same signature (credentials, opts)
-    #
-    # def realms(credentials, opts=nil)
-    #
-    # def images(credentials, ops)
-    #
-    # def instances(credentials, ops)
-    # def create_instance(credentials, image_id, opts)
-    # def start_instance(credentials, id)
-    # def stop_instance(credentials, id)
-    # def reboot_instance(credentials, id)
-    #
-    # def storage_volumes(credentials, ops)
-    #
-    # def storage_snapshots(credentials, ops)
-    #
-    # def buckets(credentials, opts = nil)
-    # def create_bucket(credentials, name, opts=nil)
-    # def delete_bucket(credentials, name, opts=nil)
-    #
-    # def blobs(credentials, opts = nil)
-    # def blob_data(credentials, bucket_id, blob_id, opts)
-    # def create_blob(credentials, bucket_id, blob_id, blob_data, opts=nil)
-    # def delete_blob(credentials, bucket_id, blob_id, opts=nil)
-    #
-    # def keys(credentials, opts)
-    # def create_key(credentials, opts)
-    # def destroy_key(credentials, opts)
-    #
-    # def firewalls(credentials, opts)
-    # def create_firewall(credentials, opts)
-    # def delete_firewall(credentials, opts)
-    # def create_firewall_rule(credentials, opts)
-    # def delete_firewall_rule(credentials, opts)
-    # def providers(credentials)
-    def realm(credentials, opts)
-      realms = realms(credentials, opts).first if has_capability?(:realms)
-    end
-
-    def image(credentials, opts)
-      images(credentials, opts).first if has_capability?(:images)
-    end
-
-    def instance(credentials, opts)
-      instances(credentials, opts).first if has_capability?(:instances)
-    end
-
-    def storage_volume(credentials, opts)
-      storage_volumes(credentials, opts).first if has_capability?(:storage_volumes)
-    end
-
-    def storage_snapshot(credentials, opts)
-      storage_snapshots(credentials, opts).first if has_capability?(:storage_snapshots)
-    end
-
-    def bucket(credentials, opts = {})
-      #list of objects within bucket
-      buckets(credentials, opts).first if has_capability?(:buckets)
-    end
-
-    def blob(credentials, opts = {})
-      blobs(credentials, opts).first if has_capability?(:blobs)
-    end
-
-    def key(credentials, opts=nil)
-      keys(credentials, opts).first if has_capability?(:keys)
-    end
-
-    def firewall(credentials, opts={})
-      firewalls(credentials, opts).first if has_capability?(:firewalls)
-    end
-
-    MEMBER_SHOW_METHODS =
-      [ :realm, :image, :instance, :storage_volume, :bucket, :blob, :key, :firewall ]
-
-    def has_capability?(capability)
-      if MEMBER_SHOW_METHODS.include?(capability.to_sym)
-        has_capability?(capability.to_s.pluralize)
-      else
-        respond_to?(capability)
-      end
-    end
-
-    def filter_on(collection, attribute, opts)
-      return collection if opts.nil?
-      return collection if opts[attribute].nil?
-      filter = opts[attribute]
-      if ( filter.is_a?( Array ) )
-        return collection.select{|e| filter.include?( e.send(attribute) ) }
-      else
-        return collection.select{|e| filter == e.send(attribute) }
-      end
-    end
-
-    def supported_collections
-      DEFAULT_COLLECTIONS
-    end
-
-    def has_collection?(collection)
-      supported_collections.include?(collection)
-    end
-
-    def catched_exceptions_list
-      { :error => [], :auth => [], :glob => [] }
-    end
-
-    def api_provider
-      Thread.current[:provider] || ENV['API_PROVIDER']
-    end
-
-    # Return an array of the providers statically configured
-    # in the driver's YAML file
-    def configured_providers
-      []
-    end
-  end
-
-end
diff --git a/server/lib/deltacloud/base_driver/exceptions.rb b/server/lib/deltacloud/base_driver/exceptions.rb
deleted file mode 100644
index a89b05f..0000000
--- a/server/lib/deltacloud/base_driver/exceptions.rb
+++ /dev/null
@@ -1,191 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-
-module Deltacloud
-  module ExceptionHandler
-
-    class DeltacloudException < StandardError
-
-      attr_accessor :code, :name, :message, :backtrace, :request
-
-      def initialize(code, name, message, backtrace, request=nil)
-        @code, @name, @message = code, name, message
-        @backtrace = backtrace
-        @request = request
-        self
-      end
-
-    end
-
-    class AuthenticationFailure < DeltacloudException
-      def initialize(e, message=nil)
-        message ||= e.message
-        super(401, e.class.name, message, e.backtrace)
-      end
-    end
-
-    class UnknownMediaTypeError < DeltacloudException
-      def initialize(e, message=nil)
-        message ||= e.message
-        super(406, e.class.name, message, e.backtrace)
-      end
-    end
-
-    class MethodNotAllowed < DeltacloudException
-      def initialize(e, message=nil)
-        message ||= e.message
-        super(405, e.class.name, message, e.backtrace)
-      end
-    end
-
-    class ValidationFailure < DeltacloudException
-      def initialize(e, message=nil)
-        message ||= e.message
-        super(400, e.class.name, message, e.backtrace)
-      end
-    end
-
-    class BackendError < DeltacloudException
-      def initialize(e, message=nil)
-        message ||= e.message
-        super(500, e.class.name, message, e.backtrace, message)
-      end
-    end
-
-    class ProviderError < DeltacloudException
-      def initialize(e, message)
-        message ||= e.message
-        super(502, e.class.name, message, e.backtrace)
-      end
-    end
-
-    class ProviderTimeout < DeltacloudException
-      def initialize(e, message)
-        message ||= e.message
-        super(504, e.class.name, message, e.backtrace)
-      end
-    end
-
-    class NotImplemented < DeltacloudException
-      def initialize(e, message)
-        message ||= e.message
-        super(501, e.class.name, message, e.backtrace)
-      end
-    end
-
-    class ObjectNotFound < DeltacloudException
-      def initialize(e, message)
-        message ||= e.message
-        super(404, e.class.name, message, e.backtrace)
-      end
-    end
-
-    class NotSupported < DeltacloudException
-      def initialize(message)
-        super(501, self.class.name, message, self.backtrace)
-      end
-    end
-
-    class ExceptionDef
-      attr_accessor :status
-      attr_accessor :message
-      attr_reader   :conditions
-      attr_reader   :handler
-
-      def initialize(conditions, &block)
-        @conditions = conditions
-        instance_eval(&block) if block_given?
-      end
-
-      def status(code)
-        self.status = code
-      end
-
-      def message(message)
-        self.message = message
-      end
-
-      def exception(handler)
-        self.handler = handler
-      end
-
-      # Condition can be class or regexp
-      #
-      def match?(e)
-        @conditions.each do |c|
-          return true if c.class == Class && e.class == c
-          return true if c.class == Regexp && (e.class.name =~ c or e.message =~ c)
-        end
-        return false
-      end
-
-      def handler(e)
-        return @handler if @handler
-        case @status
-          when 401 then Deltacloud::ExceptionHandler::AuthenticationFailure.new(e, @message)
-          when 404 then Deltacloud::ExceptionHandler::ObjectNotFound.new(e, @message)
-          when 406 then Deltacloud::ExceptionHandler::UnknownMediaTypeError.new(e, @message)
-          when 405 then Deltacloud::ExceptionHandler::MethodNotAllowed.new(e, @message)
-          when 400 then Deltacloud::ExceptionHandler::ValidationFailure.new(e, @message)
-          when 500 then Deltacloud::ExceptionHandler::BackendError.new(e, @message)
-          when 501 then Deltacloud::ExceptionHandler::NotImplemented.new(e, @message)
-          when 502 then Deltacloud::ExceptionHandler::ProviderError.new(e, @message)
-          when 504 then Deltacloud::ExceptionHandler::ProviderTimeout.new(e, @message)
-        end
-      end
-
-    end
-
-    class Exceptions
-      attr_reader :exception_definitions
-
-      def initialize(&block)
-        @exception_definitions = []
-        instance_eval(&block) if block_given?
-        self
-      end
-
-      def on(*conditions, &block)
-        @exception_definitions << ExceptionDef::new(conditions, &block) if block_given?
-      end
-    end
-
-    def self.exceptions(&block)
-      @definitions = Exceptions.new(&block).exception_definitions if block_given?
-      @definitions
-    end
-
-    def safely(&block)
-      begin
-        block.call
-      rescue
-        report_method = $stderr.respond_to?(:err) ? :err : :puts
-        Deltacloud::ExceptionHandler::exceptions.each do |exdef|
-          if exdef.match?($!)
-            new_exception = exdef.handler($!)
-            m = new_exception.message.nil? ? $!.message : new_exception.message
-            $stderr.send(report_method, "#{[$!.class.to_s, m].join(':')}\n#{$!.backtrace[0..10].join("\n")}")
-            raise exdef.handler($!) unless new_exception.nil?
-          end
-        end
-        $stderr.send(report_method, "[NO HANDLED] #{[$!.class.to_s, $!.message].join(': ')}\n#{$!.backtrace.join("\n")}")
-        raise Deltacloud::ExceptionHandler::BackendError.new($!, "Unhandled exception or status code (#{$!.message})")
-      end
-    end
-
-  end
-
-end
diff --git a/server/lib/deltacloud/base_driver/features.rb b/server/lib/deltacloud/base_driver/features.rb
deleted file mode 100644
index 37e5ef0..0000000
--- a/server/lib/deltacloud/base_driver/features.rb
+++ /dev/null
@@ -1,276 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'deltacloud/validation'
-
-# Add advertising of optional features to the base driver
-module Deltacloud
-
-  class FeatureError < StandardError; end
-  class DuplicateFeatureDeclError < FeatureError; end
-  class UndeclaredFeatureError < FeatureError; end
-
-  class BaseDriver
-
-    # An operation on a collection like cretae or show. Features
-    # can add parameters to operations
-    class Operation
-      attr_reader :name
-
-      include Deltacloud::Validation
-
-      def initialize(name, &block)
-        @name = name
-        @params = {}
-        instance_eval &block
-      end
-    end
-
-    # The declaration of a feature, defines what operations
-    # are modified by it
-    class FeatureDecl
-      attr_reader :name, :operations
-
-      def initialize(name, &block)
-        @name = name
-        @operations = []
-        instance_eval &block
-      end
-
-      def description(text=nil)
-        @description = text if text
-        @description
-      end
-
-      # Add/modify an operation or look up an existing one. If +block+ is
-      # provided, create a new operation if none exists with name
-      # +name+. Evaluate the +block+ against this instance. If no +block+
-      # is provided, look up the operation with name +name+
-      def operation(name, &block)
-        op = @operations.find { |op| op.name == name }
-        if block_given?
-          if op.nil?
-            op = Operation.new(name, &block)
-            @operations << op
-          else
-            op.instance_eval(&block)
-          end
-        end
-        op
-      end
-    end
-
-    # A specific feature enabled by a driver (see +feature+)
-    class Feature
-      attr_reader :decl, :constraints
-
-      def initialize(decl, &block)
-        @decl = decl
-        @constraints = {}
-        instance_eval &block if block_given?
-      end
-
-      def name
-        decl.name
-      end
-
-      def operations
-        decl.operations
-      end
-
-      def description
-        decl.description
-      end
-
-      def constraint(name, value)
-        @constraints[name] = value
-      end
-    end
-
-    def self.feature_decls
-      @@feature_decls ||= {}
-    end
-
-    def self.feature_decl_for(collection, name)
-      decls = feature_decls[collection]
-      if decls
-        decls.find { |dcl| dcl.name == name }
-      else
-        nil
-      end
-    end
-
-    # Declare a new feature
-    def self.declare_feature(collection, name, &block)
-      feature_decls[collection] ||= []
-      raise DuplicateFeatureDeclError if feature_decl_for(collection, name)
-      feature_decls[collection] << FeatureDecl.new(name, &block)
-    end
-
-    def self.features
-      @features ||= {}
-    end
-
-    # Declare in a driver that it supports a specific feature
-    #
-    # The same feature can be declared multiple times in a driver, so that
-    # it can be changed successively by passing in different blocks.
-    def self.feature(collection, name, &block)
-      features[collection] ||= []
-      if f = features[collection].find { |f| f.name == name }
-        f.instance_eval(&block) if block_given?
-        return f
-      end
-      unless decl = feature_decl_for(collection, name)
-        raise UndeclaredFeatureError, "No feature #{name} for #{collection}"
-      end
-      features[collection] << Feature.new(decl, &block)
-    end
-
-    def features(collection)
-      self.class.features[collection] || []
-    end
-
-    def features_for_operation(collection, operation)
-      features(collection).select do |f|
-        f.operations.detect { |o| o.name == operation }
-      end
-    end
-
-    #
-    # Declaration of optional features
-    #
-    declare_feature :images,  :owner_id do
-      description "Filter images using owner id"
-      operation :index do
-        param :owner_id,  :string,  :optional,  [],  "Owner ID"
-      end
-    end
-
-    declare_feature :images,  :user_name do
-      description "Allow specifying user name for created image"
-      operation :create do
-        param :name,  :string,  :optional,  [],  "Image name"
-      end
-    end
-
-    declare_feature :images,  :user_description do
-      description "Allow specifying user description for created image"
-      operation :create do
-        param :description, :string,  :optional,  [],  "Image description"
-      end
-    end
-
-    declare_feature :instances, :user_name do
-      description "Accept a user-defined name on instance creation"
-      operation :create do
-        param :name, :string, :optional, [], "The user-defined name"
-      end
-    end
-
-    declare_feature :instances, :user_data do
-      description "Make user-defined data available on a special webserver"
-      operation :create do
-        param :user_data, :string, :optional, [],
-        "Base64 encoded user data will be published to internal webserver"
-      end
-    end
-
-    declare_feature :instances, :user_iso do
-      description "Make user-defined ISO available inside instance"
-      operation :create do
-        param :user_iso, :string, :optional, [],
-        "Base64 encoded gzipped ISO file will be accessible as CD-ROM drive in instance"
-      end
-    end
-
-    declare_feature :instances, :user_files do
-      description "Accept up to 5 files to be placed into the instance before launch."
-      operation :create do
-        1.upto(5) do |i|
-          param :"path#{i}", :string, :optional, [],
-          "Path where to place the #{i.ordinalize} file, up to 255 characters"
-          param :"content#{i}", :string, :optional, nil,
-          "Contents for the #{i.ordinalize} file, up to 10 kB, Base64 encoded"
-        end
-      end
-    end
-
-    declare_feature :instances, :firewalls do
-      description "Put instance in one or more firewalls (security groups) on launch"
-      operation :create do
-        param :firewalls, :array, :optional, nil, "Array of firewall ID strings"
-        "Array of firewall (security group) id"
-      end
-    end
-
-    declare_feature :instances, :authentication_key do
-      operation :create do
-        param :keyname, :string,  :optional, [], "Key authentification method"
-      end
-      operation :show do
-      end
-    end
-
-    declare_feature :instances, :authentication_password do
-      operation :create do
-        param :password, :string, :optional
-      end
-    end
-
-    declare_feature :instances, :hardware_profiles do
-      description "Size instances according to changes to a hardware profile"
-      # The parameters are filled in from the hardware profiles
-    end
-
-    declare_feature :buckets, :bucket_location do
-      description "Take extra location parameter for Bucket creation (e.g. S3, 'eu' or 'us-west-1')"
-      operation :create do
-        param :location, :string, :optional
-      end
-    end
-
-    declare_feature :instances, :register_to_load_balancer do
-      description "Register instance to load balancer"
-      operation :create do
-        param :load_balancer_id, :string, :optional
-      end
-    end
-
-    declare_feature :instances, :instance_count do
-      description "Number of instances to be launch with at once"
-      operation :create do
-        param :instance_count,  :string,  :optional
-      end
-    end
-
-    declare_feature :instances, :attach_snapshot do
-      description "Attach an snapshot to instance on create"
-      operation :create do
-        param :snapshot_id,  :string,  :optional
-        param :device_name,  :string,  :optional
-      end
-    end
-
-    declare_feature :instances, :sandboxing do
-      description "Allow lanuching sandbox images"
-      operation :create do
-        param :sandbox, :string,  :optional
-      end
-    end
-
-  end
-end
diff --git a/server/lib/deltacloud/base_driver/mock_driver.rb b/server/lib/deltacloud/base_driver/mock_driver.rb
deleted file mode 100644
index 7956281..0000000
--- a/server/lib/deltacloud/base_driver/mock_driver.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'deltacloud/method_serializer'
-
-# Create 'mock' version of original driver client/gem:
-
-# Initialize driver and include Deltacloud
-include Deltacloud
-driver
-
-module Mock
-
-  class Ec2 < Aws::Ec2
-
-    include MethodSerializer::Cache
-
-    def self.cached_methods
-      [
-        :describe_images,
-        :describe_images_by_owner,
-        :describe_availability_zones,
-        :launch_instances,
-        :describe_instances,
-        :reboot_instances,
-        :create_tag,
-        :delete_tag,
-        :describe_tags,
-        :terminate_instances,
-        :describe_key_pairs,
-        :create_key_pair,
-        :delete_key_pair,
-        :create_volume,
-        :get_console_output,
-        :describe_volumes,
-        :delete_volume,
-        :attach_volume,
-        :detach_volume,
-        :describe_snapshots,
-        :associate_address,
-        :try_create_snapshot,
-      ]
-    end
-
-    MethodSerializer::Cache::wrap_methods(self, :cache_dir => File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'tests', 'ec2', 'support'))
-  end
-
-end
-
-
-# Replace original client with mock client
-Deltacloud::Drivers::EC2::EC2Driver.class_eval do
-  alias_method :original_new_client, :new_client
-
-  def new_client(credentials, provider = :ec2)
-    auth_credentials = { :access_key_id => credentials.user, :secret_access_key => credentials.password}
-    if provider == :elb
-      Mock::ELB.new(auth_credentials)
-    elsif provider == :s3
-      Mock::S3.new(auth_credentials)
-    else
-      Mock::Ec2.new(auth_credentials[:access_key_id], auth_credentials[:secret_access_key])
-    end
-  end
-
-end
diff --git a/server/lib/deltacloud/collections.rb b/server/lib/deltacloud/collections.rb
new file mode 100644
index 0000000..2363887
--- /dev/null
+++ b/server/lib/deltacloud/collections.rb
@@ -0,0 +1,54 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud
+
+  def self.collection_names
+    @collections.map { |c| c.collection_name }
+  end
+
+  def self.collections
+    @collections ||= []
+  end
+
+  module Collections
+
+    def self.collection(name)
+      Deltacloud.collections.find { |c| c.collection_name == name }
+    end
+
+    def self.deltacloud_modules
+      @deltacloud_modules ||= []
+    end
+
+    Dir[File.join(File::dirname(__FILE__), "collections", "*.rb")].each do |collection|
+      require collection
+      base_collection_name = File.basename(collection).gsub('.rb', '')
+      deltacloud_module_class = Deltacloud::Collections.const_get(base_collection_name.camelize)
+      deltacloud_modules << deltacloud_module_class
+      deltacloud_module_class.collections.each do |c|
+        Deltacloud.collections << c
+      end unless deltacloud_module_class.collections.nil?
+    end
+
+    def self.included(klass)
+      klass.class_eval do
+        Deltacloud::Collections.deltacloud_modules.each { |c| use c }
+      end
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/addresses.rb b/server/lib/deltacloud/collections/addresses.rb
new file mode 100644
index 0000000..b97d170
--- /dev/null
+++ b/server/lib/deltacloud/collections/addresses.rb
@@ -0,0 +1,83 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class Addresses < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+
+    collection :addresses do
+      description "Pool of IP addresses allocated in cloud provider"
+
+      standard_index_operation
+      standard_show_operation
+
+      operation :create, :with_capability => :create_address do
+        description "Acquire a new IP address for use with your account."
+        control do
+          @address = driver.create_address(credentials, {})
+          status 201    # Created
+          response['Location'] = address_url(@address.id)
+          respond_to do |format|
+            format.xml  { haml :"addresses/show", :ugly => true }
+            format.html { haml :"addresses/_address", :layout => false }
+            format.json { convert_to_json(:address, @address) }
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :destroy_address do
+        control do
+          driver.destroy_address(credentials, { :id => params[:id]})
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(addresses_url) }
+          end
+        end
+      end
+
+      action :associate, :with_capability => :associate_address do
+        description "Associate an IP address to an instance"
+        param :instance_id, :string, :required
+        control do
+          driver.associate_address(credentials, { :id => params[:id], :instance_id => params[:instance_id]})
+          status 202   # Accepted
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(address_url(params[:id])) }
+          end
+        end
+      end
+
+      action :disassociate, :with_capability => :associate_address do
+        description "Disassociate an IP address from an instance"
+        control do
+          driver.disassociate_address(credentials, { :id => params[:id] })
+          status 202   # Accepted
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(address_url(params[:id])) }
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/buckets.rb b/server/lib/deltacloud/collections/buckets.rb
new file mode 100644
index 0000000..044bd6a
--- /dev/null
+++ b/server/lib/deltacloud/collections/buckets.rb
@@ -0,0 +1,215 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class Buckets < Base
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    collection :buckets do
+
+      collection :blobs, :with_id => :blob_id, :no_member => true do
+
+        operation :show, :with_capability => :blob do
+          control do
+            @blob = driver.blob(credentials, { :id => params[:blob_id], 'bucket' => params[:id]} )
+            if @blob
+              respond_to do |format|
+                format.xml { haml :"blobs/show" }
+                format.html { haml :"blobs/show" }
+                format.json { convert_to_json(:blob, @blob) }
+              end
+            else
+              report_error(404)
+            end
+          end
+
+        end
+
+        operation :create, :with_capability => :create_blob do
+          description "Create new blob"
+          param :blob_id,  :string,  :required
+          param :blob_data, :hash, :required
+          control do
+            bucket_id = params[:id]
+            blob_id = params['blob_id']
+            blob_data = params['blob_data']
+            user_meta = {}
+            #metadata from params (i.e., passed by http form post, e.g. browser)
+            max = params[:meta_params]
+            if(max)
+              (1..max.to_i).each do |i|
+                key = params[:"meta_name#{i}"]
+                key = "HTTP_X_Deltacloud_Blobmeta_#{key}"
+                value = params[:"meta_value#{i}"]
+                user_meta[key] = value
+              end
+            end
+            @blob = driver.create_blob(credentials, bucket_id, blob_id, blob_data, user_meta)
+            respond_to do |format|
+              format.xml { haml :"blobs/show" }
+              format.html { haml :"blobs/show"}
+              format.json {convert_to_json(:blob, @blob)}
+            end
+          end
+        end
+
+        operation :destroy, :with_capability => :delete_blob do
+          control do
+            bucket_id = params[:id]
+            blob_id = params[:blob_id]
+            driver.delete_blob(credentials, bucket_id, blob_id)
+            status 204
+            respond_to do |format|
+              format.xml
+              format.json
+              format.html { redirect(bucket_url(bucket_id)) }
+            end
+          end
+        end
+
+        action :stream, :http_method => :put, :with_capability => :create_blob do
+          description "Stream new blob data into the blob"
+          control do
+            if(env["BLOB_SUCCESS"]) #ie got a 200ok after putting blob
+              content_type = env["CONTENT_TYPE"]
+              content_type ||=  ""
+              @blob = driver.blob(credentials, {:id => params[:blob],
+                                                'bucket' => params[:bucket]})
+              respond_to do |format|
+                format.xml { haml :"blobs/show" }
+                format.html { haml :"blobs/show" }
+                format.json { convert_to_json(:blob, @blob) }
+              end
+            elsif(env["BLOB_FAIL"])
+              report_error(500) #OK?
+            else # small blobs - < 112kb dont hit the streaming monkey patch - use 'normal' create_blob
+              # also, if running under webrick don't hit the streaming patch (Thin specific)
+              bucket_id = params[:bucket]
+              blob_id = params[:blob]
+              temp_file = Tempfile.new("temp_blob_file")
+              temp_file.write(env['rack.input'].read)
+              temp_file.flush
+              content_type = env['CONTENT_TYPE'] || ""
+              blob_data = {:tempfile => temp_file, :type => content_type}
+              user_meta = BlobHelper::extract_blob_metadata_hash(request.env)
+              @blob = driver.create_blob(credentials, bucket_id, blob_id, blob_data, user_meta)
+              temp_file.delete
+              respond_to do |format|
+                format.xml { haml :"blobs/show" }
+                format.html { haml :"blobs/show" }
+                format.json { convert_to_json(:blob, @blob) }
+              end
+            end
+          end
+        end
+
+        action :metadata, :http_method => :head, :with_capability => :blob_metadata do
+          control do
+            @blob_id = params[:blob]
+            @blob_metadata = driver.blob_metadata(credentials, {:id => params[:blob], 'bucket' => params[:bucket]})
+            if @blob_metadata
+              @blob_metadata.each do |k,v|
+                headers["X-Deltacloud-Blobmeta-#{k}"] = v
+              end
+              status 204
+              respond_to do |format|
+                format.xml
+                format.json
+              end
+            else
+              report_error(404)
+            end
+          end
+        end
+
+        action :update, :http_method => :post, :with_capability => :update_blob_metadata do
+          control do
+            meta_hash = BlobHelper::extract_blob_metadata_hash(request.env)
+            success = driver.update_blob_metadata(credentials, {'bucket'=>params[:bucket], :id =>params[:blob], 'meta_hash' => meta_hash})
+            if(success)
+              meta_hash.each do |k,v|
+                headers["X-Deltacloud-Blobmeta-#{k}"] = v
+              end
+              status 204
+              respond_to do |format|
+                format.xml
+                format.json
+              end
+            else
+              report_error(404) #FIXME is this the right error code?
+            end
+          end
+        end
+
+        action :content, :http_method => :get, :with_capability => :blob do
+          description "Download blob content"
+          control do
+            @blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
+            if @blob
+              params['content_length'] = @blob.content_length
+              params['content_type'] = @blob.content_type
+              params['content_disposition'] = "attachment; filename=#{@blob.id}"
+              BlobStream.call(env, credentials, params)
+            else
+              report_error(404)
+            end
+          end
+        end
+
+      end
+
+      get route_for('/buckets/new') do
+        respond_to do |format|
+          format.html { haml :"buckets/new" }
+        end
+      end
+
+      standard_show_operation
+      standard_index_operation
+
+      operation :create, :with_capability => :create_bucket do
+        param :name,      :string,    :required
+        control do
+          @bucket = driver.create_bucket(credentials, params[:name], params)
+          status 201
+          response['Location'] = bucket_url(@bucket.id)
+          respond_to do |format|
+            format.xml  { haml :"buckets/show" }
+            format.json { convert_to_json(:bucket, @bucket) }
+            format.html do
+              redirect bucket_url(@bucket.id) if @bucket and @bucket.id
+              redirect buckets_url
+            end
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :delete_bucket do
+        control do
+          driver.delete_bucket(credentials, params[:id], params)
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html {  redirect(buckets_url) }
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/drivers.rb b/server/lib/deltacloud/collections/drivers.rb
new file mode 100644
index 0000000..41f324a
--- /dev/null
+++ b/server/lib/deltacloud/collections/drivers.rb
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class Drivers < Base
+
+    collection :drivers do
+
+      operation :index do
+        control do
+          @drivers = Deltacloud::Drivers.driver_config
+          respond_to do |format|
+            format.xml { haml :"drivers/index" }
+            format.json { @drivers.to_json }
+            format.html { haml :"drivers/index" }
+          end 
+        end
+      end
+
+      operation :show do
+        control do
+          @name = params[:id].to_sym
+          if driver_symbol == @name
+            @providers = driver.providers(credentials)  if driver.respond_to? :providers
+          end
+          @driver = Deltacloud::Drivers.driver_config[@name]
+          halt 404 unless @driver
+          respond_to do |format|
+            format.xml { haml :"drivers/show" }
+            format.json { @driver.to_json }
+            format.html { haml :"drivers/show" }
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/firewalls.rb b/server/lib/deltacloud/collections/firewalls.rb
new file mode 100644
index 0000000..0a4242a
--- /dev/null
+++ b/server/lib/deltacloud/collections/firewalls.rb
@@ -0,0 +1,116 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class Firewalls < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    get route_for('/firewalls/:id/new_rule') do
+      @firewall_name = params[:id]
+      respond_to do |format|
+        format.html {haml :"firewalls/new_rule" }
+      end
+    end
+
+    new_route_for :firewalls
+
+    collection :firewalls do
+      description "Allow user to define firewall rules for an instance (ec2 security groups) eg expose ssh access [port 22, tcp]."
+
+      collection :rules, :with_id => :rule_id, :no_member => true do
+
+        operation :destroy, :with_capability => :delete_firewall_rule do
+          control do
+            opts = {}
+            opts[:firewall] = params[:id]
+            opts[:rule_id] = params[:rule_id]
+            driver.delete_firewall_rule(credentials, opts)
+            status 204
+            respond_to do |format|
+              format.xml
+              format.json
+              format.html {redirect firewall_url(params[:id])}
+            end
+          end
+        end
+
+      end
+
+      standard_show_operation
+      standard_index_operation
+
+      operation :create, :with_capability => :create_firewall do
+        param :name,          :string,    :required
+        param :description,   :string,    :required
+        control do
+          @firewall = driver.create_firewall(credentials, params )
+          status 201  # Created
+          response['Location'] = firewall_url(@firewall.id)
+          respond_to do |format|
+            format.xml  { haml :"firewalls/show" }
+            format.html { haml :"firewalls/show" }
+            format.json { convert_to_json(:firewall, @firewall) }
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :delete_firewall do
+        control do
+          driver.delete_firewall(credentials, params)
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html {  redirect(firewalls_url) }
+          end
+        end
+      end
+
+      action :rules, :with_capability => :create_firewall_rule do
+        param :protocol,  :required, :string, ['tcp','udp','icmp'], "Transport layer protocol for the rule"
+        param :port_from, :required, :string, [], "Start of port range for the rule"
+        param :port_to,   :required, :string, [], "End of port range for the rule"
+        control do
+          #source IPs from params
+          addresses =  params.inject([]){|result,current| result << current.last unless current.grep(/^ip[-_]address/i).empty?; result}
+          #source groups from params
+          groups = {}
+          max_groups  = params.select{|k,v| k=~/^group/}.size/2
+          for i in (1..max_groups) do
+            groups.merge!({params["group#{i}"]=>params["group#{i}owner"]})
+          end
+          params['addresses'] = addresses
+          params['groups'] = groups
+          if addresses.empty? && groups.empty?
+            raise Deltacloud::ExceptionHandler::ValidationFailure.new(
+              StandardError.new("No sources. Specify at least one source ip_address or group")
+            )
+          end
+          driver.create_firewall_rule(credentials, params)
+          @firewall = driver.firewall(credentials, {:id => params[:id]})
+          status 201
+          respond_to do |format|
+            format.xml  { haml :"firewalls/show" }
+            format.html { haml :"firewalls/show" }
+            format.json { convert_to_json(:firewall, @firewall) }
+          end
+        end
+      end
+
+    end
+  end
+end
diff --git a/server/lib/deltacloud/collections/hardware_profiles.rb b/server/lib/deltacloud/collections/hardware_profiles.rb
new file mode 100644
index 0000000..ff01d4a
--- /dev/null
+++ b/server/lib/deltacloud/collections/hardware_profiles.rb
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class HardwareProfiles < Base
+
+    collection :hardware_profiles do
+
+      standard_index_operation
+      standard_show_operation
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/images.rb b/server/lib/deltacloud/collections/images.rb
new file mode 100644
index 0000000..c8b3e08
--- /dev/null
+++ b/server/lib/deltacloud/collections/images.rb
@@ -0,0 +1,70 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class Images < Base
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    new_route_for :images do
+      @instance = Instance.new( :id => params[:instance_id] )
+      status 404 unless @instance
+    end
+
+    collection :images do
+      description "Within a cloud provider a realm represents a boundary containing resources"
+
+      operation :index, :with_capability => :images do
+        param :architecture,  :string,  :optional
+        control { filter_all(:images) }
+      end
+
+      operation :show, :with_capability => :image do
+        control { show(:image) }
+      end
+
+      operation :create, :with_capability => :create_image do
+        param :instance_id, :string, :required
+        control do
+          @image = driver.create_image(credentials, {
+            :id => params[:instance_id],
+            :name => params[:name],
+            :description => params[:description]
+          })
+          status 201  # Created
+          response['Location'] = image_url(@image.id)
+          respond_to do |format|
+            format.xml  { haml :"images/show" }
+            format.json { xml_to_json('images/show') }
+            format.html { haml :"images/show" }
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :destroy_image do
+        control do
+          driver.destroy_image(credentials, params[:id])
+          respond_to do |format|
+            format.xml { status 204 }
+            format.json { status 204 }
+            format.html { redirect(images_url) }
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/instance_states.rb b/server/lib/deltacloud/collections/instance_states.rb
new file mode 100644
index 0000000..56c1561
--- /dev/null
+++ b/server/lib/deltacloud/collections/instance_states.rb
@@ -0,0 +1,57 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class InstanceStates < Base
+
+    collection :instance_states do
+      operation :index do
+        control do
+          @machine = driver.instance_state_machine
+          respond_to do |format|
+            format.xml { haml :'instance_states/show', :layout => false }
+            format.json do
+              out = []
+              @machine.states.each do |state|
+                transitions = state.transitions.collect do |t|
+                  t.automatically? ? {:to => t.destination, :auto => 'true'} : {:to => t.destination, :action => t.action}
+                end
+                out << { :name => state, :transitions => transitions }
+              end
+              out.to_json
+            end
+            format.html { haml :'instance_states/show'}
+            format.gv { erb :"instance_states/show" }
+            format.png do
+              # Trick respond_to into looking up the right template for the
+              # graphviz file
+              gv = erb(:"instance_states/show")
+              png =  ''
+              cmd = 'dot -Kdot -Gpad="0.2,0.2" -Gsize="5.0,8.0" -Gdpi="180" -Tpng'
+              Open3.popen3( cmd ) do |stdin, stdout, stderr|
+                stdin.write( gv )
+                stdin.close()
+                png = stdout.read
+              end
+              content_type 'image/png'
+              png
+            end
+          end
+        end
+      end
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/instances.rb b/server/lib/deltacloud/collections/instances.rb
new file mode 100644
index 0000000..5202149
--- /dev/null
+++ b/server/lib/deltacloud/collections/instances.rb
@@ -0,0 +1,103 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class Instances < Base
+
+    include Deltacloud::InstanceFeatures
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    new_route_for(:instances) do
+      @instance = Instance.new( { :id=>params[:id], :image_id=>params[:image_id] } )
+      @image   = Image.new( :id => params[:image_id] )
+      @hardware_profiles = driver.hardware_profiles(credentials, :architecture => @image.architecture )
+      @realms = [Realm.new(:id => params[:realm_id])] if params[:realm_id]
+      @realms ||= driver.realms(credentials)
+    end
+
+    collection :instances do
+
+      standard_show_operation
+      standard_index_operation
+
+      operation :create, :with_capability => :create_instance do
+        param :image_id,     :string, :required
+        param :realm_id,     :string, :optional
+        param :hwp_id,       :string, :optional
+        control do
+          @instance = driver.create_instance(credentials, params[:image_id], params)
+          if @instance.kind_of? Array
+            @elements = @instance
+            action_handler = "index"
+          else
+            response['Location'] = instance_url(@instance.id)
+            action_handler = "show"
+          end
+          status 201  # Created
+          respond_to do |format|
+            format.xml  { haml :"instances/#{action_handler}" }
+            format.json { xml_to_json("instances/#{action_handler}") }
+            format.html do
+              if @elements
+                haml :"instances/index"
+              elsif @instance and @instance.id
+                response['Location'] = instance_url(@instance.id)
+                haml :"instances/show"
+              else
+                redirect instances_url
+              end
+            end
+          end
+        end
+      end
+
+      action :reboot, :with_capability => :reboot_instance do
+        description "Reboot a running instance."
+        control { instance_action(:reboot) }
+      end
+
+      action :start, :with_capability => :start_instance do
+        description "Start an instance."
+        control { instance_action(:start) }
+      end
+
+      action :stop, :with_capability => :stop_instance do
+        description "Stop a running instance."
+        control { instance_action(:stop) }
+      end
+
+      operation :destroy, :with_capability => :destroy_instance do
+        control { instance_action(:destroy) }
+      end
+
+      action :run, :with_capability => :run_instance do
+        param :id,          :string,  :required
+        param :cmd,         :string,  :required, [], "Shell command to run on instance"
+        param :private_key, :string,  :optional, [], "Private key in PEM format for authentication"
+        param :password,    :string,  :optional, [], "Password used for authentication"
+        control do
+          @output = driver.run_on_instance(credentials, params)
+          respond_to do |format|
+            format.xml { haml :"instances/run" }
+            format.html { haml :"instances/run" }
+          end
+        end
+      end
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/keys.rb b/server/lib/deltacloud/collections/keys.rb
new file mode 100644
index 0000000..55d0fa8
--- /dev/null
+++ b/server/lib/deltacloud/collections/keys.rb
@@ -0,0 +1,61 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class Keys < Base
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    get route_for('/keys/new') do
+      respond_to do |format|
+        format.html { haml :"keys/new" }
+      end
+    end
+
+    collection :keys do
+
+      standard_show_operation
+      standard_index_operation
+
+      operation :create, :with_capability => :create_key do
+        param :name,  :string,  :required
+        control do
+          @key = driver.create_key(credentials, { :key_name => params[:name] })
+          status 201
+          response['Location'] = key_url(@key.id)
+          respond_to do |format|
+            format.xml  { haml :"keys/show", :ugly => true }
+            format.html { haml :"keys/show" }
+            format.json { convert_to_json(:key, @key)}
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :destroy_key do
+        control do
+          driver.destroy_key(credentials, { :id => params[:id]})
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(keys_url) }
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/load_balancers.rb b/server/lib/deltacloud/collections/load_balancers.rb
new file mode 100644
index 0000000..d093ead
--- /dev/null
+++ b/server/lib/deltacloud/collections/load_balancers.rb
@@ -0,0 +1,85 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class LoadBalancers < Base
+    check_capability :for => lambda { |m| driver.has_capability? m }
+
+    collection :load_balancers do
+      description "Load balancers are used distribute workload across multiple instances"
+
+      standard_index_operation
+      standard_show_operation
+
+      operation :create do
+        param :name,  :string,  :required
+        param :realm_id,  :string,  :required
+        param :listener_protocol,  :string,  :required, ['HTTP', 'TCP']
+        param :listener_balancer_port,  :string,  :required
+        param :listener_instance_port,  :string,  :required
+        control do
+          @load_balancer = driver.create_load_balancer(credentials, params)
+          status 201  # Created
+          response['Location'] = load_balancer_url(@instance.id)
+          respond_to do |format|
+            format.xml  { haml :"load_balancers/show" }
+            format.json { convert_to_json(:load_balancer, @load_balancer) }
+            format.html { haml :"load_balancers/show" }
+          end
+        end
+      end
+
+      action :register do
+        param :instance_id, :string,  :required
+        control do
+          driver.lb_register_instance(credentials, params)
+          @load_balancer = driver.load_balancer(credential, params[:id])
+          respond_to do |format|
+            format.xml { haml :'load_balancers/show' }
+            format.json ( xml_to_json('load_balancers/show'))
+            format.html { haml :'load_balancers/show' }
+          end
+        end
+      end
+
+      action :unregister do
+        param :instance_id, :string,  :required
+        control do
+          driver.lb_unregister_instance(credentials, params)
+          @load_balancer = driver.load_balancer(credential, params[:id])
+          respond_to do |format|
+            format.xml { haml :'load_balancers/show' }
+            format.json ( xml_to_json('load_balancers/show'))
+            format.html { haml :'load_balancers/show' }
+          end
+        end
+      end
+
+      operation :destroy do
+        control do
+          driver.destroy_load_balancer(credentials, params[:id])
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(load_balancers_url) }
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/realms.rb b/server/lib/deltacloud/collections/realms.rb
new file mode 100644
index 0000000..3f21625
--- /dev/null
+++ b/server/lib/deltacloud/collections/realms.rb
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class Realms < Base
+
+    collection :realms do
+      description "Within a cloud provider a realm represents a boundary containing resources"
+
+      standard_index_operation
+      standard_show_operation
+
+    end
+  end
+end
diff --git a/server/lib/deltacloud/collections/storage_snapshots.rb b/server/lib/deltacloud/collections/storage_snapshots.rb
new file mode 100644
index 0000000..b468614
--- /dev/null
+++ b/server/lib/deltacloud/collections/storage_snapshots.rb
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class StorageSnapshots < Base
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    new_route_for(:storage_snapshots)
+
+    collection :storage_snapshots do
+      standard_index_operation
+      standard_show_operation
+
+      operation :create, :with_capability => :create_storage_snapshot do
+        param :volume_id, :string,  :required
+        control do
+          @storage_snapshot = driver.create_storage_snapshot(credentials, params)
+          status 201  # Created
+          response['Location'] = storage_snapshot_url(@storage_snapshot.id)
+          show(:storage_snapshot)
+        end
+      end
+
+      operation :destroy, :with_capability => :destroy_storage_snapshot do
+        control do
+          driver.destroy_storage_snapshot(credentials, params)
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(storage_snapshots_url) }
+          end
+        end
+      end
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/storage_volumes.rb b/server/lib/deltacloud/collections/storage_volumes.rb
new file mode 100644
index 0000000..9cdcd66
--- /dev/null
+++ b/server/lib/deltacloud/collections/storage_volumes.rb
@@ -0,0 +1,99 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class StorageVolumes < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    new_route_for(:storage_volumes)
+
+    get route_for("/storage_volumes/:id/attach_instance") do
+      @instances = driver.instances(credentials)
+      respond_to do |format|
+        format.html{ haml :"storage_volumes/attach"}
+      end
+    end
+
+    collection :storage_volumes do
+
+      standard_index_operation
+      standard_show_operation
+
+      operation :show, :with_capability => :storage_volume do
+        control { show(:storage_volume) }
+      end
+
+      operation :create do
+        param :snapshot_id, :string,  :optional
+        param :capacity,    :string,  :optional
+        param :realm_id,    :string,  :optional
+        control do
+          @storage_volume = driver.create_storage_volume(credentials, params)
+          status 201
+          response['Location'] = storage_volume_url(@storage_volume.id)
+          respond_to do |format|
+            format.xml  { haml :"storage_volumes/show" }
+            format.html { haml :"storage_volumes/show" }
+            format.json { convert_to_json(:storage_volume, @storage_volume) }
+          end
+        end
+      end
+
+      action :attach, :with_capability => :attach_storage_volume do
+        param :instance_id,:string,  :required
+        param :device,     :string,  :required
+        control do
+          @storage_volume = driver.attach_storage_volume(credentials, params)
+          status 202
+          respond_to do |format|
+            format.html { redirect(storage_volume_url(params[:id]))}
+            format.xml  { haml :"storage_volumes/show" }
+            format.json { convert_to_json(:storage_volume, @storage_volume) }
+          end
+        end
+      end
+
+      action :detach, :with_capability => :detach_storage_volume do
+        control do
+          volume = driver.storage_volume(credentials, :id => params[:id])
+          @storage_volume =  driver.detach_storage_volume(credentials, :id => volume.id, 
+                                                          :instance_id => volume.instance_id,
+                                                          :device => volume.device)
+          status 202
+          respond_to do |format|
+            format.html { redirect(storage_volume_url(params[:id]))}
+            format.xml  { haml :"storage_volumes/show" }
+            format.json { convert_to_json(:storage_volume, @storage_volume) }
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :destroy_storage_volume do
+        control do
+          driver.destroy_storage_volume(credentials, params)
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(storage_volumes_url) }
+          end
+        end
+      end
+
+    end
+  end
+end
diff --git a/server/lib/deltacloud/core_ext.rb b/server/lib/deltacloud/core_ext.rb
deleted file mode 100644
index fedbc18..0000000
--- a/server/lib/deltacloud/core_ext.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'deltacloud/core_ext/string'
-require 'deltacloud/core_ext/integer'
-require 'deltacloud/core_ext/hash'
-require 'deltacloud/core_ext/array'
-require 'deltacloud/core_ext/proc'
diff --git a/server/lib/deltacloud/drivers.rb b/server/lib/deltacloud/drivers.rb
index dfc998d..14e7ee0 100644
--- a/server/lib/deltacloud/drivers.rb
+++ b/server/lib/deltacloud/drivers.rb
@@ -13,25 +13,15 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-module Deltacloud
+require_relative 'drivers/exceptions'
+require_relative 'drivers/base_driver'
+require_relative 'drivers/features'
+require 'yaml'
 
+module Deltacloud
   module Drivers
 
-    require 'yaml'
-
-    DEFAULT_COLLECTIONS = [
-      :hardware_profiles,
-      :images,
-      :instances,
-      :instance_states,
-      :realms,
-      :storage_volumes,
-      :storage_snapshots
-    ]
-
-    DRIVER=ENV['API_DRIVER'] ? ENV['API_DRIVER'].to_sym : :mock
-
-    def driver_config
+    def self.driver_config
       if Thread::current[:drivers].nil?
         Thread::current[:drivers] = {}
         top_srcdir = File.join(File.dirname(__FILE__), '..', '..')
@@ -42,31 +32,5 @@ module Deltacloud
       Thread::current[:drivers]
     end
 
-    def driver_symbol
-      (Thread.current[:driver] || DRIVER).to_sym
-    end
-
-    def driver_name
-      driver_config[:"#{driver_symbol}"][:name]
-    end
-
-    def driver_class
-      basename = driver_config[:"#{driver_symbol}"][:class] || "#{driver_name}Driver"
-      Deltacloud::Drivers.const_get(driver_name).const_get(basename)
-    end
-
-    def driver_source_name
-      File.join("deltacloud", "drivers", "#{driver_symbol}", "#{driver_symbol}_driver.rb")
-    end
-
-    def driver_mock_source_name
-      return File.join('deltacloud', 'drivers', "#{driver_symbol}",
-		       "#{driver_symbol}_driver.rb") if driver_name.eql? 'Mock'
-    end
-
-    def driver
-      require driver_source_name
-      @driver ||= driver_class.new
-    end
   end
 end
diff --git a/server/lib/deltacloud/drivers/azure/azure_driver.rb b/server/lib/deltacloud/drivers/azure/azure_driver.rb
index 24feeb7..db2b6c6 100644
--- a/server/lib/deltacloud/drivers/azure/azure_driver.rb
+++ b/server/lib/deltacloud/drivers/azure/azure_driver.rb
@@ -15,7 +15,6 @@
 # under the License.
 
 #Windows Azure (WAZ) gem at http://github.com/johnnyhalife/waz-storage
-require 'deltacloud/base_driver'
 require 'waz-blobs'
 
 module Deltacloud
@@ -24,9 +23,6 @@ module Deltacloud
 
 class AzureDriver < Deltacloud::BaseDriver
 
-  def supported_collections; [:buckets]
-  end
-
 #--
 # Buckets
 #--
diff --git a/server/lib/deltacloud/drivers/base_driver.rb b/server/lib/deltacloud/drivers/base_driver.rb
new file mode 100644
index 0000000..5fb1a79
--- /dev/null
+++ b/server/lib/deltacloud/drivers/base_driver.rb
@@ -0,0 +1,265 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud
+
+  class BaseDriver
+
+    include ExceptionHandler
+
+    def self.driver_name
+      name.split('::').last.gsub('Driver', '').downcase
+    end
+
+    def self.features
+      @features ||= []
+    end
+
+    def self.features_for(entity)
+      features.inject([]) do |result, item|
+        result << item[entity] if item.has_key? entity
+        result
+      end
+    end
+
+    def self.feature(collection, feature_name)
+      return if has_feature?(collection, feature_name)
+      features << { collection => feature_name }
+    end
+
+    def self.has_feature?(collection, feature_name)
+      features.any? { |f| (f.values.first == feature_name) && (f.keys.first == collection) }
+    end
+
+    def name
+      self.class.name.split('::').last.gsub('Driver', '').downcase
+    end
+
+    def self.exceptions(&block)
+      ExceptionHandler::exceptions(&block)
+    end
+
+    def self.define_hardware_profile(name,&block)
+      @hardware_profiles ||= []
+      hw_profile = @hardware_profiles.find{|e| e.name == name}
+      return if hw_profile
+      hw_profile = ::Deltacloud::HardwareProfile.new( name, &block )
+      @hardware_profiles << hw_profile
+      hw_params = hw_profile.params
+      # FIXME: Features
+      #unless hw_params.empty?
+      #  feature :instances, :hardware_profiles do
+      #    decl.operation(:create) { add_params(hw_params) }
+      #  end
+      #end
+    end
+
+    def self.hardware_profiles
+      @hardware_profiles ||= []
+      @hardware_profiles
+    end
+
+    def hardware_profiles(credentials, opts = nil)
+      results = self.class.hardware_profiles
+      filter_hardware_profiles(results, opts)
+    end
+
+    def hardware_profile(credentials, name)
+      name = name[:id] if name.kind_of? Hash
+      hardware_profiles(credentials, :id => name).first
+    end
+
+    def filter_hardware_profiles(profiles, opts)
+      if opts
+        if v = opts[:architecture]
+          profiles = profiles.select { |hwp| hwp.include?(:architecture, v) }
+        end
+        # As a request param, we call 'name' 'id'
+        if v = opts[:id]
+          profiles = profiles.select { |hwp| hwp.name == v }
+        end
+      end
+      profiles
+    end
+
+    def find_hardware_profile(credentials, name, image_id)
+      hwp = nil
+      if name
+        unless hwp = hardware_profiles(credentials, :id => name).first
+          raise BackendError.new(400, "bad-hardware-profile-name",
+            "Hardware profile '#{name}' does not exist", nil)
+        end
+      else
+        unless image = image(credentials, :id=>image_id)
+          raise BackendError.new(400, "bad-image-id",
+              "Image with ID '#{image_id}' does not exist", nil)
+        end
+        hwp = hardware_profiles(credentials,
+                                :architecture=>image.architecture).first
+      end
+      return hwp
+    end
+
+    def self.define_instance_states(&block)
+      machine = ::Deltacloud::StateMachine.new(&block)
+      @instance_state_machine = machine
+    end
+
+    def self.instance_state_machine
+      @instance_state_machine
+    end
+
+    def instance_state_machine
+      self.class.instance_state_machine
+    end
+
+    def instance_actions_for(state)
+      actions = []
+      state_key = state.downcase.to_sym
+      states = instance_state_machine.states()
+      current_state = states.find{|e| e.name == state.underscore.to_sym }
+      if ( current_state )
+        actions = current_state.transitions.collect{|e|e.action}
+        actions.reject!{|e| e.nil?}
+      end
+      actions
+    end
+
+    def has_capability?(method)
+      (self.class.instance_methods - self.class.superclass.methods).include? method
+    end
+
+    ## Capabilities
+    # The rabbit dsl supports declaring a capability that is required
+    # in the backend driver for the call to succeed. A driver can
+    # provide a capability by implementing the method with the same
+    # name as the capability. Below is a list of the capabilities as
+    # the expected method signatures.
+    #
+    # Following the capability list are the resource member show
+    # methods. They each require that the corresponding collection
+    # method be defined
+    #
+    # TODO: standardize all of these to the same signature (credentials, opts)
+    #
+    # def realms(credentials, opts=nil)
+    #
+    # def images(credentials, ops)
+    #
+    # def instances(credentials, ops)
+    # def create_instance(credentials, image_id, opts)
+    # def start_instance(credentials, id)
+    # def stop_instance(credentials, id)
+    # def reboot_instance(credentials, id)
+    #
+    # def storage_volumes(credentials, ops)
+    #
+    # def storage_snapshots(credentials, ops)
+    #
+    # def buckets(credentials, opts = nil)
+    # def create_bucket(credentials, name, opts=nil)
+    # def delete_bucket(credentials, name, opts=nil)
+    #
+    # def blobs(credentials, opts = nil)
+    # def blob_data(credentials, bucket_id, blob_id, opts)
+    # def create_blob(credentials, bucket_id, blob_id, blob_data, opts=nil)
+    # def delete_blob(credentials, bucket_id, blob_id, opts=nil)
+    #
+    # def keys(credentials, opts)
+    # def create_key(credentials, opts)
+    # def destroy_key(credentials, opts)
+    #
+    # def firewalls(credentials, opts)
+    # def create_firewall(credentials, opts)
+    # def delete_firewall(credentials, opts)
+    # def create_firewall_rule(credentials, opts)
+    # def delete_firewall_rule(credentials, opts)
+    # def providers(credentials)
+    def realm(credentials, opts)
+      realms = realms(credentials, opts).first if has_capability?(:realms)
+    end
+
+    def image(credentials, opts)
+      images(credentials, opts).first if has_capability?(:images)
+    end
+
+    def instance(credentials, opts)
+      instances(credentials, opts).first if has_capability?(:instances)
+    end
+
+    def storage_volume(credentials, opts)
+      storage_volumes(credentials, opts).first if has_capability?(:storage_volumes)
+    end
+
+    def storage_snapshot(credentials, opts)
+      storage_snapshots(credentials, opts).first if has_capability?(:storage_snapshots)
+    end
+
+    def bucket(credentials, opts = {})
+      #list of objects within bucket
+      buckets(credentials, opts).first if has_capability?(:buckets)
+    end
+
+    def blob(credentials, opts = {})
+      blobs(credentials, opts).first if has_capability?(:blobs)
+    end
+
+    def key(credentials, opts=nil)
+      keys(credentials, opts).first if has_capability?(:keys)
+    end
+
+    def firewall(credentials, opts={})
+      firewalls(credentials, opts).first if has_capability?(:firewalls)
+    end
+
+    MEMBER_SHOW_METHODS =
+      [ :realm, :image, :instance, :storage_volume, :bucket, :blob, :key, :firewall ]
+
+    def filter_on(collection, attribute, opts)
+      return collection if opts.nil?
+      return collection if opts[attribute].nil?
+      filter = opts[attribute]
+      if ( filter.is_a?( Array ) )
+        return collection.select{|e| filter.include?( e.send(attribute) ) }
+      else
+        return collection.select{|e| filter == e.send(attribute) }
+      end
+    end
+
+    def supported_collections
+      DEFAULT_COLLECTIONS
+    end
+
+    def has_collection?(collection)
+      supported_collections.include?(collection)
+    end
+
+    def catched_exceptions_list
+      { :error => [], :auth => [], :glob => [] }
+    end
+
+    def api_provider
+      Thread.current[:provider] || ENV['API_PROVIDER']
+    end
+
+    # Return an array of the providers statically configured
+    # in the driver's YAML file
+    def configured_providers
+      []
+    end
+  end
+
+end
diff --git a/server/lib/deltacloud/drivers/condor/condor_driver.rb b/server/lib/deltacloud/drivers/condor/condor_driver.rb
index f5cb741..c139b62 100644
--- a/server/lib/deltacloud/drivers/condor/condor_driver.rb
+++ b/server/lib/deltacloud/drivers/condor/condor_driver.rb
@@ -14,9 +14,6 @@
 # under the License.
 #
 
-require 'deltacloud/base_driver'
-
-
 class Instance
   def self.convert_condor_state(state_id)
     case state_id
@@ -44,10 +41,6 @@ module Deltacloud
         feature :instances, :user_data
         feature :instances, :authentication_password
 
-        def supported_collections
-          DEFAULT_COLLECTIONS - [ :storage_volumes, :storage_snapshots ]
-        end
-
         CONDOR_MAPPER_DIR = ENV['CONDOR_MAPPER_DIR'] || '/var/tmp'
 
         def hardware_profiles(credentials, opts={})
@@ -175,7 +168,7 @@ module Deltacloud
           pending.to( :running )        .automatically
           pending.to( :finish )         .on(:destroy)
           running.to( :running )        .on( :reboot )
-          running.to( :stopping )       .on( :destroy )
+          running.to( :shutting_down )  .on( :destroy )
           pending.to( :finish )         .automatically
         end
 
diff --git a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
index 60e86e8..01b76b4 100644
--- a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
+++ b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
@@ -14,7 +14,6 @@
 # under the License.
 #
 
-require 'deltacloud/base_driver'
 require 'aws'
 
 class Instance
@@ -29,13 +28,8 @@ end
 
 module Deltacloud
   module Drivers
-    module EC2
-      class EC2Driver < Deltacloud::BaseDriver
-
-        def supported_collections
-
-          DEFAULT_COLLECTIONS + [ :keys, :buckets, :load_balancers, :addresses, :firewalls ]
-        end
+    module Ec2
+      class Ec2Driver < Deltacloud::BaseDriver
 
         feature :instances, :user_data
         feature :instances, :authentication_key
@@ -127,8 +121,7 @@ module Deltacloud
           stopped.to( :running )        .on( :start )
           running.to( :running )        .on( :reboot )
           running.to( :stopping )       .on( :stop )
-          stopping.to(:stopped)         .automatically
-          stopping.to(:finish)          .automatically
+          shutting_down.to( :stopped )  .automatically
           stopped.to( :finish )         .automatically
         end
 
@@ -413,9 +406,7 @@ module Deltacloud
           safely do
             s3_bucket = s3_client.bucket(opts['bucket'])
             if(opts[:id])
-              s3_key = s3_bucket.key(opts[:id], true)
-              raise "Blob #{opts[:id]} in Bucket #{opts['bucket']} NotFound" unless s3_key.exists?
-              blobs << convert_object(s3_key)
+              blobs << convert_object(s3_bucket.key(opts[:id], true))
             else
               s3_bucket.keys({}, true).each do |s3_object|
                 blobs << convert_object(s3_object)
@@ -471,7 +462,6 @@ module Deltacloud
           blob_meta = {}
           safely do
             the_blob = s3_client.bucket(opts['bucket']).key(opts[:id], true)
-            raise "Blob #{opts[:id]} in Bucket #{opts['bucket']} NotFound" unless the_blob.exists?
             blob_meta = the_blob.meta_headers
           end
         end
diff --git a/server/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb b/server/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb
deleted file mode 100644
index 03db2c1..0000000
--- a/server/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb
+++ /dev/null
@@ -1,186 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-module RightAws
-  class MockEc2
-
-    def initialize(opts={})
-    end
-
-    def describe_images(id)
-      load_fixtures_for(:images).select { |i| i[:aws_id].eql?(id) }
-    end
-
-    def describe_images_by_owner(id)
-      load_fixtures_for(:images).select { |i| i[:aws_owner].eql?(id) }
-    end
-
-    def describe_images(opts={})
-      load_fixtures_for(:images)
-    end
-
-    def describe_availability_zones(opts={})
-      load_fixtures_for(:realms)
-    end
-
-    def describe_instances(opts={})
-      instances = load_fixtures_for(:instances)
-      instances.each_with_index do |instance, i|
-        instances[i] = update_delayed_state(instance)
-        return [instance] if opts and opts[:id] and instance[:aws_instance_id].eql?(opts[:id])
-      end
-      update_fixtures_for(:instances, instances)
-      instances
-    end
-
-    def run_instances(image_id, min_count, max_count, group_ids, key_name, user_data='', addressing_type = nil, instance_type = nil, kernel_id = nil, ramdisk_id = nil, availability_zone = nil, block_device_mappings = nil)
-
-      instances = load_fixtures_for(:instances)
-      image = load_fixtures_for(:images).select { |img| img[:aws_id].eql?(image_id) }.first
-
-      if availability_zone
-        realm = load_fixtures_for(:realms).select { |realm| realm[:zone_name].eql?(availability_zone) }.first
-      else
-        realm = load_fixtures_for(:realms).first
-      end
-
-      raise Exception unless image
-      raise Exception unless realm
-
-      instance = { }
-      instance[:aws_image_id] = image[:aws_id]
-      instance[:aws_availability_zone] = realm[:zone_name]
-      instance[:aws_instance_type] = instance_type
-      instance[:aws_owner] = user_data
-      instance[:aws_state] = 'pending'
-      instance[:aws_reason] = ''
-      instance[:dns_name] = "#{random_dns}-01-C9.usma2.compute.amazonaws.com"
-      instance[:private_dns_name] = "#{random_dns}-02-P9.usma2.compute.amazonaws.com"
-      instance[:aws_state_code] = "0"
-      instance[:aws_key_name] = "staging"
-      instance[:aws_kernel_id] = "aki-be3adfd7"
-      instance[:aws_ramdisk_id] = "ari-ce34gad7"
-      instance[:aws_groups] = ["default"]
-      instance[:aws_instance_id] = random_instance_id
-      instance[:aws_reservation_id] = "r-aabbccdd"
-      instance[:aws_launch_time] = instance_time_format
-
-      instances << instance
-
-      update_fixtures_for(:instances, instances)
-
-      return [instance]
-    end
-
-
-    def terminate_instances(id)
-      update_instance_state(id, 'stopping', '80')
-    end
-
-    def reboot_instances(id)
-      update_instance_state(id, 'pending', '0')
-    end
-
-    alias :destroy_instance :terminate_instances
-
-    def describe_snapshots(opts={})
-      load_fixtures_for(:storage_snapshot)
-    end
-
-    def describe_volumes(opts={})
-      load_fixtures_for(:storage_volume)
-    end
-
-    private
-
-    def driver_dir
-      File::expand_path(File::join(File::dirname(__FILE__), '../../../../features/support/ec2'))
-    end
-
-    def fixtures_path
-      File::expand_path(File::join(driver_dir, 'fixtures'))
-    end
-
-    def load_fixtures_for(collection)
-      YAML.load_file(File::join(fixtures_path, "#{collection}.yaml"))
-    end
-
-    def update_fixtures_for(collection, new_data)
-      File.open(File::join(fixtures_path, "#{collection}.yaml"), 'w' ) do |out|
-        YAML.dump(new_data, out)
-      end
-      return new_data
-    end
-
-    def instance_time_format
-      DateTime.now.to_s.gsub(/\+(.+)$/, '.000Z')
-    end
-
-    def random_instance_id
-      id_1 = ("%.4s" % Time.now.to_i.to_s.reverse).reverse
-      id_2 = ("%.3s" % Time.now.to_i.to_s.reverse)
-      "i-#{id_1}f#{id_2}"
-    end
-
-    def random_dns
-      "domU-#{rand(90)+10}-#{rand(90)+10}-#{rand(90)+10}-#{rand(90)+10}"
-    end
-
-    def update_delayed_state(instance)
-      time = DateTime.now - DateTime.parse(instance[:aws_launch_time])
-      hours, minutes, seconds, frac = Date.day_fraction_to_time(time)
-
-      if (minutes>(rand(2)+1) or hours>0) and instance[:aws_state].eql?('pending')
-        instance[:aws_state], instance[:aws_state_code] = 'running', '16'
-      end
-
-      if (minutes>(rand(1)+1) or hours>0) and instance[:aws_state].eql?('stopping')
-        instance[:aws_state], instance[:aws_state_code] = 'stopped', '80'
-      end
-
-      return instance
-    end
-
-    def update_instance_state(id, state, state_code)
-      instance = describe_instances(:id => id).first
-      if instance
-        instance[:aws_state], instance[:aws_state_code] = state, state_code
-        instance[:aws_launch_time] = instance_time_format
-        instances = load_fixtures_for(:instances)
-        instances.each_with_index do |inst, i|
-          instances[i] = instance if inst[:aws_instance_id].eql?(id)
-        end
-        update_fixtures_for(:instances, instances)
-        return instance
-      else
-        raise Exception
-      end
-    end
-
-  end
-end
-
-Deltacloud::Drivers::EC2::EC2Driver.class_eval do
-  alias_method :original_new_client, :new_client
-
-  def new_client(credentials, opts={})
-    if credentials.user != 'mockuser' and credentials.password != 'mockpassword'
-      raise "AuthFailure"
-    end
-    RightAws::MockEc2.new
-  end
-
-end
diff --git a/server/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb b/server/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb
index 2270178..54c1eed 100644
--- a/server/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb
+++ b/server/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb
@@ -21,10 +21,6 @@ module Deltacloud
     module Eucalyptus
       class EucalyptusDriver < EC2::EC2Driver
 
-        def supported_collections
-          DEFAULT_COLLECTIONS + [ :keys, :buckets, :addresses, :firewalls ]
-        end
-
         feature :instances, :user_data
         feature :instances, :authentication_key
         feature :instances, :firewalls
diff --git a/server/lib/deltacloud/drivers/exceptions.rb b/server/lib/deltacloud/drivers/exceptions.rb
new file mode 100644
index 0000000..a89b05f
--- /dev/null
+++ b/server/lib/deltacloud/drivers/exceptions.rb
@@ -0,0 +1,191 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+module Deltacloud
+  module ExceptionHandler
+
+    class DeltacloudException < StandardError
+
+      attr_accessor :code, :name, :message, :backtrace, :request
+
+      def initialize(code, name, message, backtrace, request=nil)
+        @code, @name, @message = code, name, message
+        @backtrace = backtrace
+        @request = request
+        self
+      end
+
+    end
+
+    class AuthenticationFailure < DeltacloudException
+      def initialize(e, message=nil)
+        message ||= e.message
+        super(401, e.class.name, message, e.backtrace)
+      end
+    end
+
+    class UnknownMediaTypeError < DeltacloudException
+      def initialize(e, message=nil)
+        message ||= e.message
+        super(406, e.class.name, message, e.backtrace)
+      end
+    end
+
+    class MethodNotAllowed < DeltacloudException
+      def initialize(e, message=nil)
+        message ||= e.message
+        super(405, e.class.name, message, e.backtrace)
+      end
+    end
+
+    class ValidationFailure < DeltacloudException
+      def initialize(e, message=nil)
+        message ||= e.message
+        super(400, e.class.name, message, e.backtrace)
+      end
+    end
+
+    class BackendError < DeltacloudException
+      def initialize(e, message=nil)
+        message ||= e.message
+        super(500, e.class.name, message, e.backtrace, message)
+      end
+    end
+
+    class ProviderError < DeltacloudException
+      def initialize(e, message)
+        message ||= e.message
+        super(502, e.class.name, message, e.backtrace)
+      end
+    end
+
+    class ProviderTimeout < DeltacloudException
+      def initialize(e, message)
+        message ||= e.message
+        super(504, e.class.name, message, e.backtrace)
+      end
+    end
+
+    class NotImplemented < DeltacloudException
+      def initialize(e, message)
+        message ||= e.message
+        super(501, e.class.name, message, e.backtrace)
+      end
+    end
+
+    class ObjectNotFound < DeltacloudException
+      def initialize(e, message)
+        message ||= e.message
+        super(404, e.class.name, message, e.backtrace)
+      end
+    end
+
+    class NotSupported < DeltacloudException
+      def initialize(message)
+        super(501, self.class.name, message, self.backtrace)
+      end
+    end
+
+    class ExceptionDef
+      attr_accessor :status
+      attr_accessor :message
+      attr_reader   :conditions
+      attr_reader   :handler
+
+      def initialize(conditions, &block)
+        @conditions = conditions
+        instance_eval(&block) if block_given?
+      end
+
+      def status(code)
+        self.status = code
+      end
+
+      def message(message)
+        self.message = message
+      end
+
+      def exception(handler)
+        self.handler = handler
+      end
+
+      # Condition can be class or regexp
+      #
+      def match?(e)
+        @conditions.each do |c|
+          return true if c.class == Class && e.class == c
+          return true if c.class == Regexp && (e.class.name =~ c or e.message =~ c)
+        end
+        return false
+      end
+
+      def handler(e)
+        return @handler if @handler
+        case @status
+          when 401 then Deltacloud::ExceptionHandler::AuthenticationFailure.new(e, @message)
+          when 404 then Deltacloud::ExceptionHandler::ObjectNotFound.new(e, @message)
+          when 406 then Deltacloud::ExceptionHandler::UnknownMediaTypeError.new(e, @message)
+          when 405 then Deltacloud::ExceptionHandler::MethodNotAllowed.new(e, @message)
+          when 400 then Deltacloud::ExceptionHandler::ValidationFailure.new(e, @message)
+          when 500 then Deltacloud::ExceptionHandler::BackendError.new(e, @message)
+          when 501 then Deltacloud::ExceptionHandler::NotImplemented.new(e, @message)
+          when 502 then Deltacloud::ExceptionHandler::ProviderError.new(e, @message)
+          when 504 then Deltacloud::ExceptionHandler::ProviderTimeout.new(e, @message)
+        end
+      end
+
+    end
+
+    class Exceptions
+      attr_reader :exception_definitions
+
+      def initialize(&block)
+        @exception_definitions = []
+        instance_eval(&block) if block_given?
+        self
+      end
+
+      def on(*conditions, &block)
+        @exception_definitions << ExceptionDef::new(conditions, &block) if block_given?
+      end
+    end
+
+    def self.exceptions(&block)
+      @definitions = Exceptions.new(&block).exception_definitions if block_given?
+      @definitions
+    end
+
+    def safely(&block)
+      begin
+        block.call
+      rescue
+        report_method = $stderr.respond_to?(:err) ? :err : :puts
+        Deltacloud::ExceptionHandler::exceptions.each do |exdef|
+          if exdef.match?($!)
+            new_exception = exdef.handler($!)
+            m = new_exception.message.nil? ? $!.message : new_exception.message
+            $stderr.send(report_method, "#{[$!.class.to_s, m].join(':')}\n#{$!.backtrace[0..10].join("\n")}")
+            raise exdef.handler($!) unless new_exception.nil?
+          end
+        end
+        $stderr.send(report_method, "[NO HANDLED] #{[$!.class.to_s, $!.message].join(': ')}\n#{$!.backtrace.join("\n")}")
+        raise Deltacloud::ExceptionHandler::BackendError.new($!, "Unhandled exception or status code (#{$!.message})")
+      end
+    end
+
+  end
+
+end
diff --git a/server/lib/deltacloud/drivers/features.rb b/server/lib/deltacloud/drivers/features.rb
new file mode 100644
index 0000000..01d8656
--- /dev/null
+++ b/server/lib/deltacloud/drivers/features.rb
@@ -0,0 +1,111 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud
+  module InstanceFeatures
+
+    def self.included(k)
+      current_features = features
+      k.instance_eval do
+        features(&current_features)
+      end
+    end
+
+    def self.features(&block)
+      block_given? ? @features = block : @features || Proc.new{}
+    end
+
+    features do
+
+      feature :user_name, :for => :instances do
+        description "Allow to set user-defined name for the instance"
+        operation :create do
+          param :name, :string, :optional
+        end
+      end
+
+      feature :user_data, :for => :instances do
+        description "Allow to pass user-defined data into the instance"
+        operation :create do
+          param :user_data, :string, :optional
+        end
+      end
+
+      feature :user_iso, :for => :instances do
+        description  "Base64 encoded gzipped ISO file will be accessible as CD-ROM drive in instance"
+        operation :create do
+          param :user_iso, :string, :optional
+        end
+      end
+
+      feature :firewalls, :for => :instances do
+        description "Put instance in one or more firewalls (security groups) on launch"
+        operation :create do
+          param :firewalls, :array, :optional, nil, "Array of firewall ID strings"
+          "Array of firewall (security group) id"
+        end
+      end
+
+      feature :authentication_key, :for => :instances do
+        operation :create do
+          param :keyname, :string,  :optional, [], "Key authentification method"
+        end
+        operation :show do
+        end
+      end
+
+      feature :authentication_password, :for => :instances do
+        operation :create do
+          param :password, :string, :optional
+        end
+      end
+
+      feature :hardware_profiles, :for => :instances do
+        description "Size instances according to changes to a hardware profile"
+        # The parameters are filled in from the hardware profiles
+      end
+
+      feature :register_to_load_balancer, :for => :instances do
+        description "Register instance to load balancer"
+        operation :create do
+          param :load_balancer_id, :string, :optional
+        end
+      end
+
+      feature :instance_count, :for => :instances do
+        description "Number of instances to be launch with at once"
+        operation :create do
+          param :instance_count,  :string,  :optional
+        end
+      end
+
+      feature :attach_snapshot, :for => :instances do
+        description "Attach an snapshot to instance on create"
+        operation :create do
+          param :snapshot_id,  :string,  :optional
+          param :device_name,  :string,  :optional
+        end
+      end
+
+      feature :sandboxing, :for => :instances do
+        description "Allow lanuching sandbox images"
+        operation :create do
+          param :sandbox, :string,  :optional
+        end
+      end
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/drivers/gogrid/gogrid_driver.rb b/server/lib/deltacloud/drivers/gogrid/gogrid_driver.rb
index 285f58f..2a83c24 100644
--- a/server/lib/deltacloud/drivers/gogrid/gogrid_driver.rb
+++ b/server/lib/deltacloud/drivers/gogrid/gogrid_driver.rb
@@ -14,7 +14,6 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-require 'deltacloud/base_driver'
 require 'deltacloud/drivers/gogrid/gogrid_client'
 
 class Instance
@@ -61,11 +60,6 @@ class GogridDriver < Deltacloud::BaseDriver
     @hardware_profiles
   end
 
-  def supported_collections
-    DEFAULT_COLLECTIONS.reject! { |c| [ :storage_volumes, :storage_snapshots ].include?(c) }
-    DEFAULT_COLLECTIONS + [ :keys, :load_balancers ]
-  end
-
   def images(credentials, opts=nil)
     imgs = []
     if opts and opts[:id]
diff --git a/server/lib/deltacloud/drivers/google/google_driver.rb b/server/lib/deltacloud/drivers/google/google_driver.rb
index 2ffb5f8..8bc6f25 100644
--- a/server/lib/deltacloud/drivers/google/google_driver.rb
+++ b/server/lib/deltacloud/drivers/google/google_driver.rb
@@ -21,9 +21,6 @@ module Deltacloud
 
 class GoogleDriver < Deltacloud::BaseDriver
 
-  def supported_collections; [:buckets]
-  end
-
   feature :buckets, :bucket_location
 
 #--
diff --git a/server/lib/deltacloud/drivers/mock/mock_client.rb b/server/lib/deltacloud/drivers/mock/mock_client.rb
index 94c56af..248cc49 100644
--- a/server/lib/deltacloud/drivers/mock/mock_client.rb
+++ b/server/lib/deltacloud/drivers/mock/mock_client.rb
@@ -91,17 +91,6 @@ module Deltacloud::Drivers::Mock
       FileUtils.rm(fname) if File::exists?(fname)
     end
 
-    def store_cimi(collection, obj)
-      raise "Why no obj.name?" unless obj.name
-      File::open(cimi_file(collection, obj.name), "w") { |f| f.write(obj.to_json) }
-    end
-
-    def destroy_cimi(collection, id)
-      fname = cimi_file(collection, id)
-      raise "No such object: #{id} in #{collection} collection" unless File::exists?(fname)
-      FileUtils.rm(fname)
-    end
-
     def load_all_cimi(model_name)
         model_files = Dir[File::join(cimi_dir(model_name), "*.json")]
         model_files.map{|f| File.read(f)}
diff --git a/server/lib/deltacloud/drivers/mock/mock_driver.rb b/server/lib/deltacloud/drivers/mock/mock_driver.rb
index b58872c..15f06fb 100644
--- a/server/lib/deltacloud/drivers/mock/mock_driver.rb
+++ b/server/lib/deltacloud/drivers/mock/mock_driver.rb
@@ -14,28 +14,16 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-
 require 'yaml'
 require 'base64'
 require 'etc'
-require 'deltacloud/base_driver'
-require 'deltacloud/drivers/mock/mock_client'
-require 'deltacloud/drivers/mock/mock_driver_cimi_methods'
+require_relative 'mock_client'
+require_relative 'mock_driver_cimi_methods'
 
 module Deltacloud::Drivers::Mock
 
   class MockDriver < Deltacloud::BaseDriver
 
-    # If the provider is set to storage, pretend to be a storage-only
-    # driver
-    def supported_collections
-      if api_provider == 'storage'
-        [:buckets]
-      else
-        DEFAULT_COLLECTIONS + [:buckets, :keys]
-      end
-    end
-
     ( REALMS = [
       Realm.new({
         :id=>'us',
@@ -299,11 +287,6 @@ module Deltacloud::Drivers::Mock
       snapshots
     end
 
-    def destroy_storage_snapshot(credentials, opts={})
-      check_credentials(credentials)
-      @client.destroy(:storage_snapshots, opts[:id])
-    end
-
     def keys(credentials, opts={})
       check_credentials(credentials)
       result = @client.build_all(Key)
diff --git a/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb b/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
index 2dec66b..bebc45c 100644
--- a/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
+++ b/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
@@ -32,49 +32,6 @@ module Deltacloud::Drivers::Mock
       end
     end
 
-    def create_network(credentials, opts={})
-      check_credentials(credentials)
-      id = "#{opts[:env].send("networks_url")}/#{opts[:name]}"
-      net_hsh = { "id"=> id,
-                  "name" => opts[:name],
-                  "description" => opts[:description],
-                  "created" => Time.now,
-                  "state" => "STARTED",
-                  "access" => opts[:network_config].access,
-                  "bandwithLimit" => opts[:network_config].bandwidth_limit,
-                  "trafficPriority" => opts[:network_config].traffic_priority,
-                  "maxTrafficDelay" => opts[:network_config].max_traffic_delay,
-                  "maxTrafficLoss" =>opts[:network_config].max_traffic_loss,
-                  "maxTrafficJitter" =>opts[:network_config].max_traffic_jitter,
-                  "routingGroup"=> { "href" => opts[:routing_group].id },
-                  "operations" => [{"rel"=>"edit", "href"=> id},
-                                   {"rel"=>"delete", "href"=> id}]    }
-      network = CIMI::Model::Network.from_json(JSON.generate(net_hsh))
-
-      @client.store_cimi(:network, network)
-      network
-    end
-
-    def delete_network(credentials, id)
-      check_credentials(credentials)
-      @client.destroy_cimi(:network, id)
-    end
-
-    def start_network(credentials, id)
-      check_credentials(credentials)
-      update_object_state(id, "Network", "STARTED")
-    end
-
-    def stop_network(credentials, id)
-      check_credentials(credentials)
-      update_object_state(id, "Network", "STOPPED")
-    end
-
-    def suspend_network(credentials, id)
-      check_credentials(credentials)
-      update_object_state(id, "Network", "SUSPENDED")
-    end
-
     def network_configurations(credentials, opts={})
       check_credentials(credentials)
       if opts[:id].nil?
@@ -130,43 +87,6 @@ module Deltacloud::Drivers::Mock
       end
     end
 
-    def create_vsp(credentials, opts={})
-      check_credentials(credentials)
-      id = "#{opts[:env].send("vsps_url")}/#{opts[:name]}"
-      vsp_hash = { "id"    => id,
-                    "name"  => opts[:name],
-                    "description" => opts[:description],
-                    "state" => "STARTED",
-                    "created" => Time.now,
-                    "bandwidthReservation"=>opts[:vsp_config].bandwidth_reservation,
-                    "trafficPriority"=>opts[:vsp_config].traffic_priority,
-                    "maxTrafficDelay"=>opts[:vsp_config].max_traffic_delay,
-                    "maxTrafficLoss"=>opts[:vsp_config].max_traffic_loss,
-                    "maxTrafficJitter"=>opts[:vsp_config].max_traffic_jitter,
-                    "network" => {"href" => opts[:network].id},
-                    "operations" => [{"rel"=>"edit", "href"=> id},
-                                     {"rel"=>"delete", "href"=> id}]
-                   }
-      vsp = CIMI::Model::VSP.from_json(JSON.generate(vsp_hash))
-      @client.store_cimi(:vsp, vsp)
-      vsp
-    end
-
-    def start_vsp(credentials, id)
-      check_credentials(credentials)
-      update_object_state(id, "VSP", "STARTED")
-    end
-
-    def stop_vsp(credentials, id)
-      check_credentials(credentials)
-      update_object_state(id, "VSP", "STOPPED")
-    end
-
-    def delete_vsp(credentials, id)
-      check_credentials(credentials)
-      @client.destroy_cimi(:vsp, id)
-    end
-
     def vsp_configurations(credentials, opts={})
       check_credentials(credentials)
       if opts[:id].nil?
@@ -189,56 +109,6 @@ module Deltacloud::Drivers::Mock
       end
     end
 
-    def addresses(credentials, opts={})
-      check_credentials(credentials)
-      if opts[:id].nil?
-        addresses = @client.load_all_cimi(:address).map{|addr| CIMI::Model::Address.from_json(addr)}
-        addresses.map{|addr|convert_cimi_mock_urls(:address, addr, opts[:env])}.flatten
-      else
-        address = CIMI::Model::Address.from_json(@client.load_cimi(:address, opts[:id]))
-        convert_cimi_mock_urls(:address, address, opts[:env])
-      end
-    end
-
-    def create_address(credentials, opts={})
-      check_credentials(credentials)
-      id = "#{opts[:env].send("addresses_url")}/#{opts[:name]}"
-      addr_hash = { "id"    => id,
-                    "name"  => opts[:name],
-                    "description" => opts[:description],
-                    "created" => Time.now,
-                    "hostName" => opts[:address_template].hostname,
-                    "allocation" => opts[:address_template].allocation,
-                    "defaultGateway" => opts[:address_template].default_gateway,
-                    "dns" => opts[:address_template].dns,
-                    "macAddress" => opts[:address_template].mac_address,
-                    "protocol" => opts[:address_template].protocol,
-                    "mask" => opts[:address_template].mask,
-                    "network" => {"href" => opts[:address_template].network.href},
-                    "operations" => [{"rel"=>"edit", "href"=> id},
-                                     {"rel"=>"delete", "href"=> id}]
-                   }
-      address = CIMI::Model::Address.from_json(JSON.generate(addr_hash))
-      @client.store_cimi(:address, address)
-      address
-    end
-
-    def delete_address(credentials, id)
-      check_credentials(credentials)
-      @client.destroy_cimi(:address, id)
-    end
-
-    def address_templates(credentials, opts={})
-      check_credentials(credentials)
-      if opts[:id].nil?
-        address_templates = @client.load_all_cimi(:address_template).map{|addr_templ| CIMI::Model::AddressTemplate.from_json(addr_templ)}
-        address_templates.map{|addr_templ|convert_cimi_mock_urls(:address_template, addr_templ, opts[:env])}.flatten
-      else
-        address_template = CIMI::Model::AddressTemplate.from_json(@client.load_cimi(:address_template, opts[:id]))
-        convert_cimi_mock_urls(:address_template, address_template, opts[:env])
-      end
-    end
-
     private
 
     def convert_cimi_mock_urls(model_name, cimi_object, context)
@@ -270,15 +140,6 @@ module Deltacloud::Drivers::Mock
       end
     end
 
-    def update_object_state(id, object, new_state)
-      klass = CIMI::Model.const_get("#{object}")
-      symbol = object.to_s.downcase.singularize.intern
-      obj = klass.from_json(@client.load_cimi(symbol, id))
-      obj.state = new_state
-      @client.store_cimi(symbol, obj)
-      obj
-    end
-
   end
 
 end
diff --git a/server/lib/deltacloud/drivers/opennebula/opennebula_driver.rb b/server/lib/deltacloud/drivers/opennebula/opennebula_driver.rb
index 371e170..03c337f 100644
--- a/server/lib/deltacloud/drivers/opennebula/opennebula_driver.rb
+++ b/server/lib/deltacloud/drivers/opennebula/opennebula_driver.rb
@@ -28,10 +28,6 @@ module Deltacloud
 
 class OpennebulaDriver < Deltacloud::BaseDriver
 
-  def supported_collections
-    DEFAULT_COLLECTIONS - [:storage_volumes, :storage_snapshots]
-  end
-
   ######################################################################
   # Hardware profiles
   #####################################################################
@@ -152,8 +148,8 @@ class OpennebulaDriver < Deltacloud::BaseDriver
     running.to(:running)        .on( :reboot )
     running.to(:stopping)       .on( :stop )
     stopping.to(:stopped)       .automatically
-    running.to(:stopping)       .on( :destroy )
-    stopping.to(:finish)        .automatically
+    running.to(:shutting_down)  .on( :destroy )
+    shutting_down.to(:finish)   .automatically
   end
 
   def instances(credentials, opts=nil)
diff --git a/server/lib/deltacloud/drivers/openstack/openstack_driver.rb b/server/lib/deltacloud/drivers/openstack/openstack_driver.rb
index c9ec95b..5d54d5b 100644
--- a/server/lib/deltacloud/drivers/openstack/openstack_driver.rb
+++ b/server/lib/deltacloud/drivers/openstack/openstack_driver.rb
@@ -14,9 +14,9 @@
 # under the License.
 #
 
-require 'deltacloud/base_driver'
 require 'openstack/compute'
 require 'tempfile'
+
 module Deltacloud
   module Drivers
     module Openstack
@@ -27,16 +27,12 @@ module Deltacloud
         feature :instances, :user_files
         feature :images, :user_name
 
-        def supported_collections
-          DEFAULT_COLLECTIONS - [ :storage_snapshots, :storage_volumes  ] #+ [ :buckets ]
-        end
-
         define_instance_states do
           start.to( :pending )          .on( :create )
           pending.to( :running )        .automatically
           running.to( :running )        .on( :reboot )
-          running.to( :stopping )       .on( :stop )
-          stopping.to( :stopped )       .automatically
+          running.to( :shutting_down )  .on( :stop )
+          shutting_down.to( :stopped )  .automatically
           stopped.to( :finish )         .automatically
         end
 
@@ -140,7 +136,7 @@ module Deltacloud
           params[:name] = (opts[:name] && opts[:name].length>0)? opts[:name] : Time.now.to_s
           params[:imageRef] = image_id
           params[:flavorRef] =  (opts[:hwp_id] && opts[:hwp_id].length>0) ?
-                          opts[:hwp_id] : hardware_profiles(credentials).first.name
+                          opts[:hwp_id] : hardware_profiles(credentials).first
           if opts[:password] && opts[:password].length > 0
             params[:adminPass]=opts[:password]
           end
diff --git a/server/lib/deltacloud/drivers/rackspace/rackspace_driver.rb b/server/lib/deltacloud/drivers/rackspace/rackspace_driver.rb
index 1b019d4..f59f832 100644
--- a/server/lib/deltacloud/drivers/rackspace/rackspace_driver.rb
+++ b/server/lib/deltacloud/drivers/rackspace/rackspace_driver.rb
@@ -14,7 +14,6 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-require 'deltacloud/base_driver'
 require 'cloudfiles'
 require 'cloudservers'
 require 'base64'
@@ -30,10 +29,6 @@ class RackspaceDriver < Deltacloud::BaseDriver
   feature :instances, :user_files
   feature :images, :user_name
 
-  def supported_collections
-    DEFAULT_COLLECTIONS + [ :buckets ] - [ :storage_snapshots, :storage_volumes ]
-  end
-
   def hardware_profiles(credentials, opts = {})
     rs = new_client( credentials )
     results = []
@@ -194,8 +189,8 @@ class RackspaceDriver < Deltacloud::BaseDriver
     start.to( :pending )          .on( :create )
     pending.to( :running )        .automatically
     running.to( :running )        .on( :reboot )
-    running.to( :stopping )       .on( :stop )
-    stopping.to( :stopped )       .automatically
+    running.to( :shutting_down )  .on( :stop )
+    shutting_down.to( :stopped )  .automatically
     stopped.to( :finish )         .automatically
   end
 
diff --git a/server/lib/deltacloud/drivers/rhevm/rhevm_driver.rb b/server/lib/deltacloud/drivers/rhevm/rhevm_driver.rb
index 1c96df7..f138f03 100644
--- a/server/lib/deltacloud/drivers/rhevm/rhevm_driver.rb
+++ b/server/lib/deltacloud/drivers/rhevm/rhevm_driver.rb
@@ -14,27 +14,24 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-require 'deltacloud/base_driver'
 require 'rbovirt'
 
 module Deltacloud
   module Drivers
-    module RHEVM
+    module Rhevm
 
-class RHEVMDriver < Deltacloud::BaseDriver
+class RhevmDriver < Deltacloud::BaseDriver
 
-  def supported_collections
-    DEFAULT_COLLECTIONS - [:storage_snapshots]
-  end
-
-  feature :instances, :user_name do
-    constraint :max_length, 50
+  Sinatra::Rabbit::InstancesCollection.features do
+    feature :user_name, :for => :instances do
+      constrain :max_length, 50
+    end
   end
 
   feature :instances, :user_data
   feature :images, :user_name
 
-  USER_NAME_MAX = feature(:instances, :user_name).constraints[:max_length]
+  USER_NAME_MAX = Sinatra::Rabbit::InstancesCollection.feature(:user_name).constraints[:max_length]
 
   # FIXME: These values are just for ilustration
   # Also I choosed 'SERVER' and 'DESKTOP' names
diff --git a/server/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb b/server/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb
index 58f8e1b..f44336a 100644
--- a/server/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb
+++ b/server/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb
@@ -41,17 +41,16 @@ class RimuHostingClient
       headers["Authorization"] = @auth
     end
     safely do
-      r = @service.send_request(method, @uri.path + resource, data, headers)
-          puts r.body
-      res = JSON.parse(r.body)
-      res = res[res.keys[0]]
+    r = @service.send_request(method, @uri.path + resource, data, headers)
+         puts r.body
+    res = JSON.parse(r.body)
+    res = res[res.keys[0]]
 
-      if(res['response_type'] == "ERROR" and ( (res['error_info']['error_class'] == "PermissionException") or
+    if(res['response_type'] == "ERROR" and ( (res['error_info']['error_class'] == "PermissionException") or
 					     (res['error_info']['error_class'] == "LoginRequired") ))
-        raise "AuthFailure"
-      end
-      res
+      raise "AuthFailure"
     end
+    res
   end
 
   def list_images
@@ -82,6 +81,6 @@ class RimuHostingClient
   end
 end
 
+    end
   end
 end
-end
diff --git a/server/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb b/server/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb
index 67c415c..8633d53 100644
--- a/server/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb
+++ b/server/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb
@@ -16,7 +16,6 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-require "deltacloud/base_driver"
 require "deltacloud/drivers/rimuhosting/rimuhosting_client"
 
 module Deltacloud
@@ -131,9 +130,9 @@ class RimuHostingDriver < Deltacloud::BaseDriver
             :owner_id => "root",
             :instance_profile => InstanceProfile.new("none"),
             :actions => instance_actions_for("RUNNING"),
-            :public_addresses => [ InstanceAddress.new(inst["allocated_ips"]["primary_ip"] ) ],
-            :launch_time => inst["billing_info"]["order_date"]["iso_format"]
-    })
+            :public_addresses => [ InstanceAddress.new(inst["allocated_ips"]["primary_ip"] )],
+            :launch_time => inst["billing_info"]["order_date"]["iso_format"]}
+                )
   end
 
   define_instance_states do
@@ -142,9 +141,9 @@ class RimuHostingDriver < Deltacloud::BaseDriver
     pending.to( :running )        .automatically
 
     running.to( :running )        .on(:reboot)
-    running.to( :stopping )       .on(:stop)
+    running.to( :shutting_down )  .on(:stop)
 
-    stopping.to( :stopped )       .automatically
+    shutting_down.to( :stopped )  .automatically
 
     stopped.to( :finish )         .automatically
   end
diff --git a/server/lib/deltacloud/drivers/terremark/terremark_driver.rb b/server/lib/deltacloud/drivers/terremark/terremark_driver.rb
index 2dba02a..2e087cb 100644
--- a/server/lib/deltacloud/drivers/terremark/terremark_driver.rb
+++ b/server/lib/deltacloud/drivers/terremark/terremark_driver.rb
@@ -19,8 +19,7 @@
 # https://community.vcloudexpress.terremark.com/en-us/product_docs/w/wiki/d-complete-vcloud-express-api-document.aspx
 #
 # 02 May 2010
-#
-require 'deltacloud/base_driver'
+
 require 'fog'
 require 'excon'
 require 'nokogiri'
@@ -118,8 +117,8 @@ VAPP_STATE_MAP = { "0" =>  "PENDING", "1" =>  "PENDING", "2" =>  "STOPPED", "4"
     pending.to(:stopped)          .automatically
     stopped.to(:running)          .on( :start )
     running.to(:running)          .on( :reboot )
-    running.to(:stopping)         .on( :stop )
-    stopping.to(:stopped)         .automatically
+    running.to(:shutting_down)    .on( :stop )
+    shutting_down.to(:stopped)    .automatically
     stopped.to(:finish)           .on( :destroy )
    end
 
diff --git a/server/lib/deltacloud/drivers/vsphere/vsphere_driver.rb b/server/lib/deltacloud/drivers/vsphere/vsphere_driver.rb
index e16be2f..7ac908a 100644
--- a/server/lib/deltacloud/drivers/vsphere/vsphere_driver.rb
+++ b/server/lib/deltacloud/drivers/vsphere/vsphere_driver.rb
@@ -14,18 +14,17 @@
 # under the License.
 #
 
-require 'deltacloud/base_driver'
 require 'rbvmomi'
 require 'deltacloud/drivers/vsphere/vsphere_client'
 
-module Deltacloud::Drivers::VSphere
+module Deltacloud::Drivers::Vsphere
 
   MAPPER_STORAGE_ROOT = File::join("/var/tmp", "deltacloud-vsphere-#{ENV["USER"]}")
 
-  class VSphereDriver < Deltacloud::BaseDriver
+  class VsphereDriver < Deltacloud::BaseDriver
 
     include Deltacloud::Drivers::VSphere::Helper
-    include Deltacloud::Drivers::VSphere::FileManager
+    include VSphere::FileManager
 
     # You can use 'user_iso' feature to set 'user_iso' parameter when creating
     # a new instance where this parameter can hold gzipped CDROM iso which will
@@ -34,10 +33,6 @@ module Deltacloud::Drivers::VSphere
     feature :instances, :user_data
     feature :instances, :user_name
 
-    def supported_collections
-      DEFAULT_COLLECTIONS - [:storage_volumes, :storage_snapshots]
-    end
-
     # There is just one hardware profile where memory is measured using maximum
     # memory available on ESX for virtual machines and CPU using maximum free
     # CPU cores in ESX.
@@ -68,8 +63,8 @@ module Deltacloud::Drivers::VSphere
       pending.to(:stopped)        .automatically
       stopped.to(:running)        .on( :start )
       running.to(:running)        .on( :reboot )
-      running.to(:stopping)       .on( :stop )
-      stopping.to(:stopped)       .automatically
+      running.to(:shutting_down)  .on( :stop )
+      shutting_down.to(:stopped)  .automatically
       stopped.to(:finish)         .on( :destroy )
     end
 
diff --git a/server/lib/deltacloud/hardware_profile.rb b/server/lib/deltacloud/hardware_profile.rb
deleted file mode 100644
index 162f7af..0000000
--- a/server/lib/deltacloud/hardware_profile.rb
+++ /dev/null
@@ -1,192 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-module Deltacloud
-  class HardwareProfile
-
-    UNITS = {
-      :memory => "MB",
-      :storage => "GB",
-      :architecture => "label",
-      :cpu => "count"
-    }
-
-    def self.unit(name)
-      UNITS[name]
-    end
-
-    class Property
-      attr_reader :name, :kind, :default
-      # kind == :range
-      attr_reader :first, :last
-      # kind == :enum
-      attr_reader :values
-      # kind == :fixed
-      attr_reader :value
-
-      def initialize(name, values, opts = {})
-        @name = name
-        if values.is_a?(Range)
-          @kind = :range
-          @first = values.first
-          @last = values.last
-          @default = values.first
-        elsif values.is_a?(Array)
-          @kind = :enum
-          @values = values
-          @default = values.first
-        else
-          @kind = :fixed
-          @value = values
-          @default = @value
-        end
-        @default = opts[:default] if opts[:default]
-      end
-
-      def unit
-        HardwareProfile.unit(name)
-      end
-
-      def param
-        :"hwp_#{name}"
-      end
-
-      def fixed?
-        kind == :fixed
-      end
-
-      def valid?(v)
-        v = convert_property_value_type(v)
-        case kind
-          # NOTE:
-          # Currently we cannot validate fixed values because of UI
-          # limitation. In UI we have multiple hwp_* properties which overide
-          # each other.
-          # Then provider have one 'static' hardware profile and one
-          # 'customizable' when user select the static one the UI also send
-          # values from the customizable one (which will lead to a validation
-          # error because validation algorith will think that client want to
-          # overide fixed values.
-          #
-          # when :fixed then (v == @default.to_s)
-          when :fixed then true
-          when :range then match_type?(first, v) and (first..last).include?(v)
-          when :enum then match_type?(values.first, v) and values.include?(v)
-          else false
-        end
-      end
-
-      def to_param
-        Validation::Param.new([param, :string, :optional, []])
-      end
-
-      def include?(v)
-        if kind == :fixed
-          return v == value
-        else
-          return values.include?(v)
-        end
-      end
-
-      private
-
-      def match_type?(reference, value)
-        true if reference.class == value.class
-      end
-
-      def convert_property_value_type(v)
-        return v.to_f if v =~ /(\d+)\.(\d+)/
-        return v.to_i if v =~ /(\d+)/
-        v.to_s
-      end
-    end
-
-    class << self
-      def property(prop)
-        define_method(prop) do |*args|
-          values, opts, *ignored = *args
-          instvar = :"@#{prop}"
-          unless values.nil?
-            @properties[prop] = Property.new(prop, values, opts || {})
-          end
-          @properties[prop]
-        end
-      end
-    end
-
-    attr_reader :name
-    property :cpu
-    property :architecture
-    property :memory
-    property :storage
-
-    def initialize(name,&block)
-      @properties   = {}
-      @name         = name
-      instance_eval &block if block_given?
-    end
-
-    def each_property(&block)
-      @properties.each_value { |prop| yield prop }
-    end
-
-    def properties
-      @properties.values
-    end
-
-    def property(name)
-      @properties[name.to_sym]
-    end
-
-    def default?(prop, v)
-      p = @properties[prop.to_sym]
-      p && p.default.to_s == v
-    end
-
-    def to_hash
-      props = []
-      self.each_property do |p|
-        if p.kind.eql? :fixed
-          props << { :kind => p.kind, :value => p.value, :name => p.name, :unit => p.unit }
-        else
-          param = { :operation => "create", :method => "post", :name => p.name }
-          if p.kind.eql? :range
-            param[:range] = { :first => p.first, :last => p.last }
-          elsif p.kind.eql? :enum
-            param[:enum] = p.values.collect { |v| { :entry => v } }
-          end
-          param
-          props << { :kind => p.kind, :value => p.default, :name => p.name, :unit => p.unit, :param => param }
-        end
-      end
-      {
-        :id => self.name,
-        :properties => props
-      }
-    end
-
-    def include?(prop, v)
-      p = @properties[prop]
-      p.nil? || p.include?(v)
-    end
-
-    def params
-      @properties.values.inject([]) { |m, prop|
-        m << prop.to_param
-      }.compact
-    end
-  end
-end
diff --git a/server/lib/deltacloud/helpers.rb b/server/lib/deltacloud/helpers.rb
index cf8531a..7be8faf 100644
--- a/server/lib/deltacloud/helpers.rb
+++ b/server/lib/deltacloud/helpers.rb
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.  The
@@ -14,10 +13,83 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-require 'deltacloud/helpers/application_helper'
-require 'deltacloud/helpers/json_helper'
-require 'deltacloud/helpers/conversion_helper'
-require 'deltacloud/helpers/hardware_profiles_helper'
-require 'deltacloud/helpers/blob_stream'
+require_relative 'helpers/driver_helper'
+require_relative 'helpers/auth_helper'
+require_relative 'helpers/url_helper'
+require_relative 'helpers/assets_helper'
+require_relative 'helpers/deltacloud_helper'
+require_relative 'helpers/rabbit_helper'
+require_relative 'core_ext/string'
+require_relative 'core_ext/array'
+require_relative 'core_ext/hash'
+require_relative 'core_ext/integer'
+require_relative 'core_ext/proc'
+
+module Deltacloud::Collections
+  class Base < Sinatra::Base
+
+    extend Deltacloud::Helpers::Drivers
+    include Sinatra::Rabbit::Features
+
+    helpers Deltacloud::Helpers::Drivers
+    helpers Sinatra::AuthHelper
+    helpers Sinatra::UrlForHelper
+    helpers Sinatra::StaticAssets::Helpers
+    helpers Rack::RespondTo::Helpers
+    helpers Deltacloud::Helpers::Application
+
+    register Rack::RespondTo
+
+    enable :xhtml
+    enable :dump_errors
+    enable :show_errors
+    disable :show_exceptions
+
+    set :root_url, API_ROOT_URL
+    set :version, API_VERSION
+    set :root, File.join(File.dirname(__FILE__), '..', '..')
+    set :views, root + '/views'
+    set :public_folder, root + '/public'
+
+    error do
+      report_error
+    end
+
+    error Deltacloud::ExceptionHandler::ValidationFailure do
+      report_error
+    end
+
+    before do
+      # Respond with 400, If we don't get a http Host header,
+      halt 400, "Unable to find HTTP Host header" if @env['HTTP_HOST'] == nil
+    end
+
+    after do
+      headers 'Server' => 'Apache-Deltacloud/' + settings.version
+    end
+
+    def self.new_route_for(route, &block)
+      get route_for('/' + route.to_s + '/new') do
+        instance_eval(&block) if block_given?
+        respond_to do |format|
+          format.html do
+            haml :"#{route}/new"
+          end
+        end
+      end
+    end
+
+    def self.check_capability(opts={})
+      Sinatra::Rabbit.set :check_capability, opts[:for]
+    end
+
+    def self.check_features(opts={})
+      Sinatra::Rabbit.set :check_features, opts[:for]
+    end
+
+    def self.route_for(url)
+      "#{settings.root_url}#{url}"
+    end
 
-helpers ApplicationHelper, ConversionHelper, HardwareProfilesHelper, JSONHelper
+  end
+end
diff --git a/server/lib/deltacloud/helpers/application_helper.rb b/server/lib/deltacloud/helpers/application_helper.rb
deleted file mode 100644
index 7a0d58b..0000000
--- a/server/lib/deltacloud/helpers/application_helper.rb
+++ /dev/null
@@ -1,238 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-# Methods added to this helper will be available to all templates in the application.
-
-require 'benchmark'
-
-module ApplicationHelper
-
-  include Deltacloud
-
-  def instance_action_method(action)
-    action_method(action, :instances)
-  end
-
-  def action_method(action, collection)
-    collections[collection].operations[action.to_sym].method
-  end
-
-  def driver_has_feature?(feature_name, collection_name = :instances)
-    driver.features(collection_name).any? { |f| f.name == feature_name }
-  end
-
-  def driver_has_auth_features?
-    driver_has_feature?(:authentication_password) || driver_has_feature?(:authentication_key)
-  end
-
-  def driver_auth_feature_name
-    'key' if driver_has_feature?(:authentication_key)
-    'password' if driver_has_feature?(:authentication_password)
-  end
-
-  def filter_all(model)
-      filter = {}
-      filter.merge!(:id => params[:id]) if params[:id]
-      filter.merge!(:architecture => params[:architecture]) if params[:architecture]
-      filter.merge!(:owner_id => params[:owner_id]) if params[:owner_id]
-      filter.merge!(:state => params[:state]) if params[:state]
-      filter = {} if filter.keys.size.eql?(0)
-      singular = model.to_s.singularize.to_sym
-      begin
-       @benchmark = Benchmark.measure do
-          @elements = driver.send(model.to_sym, credentials, filter)
-        end
-      rescue
-        @exception = $!
-      end
-      if @elements
-        headers['X-Backend-Runtime'] = @benchmark.real.to_s
-        instance_variable_set(:"@#{model}", @elements)
-        respond_to do |format|
-          format.html { haml :"#{model}/index" }
-          format.xml { haml :"#{model}/index" }
-          format.json { convert_to_json(singular, @elements) }
-        end
-      else
-        report_error(@exception.code)
-      end
-  end
-
-  def show(model)
-    @benchmark = Benchmark.measure do
-      @element = driver.send(model, credentials, { :id => params[:id]} )
-    end
-    headers['X-Backend-Runtime'] = @benchmark.real.to_s
-    instance_variable_set("@#{model}", @element)
-    if @element
-      respond_to do |format|
-        format.html { haml :"#{model.to_s.pluralize}/show" }
-        format.xml { haml :"#{model.to_s.pluralize}/show" }
-        format.json { convert_to_json(model, @element) }
-      end
-    else
-      report_error(404)
-    end
-  end
-
-  def report_error(code=nil)
-    @error, @code = (request.env['sinatra.error'] || @exception), code
-    @code = 500 if not @code and not @error.class.method_defined? :code
-    response.status = @code || @error.code
-    respond_to do |format|
-      format.xml {  haml :"errors/#{@code || @error.code}", :layout => false }
-      format.json { json_return_error(@error) }
-      format.html { haml :"errors/#{@code || @error.code}", :layout => :error }
-    end
-  end
-
-  def instance_action(name)
-    original_instance = driver.instance(credentials, :id => params[:id])
-
-    # If original instance doesn't include called action
-    # return with 405 error (Method is not Allowed)
-    unless driver.instance_actions_for(original_instance.state).include?(name.to_sym)
-      return report_error(405)
-    end
-
-    @benchmark = Benchmark.measure do
-      @instance = driver.send(:"#{name}_instance", credentials, params[:id])
-    end
-
-    headers['X-Backend-Runtime'] = @benchmark.real.to_s
-
-    if name == :reboot
-      status 202
-    end
-
-    if name == :destroy
-      respond_to do |format|
-        format.xml { return 204 }
-        format.json { return 204 }
-        format.html { return redirect(instances_url) }
-      end
-    end
-
-    if @instance.class != Instance
-      response['Location'] = instance_url(params[:id])
-      halt
-    end
-
-    respond_to do |format|
-      format.xml { haml :"instances/show" }
-      format.html { haml :"instances/show" }
-      format.json {convert_to_json(:instance, @instance) }
-    end
-  end
-
-  def cdata(text = nil, &block)
-    text ||= capture_haml(&block)
-    "<![CDATA[#{text.strip}]]>"
-  end
-
-  def render_cdata(text)
-    "<![CDATA[#{text.strip}]]>"
-  end
-
-  def link_to_action(action, url, method)
-    capture_haml do
-      haml_tag :form, :method => :post, :action => url, :class => [:link, method], :'data-ajax' => 'false' do
-        haml_tag :input, :type => :hidden, :name => '_method', :value => method
-        haml_tag :button, :type => :submit, :'data-ajax' => 'false', :'data-inline' => "true" do
-          haml_concat action
-        end
-      end
-    end
-  end
-
-  def link_to_format(format)
-    return unless request.env['REQUEST_URI']
-    uri = request.env['REQUEST_URI']
-    return if uri.include?('format=')
-    uri += uri.include?('?') ? "&format=#{format}" : "?format=#{format}"
-    capture_haml do
-      haml_tag :a, :href => uri, :'data-ajax' => 'false', :'data-icon' => 'grid' do
-        haml_concat format.to_s.upcase
-      end
-    end
-  end
-
-  def image_for_state(state)
-    state_img = "stopped" if (state!='RUNNING' or state!='PENDING')
-    capture_haml do
-      haml_tag :img, :src => "/images/#{state}" % state.downcase, :title => state
-    end
-  end
-
-  # Reverse the entrypoints hash for a driver from drivers.yaml; note that
-  # +d+ is a hash, not an actual driver object
-  def driver_provider(d)
-    result = {}
-    if d[:entrypoints]
-      d[:entrypoints].each do |kind, details|
-        details.each do |prov, url|
-          result[prov] ||= {}
-          result[prov][kind] = url
-        end
-      end
-    end
-    result
-  end
-
-  def header(title, opts={}, &block)
-    opts[:theme] ||= 'b'
-    opts[:back] ||= 'true'
-    capture_haml do
-      haml_tag :div, :'data-role' => :header, :'data-theme' => opts[:theme], :'data-add-back-btn' => opts[:back] do
-        haml_tag :a, :'data-rel' => :back do
-          haml_concat "Back"
-        end if opts[:back] == 'true'
-        haml_tag :h1 do
-          haml_concat title
-        end
-        block.call if block_given?
-      end
-    end
-  end
-
-  def subheader(title, opts={})
-    opts[:theme] ||= 'a'
-    capture_haml do
-      haml_tag :div, :'data-role' => :header, :'data-theme' => opts[:theme] do
-        haml_tag :p, :class => 'inner-right' do
-          haml_concat title
-        end
-      end
-    end
-  end
-
-  def translate_error_code(code)
-    case code
-      when 400; { :message => "Bad Request" }
-      when 401; { :message => "Unauthorized" }
-      when 403; { :message => "Forbidden" }
-      when 404; { :message => "Not Found" }
-      when 405; { :message => "Method Not Allowed" }
-      when 406; { :message => "Not Acceptable" }
-      when 500; { :message => "Internal Server Error" }
-      when 502; { :message => "Backend Server Error" }
-      when 501; { :message => "Not Supported" }
-    end
-  end
-
-  def new_blob_form_url(bucket)
-    bucket_url(@bucket.name) + "/" + NEW_BLOB_FORM_ID
-  end
-end
diff --git a/server/lib/deltacloud/helpers/assets_helper.rb b/server/lib/deltacloud/helpers/assets_helper.rb
new file mode 100644
index 0000000..2391da7
--- /dev/null
+++ b/server/lib/deltacloud/helpers/assets_helper.rb
@@ -0,0 +1,96 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Sinatra
+  module StaticAssets
+    module Helpers
+      # In HTML <link> and <img> tags have no end tag.
+      # In XHTML, on the contrary, these tags must be properly closed.
+      #
+      # We can choose the appropriate behaviour with +closed+ option:
+      #
+      #   image_tag "/images/foo.png", :alt => "Foo itself", :closed => true
+      #
+      # The default value of +closed+ option is +false+.
+      #
+      def image_tag(source, options = {})
+        options[:src] = url_for(source)
+        tag("img", options)
+      end
+
+      def stylesheet_link_tag(*sources)
+        list, options = extract_options(sources)
+        list.collect { |source| stylesheet_tag(source, options) }.join("\n")
+      end
+
+      def javascript_script_tag(*sources)
+        list, options = extract_options(sources)
+        list.collect { |source| javascript_tag(source, options) }.join("\n")
+      end
+
+      def link_to(desc, url, options = {})
+        tag("a", options.merge(:href => url_for(url))) do
+          desc
+        end
+      end
+
+      private
+
+      def tag(name, local_options = {})
+        start_tag = "<#{name}#{tag_options(local_options) if local_options}"
+        if block_given?
+          content = yield
+          "#{start_tag}>#{content}</#{name}>"
+        else
+          "#{start_tag}#{"/" if settings.xhtml}>"
+        end
+      end
+
+      def tag_options(options)
+        unless options.empty?
+          attrs = []
+          attrs = options.map { |key, value| %(#{key}="#{Rack::Utils.escape_html(value)}") }
+          " #{attrs.sort * ' '}" unless attrs.empty?
+        end
+      end
+
+      def stylesheet_tag(source, options = {})
+        tag("link", { :type => "text/css",
+            :charset => "utf-8", :media => "screen", :rel => "stylesheet",
+            :href => url_for(source) }.merge(options))
+      end
+
+      def javascript_tag(source, options = {})
+        tag("script", { :type => "text/javascript", :charset => "utf-8",
+            :src => url_for(source) }.merge(options)) do
+            end
+      end
+
+      def extract_options(a)
+        opts = a.last.is_a?(::Hash) ? a.pop : {}
+        [a, opts]
+      end
+
+    end
+
+    def self.registered(app)
+      app.helpers StaticAssets::Helpers
+      app.disable :xhtml
+    end
+  end
+
+  register StaticAssets
+end
diff --git a/server/lib/deltacloud/helpers/auth_helper.rb b/server/lib/deltacloud/helpers/auth_helper.rb
new file mode 100644
index 0000000..eef2521
--- /dev/null
+++ b/server/lib/deltacloud/helpers/auth_helper.rb
@@ -0,0 +1,73 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+# Lazy Basic HTTP authentication. Authentication is only forced when the
+# credentials are actually needed.
+
+module Sinatra
+  module AuthHelper
+    class LazyCredentials
+      def initialize(app)
+        @app = app
+        @provided = false
+      end
+
+      def user
+        credentials!
+        @user
+      end
+
+      def password
+        credentials!
+        @password
+      end
+
+      def provided?
+        @provided
+      end
+
+      private
+      def credentials!
+        if ENV["API_USER"] && ENV["API_PASSWORD"]
+          @user = ENV["API_USER"]
+          @password = ENV["API_PASSWORD"]
+          @provided = true
+        end
+        unless provided?
+          auth = Rack::Auth::Basic::Request.new(@app.request.env)
+          @app.authorize! unless auth.provided? && auth.basic? && auth.credentials
+          @user = auth.credentials[0]
+          @password = auth.credentials[1]
+          @provided = true
+        end
+      end
+
+    end
+
+    def authorize!
+      r = "#{Thread.current[:driver]}-deltacloud@#{ENV['HOSTNAME']}"
+      response['WWW-Authenticate'] = %(Basic realm="#{r}")
+      throw(:halt, [401, report_error(401)])
+    end
+
+    # Request the current user's credentials. Actual credentials are only
+    # requested when an attempt is made to get the user name or password
+    def credentials
+      LazyCredentials.new(self)
+    end
+  end
+
+end
diff --git a/server/lib/deltacloud/helpers/blob_stream.rb b/server/lib/deltacloud/helpers/blob_stream.rb
deleted file mode 100644
index df5cdc6..0000000
--- a/server/lib/deltacloud/helpers/blob_stream.rb
+++ /dev/null
@@ -1,213 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-include Deltacloud
-begin
-  require 'eventmachine'
-  #--
-  # based on the example from
-  #   http://macournoyer.com/blog/2009/06/04/pusher-and-async-with-thin/
-  #--
-  class BlobStream
-    AsyncResponse = [-1, {}, []].freeze
-    def self.call(env, credentials, params)
-      body = DeferrableBody.new
-      #Get the headers out asap. Don't specify a content-type let
-      #the client guess and if they can't they SHOULD default to
-      #'application/octet-stream' anyway as per:
-      #http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2.1
-      EM.next_tick { env['async.callback'].call [200, {
-        'Content-Type' => "#{params['content_type']}",
-        'Content-Disposition' => params["content_disposition"],
-        'Content-Length' => "#{params['content_length']}"}, body]
-      }
-      #call the driver from here. the driver method yields for every chunk
-      #of blob it receives. Then use body.call to write that chunk as received.
-      driver.blob_data(credentials, params[:bucket], params[:blob], params) {|chunk| body.call ["#{chunk}"]} #close blob_data block
-      body.succeed
-      AsyncResponse # Tell Thin to not close connection & work other requests
-    end
-  end
-
-  class DeferrableBody
-    include EventMachine::Deferrable
-
-    def call(body)
-      body.each do |chunk|
-        @body_callback.call(chunk)
-      end
-    end
-
-    def each(&blk)
-      @body_callback = blk
-    end
-  end
-rescue LoadError => e
-  # EventMachine isn't available, disable blob streaming
-  class BlobStream
-    def self.call(env, credentials, params)
-      raise NotImplementedError.new("Blob streaming is only supported under Thin")
-    end
-  end
-end
-
-module BlobHelper
-
-  def self.extract_blob_metadata_hash(env_hash)
-    meta_array = env_hash.select{|k,v| k.match(/^HTTP[-_]X[-_]Deltacloud[-_]Blobmeta[-_]/i)}
-    metadata = meta_array.inject({}){ |result, array| result[array.first.upcase] = array.last; result}
-    metadata
-  end
-
-DELTACLOUD_BLOBMETA_HEADER = /HTTP[-_]X[-_]Deltacloud[-_]Blobmeta[-_]/i
-
-  #e.g. from HTTP-X-Deltacloud-Blobmeta-FOO:BAR to amz-meta-FOO:BAR
-  def self.rename_metadata_headers(metadata, rename_to)
-    metadata.gsub_keys(DELTACLOUD_BLOBMETA_HEADER, rename_to)
-  end
-
-end
-
-#Monkey patch for streaming blobs:
-# Normally a client will upload a blob to deltacloud and thin will put
-# this into a tempfile. Then deltacloud would stream up to the provider:
-#   i.e.  client =-->>TEMP_FILE-->> deltacloud =-->>STREAM-->> provider
-# Instead we want to recognise that this is a 'PUT blob' operation and
-# start streaming to the provider as the request is received:
-#   i.e.  client =-->>STREAM-->> deltacloud =-->>STREAM-->> provider
-module Thin
-  class Request
-
-    alias_method :move_body_to_tempfile_orig, :move_body_to_tempfile if defined?(Thin::Response)
-    private
-      def move_body_to_tempfile
-        if BlobStreamIO::is_put_blob(self)
-          @body = BlobStreamIO.new(self)
-        else
-          move_body_to_tempfile_orig
-        end
-      end
-
-  end
-end
-
-require 'net/http'
-require 'net/https'
-#monkey patch for Net:HTTP
-module Net
-  class HTTP
-
-    alias :request_orig :request
-
-    def request(req, body = nil, blob_stream = nil, &block)
-      unless blob_stream
-        return request_orig(req, body, &block)
-      end
-      @blob_req = req
-      do_start #start the connection
-
-      req.set_body_internal body
-      begin_transport req
-      req.write_header_m @socket,@curr_http_version, edit_path(req.path)
-      @socket
-    end
-
-    class Put < HTTPRequest
-      def write_header_m(sock, ver, path)
-        write_header(sock, ver, path)
-      end
-    end
-
-    def end_request
-      begin
-        res = HTTPResponse.read_new(@socket)
-      end while res.kind_of?(HTTPContinue)
-      res.reading_body(@socket, @blob_req.response_body_permitted?) {
-                                          yield res if block_given? }
-      end_transport @blob_req, res
-      do_finish
-      res
-    end
-  end
-
-end
-
-require 'base64'
-class BlobStreamIO
-
-  attr_accessor :size, :provider, :sock
-
-  def initialize(request)
-    @client_request = request
-    @size = 0
-    bucket, blob = parse_bucket_blob(request.env["PATH_INFO"])
-    user, password = parse_credentials(request.env['HTTP_AUTHORIZATION'])
-    content_type = request.env['CONTENT_TYPE'] || ""
-    #deal with blob_metadata: (X-Deltacloud-Blobmeta-name: value)
-    user_meta = BlobHelper::extract_blob_metadata_hash(request.env)
-    @content_length = request.env['CONTENT_LENGTH']
-    @http, provider_request = driver.blob_stream_connection({:user=>user,
-       :password=>password, :bucket=>bucket, :blob=>blob, :metadata=> user_meta,
-       :content_type=>content_type, :content_length=>@content_length })
-    @content_length = @content_length.to_i #for comparison of size in '<< (data)'
-    @sock = @http.request(provider_request, nil, true)
-  end
-
-  def << (data)
-    @sock.write(data)
-    @size += data.length
-    if (@size >= @content_length)
-      result = @http.end_request
-      if result.is_a?(Net::HTTPSuccess)
-        @client_request.env["BLOB_SUCCESS"] = "true"
-      else
-        @client_request.env["BLOB_FAIL"] = result.body
-      end
-    end
-  end
-
-  def rewind
-  end
-
-  #use the Request.env hash (populated by the ThinParser) to determine whether
-  #this is a post blob operation. By definition, only get here with a body of
-  # > 112kbytes - thin/lib/thin/request.rb:12 MAX_BODY = 1024 * (80 + 32)
-  def self.is_put_blob(request = nil)
-    path = request.env['PATH_INFO']
-    method = request.env['REQUEST_METHOD']
-    if ( path =~ /^#{Regexp.escape(settings.root_url)}\/buckets/ && method == 'PUT' )
-      return true
-    else
-      return false
-    end
-  end
-
-  private
-
-  def parse_bucket_blob(request_string)
-    array = request_string.split("/")
-    blob = array.pop
-    bucket = array.pop
-    return bucket, blob
-  end
-
-  def parse_credentials(request_string)
-    decoded = Base64.decode64(request_string.split('Basic ').last)
-    key = decoded.split(':').first
-    pass = decoded.split(':').last
-    return key, pass
-  end
-
-end
diff --git a/server/lib/deltacloud/helpers/conversion_helper.rb b/server/lib/deltacloud/helpers/conversion_helper.rb
deleted file mode 100644
index 310ba4b..0000000
--- a/server/lib/deltacloud/helpers/conversion_helper.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-
-require 'deltacloud/base_driver'
-
-module ConversionHelper
-
-  def convert_to_json(type, obj)
-    if ( [ :image, :realm, :instance, :storage_volume, :storage_snapshot, :hardware_profile, :key, :bucket, :blob, :firewall, :load_balancer, :address ].include?( type ) )
-      if Array.eql?(obj.class)
-        data = obj.collect do |o|
-          o.to_hash.merge({ :href => self.send(:"#{type}_url", type.eql?(:hardware_profile) ? o.name : o.id ) })
-        end
-        type = type.to_s.pluralize
-      else
-        data = obj.to_hash
-        if type == :blob
-          data.merge!({ :href => self.send(:"bucket_url", "#{data[:bucket]}/#{data[:id]}" ) })
-        else
-          data.merge!({ :href => self.send(:"#{type}_url", data[:id]) })
-          if data.has_key?(:hardware_profiles)
-            data[:hardware_profiles] = data[:hardware_profiles].inject([]){|res, hwp| res << {hwp.name => {:href => self.send(:"hardware_profile_url", hwp.name)}}; res }
-          end
-        end
-      end
-      return { :"#{type}" => data }.to_json
-    end
-  end
-
-end
diff --git a/server/lib/deltacloud/helpers/deltacloud_helper.rb b/server/lib/deltacloud/helpers/deltacloud_helper.rb
new file mode 100644
index 0000000..83741f9
--- /dev/null
+++ b/server/lib/deltacloud/helpers/deltacloud_helper.rb
@@ -0,0 +1,273 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Helpers
+  module Application
+
+    require 'benchmark'
+
+    def self.included(klass)
+      klass.class_eval do
+        set :root_url, API_ROOT_URL
+        include Sinatra::Rabbit
+        Sinatra::Rabbit.set :root_path, root_url+'/'
+      end
+    end
+
+    def instance_action_method(action)
+      action_method(action, Sinatra::Rabbit::InstancesCollection)
+    end
+
+    def action_method(action, collection)
+      http_method = collection.operation(action).http_method
+      http_method || Sinatra::Rabbit::BaseCollection.http_method_for(action)
+    end
+
+    def filter_all(model)
+      filter = {}
+      filter.merge!(:id => params[:id]) if params[:id]
+      filter.merge!(:architecture => params[:architecture]) if params[:architecture]
+      filter.merge!(:owner_id => params[:owner_id]) if params[:owner_id]
+      filter.merge!(:state => params[:state]) if params[:state]
+      filter = {} if filter.keys.size.eql?(0)
+      singular = model.to_s.singularize.to_sym
+      begin
+        @benchmark = Benchmark.measure do
+          @elements = driver.send(model.to_sym, credentials, filter)
+        end
+      rescue
+        @exception = $!
+      end
+      if @elements
+        headers['X-Backend-Runtime'] = @benchmark.real.to_s
+        instance_variable_set(:"@#{model}", @elements)
+        respond_to do |format|
+          format.html { haml :"#{model}/index" }
+          format.xml { haml :"#{model}/index" }
+          format.json { @media_type=:xml; to_json(haml(:"#{model}/index")) }
+        end
+      else
+        report_error(@exception.respond_to?(:code) ? @exception.code : 500)
+      end
+    end
+
+    def xml_to_json(model)
+      @media_type = :xml
+      to_json(haml(:"#{model}"))
+    end
+
+    def to_json(xml)
+      Crack::XML.parse(xml).to_json
+    end
+
+    def show(model)
+      @benchmark = Benchmark.measure do
+        @element = driver.send(model, credentials, { :id => params[:id]} )
+      end
+      headers['X-Backend-Runtime'] = @benchmark.real.to_s
+      instance_variable_set("@#{model}", @element)
+      if @element
+        respond_to do |format|
+          format.html { haml :"#{model.to_s.pluralize}/show" }
+          format.xml { haml :"#{model.to_s.pluralize}/show" }
+          format.json { @media_type=:xml; to_json(haml(:"#{model.to_s.pluralize}/show")) }
+        end
+      else
+        report_error(404)
+      end
+    end
+
+    def report_error(code=nil)
+      @error, @code = (request.env['sinatra.error'] || @exception), code
+      @code = 500 if not @code and not @error.class.method_defined? :code
+      response.status = @code || @error.code
+      respond_to do |format|
+        format.xml {  haml :"errors/#{@code || @error.code}", :layout => false }
+        format.html { haml :"errors/#{@code || @error.code}", :layout => :error }
+      end
+    end
+
+    def instance_action(name)
+      original_instance = driver.instance(credentials, :id => params[:id])
+
+      # If original instance doesn't include called action
+      # return with 405 error (Method is not Allowed)
+      unless driver.instance_actions_for(original_instance.state).include?(name.to_sym)
+        return report_error(405)
+      end
+
+      @benchmark = Benchmark.measure do
+        @instance = driver.send(:"#{name}_instance", credentials, params[:id])
+      end
+
+      headers['X-Backend-Runtime'] = @benchmark.real.to_s
+      status 202
+
+      if name == :destroy
+        respond_to do |format|
+          format.xml { return 204 }
+          format.json { return 204 }
+          format.html { return redirect(instances_url) }
+        end
+      end
+
+      if @instance.class != Instance
+        response['Location'] = instance_url(params[:id])
+        halt
+      end
+
+      respond_to do |format|
+        format.xml { haml :"instances/show" }
+        format.html { haml :"instances/show" }
+        format.json {convert_to_json(:instance, @instance) }
+      end
+    end
+
+    def cdata(text = nil, &block)
+      text ||= capture_haml(&block)
+      "<![CDATA[#{text.strip}]]>"
+    end
+
+    def render_cdata(text)
+      "<![CDATA[#{text.strip}]]>"
+    end
+
+    def link_to_action(action, url, method)
+      capture_haml do
+        haml_tag :form, :method => :post, :action => url, :class => [:link, method], :'data-ajax' => 'false' do
+          haml_tag :input, :type => :hidden, :name => '_method', :value => method
+          haml_tag :button, :type => :submit, :'data-ajax' => 'false', :'data-inline' => "true" do
+            haml_concat action
+          end
+        end
+      end
+    end
+
+    def link_to_format(format)
+      return unless request.env['REQUEST_URI']
+      uri = request.env['REQUEST_URI']
+      return if uri.include?('format=')
+      uri += uri.include?('?') ? "&format=#{format}" : "?format=#{format}"
+      capture_haml do
+        haml_tag :a, :href => uri, :'data-ajax' => 'false', :'data-icon' => 'grid' do
+          haml_concat format.to_s.upcase
+        end
+      end
+    end
+
+    def image_for_state(state)
+      state_img = "stopped" if (state!='RUNNING' or state!='PENDING')
+      capture_haml do
+        haml_tag :img, :src => "/images/#{state}" % state.downcase, :title => state
+      end
+    end
+
+    # Reverse the entrypoints hash for a driver from drivers.yaml; note that
+    # +d+ is a hash, not an actual driver object
+    def driver_provider(d)
+      result = {}
+      if d[:entrypoints]
+        d[:entrypoints].each do |kind, details|
+          details.each do |prov, url|
+            result[prov] ||= {}
+            result[prov][kind] = url
+          end
+        end
+      end
+      result
+    end
+
+    def header(title, opts={}, &block)
+      opts[:theme] ||= 'b'
+      opts[:back] ||= 'true'
+      capture_haml do
+        haml_tag :div, :'data-role' => :header, :'data-theme' => opts[:theme], :'data-add-back-btn' => opts[:back] do
+          haml_tag :a, :'data-rel' => :back do
+            haml_concat "Back"
+          end if opts[:back] == 'true'
+          haml_tag :h1 do
+            haml_concat title
+          end
+          block.call if block_given?
+        end
+      end
+    end
+
+    def subheader(title, opts={})
+      opts[:theme] ||= 'a'
+      capture_haml do
+        haml_tag :div, :'data-role' => :header, :'data-theme' => opts[:theme] do
+          haml_tag :p, :class => 'inner-right' do
+            haml_concat title
+          end
+        end
+      end
+    end
+
+    def translate_error_code(code)
+      case code
+      when 400; { :message => "Bad Request" }
+      when 401; { :message => "Unauthorized" }
+      when 403; { :message => "Forbidden" }
+      when 404; { :message => "Not Found" }
+      when 405; { :message => "Method Not Allowed" }
+      when 406; { :message => "Not Acceptable" }
+      when 500; { :message => "Internal Server Error" }
+      when 502; { :message => "Backend Server Error" }
+      when 501; { :message => "Not Supported" }
+      end
+    end
+
+    def new_blob_form_url(bucket)
+      bucket_url(@bucket.name) + "/" + NEW_BLOB_FORM_ID
+    end
+
+    def format_hardware_property(prop)
+      return "&empty;" unless prop
+      u = hardware_property_unit(prop)
+      case prop.kind
+      when :range
+        "#{prop.first} #{u} - #{prop.last} #{u} (default: #{prop.default} #{u})"
+      when :enum
+        prop.values.collect{ |v| "#{v} #{u}"}.join(', ') + " (default: #{prop.default} #{u})"
+      else
+        "#{prop.value} #{u}"
+      end
+    end
+
+    def format_instance_profile(ip)
+      o = ip.overrides.collect do |p, v|
+        u = hardware_property_unit(p)
+        "#{p} = #{v} #{u}"
+      end
+      if o.empty?
+        ""
+      else
+        "with #{o.join(", ")}"
+      end
+    end
+
+    private
+    def hardware_property_unit(prop)
+      u = ::Deltacloud::HardwareProfile::unit(prop)
+      u = "" if ["label", "count"].include?(u)
+      u = "vcpus" if prop == :cpu
+      u
+    end
+
+
+
+  end
+end
diff --git a/server/lib/deltacloud/helpers/driver_helper.rb b/server/lib/deltacloud/helpers/driver_helper.rb
new file mode 100644
index 0000000..18e0598
--- /dev/null
+++ b/server/lib/deltacloud/helpers/driver_helper.rb
@@ -0,0 +1,57 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Helpers
+
+  module Drivers
+
+    def driver_symbol
+      driver_name.to_sym
+    end
+
+    def driver_name
+      Thread.current[:driver] ||= ENV['API_DRIVER']
+    end
+
+    def driver_class_name
+      driver_name.camelize
+    end
+
+    def driver_source_name
+      File.join('..', 'drivers', driver_name, driver_name + '_driver.rb')
+    end
+
+    def driver_class
+      begin
+        m = Deltacloud::Drivers.const_get(driver_class_name)
+        m.const_get(driver_class_name + "Driver").new
+      rescue NameError
+        raise "[ERROR] The driver class name is not defined as #{driver_class_name}Driver"
+      end
+    end
+
+    def driver
+      $:.unshift File.join(File.dirname(__FILE__), '..', '..')
+      begin
+        require_relative driver_source_name
+        driver_class
+      rescue LoadError
+        raise "[ERROR] The driver '#{driver_name}' is unknown or not installed" unless valid_driver?
+      end
+    end
+
+  end
+
+end
diff --git a/server/lib/deltacloud/helpers/hardware_profiles_helper.rb b/server/lib/deltacloud/helpers/hardware_profiles_helper.rb
deleted file mode 100644
index 4da9d8c..0000000
--- a/server/lib/deltacloud/helpers/hardware_profiles_helper.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-module HardwareProfilesHelper
-
-  def format_hardware_property(prop)
-    return "&empty;" unless prop
-    u = hardware_property_unit(prop)
-    case prop.kind
-      when :range
-      "#{prop.first} #{u} - #{prop.last} #{u} (default: #{prop.default} #{u})"
-      when :enum
-      prop.values.collect{ |v| "#{v} #{u}"}.join(', ') + " (default: #{prop.default} #{u})"
-      else
-      "#{prop.value} #{u}"
-    end
-  end
-
-  def format_instance_profile(ip)
-    o = ip.overrides.collect do |p, v|
-      u = hardware_property_unit(p)
-      "#{p} = #{v} #{u}"
-    end
-    if o.empty?
-      ""
-    else
-      "with #{o.join(", ")}"
-    end
-  end
-
-  private
-  def hardware_property_unit(prop)
-    u = ::Deltacloud::HardwareProfile::unit(prop)
-    u = "" if ["label", "count"].include?(u)
-    u = "vcpus" if prop == :cpu
-    u
-  end
-end
diff --git a/server/lib/deltacloud/helpers/json_helper.rb b/server/lib/deltacloud/helpers/json_helper.rb
deleted file mode 100644
index aea16b6..0000000
--- a/server/lib/deltacloud/helpers/json_helper.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-module JSONHelper
-
-  def json_features_for_entrypoint(entrypoint)
-    features = driver.features(entrypoint.first).collect { |feature| feature.name }
-    features.empty? ? {} : { :features => features }
-  end
-
-  def json_return_error(error)
-    error_output=Hash.new
-    error_output[:url]    =request.env['REQUEST_URI']
-    error_output[:status] =response.status
-    error_output[:message]=error.message if error
-    error_output.to_json
-  end
-
-end
diff --git a/server/lib/deltacloud/helpers/rabbit_helper.rb b/server/lib/deltacloud/helpers/rabbit_helper.rb
new file mode 100644
index 0000000..252abe2
--- /dev/null
+++ b/server/lib/deltacloud/helpers/rabbit_helper.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+Sinatra::Rabbit::Collection.class_eval do
+
+  def self.standard_index_operation
+    collection_name = @collection_name
+    operation :index, :with_capability => collection_name do
+      control { filter_all collection_name }
+    end
+  end
+
+  def self.standard_show_operation
+    collection_name = @collection_name
+    operation :show, :with_capability => collection_name do
+      control { show collection_name.to_s.singularize.intern }
+    end
+  end
+
+end
+
diff --git a/server/lib/deltacloud/helpers/url_helper.rb b/server/lib/deltacloud/helpers/url_helper.rb
new file mode 100644
index 0000000..87bc93e
--- /dev/null
+++ b/server/lib/deltacloud/helpers/url_helper.rb
@@ -0,0 +1,112 @@
+#
+# Based on https://github.com/emk/sinatra-url-for/
+# Commit 1df339284203f8f6ed8d
+#
+# Original license:
+# Copyright (C) 2009 Eric Kidd
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the
+# following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+# USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+module Sinatra
+  module UrlForHelper
+
+    require 'uri'
+
+    def method_missing(name, *args)
+      if name.to_s =~ /^([\w\_]+)_url$/
+        if args.size > 0
+          t = $1
+          if t =~ /^(stop|reboot|destroy|start|attach|detach)_/
+            api_url_for(t.pluralize.split('_').last + '/' + args.first + '/' + $1, :full)
+          else
+            api_url_for(t.pluralize, :full) + '/' + "#{args.first}"
+          end
+        else
+          api_url_for($1, :full)
+        end
+      else
+        super
+      end
+    end
+
+    def api_url_for(url_fragment, mode=:path_only)
+      matrix_params = ''
+      if request.params['api']
+        matrix_params += ";provider=%s" % request.params['api']['provider'] if request.params['api']['provider']
+        matrix_params += ";driver=%s" % request.params['api']['driver'] if request.params['api']['driver']
+      end
+      url_fragment = "/#{url_fragment}" unless url_fragment =~ /^\// # There is no need to prefix URI with '/'
+      if mode == :path_only
+        url_for "#{settings.root_url}#{matrix_params}#{url_fragment}", mode
+      else
+        url_for "#{matrix_params}#{url_fragment}", :full
+      end
+    end
+
+    # Construct a link to +url_fragment+, which should be given relative to
+    # the base of this Sinatra app.  The mode should be either
+    # <code>:path_only</code>, which will generate an absolute path within
+    # the current domain (the default), or <code>:full</code>, which will
+    # include the site name and port number.  (The latter is typically
+    # necessary for links in RSS feeds.)  Example usage:
+    #
+    #   url_for "/"            # Returns "/myapp/"
+    #   url_for "/foo"         # Returns "/myapp/foo"
+    #   url_for "/foo", :full  # Returns "http://example.com/myapp/foo"
+    #--
+    # See README.rdoc for a list of some of the people who helped me clean
+    # up earlier versions of this code.
+    def url_for url_fragment, mode=:path_only
+      case mode
+      when :path_only
+        base = request.script_name
+      when :full
+        scheme = request.scheme
+        port = request.port
+        request_host = request.host
+        if request.env['HTTP_X_FORWARDED_FOR']
+          scheme = request.env['HTTP_X_FORWARDED_SCHEME'] || scheme
+          port = request.env['HTTP_X_FORWARDED_PORT']
+          request_host = request.env['HTTP_X_FORWARDED_HOST']
+        end
+        if (port.nil? || port == "" ||
+            (scheme == 'http' && port.to_s == '80') ||
+            (scheme == 'https' && port.to_s == '443'))
+          port = ""
+        else
+          port = ":#{port}"
+        end
+        base = "#{scheme}://#{request_host}#{port}#{request.script_name}"
+      else
+        raise TypeError, "Unknown url_for mode #{mode}"
+      end
+      uri_parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI
+      url_escape = uri_parser.escape(url_fragment)
+      # Don't add the base fragment if url_for gets called more than once
+      # per url or the url_fragment passed in is an absolute url
+      if url_escape.match(/^#{base}/) or url_escape.match(/^http/)
+        url_escape
+      else
+        "#{base}#{url_escape}"
+      end
+    end
+  end
+
+end
diff --git a/server/lib/deltacloud/method_serializer.rb b/server/lib/deltacloud/method_serializer.rb
deleted file mode 100644
index eec9abe..0000000
--- a/server/lib/deltacloud/method_serializer.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'base64'
-require 'digest'
-
-module MethodSerializer
-
-  module Cache
-
-    def cache_dir
-      storage_dir = $methods_cache_dir || File.join(File.dirname(__FILE__), 'cache')
-      class_dir = self.class.name.split('::').last
-      class_dir ||= self.class.name
-      File.join(storage_dir, class_dir.downcase)
-    end
-
-    def serialize_data(method_name, args, data)
-      File.open(cache_file_name(method_name, args), 'w') do |f|
-        f.puts(Base64.encode64(Marshal.dump(data)))
-      end
-      return data
-    end
-
-    def deserialize_data(method_name, args)
-      begin
-        data = File.readlines(cache_file_name(method_name, args)).join
-        Marshal.load(Base64.decode64(data))
-      rescue Errno::ENOENT
-        return false
-      end
-    end
-
-    def args_hash(args)
-      if args.class == Hash
-        args = args.to_a.collect {|i| [i[0].to_s, i[1]]}.sort
-      end
-      Digest::SHA1.hexdigest(args.to_s)
-    end
-
-    def cache_file_name(method_name, args)
-      FileUtils.mkdir_p(cache_dir) unless File.directory?(cache_dir)
-      method_name = $scenario_prefix ? "#{$scenario_prefix}_#{method_name}" : method_name
-      File.join(cache_dir, "#{method_name}.#{args_hash(args)}")
-    end
-
-    def self.wrap_methods(c, opts={})
-      $methods_cache_dir = opts[:cache_dir]
-      $scenario_prefix = nil
-      c.class_eval do
-        cached_methods.each do |m|
-          next if c.instance_methods(false).include?("original_#{m}")
-          alias_method "original_#{m}".to_sym, m.to_sym
-          define_method m.to_sym do |*args|
-            args = args.first if args.size.eql?(1) and not args.first.class.eql?(Array)
-            output = deserialize_data(m, args)
-            unless output
-              output = method("original_#{m}".to_sym).to_proc[args]
-              return serialize_data(m, args, output)
-            else
-              return output
-            end
-          end
-        end
-      end
-    end
-
-  end
-
-end
diff --git a/server/lib/deltacloud/models.rb b/server/lib/deltacloud/models.rb
index a794192..099afda 100644
--- a/server/lib/deltacloud/models.rb
+++ b/server/lib/deltacloud/models.rb
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.  The
@@ -14,19 +13,11 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-require 'deltacloud/models/base_model'
-require 'deltacloud/models/realm'
-require 'deltacloud/models/image'
-require 'deltacloud/models/instance'
-require 'deltacloud/models/key'
-require 'deltacloud/models/address'
-require 'deltacloud/models/instance_address'
-require 'deltacloud/models/instance_profile'
-require 'deltacloud/models/storage_snapshot'
-require 'deltacloud/models/storage_volume'
-require 'deltacloud/models/bucket'
-require 'deltacloud/models/blob'
-require 'deltacloud/models/load_balancer'
-require 'deltacloud/models/firewall'
-require 'deltacloud/models/firewall_rule'
-require 'deltacloud/models/provider'
+require_relative 'models/base_model'
+
+# Include all models
+
+Dir[File.join(File::dirname(__FILE__), "models", "*.rb")].each do |model|
+  next if model =~ /base_model\.rb$/
+  require model
+end
diff --git a/server/lib/deltacloud/models/hardware_profile.rb b/server/lib/deltacloud/models/hardware_profile.rb
new file mode 100644
index 0000000..45e77a1
--- /dev/null
+++ b/server/lib/deltacloud/models/hardware_profile.rb
@@ -0,0 +1,194 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud
+  class HardwareProfile
+
+    UNITS = {
+      :memory => "MB",
+      :storage => "GB",
+      :architecture => "label",
+      :cpu => "count"
+    }
+
+    def self.unit(name)
+      UNITS[name]
+    end
+
+    class Property
+      attr_reader :name, :kind, :default
+      # kind == :range
+      attr_reader :first, :last
+      # kind == :enum
+      attr_reader :values
+      # kind == :fixed
+      attr_reader :value
+
+      def initialize(name, values, opts = {})
+        @name = name
+        if values.is_a?(Range)
+          @kind = :range
+          @first = values.first
+          @last = values.last
+          @default = values.first
+        elsif values.is_a?(Array)
+          @kind = :enum
+          @values = values
+          @default = values.first
+        else
+          @kind = :fixed
+          @value = values
+          @default = @value
+        end
+        @default = opts[:default] if opts[:default]
+      end
+
+      def unit
+        HardwareProfile.unit(name)
+      end
+
+      def param
+        :"hwp_#{name}"
+      end
+
+      def fixed?
+        kind == :fixed
+      end
+
+      def valid?(v)
+        v = convert_property_value_type(v)
+        case kind
+          # NOTE:
+          # Currently we cannot validate fixed values because of UI
+          # limitation. In UI we have multiple hwp_* properties which overide
+          # each other.
+          # Then provider have one 'static' hardware profile and one
+          # 'customizable' when user select the static one the UI also send
+          # values from the customizable one (which will lead to a validation
+          # error because validation algorith will think that client want to
+          # overide fixed values.
+          #
+          # when :fixed then (v == @default.to_s)
+          when :fixed then true
+          when :range then match_type?(first, v) and (first..last).include?(v)
+          when :enum then match_type?(values.first, v) and values.include?(v)
+          else false
+        end
+      end
+
+      def to_param
+        if defined? Sinatra::Rabbit
+          Sinatra::Rabbit::Param.new([param, :string, :optional, []])
+        end
+      end
+
+      def include?(v)
+        if kind == :fixed
+          return v == value
+        else
+          return values.include?(v)
+        end
+      end
+
+      private
+
+      def match_type?(reference, value)
+        true if reference.class == value.class
+      end
+
+      def convert_property_value_type(v)
+        return v.to_f if v =~ /(\d+)\.(\d+)/
+        return v.to_i if v =~ /(\d+)/
+        v.to_s
+      end
+    end
+
+    class << self
+      def property(prop)
+        define_method(prop) do |*args|
+          values, opts, *ignored = *args
+          instvar = :"@#{prop}"
+          unless values.nil?
+            @properties[prop] = Property.new(prop, values, opts || {})
+          end
+          @properties[prop]
+        end
+      end
+    end
+
+    attr_reader :name
+    property :cpu
+    property :architecture
+    property :memory
+    property :storage
+
+    def initialize(name,&block)
+      @properties   = {}
+      @name         = name
+      instance_eval &block if block_given?
+    end
+
+    def each_property(&block)
+      @properties.each_value { |prop| yield prop }
+    end
+
+    def properties
+      @properties.values
+    end
+
+    def property(name)
+      @properties[name.to_sym]
+    end
+
+    def default?(prop, v)
+      p = @properties[prop.to_sym]
+      p && p.default.to_s == v
+    end
+
+    def to_hash
+      props = []
+      self.each_property do |p|
+        if p.kind.eql? :fixed
+          props << { :kind => p.kind, :value => p.value, :name => p.name, :unit => p.unit }
+        else
+          param = { :operation => "create", :method => "post", :name => p.name }
+          if p.kind.eql? :range
+            param[:range] = { :first => p.first, :last => p.last }
+          elsif p.kind.eql? :enum
+            param[:enum] = p.values.collect { |v| { :entry => v } }
+          end
+          param
+          props << { :kind => p.kind, :value => p.default, :name => p.name, :unit => p.unit, :param => param }
+        end
+      end
+      {
+        :id => self.name,
+        :properties => props
+      }
+    end
+
+    def include?(prop, v)
+      p = @properties[prop]
+      p.nil? || p.include?(v)
+    end
+
+    def params
+      @properties.values.inject([]) { |m, prop|
+        m << prop.to_param
+      }.compact
+    end
+  end
+end
diff --git a/server/lib/deltacloud/models/instance.rb b/server/lib/deltacloud/models/instance.rb
index c6835a9..c2cc0e3 100644
--- a/server/lib/deltacloud/models/instance.rb
+++ b/server/lib/deltacloud/models/instance.rb
@@ -16,8 +16,6 @@
 
 class Instance < BaseModel
 
-  include ApplicationHelper
-
   attr_accessor :owner_id
   attr_accessor :image_id
   attr_accessor :name
diff --git a/server/lib/deltacloud/models/key.rb b/server/lib/deltacloud/models/key.rb
index 86a6283..64c4cc7 100644
--- a/server/lib/deltacloud/models/key.rb
+++ b/server/lib/deltacloud/models/key.rb
@@ -23,6 +23,10 @@ class Key < BaseModel
   attr_accessor :pem_rsa_key
   attr_accessor :state
 
+  def name
+    @name || @id
+  end
+
   def is_password?
     true if @credential_type.eql?(:password)
   end
diff --git a/server/lib/deltacloud/models/state_machine.rb b/server/lib/deltacloud/models/state_machine.rb
new file mode 100644
index 0000000..19fb9f2
--- /dev/null
+++ b/server/lib/deltacloud/models/state_machine.rb
@@ -0,0 +1,99 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud
+  class StateMachine
+
+    attr_reader :states
+    def initialize(&block)
+      @states  = []
+      instance_eval &block if block
+    end
+
+    def start()
+      state(:start)
+    end
+
+    def finish()
+      state(:finish)
+    end
+
+    def state(name)
+      state = @states.find{|e| e.name == name.to_sym}
+      if ( state.nil? )
+        state = State.new( self, name.to_sym )
+        @states << state
+      end
+      state
+    end
+
+    def method_missing(sym,*args)
+      return state( sym ) if ( args.empty? )
+      super( sym, *args )
+    end
+
+    class State
+
+      attr_reader :name
+      attr_reader :transitions
+
+      def initialize(machine, name)
+        @machine = machine
+        @name    = name
+        @transitions = []
+      end
+
+      def to_s
+        self.name.to_s
+      end
+
+      def to(destination_name)
+        destination = @machine.state(destination_name)
+        transition = Transition.new( @machine, destination )
+        @transitions << transition
+        transition
+      end
+
+    end
+
+    class Transition
+
+      attr_reader :destination
+      attr_reader :action
+
+      def initialize(machine, destination)
+        @machine = machine
+        @destination = destination
+        @auto   = false
+        @action = nil
+      end
+
+      def automatically
+        @auto = true
+      end
+
+      def automatically?
+        @auto
+      end
+
+      def on(action)
+        @action = action
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/runner.rb b/server/lib/deltacloud/runner.rb
deleted file mode 100644
index aa13fa9..0000000
--- a/server/lib/deltacloud/runner.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'net/ssh'
-require 'socket'
-require 'tempfile'
-
-module Deltacloud
-
-  module Runner
-
-    class RunnerError < StandardError
-      attr_reader :message
-      def initialize(message)
-        @message = message
-        super
-      end
-    end
-
-    class InstanceSSHError < RunnerError; end
-
-    def self.execute(command, opts={})
-
-      if opts[:credentials] and (not opts[:credentials][:password] and not opts[:private_key])
-        raise RunnerError::new("Either password or key must be specified")
-      end
-
-      # First check networking and firewalling
-      network = Network::new(opts[:ip], opts[:port])
-
-      # Then check SSH availability
-      ssh = SSH::new(network, opts[:credentials], opts[:private_key])
-
-      # Finaly execute SSH command on instance
-      ssh.execute(command)
-    end
-
-    class Network
-      attr_accessor :ip, :port
-
-      def initialize(ip, port)
-        @ip, @port = ip, port
-      end
-    end
-
-    class SSH
-
-      attr_reader :network
-      attr_accessor :credentials, :key
-      attr_reader :command
-
-      def initialize(network, credentials, key=nil)
-        @network, @credentials, @key = network, credentials, key
-        @result = ""
-      end
-
-      def execute(command)
-        @command = command
-        config = ssh_config(@network, @credentials, @key)
-        begin
-          session = nil
-	  # Default timeout for connecting to an instance.
-	  # 20 seconds should be OK for most of connections, if you are
-	  # experiencing some Exceptions with Timeouts increase this value.
-	  # Please keep in mind that the HTTP request timeout is set to 60
-	  # seconds, so you need to fit into this time
-          Timeout::timeout(20) do
-            session = Net::SSH.start(@network.ip, 'root', config)
-          end
-          session.open_channel do |channel|
-            channel.on_data do |ch, data|
-              @result += data
-            end
-            channel.exec(command)
-            session.loop
-          end
-          session.close
-        rescue Exception => e
-          raise InstanceSSHError.new("#{e.class.name}: #{e.message}")
-        ensure
-          # FileUtils.rm(config[:keys].first) rescue nil
-        end
-        Deltacloud::Runner::Response.new(self, @result)
-      end
-
-      private
-
-      def ssh_config(network, credentials, key)
-        config = { :port => network.port }
-        config.merge!({ :password => credentials[:password ]}) if credentials[:password]
-        config.merge!({ :keys => [ keyfile(key) ] }) unless key.nil?
-        config
-      end
-
-      # Right now there is no way howto pass private_key using String
-      # eg. without saving key to temporary file.
-      def keyfile(key)
-        keyfile = Tempfile.new("ec2_private.key")
-        key_material = ""
-        key.split("\n").each { |line| key_material+="#{line.strip}\n" if line.strip.size>0 }
-        keyfile.write(key_material) && keyfile.close
-        puts "[*] Using #{keyfile.path} as private key"
-        keyfile.path
-      end
-
-    end
-
-    class Response
-
-      attr_reader :body
-      attr_reader :ssh
-
-      def initialize(ssh, response_body)
-        @body, @ssh = response_body, ssh
-      end
-
-    end
-
-  end
-end
diff --git a/server/lib/deltacloud/server.rb b/server/lib/deltacloud/server.rb
index 7b499d9..ebb7cb7 100644
--- a/server/lib/deltacloud/server.rb
+++ b/server/lib/deltacloud/server.rb
@@ -1,1266 +1,44 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'sinatra'
-require 'deltacloud'
+require 'rubygems'
+require 'crack'
 require 'json'
-require 'sinatra/rack_accept'
-require 'sinatra/static_assets'
-require 'sinatra/rabbit'
-require 'sinatra/lazy_auth'
-require 'erb'
+require 'yaml'
 require 'haml'
-require 'open3'
-require 'sinatra/sinatra_verbose'
-require 'sinatra/rack_driver_select'
-require 'sinatra/rack_runtime'
-require 'sinatra/rack_etag'
-require 'sinatra/rack_date'
-require 'sinatra/rack_matrix_params'
-require 'sinatra/rack_syslog'
-
-set :version, '0.5.0'
-
-include Deltacloud::Drivers
-set :drivers, Proc.new { driver_config }
-
-Sinatra::Application.register Rack::RespondTo
-
-use Rack::ETag
-use Rack::Runtime
-use Rack::MatrixParams
-use Rack::DriverSelect
-use Rack::MediaType
-use Rack::Date
-use Rack::CommonLogger
-
-configure do
-  set :root_url, "/api"
-  set :views, File::join($top_srcdir, 'views')
-  # NOTE: Change :public to :public_folder once we update sinatra to 1.3
-  # set :public_folder, File::join($top_srcdir, 'public')
-  if settings.respond_to? :public_folder
-    set :public_folder, File::join($top_srcdir, 'public')
-  else
-    set :public, File::join($top_srcdir, 'public')
-  end
-  # Try to load the driver on startup to fail early if there are issues
-  driver
-end
-
-configure :production do
-  use Rack::SyslogLogger
-  set :logger, SyslogFile.new
-  disable :logging
-  enable :show_errors
-  enable :dump_errors
-end
-
-configure :development do
-  # So we can just use puts for logging
-  set :raise_errors => false
-  set :show_exceptions, false
-  $stdout.sync = true
-  $stderr.sync = true
-end
-
-# You could use $API_HOST environment variable to change your hostname to
-# whatever you want (eg. if you running API behind NAT)
-HOSTNAME=ENV['API_HOST'] ? ENV['API_HOST'] : nil
-
-error do
-  report_error
-end
-
-error Deltacloud::ExceptionHandler::ValidationFailure do
-  report_error
-end
-
-before do
-  # Respond with 400, If we don't get a http Host header,
-  halt 400, "Unable to find HTTP Host header" if @env['HTTP_HOST'] == nil
-end
-
-after do
-  headers 'Server' => 'Apache-Deltacloud/' + settings.version
-end
-
-# Redirect to /api
-get '/' do redirect settings.root_url, 301; end
-
-
-# Generate a root route for API docs
-get "#{settings.root_url}/docs\/?" do
-  respond_to do |format|
-    format.html { haml :'docs/index' }
-    format.xml { haml :'docs/index' }
-  end
-end
-
-get "#{settings.root_url}\/?" do
-  if params[:force_auth]
-    return [401, 'Authentication failed'] unless driver.valid_credentials?(credentials)
-  end
-  @collections = [:drivers] + driver.supported_collections
-  @driver_name = driver.name unless driver.name.to_sym == DRIVER
-  @providers = driver.configured_providers
-  respond_to do |format|
-    format.xml { haml :"api/show" }
-    format.json do
-      { :api => {
-          :version => settings.version,
-          :driver => driver_symbol,
-          :links => entry_points.collect do |l|
-            { :rel => l[0], :href => l[1] }.merge(json_features_for_entrypoint(l))
-          end
-        }
-      }.to_json
-    end
-    format.html { haml :"api/show" }
-  end
-end
-
-post "#{settings.root_url}\/?"  do
-  p = {}
-  ["provider", "driver"].each { |k| p[k] = params[k] if params[k] }
-  p.delete("provider") if p["provider"] == "default"
-  q = p.map { |k,v| "#{k}=#{v}" }.join(";")
-  q = ";" + q unless q.empty?
-  redirect "#{settings.root_url}#{q}", 301
-end
-
-# Rabbit DSL
-
-collection :drivers do
-  global!
-
-  description <<EOS
-List all the drivers supported by this server.
-EOS
-
-  operation :index do
-    description "List all drivers"
-    control do
-      @drivers = settings.drivers
-      respond_to do |format|
-        format.xml { haml :"drivers/index" }
-        format.json { @drivers.to_json }
-        format.html { haml :"drivers/index" }
-      end
-    end
-  end
-
-  operation :show do
-    description "Show details for a driver"
-    param :id,      :string
-    control do
-      @name = params[:id].to_sym
-      if driver_symbol == @name
-        @providers = driver.providers(credentials)  if driver.respond_to? :providers
-      end
-      @driver = settings.drivers[@name]
-      halt 404 unless @driver
-      respond_to do |format|
-        format.xml { haml :"drivers/show" }
-        format.json { @driver.to_json }
-        format.html { haml :"drivers/show" }
-      end
-    end
-  end
-end
-
-collection :realms do
-  description <<END
-  Within a cloud provider a realm represents a boundary containing resources.
-  The exact definition of a realm is left to the cloud provider.
-  In some cases, a realm may represent different datacenters, different continents,
-  or different pools of resources within a single datacenter.
-  A cloud provider may insist that resources must all exist within a single realm in
-  order to cooperate. For instance, storage volumes may only be allowed to be mounted to
-  instances within the same realm.
-END
-
-  operation :index do
-    description <<END
-    Operation will list all available realms. Realms can be filtered using
-    the "architecture" parameter.
-END
-    with_capability :realms
-    param :id,            :string
-    param :architecture,  :string,  :optional,  [ 'i386', 'x86_64' ]
-    control { filter_all(:realms) }
-  end
-
-  #FIXME: It always shows whole list
-  operation :show do
-    description 'Show an realm identified by "id" parameter.'
-    with_capability :realm
-    param :id,           :string, :required
-    control { show(:realm) }
-  end
-
-end
-
-collection :images do
-  description <<END
-  An image is a platonic form of a machine. Images are not directly executable,
-  but are a template for creating actual instances of machines.
-END
-
-  operation :new do
-    description "Form to create a new image resource"
-    param :instance_id, :string,  "An instance from which the new image will be created from"
-    control do
-      @instance = Instance.new( :id => params[:instance_id] )
-      respond_to do |format|
-        format.html { haml :"images/new" }
-      end
-    end
-  end
-
-  operation :index do
-    description <<END
-    The images collection will return a set of all images
-    available to the current use. Images can be filtered using the
-    "owner_id" and "architecture" parameters.
-END
-    with_capability :images
-    param :id,            :string
-    param :architecture,  :string,  :optional
-    control { filter_all(:images) }
-  end
-
-  operation :show do
-    description 'Show an image identified by "id" parameter.'
-    with_capability :image
-    param :id,           :string, :required
-    control { show(:image) }
-  end
-
-  operation :create do
-    description 'Create image from instance'
-    with_capability :create_image
-    param :instance_id, :string, :required
-    control do
-      @image = driver.create_image(credentials, {
-        :id => params[:instance_id],
-        :name => params[:name],
-        :description => params[:description]
-      })
-      status 201  # Created
-      response['Location'] = image_url(@image.id)
-      respond_to do |format|
-        format.xml  { haml :"images/show" }
-        format.json { convert_to_json(:image, @image) }
-        format.html { haml :"images/show" }
-      end
-    end
-  end
-
-  operation :destroy do
-    description "Remove specified image from collection"
-    with_capability :destroy_image
-    param :id,    :string,    :required
-    control do
-      driver.destroy_image(credentials, params[:id])
-      status 204
-      respond_to do |format|
-        format.xml
-        format.json
-        format.html { redirect(images_url) }
-      end
-    end
-  end
-
-end
-
-collection :instance_states do
-  description "The possible states of an instance, and how to traverse between them "
-
-  operation :index do
-    control do
-      @machine = driver.instance_state_machine
-      respond_to do |format|
-        format.xml { haml :'instance_states/show', :layout => false }
-        format.json do
-          out = []
-          @machine.states.each do |state|
-            transitions = state.transitions.collect do |t|
-              t.automatically? ? {:to => t.destination, :auto => 'true'} : {:to => t.destination, :action => t.action}
-            end
-            out << { :name => state, :transitions => transitions }
-          end
-          out.to_json
-        end
-        format.html { haml :'instance_states/show'}
-        format.gv { erb :"instance_states/show" }
-        format.png do
-          # Trick respond_to into looking up the right template for the
-          # graphviz file
-          gv = erb(:"instance_states/show")
-          png =  ''
-          cmd = 'dot -Kdot -Gpad="0.2,0.2" -Gsize="5.0,8.0" -Gdpi="180" -Tpng'
-          Open3.popen3( cmd ) do |stdin, stdout, stderr|
-            stdin.write( gv )
-            stdin.close()
-            png = stdout.read
-          end
-          content_type 'image/png'
-          png
-        end
-      end
-    end
-  end
-end
-
-get "#{settings.root_url}/instances/:id/run" do
-  @instance = driver.instance(credentials, :id => params[:id])
-  respond_to do |format|
-    format.html { haml :"instances/run_command" }
-  end
-end
-
-collection :load_balancers do
-  description "Load balancers"
-
-  operation :new do
-    description "Form to create a new load balancer"
-    control do
-      @realms = driver.realms(credentials)
-      @instances = driver.instances(credentials) if driver_has_feature?(:register_instance, :load_balancers)
-      respond_to do |format|
-        format.html { haml :"load_balancers/new" }
-      end
-    end
-  end
-
-  operation :index do
-    description "List of all active load balancers"
-    control do
-      filter_all :load_balancers
-    end
-  end
-
-  operation :show do
-    description "Show details about given load balancer"
-    param :id,  :string,  :required
-    control { show :load_balancer }
-  end
-
-  operation :create do
-    description "Create a new load balancer"
-    param :name,  :string,  :required
-    param :realm_id,  :string,  :required
-    param :listener_protocol,  :string,  :required, ['HTTP', 'TCP']
-    param :listener_balancer_port,  :string,  :required
-    param :listener_instance_port,  :string,  :required
-    control do
-      @load_balancer = driver.create_load_balancer(credentials, params)
-      status 201  # Created
-      response['Location'] = load_balancer_url(@instance.id)
-      respond_to do |format|
-        format.xml  { haml :"load_balancers/show" }
-        format.json { convert_to_json(:load_balancer, @load_balancer) }
-        format.html { haml :"load_balancers/show" }
-      end
-    end
-  end
-
-  operation :register, :method => :post, :member => true do
-    description "Add instance to loadbalancer"
-    param :id,  :string,  :required
-    param :instance_id, :string,  :required
-    control do
-      driver.lb_register_instance(credentials, params)
-      status 204
-      respond_to do |format|
-        format.xml
-        format.json
-        format.html { redirect(load_balancer_url(params[:id])) }
-      end
-    end
-  end
-
-  operation :unregister, :method => :post, :member => true do
-    description "Remove instance from loadbalancer"
-    param :id,  :string,  :required
-    param :instance_id, :string,  :required
-    control do
-      driver.lb_unregister_instance(credentials, params)
-      status 204
-      respond_to do |format|
-        format.xml
-        format.json
-        format.html { redirect(load_balancer_url(params[:id])) }
-      end
-    end
-  end
-
-  operation :destroy do
-    description "Destroy given load balancer"
-    param :id,  :string,  :required
-    control do
-      driver.destroy_load_balancer(credentials, params[:id])
-      status 204
-      respond_to do |format|
-        format.xml
-        format.json
-        format.html { redirect(load_balancers_url) }
-      end
-    end
-  end
-
-end
-
-
-collection :instances do
-  description <<END
-  An instance is a concrete machine realized from an image.
-  The images collection may be obtained by following the link from the primary entry-point.
-END
-
-  operation :new do
-    description "Form for creating a new instance resource"
-    param :image_id,  :string,  "Image from which will be the new instance created from"
-    param :realm_id,  :string, :optional
-    if driver_has_feature? :authentication_key
-      param :authentication_key, :string, :optional
-    end
-    if driver_has_feature? :firewalls
-      param :firewalls, :string, :optional
-    end
-    control do
-      @instance = Instance.new( { :id=>params[:id], :image_id=>params[:image_id] } )
-      @image   = Image.new( :id => params[:image_id] )
-      @hardware_profiles = driver.hardware_profiles(credentials, :architecture => @image.architecture )
-      @realms = [Realm.new(:id => params[:realm_id])] if params[:realm_id]
-      @realms ||= driver.realms(credentials)
-      @keys = driver.keys(credentials) if driver_has_feature?(:authentication_key)
-      @firewalls = driver.firewalls(credentials) if driver_has_feature?(:firewalls)
-      respond_to do |format|
-        format.html do
-          haml :'instances/new'
-        end
-      end
-    end
-  end
-
-  operation :index do
-    description "List all instances."
-    with_capability :instances
-    param :id,            :string,  :optional
-    param :state,         :string,  :optional
-    control { filter_all(:instances) }
-  end
-
-  operation :show do
-    description 'Show an instance identified by "id" parameter.'
-    with_capability :instance
-    param :id,           :string, :required
-    control { show(:instance) }
-  end
-
-  operation :create do
-    description "Create a new instance."
-    with_capability :create_instance
-    param :image_id,     :string, :required
-    param :realm_id,     :string, :optional
-    param :hwp_id,       :string, :optional
-    control do
-      @instance = driver.create_instance(credentials, params[:image_id], params)
-      if @instance.kind_of? Array
-        @elements = @instance
-        action_handler = "index"
-      else
-        response['Location'] = instance_url(@instance.id)
-        action_handler = "show"
-      end
-      status 201  # Created
-      respond_to do |format|
-        format.xml  { haml :"instances/#{action_handler}" }
-        format.json do
-          if @elements
-            convert_to_json(:instances, @elements)
-          else
-            convert_to_json(:instance, @instance)
-          end
-        end
-        format.html do
-          if @elements
-            haml :"instances/index"
-          elsif @instance and @instance.id
-            response['Location'] = instance_url(@instance.id)
-            haml :"instances/show"
-          else
-            redirect instances_url
-          end
-        end
-      end
-    end
-  end
-
-  operation :reboot, :method => :post, :member => true do
-    description "Reboot a running instance."
-    with_capability :reboot_instance
-    param :id,           :string, :required
-    control { instance_action(:reboot) }
-  end
-
-  operation :start, :method => :post, :member => true do
-    description "Start an instance."
-    with_capability :start_instance
-    param :id,           :string, :required
-    control { instance_action(:start) }
-  end
-
-  operation :stop, :method => :post, :member => true do
-    description "Stop a running instance."
-    with_capability :stop_instance
-    param :id,           :string, :required
-    control { instance_action(:stop) }
-  end
-
-  operation :destroy do
-    description "Destroy an instance."
-    with_capability :destroy_instance
-    param :id,           :string, :required
-    control { instance_action(:destroy) }
-  end
-
-  operation :run, :method => :post, :member => true do
-    description <<END
-  Run command on instance. Either password or private key must be send
-  in order to execute command. Authetication method should be advertised
-  in instance.
-END
-    with_capability :run_on_instance
-    param :id,          :string,  :required
-    param :cmd,         :string,  :required, [], "Shell command to run on instance"
-    param :private_key, :string,  :optional, [], "Private key in PEM format for authentication"
-    param :password,    :string,  :optional, [], "Password used for authentication"
-    control do
-      @output = driver.run_on_instance(credentials, params)
-      respond_to do |format|
-        format.xml { haml :"instances/run" }
-        format.html { haml :"instances/run" }
-      end
-    end
-  end
-end
-
-collection :hardware_profiles do
-  description <<END
- A hardware profile represents a configuration of resources upon which a
- machine may be deployed. It defines aspects such as local disk storage,
- available RAM, and architecture. Each provider is free to define as many
- (or as few) hardware profiles as desired.
-END
-
-  operation :index do
-    description "List of available hardware profiles."
-    with_capability :hardware_profiles
-    param :id,          :string
-    param :architecture,  :string,  :optional,  [ 'i386', 'x86_64' ]
-    control do
-        @profiles = driver.hardware_profiles(credentials, params)
-        respond_to do |format|
-          format.xml  { haml :'hardware_profiles/index' }
-          format.html  { haml :'hardware_profiles/index' }
-          format.json { convert_to_json(:hardware_profile, @profiles) }
-        end
-    end
-  end
-
-  operation :show do
-    description "Show specific hardware profile."
-    with_capability :hardware_profile
-    param :id,          :string,    :required
-    control do
-      @profile =  driver.hardware_profile(credentials, params[:id])
-      if @profile
-        respond_to do |format|
-          format.xml { haml :'hardware_profiles/show', :layout => false }
-          format.html { haml :'hardware_profiles/show' }
-          format.json { convert_to_json(:hardware_profile, @profile) }
-        end
-      else
-        report_error(404)
-      end
-    end
-  end
-
-end
-
-collection :storage_snapshots do
-  description "Storage snapshots description here"
-
-  operation :new do
-    description "A form to create a new storage snapshot"
-    control do
-      respond_to do |format|
-        format.html { haml :"storage_snapshots/new" }
-      end
-    end
-  end
-
-  operation :index do
-    description "List of storage snapshots."
-    with_capability :storage_snapshots
-    param :id,            :string
-    control { filter_all(:storage_snapshots) }
-  end
-
-  operation :show do
-    description "Show storage snapshot."
-    with_capability :storage_snapshot
-    param :id,          :string,    :required
-    control { show(:storage_snapshot) }
-  end
-
-  operation :create do
-    description "Create a new snapshot from volume"
-    with_capability :create_storage_snapshot
-    param :volume_id, :string,  :required
-    control do
-      @storage_snapshot = driver.create_storage_snapshot(credentials, params)
-      status 201  # Created
-      response['Location'] = storage_snapshot_url(@storage_snapshot.id)
-      show(:storage_snapshot)
-    end
-  end
-
-  operation :destroy do
-    description "Delete storage snapshot"
-    with_capability :destroy_storage_snapshot
-    param :id,  :string,  :required
-    control do
-      driver.destroy_storage_snapshot(credentials, params)
-      status 204
-      respond_to do |format|
-        format.xml
-        format.json
-        format.html { redirect(storage_snapshots_url) }
-      end
-    end
-  end
-end
-
-collection :storage_volumes do
-  description "Storage volumes description here"
-
-  operation :new do
-    description "A form to create a new storage volume"
-    control do
-      respond_to do |format|
-        format.html { haml :"storage_volumes/new" }
-      end
-    end
-  end
-
-  operation :index do
-    description "List of storage volumes."
-    with_capability :storage_volumes
-    param :id,            :string
-    control { filter_all(:storage_volumes) }
-  end
-
-  operation :show do
-    description "Show storage volume."
-    with_capability :storage_volume
-    param :id,          :string,    :required
-    control { show(:storage_volume) }
-  end
-
-  operation :create do
-    description "Create a new storage volume"
-    with_capability :create_storage_volume
-    param :snapshot_id, :string,  :optional
-    param :capacity,    :string,  :optional
-    param :realm_id,    :string,  :optional
-    control do
-      @storage_volume = driver.create_storage_volume(credentials, params)
-      status 201
-      response['Location'] = storage_volume_url(@storage_volume.id)
-      respond_to do |format|
-        format.xml  { haml :"storage_volumes/show" }
-        format.html { haml :"storage_volumes/show" }
-        format.json { convert_to_json(:storage_volume, @storage_volume) }
-      end
-    end
-  end
-
-  operation :attach_instance, :method=>:get, :member=>true  do
-    description "A form to attach a storage volume to an instance"
-    control do
-      @instances = driver.instances(credentials)
-      respond_to do |format|
-        format.html{ haml :"storage_volumes/attach"}
-      end
-    end
-  end
-
-  operation :attach, :method => :post, :member => true do
-    description "Attach storage volume to instance"
-    with_capability :attach_storage_volume
-    param :id,         :string,  :required
-    param :instance_id,:string,  :required
-    param :device,     :string,  :required
-    control do
-      @storage_volume = driver.attach_storage_volume(credentials, params)
-      status 202
-      respond_to do |format|
-        format.html { redirect(storage_volume_url(params[:id]))}
-        format.xml  { haml :"storage_volumes/show" }
-        format.json { convert_to_json(:storage_volume, @storage_volume) }
-      end
-    end
-  end
-
-  operation :detach, :method => :post, :member => true do
-    description "Detach storage volume to instance"
-    with_capability :detach_storage_volume
-    param :id,         :string,  :required
-    control do
-      volume = driver.storage_volume(credentials, :id => params[:id])
-      @storage_volume =  driver.detach_storage_volume(credentials, :id => volume.id, :instance_id => volume.instance_id, :device => volume.device)
-      status 202
-      respond_to do |format|
-        format.html { redirect(storage_volume_url(params[:id]))}
-        format.xml  { haml :"storage_volumes/show" }
-        format.json { convert_to_json(:storage_volume, @storage_volume) }
-      end
-    end
-  end
-
-  operation :destroy do
-    description "Destroy storage volume"
-    with_capability :destroy_storage_volume
-    param :id,          :string,  :optional
-    control do
-      driver.destroy_storage_volume(credentials, params)
-      status 204
-      respond_to do |format|
-        format.xml
-        format.json
-        format.html { redirect(storage_volumes_url) }
-      end
-    end
-  end
-
-end
-
-collection :keys do
-  description "Instance authentication credentials."
-
-  operation :new do
-    description "A form to create a new key resource"
-    control do
-      respond_to do |format|
-        format.html { haml :"keys/new" }
-      end
-    end
-  end
-
-  operation :index do
-    description "List all available credentials which could be used for instance authentication."
-    with_capability :keys
-    control do
-      filter_all :keys
-    end
-  end
-
-  operation :show do
-    description "Show details about given instance credential."
-    with_capability :key
-    param :id,  :string,  :required
-    control { show :key }
-  end
-
-  operation :create do
-    description "Create a new instance credential if backend supports this."
-    with_capability :create_key
-    param :name,  :string,  :required
-    control do
-      @key = driver.create_key(credentials, { :key_name => params[:name] })
-      status 201
-      response['Location'] = key_url(@key.id)
-      respond_to do |format|
-        format.xml  { haml :"keys/show", :ugly => true }
-        format.html { haml :"keys/show" }
-        format.json { convert_to_json(:key, @key)}
-      end
-    end
-  end
-
-  operation :destroy do
-    description "Destroy given instance credential if backend supports this."
-    with_capability :destroy_key
-    param :id,  :string,  :required
-    control do
-      driver.destroy_key(credentials, { :id => params[:id]})
-      status 204
-      respond_to do |format|
-        format.xml
-        format.json
-        format.html { redirect(keys_url) }
-      end
-    end
-  end
-
-end
-
-#get html form for creating a new blob
-
-# The URL for getting the new blob form for the HTML UI looks like the URL
-# for getting the details of an existing blob. To make collisions less
-# likely, we use a name for the form that will rarely be the name of an
-# existing blob
-NEW_BLOB_FORM_ID = "new_blob_form_d15cfd90"
-
-get "#{settings.root_url}/buckets/:bucket/#{NEW_BLOB_FORM_ID}" do
-  @bucket_id = params[:bucket]
-  respond_to do |format|
-    format.html {haml :"blobs/new"}
-  end
-end
-
-collection :buckets do
-  description "Cloud Storage buckets - aka buckets|directories|folders"
-
-  collection :blobs do
-    description "Blobs associated with given bucket"
-
-    operation :show do
-      description "Display blob"
-      control do
-        @blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
-        if @blob
-          respond_to do |format|
-            format.xml { haml :"blobs/show" }
-            format.html { haml :"blobs/show" }
-            format.json { convert_to_json(:blob, @blob) }
-          end
-        else
-          report_error(404)
-        end
-      end
-
-    end
-
-    operation :create do
-      description "Create new blob"
-      param :blob_id,  :string,  :required
-      param :blob_data, :hash, :required
-      control do
-        bucket_id = params[:bucket]
-        blob_id = params['blob_id']
-        blob_data = params['blob_data']
-        user_meta = {}
-        #metadata from params (i.e., passed by http form post, e.g. browser)
-        max = params[:meta_params]
-        if(max)
-          (1..max.to_i).each do |i|
-            key = params[:"meta_name#{i}"]
-            key = "HTTP_X_Deltacloud_Blobmeta_#{key}"
-            value = params[:"meta_value#{i}"]
-            user_meta[key] = value
-          end
-        end
-        @blob = driver.create_blob(credentials, bucket_id, blob_id, blob_data, user_meta)
-        respond_to do |format|
-          format.xml { haml :"blobs/show" }
-          format.html { haml :"blobs/show"}
-          format.json {convert_to_json(:blob, @blob)}
-        end
-      end
-    end
-
-    operation :destroy do
-      description "Destroy given blob"
-      control do
-        bucket_id = params[:bucket]
-        blob_id = params[:blob]
-        driver.delete_blob(credentials, bucket_id, blob_id)
-        status 204
-        respond_to do |format|
-          format.xml
-          format.json
-          format.html { redirect(bucket_url(bucket_id)) }
-        end
-      end
-    end
-
-    operation :stream, :member => true, :standard => true, :method => :put do
-      description "Stream new blob data into the blob"
-      control do
-        if(env["BLOB_SUCCESS"]) #ie got a 200ok after putting blob
-          content_type = env["CONTENT_TYPE"]
-          content_type ||=  ""
-          @blob = driver.blob(credentials, {:id => params[:blob],
-                                            'bucket' => params[:bucket]})
-          respond_to do |format|
-            format.xml { haml :"blobs/show" }
-            format.html { haml :"blobs/show" }
-            format.json { convert_to_json(:blob, @blob) }
-          end
-        elsif(env["BLOB_FAIL"])
-          report_error(500) #OK?
-        else # small blobs - < 112kb dont hit the streaming monkey patch - use 'normal' create_blob
-          # also, if running under webrick don't hit the streaming patch (Thin specific)
-          bucket_id = params[:bucket]
-          blob_id = params[:blob]
-          temp_file = Tempfile.new("temp_blob_file")
-          temp_file.write(env['rack.input'].read)
-          temp_file.flush
-          content_type = env['CONTENT_TYPE'] || ""
-          blob_data = {:tempfile => temp_file, :type => content_type}
-          user_meta = BlobHelper::extract_blob_metadata_hash(request.env)
-          @blob = driver.create_blob(credentials, bucket_id, blob_id, blob_data, user_meta)
-          temp_file.delete
-          respond_to do |format|
-            format.xml { haml :"blobs/show" }
-            format.html { haml :"blobs/show" }
-            format.json { convert_to_json(:blob, @blob) }
-          end
-        end
-      end
-    end
-
-    operation :metadata, :member => true, :standard => true, :method => :head do
-      description "Get blob metadata"
-      control do
-        @blob_id = params[:blob]
-        @blob_metadata = driver.blob_metadata(credentials, {:id => params[:blob], 'bucket' => params[:bucket]})
-        if @blob_metadata
-          @blob_metadata.each do |k,v|
-            headers["X-Deltacloud-Blobmeta-#{k}"] = v
-          end
-          status 204
-          respond_to do |format|
-            format.xml
-            format.json
-          end
-        else
-          report_error(404)
-        end
-      end
-    end
-
-    operation :update, :member => true, :method => :post do
-      description "Update blob metadata"
-      control do
-        meta_hash = BlobHelper::extract_blob_metadata_hash(request.env)
-        success = driver.update_blob_metadata(credentials, {'bucket'=>params[:bucket], :id =>params[:blob], 'meta_hash' => meta_hash})
-        if(success)
-          meta_hash.each do |k,v|
-            headers["X-Deltacloud-Blobmeta-#{k}"] = v
-          end
-          status 204
-          respond_to do |format|
-            format.xml
-            format.json
-          end
-        else
-          report_error(404) #FIXME is this the right error code?
-        end
-      end
-    end
+require 'sinatra/base'
+require 'sinatra/rabbit'
 
-    operation :content, :member => true, :method => :get do
-      description "Download blob content"
-      control do
-        @blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
-        if @blob
-          params['content_length'] = @blob.content_length
-          params['content_type'] = @blob.content_type
-          params['content_disposition'] = "attachment; filename=#{@blob.id}"
-          BlobStream.call(env, credentials, params)
-        else
-          report_error(404)
-        end
-      end
-    end
+require_relative '../sinatra'
+require_relative './models'
+require_relative './drivers'
+require_relative './helpers'
+require_relative './collections'
 
-  end
 
-  operation :new do
-    description "A form to create a new bucket resource"
-    control do
-      respond_to do |format|
-        format.html { haml :"buckets/new" }
-      end
-    end
-  end
+module Deltacloud
+  class API < Collections::Base
 
-  operation :index do
-    description "List buckets associated with this account"
-    with_capability :buckets
-    param :id,        :string
-    param :name,      :string
-    param :size,      :string
-    control { filter_all(:buckets) }
-  end
+    # Enable logging
+    use Rack::CommonLogger
+    use Rack::Date
+    use Rack::ETag
+    use Rack::MatrixParams
+    use Rack::DriverSelect
+    use Rack::Accept
+    use Rack::MediaType
 
-  operation :show do
-    description "Show bucket"
-    with_capability :bucket
-    param :id,        :string
-    control { show(:bucket) }
-  end
+    include Deltacloud::Helpers
+    include Deltacloud::Collections
 
-  operation :create do
-    description "Create a new bucket (POST /api/buckets)"
-    with_capability :create_bucket
-    param :name,      :string,    :required
-    control do
-      @bucket = driver.create_bucket(credentials, params[:name], params)
-      status 201
-      response['Location'] = bucket_url(@bucket.id)
-      respond_to do |format|
-        format.xml  { haml :"buckets/show" }
-        format.json { convert_to_json(:bucket, @bucket) }
-        format.html do
-          redirect bucket_url(@bucket.id) if @bucket and @bucket.id
-          redirect buckets_url
-        end
+    get API_ROOT_URL do
+      if params[:force_auth]
+        return [401, 'Authentication failed'] unless driver.valid_credentials?(credentials)
       end
-    end
-  end
-
-  operation :destroy do
-    description "Delete a bucket by name - bucket must be empty"
-    with_capability :delete_bucket
-    param :id,    :string,    :required
-    control do
-      driver.delete_bucket(credentials, params[:id], params)
-      status 204
       respond_to do |format|
-        format.xml
-        format.json
-        format.html {  redirect(buckets_url) }
+        format.xml { haml :"api/show" }
+        format.json { xml_to_json :"api/show" }
+        format.html { haml :"api/show" }
       end
     end
-  end
-
-end
 
-get "#{settings.root_url}/addresses/:id/associate" do
-  @instances = driver.instances(credentials)
-  @address = Address::new(:id => params[:id])
-  respond_to do |format|
-    format.html { haml :"addresses/associate" }
   end
 end
 
-collection :addresses do
-  description "Manage IP addresses"
-
-  operation :index do
-    description "List IP addresses assigned to your account."
-    with_capability :addresses
-    control do
-      filter_all :addresses
-    end
-  end
-
-  operation :show do
-    description "Show details about IP addresses specified by given ID"
-    with_capability :address
-    param :id,  :string,  :required
-    control { show :address }
-  end
-
-  operation :create do
-    description "Acquire a new IP address for use with your account."
-    with_capability :create_address
-    control do
-      @address = driver.create_address(credentials, {})
-      status 201    # Created
-      response['Location'] = address_url(@address.id)
-      respond_to do |format|
-        format.xml  { haml :"addresses/show", :ugly => true }
-        format.html { haml :"addresses/_address", :layout => false }
-        format.json { convert_to_json(:address, @address) }
-      end
-    end
-  end
-
-  operation :destroy do
-    description "Release an IP address associated with your account"
-    with_capability :destroy_address
-    param :id,  :string,  :required
-    control do
-      driver.destroy_address(credentials, { :id => params[:id]})
-      status 204
-      respond_to do |format|
-        format.xml
-        format.json
-        format.html { redirect(addresses_url) }
-      end
-    end
-  end
-
-  operation :associate, :method => :post, :member => true do
-    description "Associate an IP address to an instance"
-    with_capability :associate_address
-    param :id, :string, :required
-    param :instance_id, :string, :required
-    control do
-      driver.associate_address(credentials, { :id => params[:id], :instance_id => params[:instance_id]})
-      status 202   # Accepted
-      respond_to do |format|
-        format.xml
-        format.json
-        format.html { redirect(address_url(params[:id])) }
-      end
-    end
-  end
-
-  operation :disassociate, :method => :post, :member => true do
-    description "Disassociate an IP address from an instance"
-    with_capability :associate_address
-    param :id, :string, :required
-    control do
-      driver.disassociate_address(credentials, { :id => params[:id] })
-      status 202   # Accepted
-      respond_to do |format|
-        format.xml
-        format.json
-        format.html { redirect(address_url(params[:id])) }
-      end
-    end
-  end
-
-end
-
-#delete a firewall rule
-delete '/api/firewalls/:firewall/:rule' do
-  opts = {}
-  opts[:firewall] = params[:firewall]
-  opts[:rule_id] = params[:rule]
-  driver.delete_firewall_rule(credentials, opts)
-  status 204
-  respond_to do |format|
-    format.xml
-    format.json
-    format.html {redirect firewall_url(params[:firewall])}
-  end
-end
-
-#FIREWALLS
-collection :firewalls do
-  description "Allow user to define firewall rules for an instance (ec2 security groups) eg expose ssh access [port 22, tcp]."
-
-  operation :new do
-    description "A form to create a new firewall resource"
-    control do
-      respond_to do |format|
-        format.html { haml :"firewalls/new" }
-      end
-    end
-  end
-
-  operation :new_rule, :form => true, :member => true, :method => :get do
-    description "A form to create a new firewall rule"
-    param :id,  :string,  :required
-    control do
-      @firewall_name = params[:id]
-      respond_to do |format|
-        format.html {haml :"firewalls/new_rule" }
-      end
-    end
-  end
-
-  operation :index do
-    description 'List all firewalls'
-    with_capability :firewalls
-    control { filter_all(:firewalls) }
-  end
-
-  operation :show do
-    description 'Show details for a specific firewall - list all rules'
-    with_capability :firewall
-    param :id,            :string,    :required
-    control { show(:firewall) }
-  end
-
-  operation :create do
-    description 'Create a new firewall'
-    with_capability :create_firewall
-    param :name,          :string,    :required
-    param :description,   :string,    :required
-    control do
-      @firewall = driver.create_firewall(credentials, params )
-      status 201  # Created
-      response['Location'] = firewall_url(@firewall.id)
-      respond_to do |format|
-        format.xml  { haml :"firewalls/show" }
-        format.html { haml :"firewalls/show" }
-        format.json { convert_to_json(:firewall, @firewall) }
-      end
-    end
-  end
-
-  operation :destroy do
-    description 'Delete a specified firewall - error if firewall has rules'
-    with_capability :delete_firewall
-    param :id,            :string,    :required
-    control do
-      driver.delete_firewall(credentials, params)
-      status 204
-      respond_to do |format|
-        format.xml
-        format.json
-        format.html {  redirect(firewalls_url) }
-      end
-    end
-  end
-
-  #create a new firewall rule - POST /api/firewalls/:firewall/rules
-  operation :rules, :method => :post, :member => true do
-    description 'Create a new firewall rule for the specified firewall'
-    param :id,  :required, :string, [],  "Name of firewall in which to apply this rule"
-    param :protocol,  :required, :string, ['tcp','udp','icmp'], "Transport layer protocol for the rule"
-    param :port_from, :required, :string, [], "Start of port range for the rule"
-    param :port_to,   :required, :string, [], "End of port range for the rule"
-    with_capability :create_firewall_rule
-    control do
-      #source IPs from params
-      addresses =  params.inject([]){|result,current| result << current.last unless current.grep(/^ip[-_]address/i).empty?; result}
-      #source groups from params
-      groups = {}
-      max_groups  = params.select{|k,v| k=~/^group/}.size/2
-      for i in (1..max_groups) do
-        groups.merge!({params["group#{i}"]=>params["group#{i}owner"]})
-      end
-      params['addresses'] = addresses
-      params['groups'] = groups
-      if addresses.empty? && groups.empty?
-        raise Deltacloud::ExceptionHandler::ValidationFailure.new(
-          StandardError.new("No sources. Specify at least one source ip_address or group")
-        )
-      end
-      driver.create_firewall_rule(credentials, params)
-      @firewall = driver.firewall(credentials, {:id => params[:id]})
-      status 201
-      respond_to do |format|
-        format.xml  { haml :"firewalls/show" }
-        format.html { haml :"firewalls/show" }
-        format.json { convert_to_json(:firewall, @firewall) }
-      end
-    end
-  end
-
-end
diff --git a/server/lib/deltacloud/state_machine.rb b/server/lib/deltacloud/state_machine.rb
deleted file mode 100644
index facd4ba..0000000
--- a/server/lib/deltacloud/state_machine.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-module Deltacloud
-  class StateMachine
-
-    attr_reader :states
-    def initialize(opts = {}, &block)
-      @all_states = opts[:all_states]
-      @all_actions = opts[:all_actions]
-      @states  = []
-      instance_eval &block if block
-    end
-
-    def start()
-      state(:start)
-    end
-
-    def finish()
-      state(:finish)
-    end
-
-    def state(name)
-      unless valid_state_name?(name)
-        raise "State '#{name}' not in list of allowed states"
-      end
-      state = @states.find{|e| e.name == name.to_sym}
-      if ( state.nil? )
-        state = State.new( self, name.to_sym )
-        @states << state
-      end
-      state
-    end
-
-    def valid_state_name?(name)
-      @all_states.nil? || @all_states.include?(name.to_sym)
-    end
-
-    def valid_action_name?(name)
-      @all_actions.nil? || @all_actions.include?(name.to_sym)
-    end
-
-    def method_missing(sym,*args)
-      return state( sym ) if ( args.empty? )
-      super( sym, *args )
-    end
-
-    class State
-
-      attr_reader :name
-      attr_reader :transitions
-
-      def initialize(machine, name)
-        @machine = machine
-        @name    = name
-        @transitions = []
-      end
-
-      def to_s
-        self.name.to_s
-      end
-
-      def to(destination_name)
-        destination = @machine.state(destination_name)
-        transition = Transition.new( @machine, destination )
-        @transitions << transition
-        transition
-      end
-
-    end
-
-    class Transition
-
-      attr_reader :destination
-      attr_reader :action
-
-      def initialize(machine, destination)
-        @machine = machine
-        @destination = destination
-        @auto   = false
-        @action = nil
-      end
-
-      def automatically
-        @auto = true
-      end
-
-      def automatically?
-        @auto
-      end
-
-      def on(action)
-        unless @machine.valid_action_name?(action)
-          raise "Action '#{action}' not in list of allowed actions"
-        end
-        @action = action
-      end
-
-    end
-
-  end
-end
diff --git a/server/lib/deltacloud/validation.rb b/server/lib/deltacloud/validation.rb
deleted file mode 100644
index 3d29225..0000000
--- a/server/lib/deltacloud/validation.rb
+++ /dev/null
@@ -1,100 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-module Deltacloud::Validation
-
-  class Param
-    attr_reader :name, :klass, :type, :options, :description
-
-    def initialize(args)
-      @name = args[0]
-      @klass = args[1] || :string
-      @type = args[2] || :optional
-      @options = args[3] || []
-      @description = args[4] || ''
-    end
-
-    def required?
-      type.eql?(:required)
-    end
-
-    def optional?
-      type.eql?(:optional)
-    end
-
-    def valid_value?(value)
-      true if (options.kind_of?(Range) or options.kind_of?(Array)) and options.include?(value)
-      true if options.kind_of?(String) and not options.empty?
-    end
-
-    def valid_hwp_value?(profile, value)
-      profile.property(@name.to_s.gsub(/^hwp_/, '')).valid?(value)
-    end
-
-    def hwp_property?
-      true if name.to_s =~ /^hwp_(cpu|memory|storage|architecture)/
-    end
-  end
-
-  def param(*args)
-    raise "Duplicate param #{args[0]} #{params.inspect} #{self.class.name}" if params[args[0]]
-    p = Param.new(args)
-    params[p.name] = p
-  end
-
-  def params
-    @params ||= {}
-    @params
-  end
-
-  # Add the parameters in hash +new+ to already existing parameters. If
-  # +new+ contains a parameter with an already existing name, the old
-  # definition is clobbered.
-  def add_params(new)
-    # We do not check for duplication on purpose: multiple calls
-    # to add_params should be cumulative
-    new.each { |p|  @params[p.name] = p }
-  end
-
-  def each_param(&block)
-    params.each_value { |p| yield p }
-  end
-
-  def validate(current_driver, all_params, values, credentials)
-    all_params.each do |key, p|
-      if p.required? and not values[p.name]
-        raise validation_exception "Required parameter #{p.name} not found"
-      end
-      next unless values[p.name]
-      if p.hwp_property?
-        profile = current_driver.hardware_profile(credentials, values['hwp_id'])
-        raise validation_exception("Unknown hardware profile selected #{values['hwp_id']}") unless profile
-        unless p.valid_hwp_value?(profile, values[p.name])
-          raise validation_exception("Hardware profile property #{p.name} has invalid value #{values[p.name]}")
-        end
-      else
-        if not p.options.empty? and p.valid_value?(values[p.name])
-          raise validation_exception("Parameter #{p.name} has value #{values[p.name]} which is not in #{p.options.join(", ")}")
-        end
-      end
-    end
-  end
-
-  def validation_exception(message)
-    Deltacloud::ExceptionHandler::ValidationFailure.new(StandardError.new(message))
-  end
-
-end
diff --git a/server/lib/sinatra.rb b/server/lib/sinatra.rb
new file mode 100644
index 0000000..6179d55
--- /dev/null
+++ b/server/lib/sinatra.rb
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+require_relative 'sinatra/rack_date'
+require_relative 'sinatra/rack_etag'
+require_relative 'sinatra/rack_matrix_params'
+require_relative 'sinatra/rack_driver_select'
+require_relative 'sinatra/accept_media_types'
+require_relative 'sinatra/rack_accept'
diff --git a/server/lib/sinatra/lazy_auth.rb b/server/lib/sinatra/lazy_auth.rb
deleted file mode 100644
index fb94dd9..0000000
--- a/server/lib/sinatra/lazy_auth.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'sinatra/base'
-
-# Lazy Basic HTTP authentication. Authentication is only forced when the
-# credentials are actually needed.
-module Sinatra
-  module LazyAuth
-    class LazyCredentials
-      def initialize(app)
-        @app = app
-        @provided = false
-      end
-
-      def user
-        credentials!
-        @user
-      end
-
-      def password
-        credentials!
-        @password
-      end
-
-      def provided?
-        @provided
-      end
-
-      private
-      def credentials!
-        if ENV["API_USER"] && ENV["API_PASSWORD"]
-          @user = ENV["API_USER"]
-          @password = ENV["API_PASSWORD"]
-          @provided = true
-        end
-        unless provided?
-          auth = Rack::Auth::Basic::Request.new(@app.request.env)
-          @app.authorize! unless auth.provided? && auth.basic? && auth.credentials
-          @user = auth.credentials[0]
-          @password = auth.credentials[1]
-          @provided = true
-        end
-      end
-
-    end
-
-    def authorize!
-      r = "#{driver_symbol}-deltacloud@#{HOSTNAME}"
-      response['WWW-Authenticate'] = %(Basic realm="#{r}")
-      throw(:halt, [401, report_error(401)])
-    end
-
-    # Request the current user's credentials. Actual credentials are only
-    # requested when an attempt is made to get the user name or password
-    def credentials
-      LazyCredentials.new(self)
-    end
-  end
-
-  helpers LazyAuth
-end
diff --git a/server/lib/sinatra/rabbit.rb b/server/lib/sinatra/rabbit.rb
deleted file mode 100644
index 5c63fd9..0000000
--- a/server/lib/sinatra/rabbit.rb
+++ /dev/null
@@ -1,441 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'sinatra/base'
-require 'sinatra/url_for'
-require 'deltacloud/validation'
-require 'deltacloud/backend_capability'
-
-module Sinatra
-
-  module Rabbit
-
-    def self.routes
-      @routes ||= []
-    end
-
-    class DuplicateParamException < Deltacloud::ExceptionHandler::DeltacloudException; end
-    class DuplicateOperationException < Deltacloud::ExceptionHandler::DeltacloudException; end
-    class DuplicateCollectionException < Deltacloud::ExceptionHandler::DeltacloudException; end
-    class UnsupportedCollectionException < Deltacloud::ExceptionHandler::DeltacloudException
-      def initialize
-        # The server understood the request, but is refusing to fulfill it. Authorization will not help and the request
-        # SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request
-        # has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish
-        # to make this information available to the client, the status code 404 (Not Found) can be used instead.
-        super(403, 'UnsupportedCollection', "Requested collection is not supported for current provider", [])
-      end
-    end
-
-    class Operation
-      attr_reader :name, :method, :collection, :member
-
-      include ::Deltacloud::BackendCapability
-      include ::Deltacloud::Validation
-      include ::ApplicationHelper
-
-      STANDARD = {
-        :new => { :method => :get, :member => false, :form => true },
-        :index => { :method => :get, :member => false },
-        :show =>  { :method => :get, :member => true },
-        :create => { :method => :post, :member => false },
-        :update => { :method => :put, :member => true },
-        :destroy => { :method => :delete, :member => true }
-      }
-
-      def initialize(coll, name, opts, &block)
-        @name = name.to_sym
-        opts = STANDARD[@name].merge(opts) if standard?
-        @path_generator = opts[:path_generator]
-        @collection, @standard = coll, opts[:standard]
-        raise "No method for operation #{name}" unless opts[:method]
-        @method = opts[:method].to_sym
-        @member = opts[:member]
-        @description = ""
-        instance_eval(&block) if block_given?
-        generate_documentation
-        generate_options
-      end
-
-      def http_method
-        @method
-      end
-
-      def standard?
-        STANDARD.keys.include?(name) || @standard
-      end
-
-      def form?
-        STANDARD[name] and STANDARD[name][:form]
-      end
-
-      def description(text="")
-        return @description if text.blank?
-        @description = text
-      end
-
-      def generate_documentation
-        coll, oper = @collection, self
-        Rabbit::routes << [:get, "#{settings.root_url}/docs/#{@collection.name}/#{@name}"]
-        ::Sinatra::Application.get("#{settings.root_url}/docs/#{@collection.name}/#{@name}") do
-          @collection, @operation = coll, oper
-          @features = driver.features_for_operation(coll.name, oper.name)
-          respond_to do |format|
-            format.html { haml :'docs/operation' }
-            format.xml { haml :'docs/operation' }
-          end
-        end
-      end
-
-      def generate_options
-        current_operation = self
-        Rabbit::routes << [:options, "#{settings.root_url}/#{current_operation.collection.name}/#{current_operation.name}"]
-        ::Sinatra::Application.options("#{settings.root_url}/#{current_operation.collection.name}/#{current_operation.name}") do
-          required_params = current_operation.effective_params(driver).collect do |name, validation|
-            name.to_s if validation.type.eql?(:required)
-          end.compact.join(',')
-          optional_params = current_operation.effective_params(driver).collect do |name, validation|
-            name.to_s if validation.type.eql?(:optional)
-          end.compact.join(',')
-          headers 'X-Required-Parameters' => required_params
-          headers 'X-Optional-Parameters' => optional_params
-          [200, '']
-        end
-      end
-
-      def control(&block)
-        op = self
-        @control = Proc.new do
-          op.collection.check_supported(driver)
-          op.check_capability(driver)
-          op.validate(driver, op.effective_params(driver), params, credentials)
-          instance_eval(&block)
-        end
-      end
-
-      def member?
-        if standard?
-          @member || STANDARD[name][:member]
-        else
-          @member
-        end
-      end
-
-      def path(args = {})
-        return @path_generator.call(self) if @path_generator
-        if member?
-          if standard?
-            "#{@collection.name}/:id"
-          else
-            "#{@collection.name}/:id/#{name}"
-          end
-        else
-          if form?
-            "#{@collection.name}/#{name}"
-          else
-            "#{@collection.name}"
-          end
-        end
-      end
-
-      def generate
-        Rabbit::routes << [@method, "#{settings.root_url}/#{path}"]
-        ::Sinatra::Application.send(@method, "#{settings.root_url}/#{path}", {}, &@control)
-        # Set up some Rails-like URL helpers
-        if name == :index
-          gen_route "#{@collection.name}_url"
-        elsif name == :show
-          gen_route "#{@collection.name.to_s.singularize}_url"
-        else
-          gen_route "#{name}_#{@collection.name.to_s.singularize}_url"
-        end
-      end
-
-      # Return a hash of all params, the params statically defined for this
-      # operation plus the params defined by any features in the +driver+
-      # that might modify this operation
-      def effective_params(driver)
-        driver.features(@collection.name).collect do |f|
-          f.decl.operation(@name)
-        end.flatten.select { |op| op }.inject(params.dup) do |result, fop|
-          fop.params.each_key do |k|
-            if result.has_key?(k)
-              raise DuplicateParamException, "Parameter '#{k}' for operation #{fop.name} in collection #{@collection.name}"
-            else
-              result[k] = fop.params[k]
-            end
-          end
-          result
-        end
-      end
-
-      private
-      def gen_route(name)
-        route_url = path
-        if @member
-          ::Sinatra::Application.send(:define_method, name) do |id, *args|
-            url = query_url(route_url, args[0])
-            api_url_for url.gsub(/:id/, id.to_s), :full
-          end
-        else
-          ::Sinatra::Application.send(:define_method, name) do |*args|
-            url = query_url(route_url, args[0])
-            api_url_for url, :full
-          end
-        end
-      end
-    end
-
-    class Collection
-      attr_reader :name, :operations, :subcollections
-
-      def initialize(name, options={}, &block)
-        @name = name
-        @description = ""
-        @operations, @subcollections = {}, {}
-        @global = options[:global] || false
-        instance_eval(&block) if block_given?
-        generate_documentation
-        generate_head
-        generate_options
-      end
-
-      def subcollection?
-        self.class == SubCollection
-      end
-
-      # Set/Return description for collection
-      # If first parameter is not present, full description will be
-      # returned.
-      def description(text='')
-        return @description if text.blank?
-        @description = text
-      end
-
-      # Mark this collection as global, i.e. independent of any specific
-      # driver
-      def global!
-        @global = true
-      end
-
-      # Return +true+ if this collection is global, i.e. independent of any
-      # specific driver
-      def global?
-        @global
-      end
-
-      def generate_head
-        current_collection = self
-        Rabbit::routes << [:head, "#{settings.root_url}/#{name}"]
-        ::Sinatra::Application.head("#{settings.root_url}/#{name}") do
-          methods_allowed = current_collection.operations.collect { |o| o[1].method.to_s.upcase }.uniq.join(',')
-          headers 'Allow' => "HEAD,OPTIONS,#{methods_allowed}"
-          [200, '']
-        end
-      end
-
-      def generate_options
-        current_collection = self
-        Rabbit::routes << [:options, "#{settings.root_url}/#{name}"]
-        ::Sinatra::Application.options("#{settings.root_url}/#{name}") do
-          operations_allowed = current_collection.operations.collect { |o| o[0] }.join(',')
-          headers 'X-Operations-Allowed' => operations_allowed
-          [200, '']
-        end
-      end
-
-      def generate_documentation
-        coll = self
-        Rabbit::routes << [:get, "#{settings.root_url}/docs/#{@name}"]
-        ::Sinatra::Application.get("#{settings.root_url}/docs/#{@name}") do
-          coll.check_supported(driver)
-          @collection = coll
-          @operations = coll.operations
-          @features = driver.features(coll.name)
-          respond_to do |format|
-            format.html { haml :'docs/collection' }
-            format.xml { haml :'docs/collection' }
-          end
-        end
-      end
-
-      # Add a new operation for this collection. For the standard REST
-      # operations :index, :show, :update, and :destroy, we already know
-      # what method to use and whether this is an operation on the URL for
-      # individual elements or for the whole collection.
-      #
-      # For non-standard operations, options must be passed:
-      #  :method : one of the HTTP methods
-      #  :member : whether this is an operation on the collection or an
-      #            individual element (FIXME: custom operations on the
-      #            collection will use a nonsensical URL) The URL for the
-      #            operation is the element URL with the name of the operation
-      #            appended
-      #
-      # This also defines a helper method like show_instance_url that returns
-      # the URL to this operation (in request context)
-      def operation(name, opts = {}, &block)
-        if @operations.keys.include?(name)
-          raise DuplicateOperationException::new(500, "DuplicateOperation", "Operation #{name} is already defined", [])
-        end
-        @operations[name] = Operation.new(self, name, opts, &block)
-      end
-
-      def collection(name, opts={}, &block)
-        if subcollections.keys.include?(name)
-          raise DuplicateOperationException::new(500, "DuplicateSubcollection", "Subcollection #{name} is already defined", [])
-        end
-        subcollections[name] = SubCollection.new(self, name, opts, &block)
-        subcollections[name].generate
-      end
-
-      def generate
-        operations.values.reject { |op| op.member }.each { |o| o.generate }
-        operations.values.select { |op| op.member }.each { |o| o.generate }
-        app = ::Sinatra::Application
-        collname = name # Work around Ruby's weird scoping/capture
-        app.send(:define_method, "#{name.to_s.singularize}_url") do |id|
-          api_url_for "#{collname}/#{id}", :full
-        end
-        if index_op = operations[:index]
-          app.send(:define_method, "#{name}_url") do
-            api_url_for index_op.path.gsub(/\/\?$/,''), :full
-          end
-        end
-      end
-
-      def check_supported(driver)
-        unless global? || driver.has_collection?(@name) || self.kind_of?(Sinatra::Rabbit::SubCollection)
-          raise UnsupportedCollectionException
-        end
-      end
-    end
-
-    class SubCollection < Collection
-
-      attr_accessor :parent
-
-      def initialize(parent, name, opts={}, &block)
-        self.parent = parent
-        super(name, &block)
-      end
-
-      def operation(name, opts = {}, &block)
-        if @operations.keys.include?(name)
-          raise DuplicateOperationException::new(500, "DuplicateOperation", "Operation #{name} is already defined", [])
-        end
-        # Preserve self as local variable to workaround Ruby namespace
-        # weirdness
-        c = self
-        path_generator = Proc.new do |obj|
-          if obj.member?
-            if obj.standard?
-              "#{parent.name}/:#{parent.name.to_s.singularize}/:#{c.name.to_s.singularize}"
-            else
-              "#{parent.name}/:#{parent.name.to_s.singularize}/:#{c.name.to_s.singularize}/#{name}"
-            end
-          else
-            if obj.form?
-              "#{parent.name}/:id/:#{parent.name.to_s.singularize}/#{obj.name}"
-            else
-              "#{parent.name}/:#{parent.name.to_s.singularize}"
-            end
-          end
-        end
-        opts.merge!({
-          :path_generator => path_generator
-        })
-        @operations[name] = Operation.new(self, name, opts, &block)
-      end
-
-      def generate
-        operations.values.reject { |op| op.member }.each { |o| o.generate }
-        operations.values.select { |op| op.member }.each { |o| o.generate }
-        app = ::Sinatra::Application
-        collname = name # Work around Ruby's weird scoping/capture
-        app.send(:define_method, "#{parent.name.to_s}_#{name.to_s.singularize}_url") do |id, subid|
-          api_url_for "#{collname}/#{id}/#{subid}", :full
-        end
-        if index_op = operations[:index]
-          app.send(:define_method, "#{parent.name.to_s}_#{name}_url") do
-            api_url_for index_op.path.gsub(/\/\?$/,''), :full
-          end
-        end
-      end
-
-    end
-
-    def collections
-      @collections ||= {}
-    end
-
-    # Create a new collection. NAME should be the pluralized name of the
-    # collection.
-    #
-    # Adds a helper method #{name}_url which returns the URL to the :index
-    # operation on this collection.
-    def collection(name, &block)
-      raise DuplicateCollectionException if collections[name]
-      collections[name] = Collection.new(name, &block)
-      collections[name].generate
-    end
-
-    def global_collection(name, &block)
-      raise DuplicateCollectionException if collections[name]
-      collections[name] = Collection.new(name, { :global => true }, &block)
-      collections[name].generate
-    end
-
-    # Make sure this collection can be accessed, regardless of whether the
-    # driver supports it or not
-    def global_collection(name, &block)
-      raise DuplicateCollectionException if collections[name]
-      collections[name] = Collection.new(name, :global => true, &block)
-      collections[name].generate
-    end
-  end
-
-  module RabbitHelper
-    def query_url(url, params)
-      return url if params.nil? || params.empty?
-      url + "?#{URI.escape(params.collect{|k,v| "#{k}=#{v}"}.join('&'))}"
-    end
-
-    def entry_points
-      collections.values.select { |coll|
-        coll.global? || driver.has_collection?(coll.name)
-      }.inject([]) do |m, coll|
-        url = api_url_for coll.operations[:index].path, :full
-        m << [ coll.name, url ]
-      end
-    end
-  end
-
-  register Rabbit
-  helpers RabbitHelper
-end
-
-# In Sinatra < 1.2 there was no helper to create OPTIONS route
-unless Sinatra::Base.respond_to? :options
-  configure do
-    class << Sinatra::Base
-      def options(path, opts={}, &block)
-        route 'OPTIONS', path, opts, &block
-      end
-    end
-    Sinatra::Delegator.delegate :options
-  end
-end
diff --git a/server/lib/sinatra/rack_accept.rb b/server/lib/sinatra/rack_accept.rb
index 2ad52c7..e4a0f1f 100644
--- a/server/lib/sinatra/rack_accept.rb
+++ b/server/lib/sinatra/rack_accept.rb
@@ -12,11 +12,8 @@
 # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
 
-require 'sinatra/base'
 require 'rack/accept'
 
-use Rack::Accept
-
 module Rack
 
   module RespondTo
@@ -26,7 +23,6 @@ module Rack
     # We need to overide the default render method to supply correct path to the
     # template, since Sinatra is by default looking in the current __FILE__ path
     def self.registered(app)
-      app.helpers Rack::RespondTo::Helpers
       app.class_eval do
         alias :render_without_format :render
         def render(*args, &block)
diff --git a/server/lib/sinatra/rack_cimi.rb b/server/lib/sinatra/rack_cimi.rb
deleted file mode 100644
index 6d5ea78..0000000
--- a/server/lib/sinatra/rack_cimi.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-module Rack
-  # Automatically sets the X-CIMI-Specification-Version header on all responses.
-  #
-  class CIMI
-
-    def initialize(app, no_cache_control = nil, cache_control = nil)
-      @app = app
-    end
-
-    def call(env)
-      status, headers, body = @app.call(env)
-      headers['X-CIMI-Specification-Version'] = '0.0.66'
-      [status, headers, body]
-    end
-
-  end
-end
-
diff --git a/server/lib/sinatra/rack_matrix_params.rb b/server/lib/sinatra/rack_matrix_params.rb
index 177e745..0d9339b 100644
--- a/server/lib/sinatra/rack_matrix_params.rb
+++ b/server/lib/sinatra/rack_matrix_params.rb
@@ -51,9 +51,7 @@ module Rack
         while param=sub_components.pop do
           if value
             matrix_params[sub_components.first] ||= {}
-            matrix_params[sub_components.first].merge!(
-                                                       param => value
-                                                       )
+            matrix_params[sub_components.first].merge!(param => value)
             value=nil
             next
           else
diff --git a/server/lib/sinatra/rack_runtime.rb b/server/lib/sinatra/rack_runtime.rb
deleted file mode 100644
index dc56fc7..0000000
--- a/server/lib/sinatra/rack_runtime.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (c) 2008 The Committers
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-module Rack
-  # Sets an "X-Runtime" response header, indicating the response
-  # time of the request, in seconds
-  #
-  # You can put it right before the application to see the processing
-  # time, or before all the other middlewares to include time for them,
-  # too.
-  class Runtime
-    def initialize(app, name = nil)
-      @app = app
-      @header_name = "X-Runtime"
-      @header_name << "-#{name}" if name
-    end
-
-    def call(env)
-      start_time = Time.now
-      status, headers, body = @app.call(env)
-      request_time = Time.now - start_time
-
-      if !headers.has_key?(@header_name)
-        headers[@header_name] = "%0.6f" % request_time
-      end
-
-      [status, headers, body]
-    end
-  end
-end
-
diff --git a/server/lib/sinatra/rack_syslog.rb b/server/lib/sinatra/rack_syslog.rb
deleted file mode 100644
index 5565179..0000000
--- a/server/lib/sinatra/rack_syslog.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-begin
-  require 'syslog'
-  USE_SYSLOG = true
-rescue LoadError => e
-  USE_SYSLOG = false
-end
-
-require 'sinatra/body_proxy'
-
-class SyslogFile < File
-
-  def initialize
-    @log = USE_SYSLOG ? Syslog.open($0, Syslog::LOG_PID | Syslog::LOG_LOCAL5) : Logger.new(STDOUT)
-  end
-
-  def write(string)
-    @log.warning(string) if string.strip.length > 0
-    return string.chars.count
-  end
-
-  def info(msg)
-    @log.info("%s" % msg)
-  end
-
-  def err(msg)
-    @log.err("%s" % msg)
-  end
-
-  alias :warning :err
-
-end
-
-# Code bellow was originaly copied from Rack::CommonLogger
-# https://raw.github.com/rack/rack/master/lib/rack/commonlogger.rb
-
-module Rack
-  # Rack::CommonLogger forwards every request to an +app+ given, and
-  # logs a line in the Apache common log format to the +logger+, or
-  # rack.errors by default.
-  class SyslogLogger
-
-    # Common Log Format: http://httpd.apache.org/docs/1.3/logs.html#common
-    # lilith.local - - [07/Aug/2006 23:58:02] "GET / HTTP/1.1" 500 -
-    #             %{%s - %s [%s] "%s %s%s %s" %d %s\n} %
-    FORMAT = %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f}
-
-    def initialize(app, logger=nil)
-      @app = app
-      @logger = logger || @app.settings.logger || $stdout
-    end
-
-    def call(env)
-      began_at = Time.now
-      status, header, body = @app.call(env)
-      header = Utils::HeaderHash.new(header)
-      body = Rack::BodyProxy.new(body) do
-        log(env, status, header, began_at)
-      end
-      body.close
-      [status, header, body]
-    end
-
-    def log(env, status, header, began_at)
-      now = Time.now
-      length = extract_content_length(header)
-
-      if status.to_s =~ /5(\d{2})/
-        method = :err
-      else
-        method = :info
-      end
-
-      logger = @logger
-      logger.send(method, FORMAT % [
-        env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
-        env["REMOTE_USER"] || "-",
-        now.strftime("%d/%b/%Y %H:%M:%S"),
-        env["REQUEST_METHOD"],
-        env["PATH_INFO"],
-        env["QUERY_STRING"].empty? ? "" : "?"+env["QUERY_STRING"],
-        env["HTTP_VERSION"],
-        status.to_s[0..3],
-        length,
-        now - began_at ])
-    end
-
-    def extract_content_length(headers)
-      value = headers['Content-Length'] or return '-'
-      value.to_s == '0' ? '-' : value
-    end
-  end
-end
-
diff --git a/server/lib/sinatra/sinatra_verbose.rb b/server/lib/sinatra/sinatra_verbose.rb
deleted file mode 100644
index c016ec0..0000000
--- a/server/lib/sinatra/sinatra_verbose.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'sinatra/base'
-
-module Sinatra
-  module VerboseLogger
-
-    module Helpers
-
-      def info(message)
-        puts sprintf("\033[1;34m[INFO: #{caller_method_name}]\033[0m: %s", message.inspect)
-      end
-
-      alias :debug :info
-
-      def warn(message)
-        puts sprintf("\033[1;31m[WARN: #{caller_method_name}]\033[0m: %s", message.inspect)
-      end
-
-      private
-
-      def caller_method_name
-        caller(2).first
-      end
-
-    end
-
-    def enable_verbose_logging!
-      disable :logging
-      before {
-        puts sprintf("\n\033[1;29mProcessing %s\033[0m (for %s at #{Time.now}) [%s] [\033[1;29m%s\033[0m]",
-                     request.path_info, request.ip, request.request_method, driver_name)
-        puts "Parameters: #{params.inspect}"
-        if provider=Thread::current[:provider] || ENV['API_PROVIDER']
-          puts "Provider: #{provider}"
-        end
-        puts "Authentication: #{request.env['HTTP_AUTHORIZATION'].split(' ').first}" if request.env['HTTP_AUTHORIZATION']
-        puts "Server: #{request.env['SERVER_SOFTWARE']}"
-        puts "Accept: #{request.env['HTTP_ACCEPT']}"
-        puts
-      }
-      after {
-        puts sprintf("\nCompleted in \033[1;29m%4f\033[0m | %4f | %s | \033[1;36m%s\033[0m | %s\n",
-                     response.header['X-Backend-Runtime'] || 0, response.header['X-Runtime'] || 0, response.status, response.content_type, request.url)
-      }
-    end
-
-    def self.registered(app)
-      app.helpers VerboseLogger::Helpers
-      app.enable_verbose_logging! if ENV['API_VERBOSE']
-    end
-  end
-end
-
-Sinatra::Application.register Sinatra::VerboseLogger
-
-Deltacloud::BaseDriver.class_eval do
-  include Sinatra::VerboseLogger::Helpers
-end
diff --git a/server/lib/sinatra/static_assets.rb b/server/lib/sinatra/static_assets.rb
deleted file mode 100644
index 5233965..0000000
--- a/server/lib/sinatra/static_assets.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-require 'sinatra/base'
-require 'sinatra/url_for'
-
-module Sinatra
-  module StaticAssets
-    module Helpers
-      # In HTML <link> and <img> tags have no end tag.
-      # In XHTML, on the contrary, these tags must be properly closed.
-      #
-      # We can choose the appropriate behaviour with +closed+ option:
-      #
-      #   image_tag "/images/foo.png", :alt => "Foo itself", :closed => true
-      #
-      # The default value of +closed+ option is +false+.
-      #
-      def image_tag(source, options = {})
-        options[:src] = url_for(source)
-        tag("img", options)
-      end
-
-      def stylesheet_link_tag(*sources)
-        list, options = extract_options(sources)
-        list.collect { |source| stylesheet_tag(source, options) }.join("\n")
-      end
-
-      def javascript_script_tag(*sources)
-        list, options = extract_options(sources)
-        list.collect { |source| javascript_tag(source, options) }.join("\n")
-      end
-
-      def link_to(desc, url, options = {})
-        tag("a", options.merge(:href => url_for(url))) do
-          desc
-        end
-      end
-
-      private
-
-      def tag(name, local_options = {})
-        start_tag = "<#{name}#{tag_options(local_options) if local_options}"
-        if block_given?
-          content = yield
-          "#{start_tag}>#{content}</#{name}>"
-        else
-          "#{start_tag}#{"/" if settings.xhtml}>"
-        end
-      end
-
-      def tag_options(options)
-        unless options.empty?
-          attrs = []
-          attrs = options.map { |key, value| %(#{key}="#{Rack::Utils.escape_html(value)}") }
-          " #{attrs.sort * ' '}" unless attrs.empty?
-        end
-      end
-
-      def stylesheet_tag(source, options = {})
-        tag("link", { :type => "text/css",
-            :charset => "utf-8", :media => "screen", :rel => "stylesheet",
-            :href => url_for(source) }.merge(options))
-      end
-
-      def javascript_tag(source, options = {})
-        tag("script", { :type => "text/javascript", :charset => "utf-8",
-            :src => url_for(source) }.merge(options)) do
-            end
-      end
-
-      def extract_options(a)
-        opts = a.last.is_a?(::Hash) ? a.pop : {}
-        [a, opts]
-      end
-
-    end
-
-    def self.registered(app)
-      app.helpers StaticAssets::Helpers
-      app.disable :xhtml
-    end
-  end
-
-  register StaticAssets
-end
diff --git a/server/lib/sinatra/url_for.rb b/server/lib/sinatra/url_for.rb
deleted file mode 100644
index fba6668..0000000
--- a/server/lib/sinatra/url_for.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-#
-# Based on https://github.com/emk/sinatra-url-for/
-# Commit 1df339284203f8f6ed8d
-#
-# Original license:
-# Copyright (C) 2009 Eric Kidd
-#
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to permit
-# persons to whom the Software is furnished to do so, subject to the
-# following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-# USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-require 'uri'
-
-module Sinatra
-  module UrlForHelper
-
-    def api_url_for(url_fragment, mode=:path_only)
-      matrix_params = ''
-      if request.params['api']
-        matrix_params += ";provider=%s" % request.params['api']['provider'] if request.params['api']['provider']
-        matrix_params += ";driver=%s" % request.params['api']['driver'] if request.params['api']['driver']
-      end
-      url_fragment = "/#{url_fragment}" unless url_fragment =~ /^\// # There is no need to prefix URI with '/'
-      url_for "#{settings.root_url}#{matrix_params}#{url_fragment}", mode
-    end
-
-    # Construct a link to +url_fragment+, which should be given relative to
-    # the base of this Sinatra app.  The mode should be either
-    # <code>:path_only</code>, which will generate an absolute path within
-    # the current domain (the default), or <code>:full</code>, which will
-    # include the site name and port number.  (The latter is typically
-    # necessary for links in RSS feeds.)  Example usage:
-    #
-    #   url_for "/"            # Returns "/myapp/"
-    #   url_for "/foo"         # Returns "/myapp/foo"
-    #   url_for "/foo", :full  # Returns "http://example.com/myapp/foo"
-    #--
-    # See README.rdoc for a list of some of the people who helped me clean
-    # up earlier versions of this code.
-    def url_for url_fragment, mode=:path_only
-      case mode
-      when :path_only
-        base = request.script_name
-      when :full
-        scheme = request.scheme
-        port = request.port
-        request_host = request.host
-        if request.env['HTTP_X_FORWARDED_FOR']
-          scheme = request.env['HTTP_X_FORWARDED_SCHEME'] || scheme
-          port = request.env['HTTP_X_FORWARDED_PORT']
-          request_host = request.env['HTTP_X_FORWARDED_HOST']
-        end
-        if (port.nil? || port == "" ||
-            (scheme == 'http' && port.to_s == '80') ||
-            (scheme == 'https' && port.to_s == '443'))
-          port = ""
-        else
-          port = ":#{port}"
-        end
-        base = "#{scheme}://#{request_host}#{port}#{request.script_name}"
-      else
-        raise TypeError, "Unknown url_for mode #{mode}"
-      end
-      url_escape = URI.escape(url_fragment)
-      # Don't add the base fragment if url_for gets called more than once
-      # per url or the url_fragment passed in is an absolute url
-      if url_escape.match(/^#{base}/) or url_escape.match(/^http/)
-        url_escape
-      else
-        "#{base}#{url_escape}"
-      end
-    end
-  end
-
-
-
-  helpers UrlForHelper
-end
diff --git a/server/tests/drivers/api/api_test.rb b/server/tests/drivers/api/api_test.rb
new file mode 100644
index 0000000..3308365
--- /dev/null
+++ b/server/tests/drivers/api/api_test.rb
@@ -0,0 +1,115 @@
+describe 'Deltacloud API' do
+  include Deltacloud::Test
+
+  it 'return HTTP_OK when accessing API entrypoint' do
+    get API_ROOT_URL
+    last_response.status.must_equal 200
+  end
+
+  it 'advertise the current driver in API entrypoint' do
+    get API_ROOT_URL
+    xml_response.root[:driver].must_equal ENV['API_DRIVER']
+  end
+
+  it 'advertise the current API version in API entrypoint' do
+    get API_ROOT_URL
+    xml_response.root[:version].must_equal API_VERSION
+  end
+
+  it 'advertise the current API version in HTTP headers' do
+    get API_ROOT_URL
+    last_response.headers['Server'].must_equal "Apache-Deltacloud/#{API_VERSION}"
+  end
+
+  it 'must include the ETag in HTTP headers' do
+    get API_ROOT_URL
+    last_response.headers['ETag'].wont_be_nil
+  end
+
+  it 'advertise collections in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link').wont_be_empty
+  end
+
+  it 'include the :href and :rel attribute for each collection in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link').each do |collection|
+      collection[:href].wont_be_nil
+      collection[:rel].wont_be_nil
+    end
+  end
+
+  it 'uses the absolute URI in the :href attribute for each collection in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link').each do |collection|
+      collection[:href].must_match /^http/
+    end
+  end
+
+  it 'advertise features for some collections in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link/feature').wont_be_empty
+  end
+
+  it 'advertise the name of the feature for some collections in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link/feature').each do |f|
+      f[:name].wont_be_nil
+    end
+  end
+
+  it 'must change the media type from XML to JSON using Accept headers' do
+    header 'Accept', 'application/json'
+    get API_ROOT_URL
+    last_response.headers['Content-Type'].must_equal 'application/json'
+  end
+
+  it 'must change the media type to JSON using the "?format" parameter in URL' do
+    get API_ROOT_URL, { :format => 'json' }
+    last_response.headers['Content-Type'].must_equal 'application/json'
+  end
+
+  it 'must change the driver when using X-Deltacloud-Driver HTTP header' do
+    header 'X-Deltacloud-Driver', 'ec2'
+    get API_ROOT_URL
+    xml_response.root[:driver].must_equal 'ec2'
+    header 'X-Deltacloud-Driver', 'mock'
+    get API_ROOT_URL
+    xml_response.root[:driver].must_equal 'mock'
+  end
+
+  it 'must change the features when driver is swapped using HTTP headers' do
+    header 'X-Deltacloud-Driver', 'ec2'
+    get API_ROOT_URL
+    # The 'user_name' feature is not supported currently for the EC2 driver
+    (xml_response/'api/link/feature').map { |f| f[:name] }.wont_include 'user_name'
+    header 'X-Deltacloud-Driver', 'mock'
+    get API_ROOT_URL
+    # But it's supported in Mock driver
+    (xml_response/'api/link/feature').map { |f| f[:name] }.must_include 'user_name'
+  end
+
+  it 'must re-validate the driver credentials when using "?force_auth" parameter in URL' do
+    get API_ROOT_URL, { :force_auth => '1' }
+    last_response.status.must_equal 401
+    auth_as_mock
+    get API_ROOT_URL, { :force_auth => '1' }
+    last_response.status.must_equal 200
+  end
+
+  it 'must change the API PROVIDER using the /api;provider matrix parameter in URI' do
+    get API_ROOT_URL + ';provider=test1'
+    xml_response.root[:provider].wont_be_nil
+    xml_response.root[:provider].must_equal 'test1'
+    get API_ROOT_URL + ';provider=test2'
+    xml_response.root[:provider].must_equal 'test2'
+  end
+
+  it 'must change the API DRIVER using the /api;driver matrix parameter in URI' do
+    get API_ROOT_URL + ';driver=ec2'
+    xml_response.root[:driver].must_equal 'ec2'
+    get API_ROOT_URL + ';driver=mock'
+    xml_response.root[:driver].must_equal 'mock'
+  end
+
+end
diff --git a/server/tests/drivers/api/buckets_test.rb b/server/tests/drivers/api/buckets_test.rb
new file mode 100644
index 0000000..47b8007
--- /dev/null
+++ b/server/tests/drivers/api/buckets_test.rb
@@ -0,0 +1,194 @@
+describe 'Deltacloud API buckets' do
+  include Deltacloud::Test
+
+  it 'must advertise have the buckets collection in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link[@rel=buckets]').wont_be_empty
+  end
+
+  it 'must require authentication to access the "bucket" collection' do
+    get collection_url(:buckets)
+    last_response.status.must_equal 401
+  end
+
+  it 'should respond with HTTP_OK when accessing the :buckets collection with authentication' do
+    auth_as_mock
+    get collection_url(:buckets)
+    last_response.status.must_equal 200
+  end
+
+  it 'should support the JSON media type' do
+    auth_as_mock
+    header 'Accept', 'application/json'
+    get collection_url(:buckets)
+    last_response.status.must_equal 200
+    last_response.headers['Content-Type'].must_equal 'application/json'
+  end
+
+  it 'must include the ETag in HTTP headers' do
+    auth_as_mock
+    get collection_url(:buckets)
+    last_response.headers['ETag'].wont_be_nil
+  end
+
+  it 'must have the "buckets" element on top level' do
+    auth_as_mock
+    get collection_url(:buckets)
+    xml_response.root.name.must_equal 'buckets'
+  end
+
+  it 'must have some "bucket" elements inside "buckets"' do
+    auth_as_mock
+    get collection_url(:buckets)
+    (xml_response/'buckets/bucket').wont_be_empty
+  end
+
+  it 'must provide the :id attribute for each bucket in collection' do
+    auth_as_mock
+    get collection_url(:buckets)
+    (xml_response/'buckets/bucket').each do |r|
+      r[:id].wont_be_nil
+    end
+  end
+
+  it 'must include the :href attribute for each "bucket" element in collection' do
+    auth_as_mock
+    get collection_url(:buckets)
+    (xml_response/'buckets/bucket').each do |r|
+      r[:href].wont_be_nil
+    end
+  end
+
+  it 'must use the absolute URL in each :href attribute' do
+    auth_as_mock
+    get collection_url(:buckets)
+    (xml_response/'buckets/bucket').each do |r|
+      r[:href].must_match /^http/
+    end
+  end
+
+  it 'must have the URL ending with the :id of the bucket' do
+    auth_as_mock
+    get collection_url(:buckets)
+    (xml_response/'buckets/bucket').each do |r|
+      r[:href].must_match /#{r[:id]}$/
+    end
+  end
+
+  it 'must return the list of valid parameters for the :index action' do
+    auth_as_mock
+    options collection_url(:buckets) + '/index'
+    last_response.headers['Allow'].wont_be_nil
+  end
+
+  it 'must have the "name" element defined for each bucket in collection' do
+    auth_as_mock
+    get collection_url(:buckets)
+    (xml_response/'buckets/bucket').each do |r|
+      (r/'name').wont_be_nil
+    end
+  end
+
+  it 'must have the "state" element defined for each bucket in collection' do
+    auth_as_mock
+    get collection_url(:buckets)
+    (xml_response/'buckets/bucket').each do |r|
+      (r/'state').wont_be_nil
+    end
+  end
+
+  it 'must return the full "bucket" when following the URL in bucket element' do
+    auth_as_mock
+    get collection_url(:buckets)
+    (xml_response/'buckets/bucket').each do |r|
+      get collection_url(:buckets) + '/' + r[:id]
+      last_response.status.must_equal 200
+    end
+  end
+
+  it 'must have the "name" element for the bucket and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:buckets)
+    (xml_response/'buckets/bucket').each do |r|
+      get collection_url(:buckets) + '/' + r[:id]
+      (xml_response/'name').wont_be_empty
+      (xml_response/'name').first.text.must_equal((r/'name').first.text)
+    end
+  end
+
+  it 'must have the "size" element for the bucket and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:buckets)
+    (xml_response/'buckets/bucket').each do |r|
+      get collection_url(:buckets) + '/' + r[:id]
+      (xml_response/'size').wont_be_empty
+      (xml_response/'size').first.text.must_equal((r/'size').first.text)
+    end
+  end
+
+  it 'must have the "blob" elements for the bucket and it should match with the ones in collection' do
+    auth_as_mock
+    get collection_url(:buckets)
+    (xml_response/'buckets/bucket').each do |r|
+      get collection_url(:buckets) + '/' + r[:id]
+      (xml_response/'bucket/blob').wont_be_empty
+      (xml_response/'bucket/blob').size.to_s.must_equal (xml_response/'size').first.text
+      (xml_response/'bucket/blob').each do |b|
+        b[:id].wont_be_nil
+        b[:href].wont_be_nil
+        b[:href].must_match /^http/
+        b[:href].must_match /#{r[:id]}\/#{b[:id]}$/
+      end
+    end
+  end
+
+  it 'must have the "blob" elements for the bucket and it should match with the ones in collection' do
+    auth_as_mock
+    get collection_url(:buckets)
+    (xml_response/'buckets/bucket').each do |r|
+      get collection_url(:buckets) + '/' + r[:id]
+      (xml_response/'bucket/blob').wont_be_empty
+      (xml_response/'bucket/blob').size.to_s.must_equal (xml_response/'size').first.text
+      (xml_response/'bucket/blob').each do |b|
+        b[:id].wont_be_nil
+        b[:href].wont_be_nil
+        b[:href].must_match /^http/
+        b[:href].must_match /#{r[:id]}\/#{b[:id]}$/
+      end
+    end
+  end
+
+  it 'must allow to get all blobs details and the details should be set correctly' do
+    auth_as_mock
+    get collection_url(:buckets)
+    (xml_response/'buckets/bucket').each do |r|
+      get collection_url(:buckets) + '/' + r[:id]
+      (xml_response/'bucket/blob').each do |b|
+        get collection_url(:buckets) + '/' + r[:id] + '/' + b[:id]
+        xml_response.root.name.must_equal 'blob'
+        xml_response.root[:id].must_equal b[:id]
+        (xml_response/'bucket').wont_be_empty
+        (xml_response/'bucket').size.must_equal 1
+        (xml_response/'bucket').first[:id].wont_be_nil
+        (xml_response/'bucket').first[:href].wont_be_nil
+        (xml_response/'content_length').wont_be_empty
+        (xml_response/'content_length').size.must_equal 1
+        (xml_response/'content_length').first.text.must_match /^(\d+)$/
+        (xml_response/'content_type').wont_be_empty
+        (xml_response/'content_type').size.must_equal 1
+        (xml_response/'content_type').first.text.wont_be_empty
+        (xml_response/'last_modified').wont_be_empty
+        (xml_response/'last_modified').size.must_equal 1
+        (xml_response/'last_modified').first.text.wont_be_empty
+        (xml_response/'content').wont_be_empty
+        (xml_response/'content').size.must_equal 1
+        (xml_response/'content').first[:rel].wont_be_nil
+        (xml_response/'content').first[:rel].must_equal 'blob_content'
+        (xml_response/'content').first[:href].wont_be_nil
+        (xml_response/'content').first[:href].must_match /^http/
+        (xml_response/'content').first[:href].must_match /\/content$/
+      end
+    end
+  end
+
+end
diff --git a/server/tests/drivers/api/common.rb b/server/tests/drivers/api/common.rb
new file mode 100644
index 0000000..a45c1f4
--- /dev/null
+++ b/server/tests/drivers/api/common.rb
@@ -0,0 +1,58 @@
+unless Kernel.respond_to?(:require_relative)
+  module Kernel
+    def require_relative(path)
+      require File.join(File.dirname(caller[0]), path.to_str)
+    end
+  end
+end
+
+API_ROOT_URL = "/api" unless defined?(API_ROOT_URL)
+API_VERSION = "1.0.0" unless defined?(API_VERSION)
+ENV['API_DRIVER'] ||= 'mock'
+
+ENV['API_USERNAME'] ||= 'mockuser'
+ENV['API_PASSWORD'] ||= 'mockpassword'
+
+require_relative '../../lib/deltacloud/server.rb'
+
+require 'minitest/autorun'
+require 'rack/test'
+require 'nokogiri'
+require 'json'
+
+require 'pp'
+
+module Deltacloud
+  module Test
+    include Rack::Test::Methods
+
+    def included?(sub)
+      sub.class_eval do
+        before do
+          header 'Accept', 'application/xml'
+        end
+      end
+    end
+
+    def xml_response
+      Nokogiri::XML(last_response.body)
+    end
+
+    def auth_as_mock
+      authorize ENV['API_USERNAME'], ENV['API_PASSWORD']
+    end
+
+    def collection_url(collection)
+      [API_ROOT_URL, collection.to_s].join('/')
+    end
+
+    def app
+      Rack::Builder.new {
+        map '/' do
+          use Rack::Static, :urls => ["/stylesheets", "/javascripts"], :root => "public"
+          run Rack::Cascade.new([Deltacloud::API])
+        end
+      }
+    end
+  end
+end
diff --git a/server/tests/drivers/api/drivers_test.rb b/server/tests/drivers/api/drivers_test.rb
new file mode 100644
index 0000000..41c2e66
--- /dev/null
+++ b/server/tests/drivers/api/drivers_test.rb
@@ -0,0 +1,120 @@
+describe 'Deltacloud API drivers' do
+  include Deltacloud::Test
+
+  it 'must advertise have the drivers collection in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link[@rel=drivers]').wont_be_empty
+  end
+
+  it 'must not require authentication to access the "driver" collection' do
+    get collection_url(:drivers)
+    last_response.status.must_equal 200
+  end
+
+  it 'should respond with HTTP_OK when accessing the :drivers collection with authentication' do
+    get collection_url(:drivers)
+    last_response.status.must_equal 200
+  end
+
+  it 'should support the JSON media type' do
+    header 'Accept', 'application/json'
+    get collection_url(:drivers)
+    last_response.status.must_equal 200
+    last_response.headers['Content-Type'].must_equal 'application/json'
+  end
+
+  it 'must include the ETag in HTTP headers' do
+    get collection_url(:drivers)
+    last_response.headers['ETag'].wont_be_nil
+  end
+
+  it 'must have the "drivers" element on top level' do
+    get collection_url(:drivers)
+    xml_response.root.name.must_equal 'drivers'
+  end
+
+  it 'must have some "driver" elements inside "drivers"' do
+    get collection_url(:drivers)
+    (xml_response/'drivers/driver').wont_be_empty
+  end
+
+  it 'must provide the :id attribute for each driver in collection' do
+    get collection_url(:drivers)
+    (xml_response/'drivers/driver').each do |r|
+      r[:id].wont_be_nil
+    end
+  end
+
+  it 'must include the :href attribute for each "driver" element in collection' do
+    get collection_url(:drivers)
+    (xml_response/'drivers/driver').each do |r|
+      r[:href].wont_be_nil
+    end
+  end
+
+  it 'must use the absolute URL in each :href attribute' do
+    get collection_url(:drivers)
+    (xml_response/'drivers/driver').each do |r|
+      r[:href].must_match /^http/
+    end
+  end
+
+  it 'must have the URL ending with the :id of the driver' do
+    get collection_url(:drivers)
+    (xml_response/'drivers/driver').each do |r|
+      r[:href].must_match /#{r[:id]}$/
+    end
+  end
+
+  it 'must return the list of valid parameters for the :index action' do
+    options collection_url(:drivers) + '/index'
+    last_response.headers['Allow'].wont_be_nil
+  end
+
+  it 'must have the "name" element defined for each driver in collection' do
+    get collection_url(:drivers)
+    (xml_response/'drivers/driver').each do |r|
+      (r/'name').wont_be_nil
+    end
+  end
+
+
+  it 'must return the full "driver" when following the URL in driver element' do
+    get collection_url(:drivers)
+    (xml_response/'drivers/driver').each do |r|
+      get collection_url(:drivers) + '/' + r[:id]
+      last_response.status.must_equal 200
+    end
+  end
+
+  it 'must have the "name" element for the driver and it should match with the one in collection' do
+    get collection_url(:drivers)
+    (xml_response/'drivers/driver').each do |r|
+      get collection_url(:drivers) + '/' + r[:id]
+      (xml_response/'name').wont_be_empty
+      (xml_response/'name').first.text.must_equal((r/'name').first.text)
+    end
+  end
+
+  it 'should advertise available providers for some drivers' do
+    get collection_url(:drivers)
+    (xml_response/'drivers/driver/provider').each do |p|
+      p[:id].wont_be_nil
+    end
+  end
+
+  it 'should expose entrypoints for each provider if driver has providers defined' do
+    get collection_url(:drivers)
+    (xml_response/'drivers/driver/provider').each do |p|
+      get collection_url(:drivers) + '/' + p.parent[:id]
+      (xml_response/"driver/provider[@id=#{p[:id]}]").wont_be_empty
+      (xml_response/"driver/provider[@id=#{p[:id]}]").size.must_equal 1
+      (xml_response/"driver/provider[@id=#{p[:id]}]/entrypoint").wont_be_empty
+      (xml_response/"driver/provider[@id=#{p[:id]}]/entrypoint").each do |e|
+        e[:kind].wont_be_nil
+        e.text.wont_be_empty
+      end
+    end
+  end
+
+end
diff --git a/server/tests/drivers/api/hardware_profiles_test.rb b/server/tests/drivers/api/hardware_profiles_test.rb
new file mode 100644
index 0000000..3dad5a8
--- /dev/null
+++ b/server/tests/drivers/api/hardware_profiles_test.rb
@@ -0,0 +1,221 @@
+describe 'Deltacloud API Hardware Profiles' do
+  include Deltacloud::Test
+
+  it 'must advertise have the hardware_profiles collection in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link[@rel=hardware_profiles]').wont_be_empty
+  end
+
+  it 'should respond with HTTP_OK when accessing the :hardware_profiles collection with authentication' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    last_response.status.must_equal 200
+  end
+
+  it 'should support the JSON media type' do
+    auth_as_mock
+    header 'Accept', 'application/json'
+    get collection_url(:hardware_profiles)
+    last_response.status.must_equal 200
+    last_response.headers['Content-Type'].must_equal 'application/json'
+  end
+
+  it 'must include the ETag in HTTP headers' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    last_response.headers['ETag'].wont_be_nil
+  end
+
+  it 'must have the "hardware_profiles" element on top level' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    xml_response.root.name.must_equal 'hardware_profiles'
+  end
+
+  it 'must have some "hardware_profile" elements inside "hardware_profiles"' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').wont_be_empty
+  end
+
+  it 'must provide the :id attribute for each hardware_profile in collection' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      r[:id].wont_be_nil
+    end
+  end
+
+  it 'must include the :href attribute for each "hardware_profile" element in collection' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      r[:href].wont_be_nil
+    end
+  end
+
+  it 'must use the absolute URL in each :href attribute' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      r[:href].must_match /^http/
+    end
+  end
+
+  it 'must have the URL ending with the :id of the hardware_profile' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      r[:href].must_match /#{r[:id]}$/
+    end
+  end
+
+  it 'must return the list of valid parameters for the :index action' do
+    auth_as_mock
+    options collection_url(:hardware_profiles) + '/index'
+    last_response.headers['Allow'].wont_be_nil
+  end
+
+  it 'must have the "name" element defined for each hardware_profile in collection' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      (r/'name').wont_be_empty
+    end
+  end
+
+  it 'should have the "property" element defined if not the opaque hardware_profile' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      next if r[:id] == 'opaque'
+      (r/'property').wont_be_empty
+    end
+  end
+
+  it 'must define the :kind attribute for each "property" ' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      next if r[:id] == 'opaque'
+      (r/'property').each { |p| p[:kind].wont_be_nil }
+    end
+  end
+
+  it 'must define the :name attribute for each "property" ' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      next if r[:id] == 'opaque'
+      (r/'property').each { |p| p[:name].wont_be_nil }
+    end
+  end
+
+  it 'must define the :unit attribute for each "property" ' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      next if r[:id] == 'opaque'
+      (r/'property').each { |p| p[:unit].wont_be_nil }
+    end
+  end
+
+  it 'must define the :value attribute for each "property" ' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      next if r[:id] == 'opaque'
+      (r/'property').each { |p| p[:value].wont_be_nil }
+    end
+  end
+
+  it 'must define the "param" element if property kind is not "fixed"' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      next if r[:id] == 'opaque'
+      (r/'property').each do |p|
+        next if p[:kind] == 'fixed'
+        (p/'param').wont_be_empty
+        (p/'param').size.must_equal 1
+        (p/'param').first[:href].wont_be_nil
+        (p/'param').first[:href].must_match /^http/
+        (p/'param').first[:method].wont_be_nil
+        (p/'param').first[:name].wont_be_nil
+        (p/'param').first[:operation].wont_be_nil
+      end
+    end
+  end
+
+  it 'must provide the list of valid values when the property is defined as "enum"' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      next if r[:id] == 'opaque'
+      (r/'property').each do |p|
+        next if p[:kind] != 'enum'
+        (p/'enum/entry').wont_be_empty
+        (p/'enum/entry').each { |e| e[:value].wont_be_nil }
+      end
+    end
+  end
+
+  it 'must provide the range of valid values when the property is defined as "range"' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      next if r[:id] == 'opaque'
+      (r/'property').each do |p|
+        next if p[:kind] != 'range'
+        (p/'range').wont_be_empty
+        (p/'range').size.must_equal 1
+        (p/'range').first[:first].wont_be_nil
+        (p/'range').first[:last].wont_be_nil
+      end
+    end
+  end
+
+  it 'must provide the default value within the range if property defined as "range"' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      next if r[:id] == 'opaque'
+      (r/'property').each do |p|
+        next if p[:kind] != 'range'
+        ((p/'range').first[:first].to_i..(p/'range').first[:last].to_i).include?(p[:value].to_i).must_equal true
+      end
+    end
+  end
+
+  it 'must provide the default value that is included in enum list if property defined as "enum"' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      next if r[:id] == 'opaque'
+      (r/'property').each do |p|
+        next if p[:kind] != 'enum'
+        (p/'enum/entry').map { |e| e[:value] }.include?(p[:value]).must_equal true
+      end
+    end
+  end
+
+  it 'must return the full "hardware_profile" when following the URL in hardware_profile element' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      get collection_url(:hardware_profiles) + '/' + r[:id]
+      last_response.status.must_equal 200
+    end
+  end
+
+  it 'must have the "name" element for the hardware_profile and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:hardware_profiles)
+    (xml_response/'hardware_profiles/hardware_profile').each do |r|
+      get collection_url(:hardware_profiles) + '/' + r[:id]
+      (xml_response/'name').wont_be_empty
+      (xml_response/'name').first.text.must_equal((r/'name').first.text)
+    end
+  end
+
+end
diff --git a/server/tests/drivers/api/images_test.rb b/server/tests/drivers/api/images_test.rb
new file mode 100644
index 0000000..3faf752
--- /dev/null
+++ b/server/tests/drivers/api/images_test.rb
@@ -0,0 +1,194 @@
+describe 'Deltacloud API Images' do
+  include Deltacloud::Test
+
+  it 'must advertise have the images collection in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link[@rel=images]').wont_be_empty
+  end
+
+  it 'must require authentication to access the "image" collection' do
+    get collection_url(:images)
+    last_response.status.must_equal 401
+  end
+
+  it 'should respond with HTTP_OK when accessing the :images collection with authentication' do
+    auth_as_mock
+    get collection_url(:images)
+    last_response.status.must_equal 200
+  end
+
+  it 'should support the JSON media type' do
+    auth_as_mock
+    header 'Accept', 'application/json'
+    get collection_url(:images)
+    last_response.status.must_equal 200
+    last_response.headers['Content-Type'].must_equal 'application/json'
+  end
+
+  it 'must include the ETag in HTTP headers' do
+    auth_as_mock
+    get collection_url(:images)
+    last_response.headers['ETag'].wont_be_nil
+  end
+
+  it 'must have the "images" element on top level' do
+    auth_as_mock
+    get collection_url(:images)
+    xml_response.root.name.must_equal 'images'
+  end
+
+  it 'must have some "image" elements inside "images"' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').wont_be_empty
+  end
+
+  it 'must provide the :id attribute for each image in collection' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      r[:id].wont_be_nil
+    end
+  end
+
+  it 'must include the :href attribute for each "image" element in collection' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      r[:href].wont_be_nil
+    end
+  end
+
+  it 'must use the absolute URL in each :href attribute' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      r[:href].must_match /^http/
+    end
+  end
+
+  it 'must have the URL ending with the :id of the image' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      r[:href].must_match /#{r[:id]}$/
+    end
+  end
+
+  it 'must return the list of valid parameters for the :index action' do
+    auth_as_mock
+    options collection_url(:images) + '/index'
+    last_response.headers['Allow'].wont_be_nil
+  end
+
+  it 'must have the "name" element defined for each image in collection' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      (r/'name').wont_be_empty
+    end
+  end
+
+  it 'must have the "state" element defined for each image in collection' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      (r/'state').wont_be_empty
+    end
+  end
+
+  it 'must return the full "image" when following the URL in image element' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      get collection_url(:images) + '/' + r[:id]
+      last_response.status.must_equal 200
+    end
+  end
+
+  it 'must have the "name" element for the image and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      get collection_url(:images) + '/' + r[:id]
+      (xml_response/'name').wont_be_empty
+      (xml_response/'name').first.text.must_equal((r/'name').first.text)
+    end
+  end
+
+  it 'must have the "name" element for the image and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      get collection_url(:images) + '/' + r[:id]
+      (xml_response/'state').wont_be_empty
+      (xml_response/'state').first.text.must_equal((r/'state').first.text)
+    end
+  end
+
+  it 'should have the "owner_id" element for each image' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      get collection_url(:images) + '/' + r[:id]
+      (xml_response/'owner_id').wont_be_empty
+    end
+  end
+
+  it 'should have the "description" element for each image' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      get collection_url(:images) + '/' + r[:id]
+      (xml_response/'description').wont_be_empty
+    end
+  end
+
+  it 'should have the "architecture" element for each image' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      get collection_url(:images) + '/' + r[:id]
+      (xml_response/'architecture').wont_be_empty
+    end
+  end
+
+  it 'should include the list of compatible hardware_profiles for each image' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      get collection_url(:images) + '/' + r[:id]
+      (xml_response/'hardware_profiles/hardware_profile').wont_be_empty
+      (xml_response/'hardware_profiles/hardware_profile').each do |hwp|
+        hwp[:href].wont_be_nil
+        hwp[:href].must_match /^http/
+        hwp[:id].wont_be_nil
+        hwp[:href].must_match /\/#{hwp[:id]}$/
+        hwp[:rel].must_equal 'hardware_profile'
+      end
+    end
+  end
+
+  it 'should advertise the list of actions that can be executed for each image' do
+    auth_as_mock
+    get collection_url(:images)
+    (xml_response/'images/image').each do |r|
+      get collection_url(:images) + '/' + r[:id]
+      (xml_response/'actions/link').wont_be_empty
+      (xml_response/'actions/link').each do |l|
+        l[:href].wont_be_nil
+        l[:href].must_match /^http/
+        l[:method].wont_be_nil
+        l[:rel].wont_be_nil
+      end
+    end
+  end
+
+  it 'should give client HTML form to create new image' do
+    auth_as_mock
+    header 'Accept', 'text/html'
+    get collection_url(:images) + '/new'
+    last_response.status.must_equal 200
+  end
+
+end
diff --git a/server/tests/drivers/api/instances_test.rb b/server/tests/drivers/api/instances_test.rb
new file mode 100644
index 0000000..c601a6f
--- /dev/null
+++ b/server/tests/drivers/api/instances_test.rb
@@ -0,0 +1,340 @@
+describe 'Deltacloud API instances' do
+  include Deltacloud::Test
+
+  it 'must advertise have the instances collection in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link[@rel=instances]').wont_be_empty
+  end
+
+  it 'must require authentication to access the "instance" collection' do
+    get collection_url(:instances)
+    last_response.status.must_equal 401
+  end
+
+  it 'should respond with HTTP_OK when accessing the :instances collection with authentication' do
+    auth_as_mock
+    get collection_url(:instances)
+    last_response.status.must_equal 200
+  end
+
+  it 'should support the JSON media type' do
+    auth_as_mock
+    header 'Accept', 'application/json'
+    get collection_url(:instances)
+    last_response.status.must_equal 200
+    last_response.headers['Content-Type'].must_equal 'application/json'
+  end
+
+  it 'must include the ETag in HTTP headers' do
+    auth_as_mock
+    get collection_url(:instances)
+    last_response.headers['ETag'].wont_be_nil
+  end
+
+  it 'must have the "instances" element on top level' do
+    auth_as_mock
+    get collection_url(:instances)
+    xml_response.root.name.must_equal 'instances'
+  end
+
+  it 'must have some "instance" elements inside "instances"' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').wont_be_empty
+  end
+
+  it 'must provide the :id attribute for each instance in collection' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      r[:id].wont_be_nil
+    end
+  end
+
+  it 'must include the :href attribute for each "instance" element in collection' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      r[:href].wont_be_nil
+    end
+  end
+
+  it 'must use the absolute URL in each :href attribute' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      r[:href].must_match /^http/
+    end
+  end
+
+  it 'must have the URL ending with the :id of the instance' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      r[:href].must_match /#{r[:id]}$/
+    end
+  end
+
+  it 'must return the list of valid parameters for the :index action' do
+    auth_as_mock
+    options collection_url(:instances) + '/index'
+    last_response.headers['Allow'].wont_be_nil
+  end
+
+  it 'must have the "name" element defined for each instance in collection' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      (r/'name').wont_be_empty
+    end
+  end
+
+  it 'must have the "state" element defined for each instance in collection' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      (r/'state').wont_be_empty
+      (r/'state').first.must_match /(RUNNING|STOPPED|PENDING)/
+    end
+  end
+
+  it 'must return the full "instance" when following the URL in instance element' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      get collection_url(:instances) + '/' + r[:id]
+      last_response.status.must_equal 200
+    end
+  end
+
+  it 'must have the "name" element for the instance and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      get collection_url(:instances) + '/' + r[:id]
+      (xml_response/'name').wont_be_empty
+      (xml_response/'name').first.text.must_equal((r/'name').first.text)
+    end
+  end
+
+  it 'must have the "name" element for the instance and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      get collection_url(:instances) + '/' + r[:id]
+      (xml_response/'state').wont_be_empty
+      (xml_response/'state').first.text.must_equal((r/'state').first.text)
+    end
+  end
+
+  it 'must have the "owner_id" element for the instance and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      get collection_url(:instances) + '/' + r[:id]
+      (xml_response/'owner_id').wont_be_empty
+      (xml_response/'owner_id').first.text.must_equal((r/'owner_id').first.text)
+    end
+  end
+
+  it 'must link to the realm that was used to during instance creation' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      get collection_url(:instances) + '/' + r[:id]
+      (xml_response/'realm').wont_be_empty
+      (xml_response/'realm').size.must_equal 1
+      (xml_response/'realm').first[:id].wont_be_nil
+      (xml_response/'realm').first[:href].wont_be_nil
+      (xml_response/'realm').first[:href].must_match /\/#{(xml_response/'realm').first[:id]}$/
+    end
+  end
+
+  it 'must link to the image that was used to during instance creation' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      get collection_url(:instances) + '/' + r[:id]
+      (xml_response/'image').wont_be_empty
+      (xml_response/'image').size.must_equal 1
+      (xml_response/'image').first[:id].wont_be_nil
+      (xml_response/'image').first[:href].wont_be_nil
+      (xml_response/'image').first[:href].must_match /\/#{(xml_response/'image').first[:id]}$/
+    end
+  end
+
+  it 'must link to the hardware_profile that was used to during instance creation' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      get collection_url(:instances) + '/' + r[:id]
+      (xml_response/'hardware_profile').wont_be_empty
+      (xml_response/'hardware_profile').size.must_equal 1
+      (xml_response/'hardware_profile').first[:id].wont_be_nil
+      (xml_response/'hardware_profile').first[:href].wont_be_nil
+      (xml_response/'hardware_profile').first[:href].must_match /\/#{(xml_response/'hardware_profile').first[:id]}$/
+    end
+  end
+
+  it 'should advertise the public and private addresses of the instance' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      get collection_url(:instances) + '/' + r[:id]
+      (xml_response/'public_addresses').wont_be_empty
+      (xml_response/'public_addresses').size.must_equal 1
+      (xml_response/'public_addresses/address').each do |a|
+        a[:type].wont_be_nil
+        a.text.strip.wont_be_empty
+      end
+      (xml_response/'private_addresses').wont_be_empty
+      (xml_response/'private_addresses').size.must_equal 1
+      (xml_response/'private_addresses/address').each do |a|
+        a[:type].wont_be_nil
+        a.text.strip.wont_be_empty
+      end
+    end
+  end
+
+  it 'should advertise the storage volumes used by the instance' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      get collection_url(:instances) + '/' + r[:id]
+      (xml_response/'storage_volumes').wont_be_empty
+    end
+  end
+
+  it 'should advertise the list of actions that can be executed for each instance' do
+    auth_as_mock
+    get collection_url(:instances)
+    (xml_response/'instances/instance').each do |r|
+      get collection_url(:instances) + '/' + r[:id]
+      (xml_response/'actions/link').wont_be_empty
+      (xml_response/'actions/link').each do |l|
+        l[:href].wont_be_nil
+        l[:href].must_match /^http/
+        l[:method].wont_be_nil
+        l[:rel].wont_be_nil
+      end
+    end
+  end
+
+  it 'should allow to create and destroy new instance using the first available image without realm' do
+    auth_as_mock
+    get collection_url(:images)
+    image_id = (xml_response/'images/image').first[:id]
+    image_id.wont_be_nil
+    post collection_url(:instances), {
+      :image_id => image_id
+    }
+    last_response.status.must_equal 201 # HTTP_CREATED
+    last_response.headers['Location'].wont_be_nil # Location header must be set, pointing to new the instance
+    instance_id = last_response.headers['Location'].split('/').last
+    # Get the instance and check if ID and image is set correctly
+    get collection_url(:instances) + '/' + instance_id
+    last_response.status.must_equal 200 # HTTP_OK
+    (xml_response/'instance').first[:id].must_equal instance_id
+    (xml_response/'instance/image').first[:id].must_equal image_id
+    # If instance is RUNNING then stop it
+    if (xml_response/'instance/state').first.text == 'RUNNING'
+      post collection_url(:instances) + '/' + instance_id + '/stop'
+      last_response.status.must_equal 202 # HTTP_NO_CONTENT
+    end
+    # Delete created instance
+    delete collection_url(:instances) + '/' + instance_id
+    last_response.status.must_equal 204 # HTTP_NO_CONTENT
+  end
+
+  it 'should allow to create and destroy new instance using the first available image within first realm' do
+    auth_as_mock
+    get collection_url(:images)
+    image_id = (xml_response/'images/image').first[:id]
+    get collection_url(:realms)
+    realm_id = (xml_response/'realms/realm').first[:id]
+    image_id.wont_be_nil
+    realm_id.wont_be_nil
+    post collection_url(:instances), {
+      :image_id => image_id,
+      :realm_id => realm_id,
+    }
+    last_response.status.must_equal 201 # HTTP_CREATED
+    last_response.headers['Location'].wont_be_nil # Location header must be set, pointing to new the instance
+    instance_id = last_response.headers['Location'].split('/').last
+    # Get the instance and check if ID and image is set correctly
+    get collection_url(:instances) + '/' + instance_id
+    last_response.status.must_equal 200 # HTTP_OK
+    (xml_response/'instance').first[:id].must_equal instance_id
+    (xml_response/'instance/image').first[:id].must_equal image_id
+    (xml_response/'instance/realm').first[:id].must_equal realm_id
+    # If instance is RUNNING then stop it
+    if (xml_response/'instance/state').first.text == 'RUNNING'
+      post collection_url(:instances) + '/' + instance_id + '/stop'
+      last_response.status.must_equal 202 # HTTP_NO_CONTENT
+    end
+    # Delete created instance
+    delete collection_url(:instances) + '/' + instance_id
+    last_response.status.must_equal 204 # HTTP_NO_CONTENT
+  end
+
+  it 'should allow to create and destroy new instance using the first available image with user defined name' do
+    auth_as_mock
+    get collection_url(:images)
+    image_id = (xml_response/'images/image').first[:id]
+    image_id.wont_be_nil
+    name = "i#{Time.now.to_i}"
+    post collection_url(:instances), {
+      :image_id => image_id,
+      :name => name
+    }
+    last_response.status.must_equal 201 # HTTP_CREATED
+    last_response.headers['Location'].wont_be_nil # Location header must be set, pointing to new the instance
+    instance_id = last_response.headers['Location'].split('/').last
+    # Get the instance and check if ID and image is set correctly
+    get collection_url(:instances) + '/' + instance_id
+    last_response.status.must_equal 200 # HTTP_OK
+    (xml_response/'instance').first[:id].must_equal instance_id
+    (xml_response/'instance/image').first[:id].must_equal image_id
+    (xml_response/'instance/name').first.text.must_equal name
+    # If instance is RUNNING then stop it
+    if (xml_response/'instance/state').first.text == 'RUNNING'
+      post collection_url(:instances) + '/' + instance_id + '/stop'
+      last_response.status.must_equal 202 # HTTP_NO_CONTENT
+    end
+    # Delete created instance
+    delete collection_url(:instances) + '/' + instance_id
+    last_response.status.must_equal 204 # HTTP_NO_CONTENT
+  end
+
+  it 'should allow to create and destroy new instance using the first available image and first hardware_profile' do
+    auth_as_mock
+    get collection_url(:images)
+    image_id = (xml_response/'images/image').first[:id]
+    get collection_url(:hardware_profiles)
+    hwp_id = (xml_response/'hardware_profiles/hardware_profile').first[:id]
+    image_id.wont_be_nil
+    name = "i#{Time.now.to_i}"
+    post collection_url(:instances), {
+      :image_id => image_id,
+      :hwp_id => hwp_id
+    }
+    last_response.status.must_equal 201 # HTTP_CREATED
+    last_response.headers['Location'].wont_be_nil # Location header must be set, pointing to new the instance
+    instance_id = last_response.headers['Location'].split('/').last
+    # Get the instance and check if ID and image is set correctly
+    get collection_url(:instances) + '/' + instance_id
+    last_response.status.must_equal 200 # HTTP_OK
+    (xml_response/'instance').first[:id].must_equal instance_id
+    (xml_response/'instance/image').first[:id].must_equal image_id
+    (xml_response/'instance/hardware_profile').first[:id].must_equal hwp_id
+    # If instance is RUNNING then stop it
+    if (xml_response/'instance/state').first.text == 'RUNNING'
+      post collection_url(:instances) + '/' + instance_id + '/stop'
+      last_response.status.must_equal 202 # HTTP_NO_CONTENT
+    end
+    # Delete created instance
+    delete collection_url(:instances) + '/' + instance_id
+    last_response.status.must_equal 204 # HTTP_NO_CONTENT
+  end
+
+end
diff --git a/server/tests/drivers/api/keys_test.rb b/server/tests/drivers/api/keys_test.rb
new file mode 100644
index 0000000..9267b5a
--- /dev/null
+++ b/server/tests/drivers/api/keys_test.rb
@@ -0,0 +1,158 @@
+describe 'Deltacloud API Keys' do
+  include Deltacloud::Test
+
+  it 'must advertise have the keys collection in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link[@rel=keys]').wont_be_empty
+  end
+
+  it 'must require authentication to access the "key" collection' do
+    get collection_url(:keys)
+    last_response.status.must_equal 401
+  end
+
+  it 'should respond with HTTP_OK when accessing the :keys collection with authentication' do
+    auth_as_mock
+    get collection_url(:keys)
+    last_response.status.must_equal 200
+  end
+
+  it 'should support the JSON media type' do
+    auth_as_mock
+    header 'Accept', 'application/json'
+    get collection_url(:keys)
+    last_response.status.must_equal 200
+    last_response.headers['Content-Type'].must_equal 'application/json'
+  end
+
+  it 'must include the ETag in HTTP headers' do
+    auth_as_mock
+    get collection_url(:keys)
+    last_response.headers['ETag'].wont_be_nil
+  end
+
+  it 'must have the "keys" element on top level' do
+    auth_as_mock
+    get collection_url(:keys)
+    xml_response.root.name.must_equal 'keys'
+  end
+
+  it 'must have some "key" elements inside "keys"' do
+    auth_as_mock
+    get collection_url(:keys)
+    (xml_response/'keys/key').wont_be_empty
+  end
+
+  it 'must tell the kind of "key" elements inside "keys"' do
+    auth_as_mock
+    get collection_url(:keys)
+    (xml_response/'keys/key').each do |k|
+      k[:type].must_match /(key|password)/
+    end
+  end
+
+  it 'must provide the :id attribute for each key in collection' do
+    auth_as_mock
+    get collection_url(:keys)
+    (xml_response/'keys/key').each do |r|
+      r[:id].wont_be_nil
+    end
+  end
+
+  it 'must include the :href attribute for each "key" element in collection' do
+    auth_as_mock
+    get collection_url(:keys)
+    (xml_response/'keys/key').each do |r|
+      r[:href].wont_be_nil
+    end
+  end
+
+  it 'must use the absolute URL in each :href attribute' do
+    auth_as_mock
+    get collection_url(:keys)
+    (xml_response/'keys/key').each do |r|
+      r[:href].must_match /^http/
+    end
+  end
+
+  it 'must have the URL ending with the :id of the key' do
+    auth_as_mock
+    get collection_url(:keys)
+    (xml_response/'keys/key').each do |r|
+      r[:href].must_match /#{r[:id]}$/
+    end
+  end
+
+  it 'must return the list of valid parameters for the :index action' do
+    auth_as_mock
+    options collection_url(:keys) + '/index'
+    last_response.headers['Allow'].wont_be_nil
+  end
+
+  it 'must have the "name" element defined for each key in collection' do
+    auth_as_mock
+    get collection_url(:keys)
+    (xml_response/'keys/key').each do |r|
+      (r/'name').wont_be_empty
+    end
+  end
+
+
+  it 'must return the full "key" when following the URL in key element' do
+    auth_as_mock
+    get collection_url(:keys)
+    (xml_response/'keys/key').each do |r|
+      get collection_url(:keys) + '/' + r[:id]
+      last_response.status.must_equal 200
+    end
+  end
+
+  it 'must have the "name" element for the key and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:keys)
+    (xml_response/'keys/key').each do |r|
+      get collection_url(:keys) + '/' + r[:id]
+      (xml_response/'name').wont_be_empty
+      (xml_response/'name').first.text.must_equal((r/'name').first.text)
+    end
+  end
+
+  it 'must have the "name" element for the key and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:keys)
+    (xml_response/'keys/key').each do |r|
+      get collection_url(:keys) + '/' + r[:id]
+      (xml_response/'state').wont_be_empty
+      (xml_response/'state').first.text.must_equal((r/'state').first.text)
+    end
+  end
+
+  it 'should advertise the list of actions that can be executed for each key' do
+    auth_as_mock
+    get collection_url(:keys)
+    (xml_response/'keys/key').each do |r|
+      get collection_url(:keys) + '/' + r[:id]
+      (xml_response/'actions/link').wont_be_empty
+      (xml_response/'actions/link').each do |l|
+        l[:href].wont_be_nil
+        l[:href].must_match /^http/
+        l[:method].wont_be_nil
+        l[:rel].wont_be_nil
+      end
+    end
+  end
+
+  it 'should allow to create a new key and then remove it' do
+    auth_as_mock
+    key_name = Time.now.to_i.to_s
+    post collection_url(:keys), {
+      :name => 'test_key_'+key_name
+    }
+    last_response.status.must_equal 201 # HTTP_CREATED
+    get collection_url(:keys) + '/' + 'test_key_'+key_name
+    last_response.status.must_equal 200 # HTTP_OK
+    delete collection_url(:keys) + '/' + 'test_key_'+key_name
+    last_response.status.must_equal 204 # HTTP_NO_CONTENT
+  end
+
+end
diff --git a/server/tests/drivers/api/realms_test.rb b/server/tests/drivers/api/realms_test.rb
new file mode 100644
index 0000000..6bc9101
--- /dev/null
+++ b/server/tests/drivers/api/realms_test.rb
@@ -0,0 +1,129 @@
+describe 'Deltacloud API Realms' do
+  include Deltacloud::Test
+
+  it 'must advertise have the realms collection in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link[@rel=realms]').wont_be_empty
+  end
+
+  it 'must require authentication to access the "realm" collection' do
+    get collection_url(:realms)
+    last_response.status.must_equal 401
+  end
+
+  it 'should respond with HTTP_OK when accessing the :realms collection with authentication' do
+    auth_as_mock
+    get collection_url(:realms)
+    last_response.status.must_equal 200
+  end
+
+  it 'should support the JSON media type' do
+    auth_as_mock
+    header 'Accept', 'application/json'
+    get collection_url(:realms)
+    last_response.status.must_equal 200
+    last_response.headers['Content-Type'].must_equal 'application/json'
+  end
+
+  it 'must include the ETag in HTTP headers' do
+    auth_as_mock
+    get collection_url(:realms)
+    last_response.headers['ETag'].wont_be_nil
+  end
+
+  it 'must have the "realms" element on top level' do
+    auth_as_mock
+    get collection_url(:realms)
+    xml_response.root.name.must_equal 'realms'
+  end
+
+  it 'must have some "realm" elements inside "realms"' do
+    auth_as_mock
+    get collection_url(:realms)
+    (xml_response/'realms/realm').wont_be_empty
+  end
+
+  it 'must provide the :id attribute for each realm in collection' do
+    auth_as_mock
+    get collection_url(:realms)
+    (xml_response/'realms/realm').each do |r|
+      r[:id].wont_be_nil
+    end
+  end
+
+  it 'must include the :href attribute for each "realm" element in collection' do
+    auth_as_mock
+    get collection_url(:realms)
+    (xml_response/'realms/realm').each do |r|
+      r[:href].wont_be_nil
+    end
+  end
+
+  it 'must use the absolute URL in each :href attribute' do
+    auth_as_mock
+    get collection_url(:realms)
+    (xml_response/'realms/realm').each do |r|
+      r[:href].must_match /^http/
+    end
+  end
+
+  it 'must have the URL ending with the :id of the realm' do
+    auth_as_mock
+    get collection_url(:realms)
+    (xml_response/'realms/realm').each do |r|
+      r[:href].must_match /#{r[:id]}$/
+    end
+  end
+
+  it 'must return the list of valid parameters for the :index action' do
+    auth_as_mock
+    options collection_url(:realms) + '/index'
+    last_response.headers['Allow'].wont_be_nil
+  end
+
+  it 'must have the "name" element defined for each realm in collection' do
+    auth_as_mock
+    get collection_url(:realms)
+    (xml_response/'realms/realm').each do |r|
+      (r/'name').wont_be_empty
+    end
+  end
+
+  it 'must have the "state" element defined for each realm in collection' do
+    auth_as_mock
+    get collection_url(:realms)
+    (xml_response/'realms/realm').each do |r|
+      (r/'state').wont_be_empty
+    end
+  end
+
+  it 'must return the full "realm" when following the URL in realm element' do
+    auth_as_mock
+    get collection_url(:realms)
+    (xml_response/'realms/realm').each do |r|
+      get collection_url(:realms) + '/' + r[:id]
+      last_response.status.must_equal 200
+    end
+  end
+
+  it 'must have the "name" element for the realm and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:realms)
+    (xml_response/'realms/realm').each do |r|
+      get collection_url(:realms) + '/' + r[:id]
+      (xml_response/'name').wont_be_empty
+      (xml_response/'name').first.text.must_equal((r/'name').first.text)
+    end
+  end
+
+  it 'must have the "state" element for the realm and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:realms)
+    (xml_response/'realms/realm').each do |r|
+      get collection_url(:realms) + '/' + r[:id]
+      (xml_response/'state').wont_be_empty
+      (xml_response/'state').first.text.must_equal((r/'state').first.text)
+    end
+  end
+
+end
diff --git a/server/tests/drivers/api/storage_snapshots_test.rb b/server/tests/drivers/api/storage_snapshots_test.rb
new file mode 100644
index 0000000..52ea847
--- /dev/null
+++ b/server/tests/drivers/api/storage_snapshots_test.rb
@@ -0,0 +1,111 @@
+describe 'Deltacloud API storage_snapshots' do
+  include Deltacloud::Test
+
+  it 'must advertise have the storage_snapshots collection in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link[@rel=storage_snapshots]').wont_be_empty
+  end
+
+  it 'must require authentication to access the "storage_snapshot" collection' do
+    get collection_url(:storage_snapshots)
+    last_response.status.must_equal 401
+  end
+
+  it 'should respond with HTTP_OK when accessing the :storage_snapshots collection with authentication' do
+    auth_as_mock
+    get collection_url(:storage_snapshots)
+    last_response.status.must_equal 200
+  end
+
+  it 'should support the JSON media type' do
+    auth_as_mock
+    header 'Accept', 'application/json'
+    get collection_url(:storage_snapshots)
+    last_response.status.must_equal 200
+    last_response.headers['Content-Type'].must_equal 'application/json'
+  end
+
+  it 'must include the ETag in HTTP headers' do
+    auth_as_mock
+    get collection_url(:storage_snapshots)
+    last_response.headers['ETag'].wont_be_nil
+  end
+
+  it 'must have the "storage_snapshots" element on top level' do
+    auth_as_mock
+    get collection_url(:storage_snapshots)
+    xml_response.root.name.must_equal 'storage_snapshots'
+  end
+
+  it 'must have some "storage_snapshot" elements inside "storage_snapshots"' do
+    auth_as_mock
+    get collection_url(:storage_snapshots)
+    (xml_response/'storage_snapshots/storage_snapshot').wont_be_empty
+  end
+
+  it 'must provide the :id attribute for each storage_snapshot in collection' do
+    auth_as_mock
+    get collection_url(:storage_snapshots)
+    (xml_response/'storage_snapshots/storage_snapshot').each do |r|
+      r[:id].wont_be_nil
+    end
+  end
+
+  it 'must include the :href attribute for each "storage_snapshot" element in collection' do
+    auth_as_mock
+    get collection_url(:storage_snapshots)
+    (xml_response/'storage_snapshots/storage_snapshot').each do |r|
+      r[:href].wont_be_nil
+    end
+  end
+
+  it 'must use the absolute URL in each :href attribute' do
+    auth_as_mock
+    get collection_url(:storage_snapshots)
+    (xml_response/'storage_snapshots/storage_snapshot').each do |r|
+      r[:href].must_match /^http/
+    end
+  end
+
+  it 'must have the URL ending with the :id of the storage_snapshot' do
+    auth_as_mock
+    get collection_url(:storage_snapshots)
+    (xml_response/'storage_snapshots/storage_snapshot').each do |r|
+      r[:href].must_match /#{r[:id]}$/
+    end
+  end
+
+  it 'must return the list of valid parameters for the :index action' do
+    auth_as_mock
+    options collection_url(:storage_snapshots) + '/index'
+    last_response.headers['Allow'].wont_be_nil
+  end
+
+  it 'must have the "name" element defined for each storage_snapshot in collection' do
+    auth_as_mock
+    get collection_url(:storage_snapshots)
+    (xml_response/'storage_snapshots/storage_snapshot').each do |r|
+      (r/'name').wont_be_empty
+    end
+  end
+
+  it 'must return the full "storage_snapshot" when following the URL in storage_snapshot element' do
+    auth_as_mock
+    get collection_url(:storage_snapshots)
+    (xml_response/'storage_snapshots/storage_snapshot').each do |r|
+      get collection_url(:storage_snapshots) + '/' + r[:id]
+      last_response.status.must_equal 200
+    end
+  end
+
+  it 'must have the "name" element for the storage_snapshot and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:storage_snapshots)
+    (xml_response/'storage_snapshots/storage_snapshot').each do |r|
+      get collection_url(:storage_snapshots) + '/' + r[:id]
+      (xml_response/'name').wont_be_empty
+      (xml_response/'name').first.text.must_equal((r/'name').first.text)
+    end
+  end
+
+end
diff --git a/server/tests/drivers/api/storage_volumes_test.rb b/server/tests/drivers/api/storage_volumes_test.rb
new file mode 100644
index 0000000..cbafd5d
--- /dev/null
+++ b/server/tests/drivers/api/storage_volumes_test.rb
@@ -0,0 +1,119 @@
+describe 'Deltacloud API storage_volumes' do
+  include Deltacloud::Test
+
+  it 'must advertise have the storage_volumes collection in API entrypoint' do
+    get API_ROOT_URL
+    (xml_response/'api/link[@rel=storage_volumes]').wont_be_empty
+  end
+
+  it 'must require authentication to access the "storage_volume" collection' do
+    get collection_url(:storage_volumes)
+    last_response.status.must_equal 401
+  end
+
+  it 'should respond with HTTP_OK when accessing the :storage_volumes collection with authentication' do
+    auth_as_mock
+    get collection_url(:storage_volumes)
+    last_response.status.must_equal 200
+  end
+
+  it 'should support the JSON media type' do
+    auth_as_mock
+    header 'Accept', 'application/json'
+    get collection_url(:storage_volumes)
+    last_response.status.must_equal 200
+    last_response.headers['Content-Type'].must_equal 'application/json'
+  end
+
+  it 'must include the ETag in HTTP headers' do
+    auth_as_mock
+    get collection_url(:storage_volumes)
+    last_response.headers['ETag'].wont_be_nil
+  end
+
+  it 'must have the "storage_volumes" element on top level' do
+    auth_as_mock
+    get collection_url(:storage_volumes)
+    xml_response.root.name.must_equal 'storage_volumes'
+  end
+
+  it 'must have some "storage_volume" elements inside "storage_volumes"' do
+    auth_as_mock
+    get collection_url(:storage_volumes)
+    (xml_response/'storage_volumes/storage_volume').wont_be_empty
+  end
+
+  it 'must provide the :id attribute for each storage_volume in collection' do
+    auth_as_mock
+    get collection_url(:storage_volumes)
+    (xml_response/'storage_volumes/storage_volume').each do |r|
+      r[:id].wont_be_nil
+    end
+  end
+
+  it 'must include the :href attribute for each "storage_volume" element in collection' do
+    auth_as_mock
+    get collection_url(:storage_volumes)
+    (xml_response/'storage_volumes/storage_volume').each do |r|
+      r[:href].wont_be_nil
+    end
+  end
+
+  it 'must use the absolute URL in each :href attribute' do
+    auth_as_mock
+    get collection_url(:storage_volumes)
+    (xml_response/'storage_volumes/storage_volume').each do |r|
+      r[:href].must_match /^http/
+    end
+  end
+
+  it 'must have the URL ending with the :id of the storage_volume' do
+    auth_as_mock
+    get collection_url(:storage_volumes)
+    (xml_response/'storage_volumes/storage_volume').each do |r|
+      r[:href].must_match /#{r[:id]}$/
+    end
+  end
+
+  it 'must return the list of valid parameters for the :index action' do
+    auth_as_mock
+    options collection_url(:storage_volumes) + '/index'
+    last_response.headers['Allow'].wont_be_nil
+  end
+
+  it 'must have the "name" element defined for each storage_volume in collection' do
+    auth_as_mock
+    get collection_url(:storage_volumes)
+    (xml_response/'storage_volumes/storage_volume').each do |r|
+      (r/'name').wont_be_empty
+    end
+  end
+
+  it 'must have the "state" element defined for each storage_volume in collection' do
+    auth_as_mock
+    get collection_url(:storage_volumes)
+    (xml_response/'storage_volumes/storage_volume').each do |r|
+      (r/'state').wont_be_empty
+    end
+  end
+
+  it 'must return the full "storage_volume" when following the URL in storage_volume element' do
+    auth_as_mock
+    get collection_url(:storage_volumes)
+    (xml_response/'storage_volumes/storage_volume').each do |r|
+      get collection_url(:storage_volumes) + '/' + r[:id]
+      last_response.status.must_equal 200
+    end
+  end
+
+  it 'must have the "name" element for the storage_volume and it should match with the one in collection' do
+    auth_as_mock
+    get collection_url(:storage_volumes)
+    (xml_response/'storage_volumes/storage_volume').each do |r|
+      get collection_url(:storage_volumes) + '/' + r[:id]
+      (xml_response/'name').wont_be_empty
+      (xml_response/'name').first.text.must_equal((r/'name').first.text)
+    end
+  end
+
+end
diff --git a/server/views/api/show.html.haml b/server/views/api/show.html.haml
index 265739d..66d1f3a 100644
--- a/server/views/api/show.html.haml
+++ b/server/views/api/show.html.haml
@@ -3,10 +3,11 @@
 
 %div{ :'data-role' => :content, :'data-theme' => 'c'}
   %ul{ :'data-role' => :listview, :'data-inset' => 'true'}
-    - @collections.sort_by { |k| k.to_s }.each do |key|
-      %li= link_to key.to_s.gsub('_', ' ').titlecase, api_url_for(key), :'data-icon' => "arrow-r", :'data-ajax' => false
+    - Deltacloud.collections.each do |c|
+      - next unless c.operation(:index).has_capability?
+      %li= link_to c.collection_name.to_s.gsub('_', ' ').titlecase, api_url_for(c.collection_name), :'data-icon' => "arrow-r", :'data-ajax' => false
 
-- if @providers.size > 1
+- unless driver.configured_providers.empty?
   %div{ :'data-role' => :footer, :'data-theme' => 'a'}
     %form{ :action => settings.root_url, :method => :post, :'data-ajax' => 'false'}
       - if @driver_name
diff --git a/server/views/api/show.xml.haml b/server/views/api/show.xml.haml
index 2b9f653..ad2df09 100644
--- a/server/views/api/show.xml.haml
+++ b/server/views/api/show.xml.haml
@@ -1,7 +1,6 @@
-%api{ :version => settings.version, :driver => driver_symbol }
-  - for entry_point in entry_points
-    %link{ :rel=>entry_point[0], :href=>entry_point[1] }
-      - for feature in driver.features(entry_point[0])
-        %feature{ :name=>feature.name }
-          - for name,value in feature.constraints
-            %constraint{ :name=>name, :value=>value }
+%api{ :version => settings.version, :driver => driver_symbol, :provider => Thread.current[:provider] || ENV['API_PROVIDER'] }
+  - Deltacloud.collections.each do |c|
+    - next unless c.operation(:index).has_capability?
+    %link{ :rel => c.collection_name, :href => self.send(:"#{c.collection_name}_url")}
+      - c.features.select { |f| driver.class.has_feature?(c.collection_name, f.name) }.each do |f|
+        %feature{ :name => f.name }
diff --git a/server/views/blobs/show.xml.haml b/server/views/blobs/show.xml.haml
index 34b9cca..bde9e80 100644
--- a/server/views/blobs/show.xml.haml
+++ b/server/views/blobs/show.xml.haml
@@ -1,11 +1,14 @@
 !!! XML
 %blob{:href => bucket_url(@blob.bucket) + '/' + @blob.id, :id => @blob.id}
+  %bucket{ :id => @blob.bucket, :href => bucket_url(@blob.bucket)}
   - @blob.attributes.select{ |attr| (attr!=:id && attr!=:user_metadata) }.each do |attribute|
+    - next if attribute == :bucket
     - unless attribute == :content
       - haml_tag(attribute, :<) do
         - haml_concat @blob.send(attribute)
   %user_metadata
-    - @blob.user_metadata.each do |k, v|
-      %entry{:key => k}
-        #{cdata v}
-  %content{:href => bucket_url(@blob.bucket) + '/' + @blob.id + '/content'}
+    - if @blob.user_metadata.respond_to? :each
+      - @blob.user_metadata.each do |k, v|
+        %entry{:key => k}
+          #{cdata v}
+  %content{:href => bucket_url(@blob.bucket) + '/' + @blob.id + '/content', :rel => 'blob_content'}
diff --git a/server/views/hardware_profiles/index.html.haml b/server/views/hardware_profiles/index.html.haml
index 64e3455..59d43eb 100644
--- a/server/views/hardware_profiles/index.html.haml
+++ b/server/views/hardware_profiles/index.html.haml
@@ -3,7 +3,7 @@
 
 %div{ :'data-role' => :content, :'data-theme' => 'c'}
   %ul{ :'data-role' => :listview, :'data-inset' => :true }
-    - for profile in @profiles
+    - for profile in @hardware_profiles
       %li{ :'data-theme' => 'c'}
         %a{ :href => hardware_profile_url(profile.name)}
           %img{ :class => 'ui-link-thumb', :src => '/images/profile.png'}
diff --git a/server/views/hardware_profiles/index.xml.haml b/server/views/hardware_profiles/index.xml.haml
index cf0a69f..25e0496 100644
--- a/server/views/hardware_profiles/index.xml.haml
+++ b/server/views/hardware_profiles/index.xml.haml
@@ -1,4 +1,4 @@
 !!! XML
 %hardware_profiles
-  - @profiles.each do |prof|
-    = haml :'hardware_profiles/show', :locals => { :@profile => prof, :partial => true }
+  - @hardware_profiles.each do |prof|
+    = haml :'hardware_profiles/show', :locals => { :@hardware_profile => prof, :partial => true }
diff --git a/server/views/hardware_profiles/show.html.haml b/server/views/hardware_profiles/show.html.haml
index c27690e..033e94d 100644
--- a/server/views/hardware_profiles/show.html.haml
+++ b/server/views/hardware_profiles/show.html.haml
@@ -1,12 +1,12 @@
 =header "Hardware profiles"
-=subheader @profile.name
+=subheader @hardware_profile.name
 
 %div{ :'data-role' => :content, :'data-theme' => 'c'}
   %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'd'}
     %li{ :'data-role' => 'list-divider'} Name
     %li
-      %p{ :'data-role' => 'fieldcontain'}=@profile.name
-    - @profile.each_property do |p|
+      %p{ :'data-role' => 'fieldcontain'}=@hardware_profile.name
+    - @hardware_profile.each_property do |p|
       %li{ :'data-role' => 'list-divider'} #{p.name.to_s.titlecase}
       %li
         %p{ :'data-role' => 'fieldcontain'}
diff --git a/server/views/hardware_profiles/show.xml.haml b/server/views/hardware_profiles/show.xml.haml
index 094ffd5..21e488c 100644
--- a/server/views/hardware_profiles/show.xml.haml
+++ b/server/views/hardware_profiles/show.xml.haml
@@ -1,9 +1,9 @@
 - unless defined?(partial)
   !!! XML
-%hardware_profile{ :href => hardware_profile_url(@profile.name), :id => @profile.name }
+%hardware_profile{ :href => hardware_profile_url(@hardware_profile.name), :id => @hardware_profile.name }
   %name<
-    =@profile.name
-  - @profile.each_property do |prop|
+    = @hardware_profile.name
+  - @hardware_profile.each_property do |prop|
     - attr = { :name => prop.name, :kind => prop.kind, :unit => prop.unit }
     - if prop.kind == :fixed
       %property{ attr, :value => prop.value }/
diff --git a/server/views/instances/new.html.haml b/server/views/instances/new.html.haml
index 2347022..4d466d6 100644
--- a/server/views/instances/new.html.haml
+++ b/server/views/instances/new.html.haml
@@ -21,53 +21,9 @@
   %form{ :action => instances_url, :method => :post, :class => :new_instance, :'data-ajax' => 'false'}
     %input{ :name => :image_id, :type => :hidden, :value => @instance.image_id }/
 
-    - if driver_has_feature?(:user_name)
-      %div{ 'data-role' => :fieldcontain }
-        %label{ :for => :name} Instance name:
-        %input{ :type => :text, :id => :name, :name => :name, :value => '' }
-
-    %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
-      %h3 Additional parameters
-
-      - if driver_has_feature?(:user_data)
-        %div{ 'data-role' => :fieldcontain }
-          %label{ :for => :user_data} Base64 encoded user-data:
-          %textarea{ :id => :user_data, :name => :user_data, :value => '' }
-          %br/
-          %a{ :href => "", :onclick => 'encodeb64();', :'data-ajax' => 'false'} Encode data
-
-      - if driver_has_feature?(:instance_count)
-        %div{ 'data-role' => :fieldcontain }
-          %label{ :for => :instance_count} # of instances to be launched:
-          %input{ :type => :text, :id => :instance_count, :name => :instance_count, :value => '1' }
-
-      - if driver_has_feature?(:authentication_key)
-        %div{ 'data-role' => :fieldcontain }
-          %label{ :for => :keyname, :class => 'ui-input-text'} Instance SSH key:
-          %select{:name => 'keyname', :'data-native-menu' => "true" }
-            %option{ :value => ''} None
-            - @keys.each do |key|
-              %option{ :value => key.id } #{key.id}
-
-      - if driver_has_feature?(:register_to_load_balancer)
-        %div{ 'data-role' => :fieldcontain }
-          %label{ :for => :load_balancer_id, :class => 'ui-input-text'} Register to loadbalancer:
-          %select{:name => 'load_balancer_id', :'data-native-menu' => "true" }
-            %option{ :value => ''} None
-            - @load_balancers.each do |load_balancer|
-              %option{:value => load_balancer.id} #{load_balancer.id}
-
-      - if driver_has_feature?(:firewalls)
-        %div{ 'data-role' => :fieldcontain }
-          %fieldset{ :'data-role' => 'controlgroup'}
-            %legend Register to firewall:
-            - @firewalls.each_index do |i|
-              - if @firewalls[i].name == 'default'
-                %input{:type => :checkbox, :value => @firewalls[i].name, :name => "firewalls#{i}", :checked => :true, :id => "firewalls#{i}"}/
-                %label{:for => "firewalls#{i}"} Default
-              - else
-                %input{:type => :checkbox, :value => @firewalls[i].name, :name => "firewalls#{i}", :id => "firewalls#{i}"}/
-                %label{:for => "firewalls#{i}"}=@firewalls[i].name
+    %div{ 'data-role' => :fieldcontain }
+      %label{ :for => :name} Instance name:
+      %input{ :type => :text, :id => :name, :name => :name, :value => '' }
 
     - if !@hardware_profiles.empty?
       %div{ 'data-role' => :fieldcontain }
diff --git a/server/views/instances/show.xml.haml b/server/views/instances/show.xml.haml
index b2fd5bf..c9ee237 100644
--- a/server/views/instances/show.xml.haml
+++ b/server/views/instances/show.xml.haml
@@ -45,16 +45,4 @@
     %storage_volumes<
       - @instance.storage_volumes.each do |volume|
         %storage_volume{:href=> storage_volume_url(volume.keys.first), :id => volume.keys.first, :device => volume.values.first}
-  - if driver_has_auth_features?
-    %authentication{ :type => driver_auth_feature_name }
-      - if @instance.authn_feature_failed?
-        %error  #{@instance.authn_error}
-      - else
-        - if @instance.password
-          %login
-            %username #{@instance.username}
-            %password=cdata(@instance.password)
-        - if @instance.keyname
-          %login
-            %keyname #{@instance.keyname}
 
diff --git a/server/views/keys/show.xml.haml b/server/views/keys/show.xml.haml
index abb513b..2e98d0d 100644
--- a/server/views/keys/show.xml.haml
+++ b/server/views/keys/show.xml.haml
@@ -1,6 +1,7 @@
 - unless defined?(partial)
   !!! XML
 %key{ :href => key_url(@key.id), :id => @key.id, :type => "#{@key.credential_type}" }
+  %name=@key.name
   %actions
     - if driver.respond_to?(:destroy_key)
       %link{ :rel => "destroy", :method => "delete", :href => destroy_key_url(@key.id)}
diff --git a/server/views/storage_snapshots/show.xml.haml b/server/views/storage_snapshots/show.xml.haml
index c151c1e..a47a652 100644
--- a/server/views/storage_snapshots/show.xml.haml
+++ b/server/views/storage_snapshots/show.xml.haml
@@ -1,9 +1,7 @@
 - unless defined?(partial)
   !!! XML
 %storage_snapshot{:href => storage_snapshot_url(@storage_snapshot.id), :id => @storage_snapshot.id }
+  %name=@storage_snapshot.id
   %created<
     =@storage_snapshot.created
   %storage_volume{:href => storage_volume_url(@storage_snapshot.storage_volume_id), :id => @storage_snapshot.storage_volume_id}
-  %actions
-    - if driver.respond_to? :destroy_storage_snapshot
-      %link{:rel => :destroy, :method => :delete, :href => destroy_storage_snapshot_url(@storage_snapshot.id)}
diff --git a/server/views/storage_volumes/show.html.haml b/server/views/storage_volumes/show.html.haml
index aabdd85..1c1f458 100644
--- a/server/views/storage_volumes/show.html.haml
+++ b/server/views/storage_volumes/show.html.haml
@@ -4,6 +4,7 @@
 %div{ :'data-role' => :content, :'data-theme' => 'c'}
   %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'd'}
     %li{ :'data-role' => 'list-divider'} Name
+    %p{ :'data-role' => 'fieldcontain'}=@storage_volume.id
     %li
       %p{ :'data-role' => 'fieldcontain'}=@storage_volume.id
     %li{ :'data-role' => 'list-divider'} Created
diff --git a/server/views/storage_volumes/show.xml.haml b/server/views/storage_volumes/show.xml.haml
index 440609b..f9f5f25 100644
--- a/server/views/storage_volumes/show.xml.haml
+++ b/server/views/storage_volumes/show.xml.haml
@@ -9,9 +9,8 @@
   - if @storage_volume.kind
     %kind<
       = @storage_volume.kind
-  - if @storage_volume.name
-    %name<
-      = @storage_volume.name
+  %name<
+    = @storage_volume.name || @storage_volume.id
   - if @storage_volume.device
     %device<
       = @storage_volume.device
-- 
1.7.10


Mime
View raw message