You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by lu...@redhat.com on 2013/03/14 01:33:32 UTC
RFC: Separate CIMI (de)serialization from server functionality (rev 3)
This is the third take on splitting server-side functionality out of our
models. As in previous attempts, CIMI::Model is now solely concerned with
(se)serialization, whereas CIMI::Service does all the actual server-side
functionality.
FWIW, the unit and blackbox tests all pass for me with this patch series
...
Also recorded as http://tracker.deltacloud.org/set/389
David
[PATCH 08/14] CIMI: Migrated service methods from CIMI::Model to CIMI::Service
Posted by lu...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>
---
server/lib/cimi/models/action.rb | 4 -
server/lib/cimi/models/address.rb | 38 -------
server/lib/cimi/models/address_create.rb | 31 ------
server/lib/cimi/models/address_template.rb | 47 ---------
server/lib/cimi/models/address_template_create.rb | 16 ---
server/lib/cimi/models/cloud_entry_point.rb | 28 ------
server/lib/cimi/models/credential.rb | 34 -------
server/lib/cimi/models/credential_create.rb | 26 -----
server/lib/cimi/models/credential_template.rb | 2 -
server/lib/cimi/models/disk.rb | 56 -----------
server/lib/cimi/models/forwarding_group.rb | 8 --
.../lib/cimi/models/forwarding_group_template.rb | 8 --
server/lib/cimi/models/machine_configuration.rb | 31 ------
server/lib/cimi/models/machine_create.rb | 30 +-----
server/lib/cimi/models/machine_image_create.rb | 19 ----
server/lib/cimi/models/machine_template.rb | 35 -------
server/lib/cimi/models/machine_template_create.rb | 12 ---
server/lib/cimi/models/machine_volume.rb | 65 ------------
server/lib/cimi/models/network.rb | 32 ------
server/lib/cimi/models/network_configuration.rb | 15 ---
server/lib/cimi/models/network_create.rb | 23 -----
server/lib/cimi/models/network_port.rb | 73 --------------
.../lib/cimi/models/network_port_configuration.rb | 8 --
server/lib/cimi/models/network_port_template.rb | 8 --
server/lib/cimi/models/network_template.rb | 10 --
server/lib/cimi/models/resource_metadata.rb | 90 +----------------
server/lib/cimi/models/system.rb | 52 +++-------
server/lib/cimi/models/system_template.rb | 44 +++------
server/lib/cimi/models/volume.rb | 59 -----------
server/lib/cimi/models/volume_configuration.rb | 63 ------------
server/lib/cimi/models/volume_create.rb | 38 -------
server/lib/cimi/models/volume_image.rb | 30 ------
server/lib/cimi/models/volume_image_create.rb | 25 -----
server/lib/cimi/models/volume_template.rb | 41 --------
server/lib/cimi/models/volume_template_create.rb | 12 ---
server/lib/cimi/service.rb | 35 +++++++
server/lib/cimi/service/action.rb | 21 ++++
server/lib/cimi/service/address.rb | 56 +++++++++++
server/lib/cimi/service/address_create.rb | 45 +++++++++
server/lib/cimi/service/address_template.rb | 71 +++++++++++++
server/lib/cimi/service/address_template_create.rb | 34 +++++++
server/lib/cimi/service/cloud_entry_point.rb | 46 +++++++++
server/lib/cimi/service/credential.rb | 52 ++++++++++
server/lib/cimi/service/credential_create.rb | 38 +++++++
server/lib/cimi/service/credential_template.rb | 20 ++++
server/lib/cimi/service/disk.rb | 80 +++++++++++++++
server/lib/cimi/service/forwarding_group.rb | 26 +++++
.../lib/cimi/service/forwarding_group_template.rb | 26 +++++
server/lib/cimi/service/machine.rb | 14 +--
server/lib/cimi/service/machine_configuration.rb | 54 ++++++++++
server/lib/cimi/service/machine_create.rb | 49 +++++++++
server/lib/cimi/service/machine_image.rb | 6 +-
server/lib/cimi/service/machine_image_create.rb | 35 +++++++
server/lib/cimi/service/machine_template.rb | 61 ++++++++++++
server/lib/cimi/service/machine_template_create.rb | 29 ++++++
server/lib/cimi/service/machine_volume.rb | 74 ++++++++++++++
server/lib/cimi/service/network.rb | 51 ++++++++++
server/lib/cimi/service/network_configuration.rb | 36 +++++++
server/lib/cimi/service/network_create.rb | 39 ++++++++
server/lib/cimi/service/network_port.rb | 97 ++++++++++++++++++
.../lib/cimi/service/network_port_configuration.rb | 26 +++++
server/lib/cimi/service/network_port_template.rb | 26 +++++
server/lib/cimi/service/network_template.rb | 28 ++++++
server/lib/cimi/service/resource_metadata.rb | 110 +++++++++++++++++++++
server/lib/cimi/service/system.rb | 45 +++++++++
server/lib/cimi/service/system_template.rb | 32 ++++++
server/lib/cimi/service/volume.rb | 81 +++++++++++++++
server/lib/cimi/service/volume_configuration.rb | 92 +++++++++++++++++
server/lib/cimi/service/volume_create.rb | 47 +++++++++
server/lib/cimi/service/volume_image.rb | 44 +++++++++
server/lib/cimi/service/volume_image_create.rb | 42 ++++++++
server/lib/cimi/service/volume_template.rb | 61 ++++++++++++
server/lib/cimi/service/volume_template_create.rb | 29 ++++++
73 files changed, 1779 insertions(+), 1092 deletions(-)
create mode 100644 server/lib/cimi/service/action.rb
create mode 100644 server/lib/cimi/service/address.rb
create mode 100644 server/lib/cimi/service/address_create.rb
create mode 100644 server/lib/cimi/service/address_template.rb
create mode 100644 server/lib/cimi/service/address_template_create.rb
create mode 100644 server/lib/cimi/service/cloud_entry_point.rb
create mode 100644 server/lib/cimi/service/credential.rb
create mode 100644 server/lib/cimi/service/credential_create.rb
create mode 100644 server/lib/cimi/service/credential_template.rb
create mode 100644 server/lib/cimi/service/disk.rb
create mode 100644 server/lib/cimi/service/forwarding_group.rb
create mode 100644 server/lib/cimi/service/forwarding_group_template.rb
create mode 100644 server/lib/cimi/service/machine_configuration.rb
create mode 100644 server/lib/cimi/service/machine_create.rb
create mode 100644 server/lib/cimi/service/machine_image_create.rb
create mode 100644 server/lib/cimi/service/machine_template.rb
create mode 100644 server/lib/cimi/service/machine_template_create.rb
create mode 100644 server/lib/cimi/service/machine_volume.rb
create mode 100644 server/lib/cimi/service/network.rb
create mode 100644 server/lib/cimi/service/network_configuration.rb
create mode 100644 server/lib/cimi/service/network_create.rb
create mode 100644 server/lib/cimi/service/network_port.rb
create mode 100644 server/lib/cimi/service/network_port_configuration.rb
create mode 100644 server/lib/cimi/service/network_port_template.rb
create mode 100644 server/lib/cimi/service/network_template.rb
create mode 100644 server/lib/cimi/service/resource_metadata.rb
create mode 100644 server/lib/cimi/service/system.rb
create mode 100644 server/lib/cimi/service/system_template.rb
create mode 100644 server/lib/cimi/service/volume.rb
create mode 100644 server/lib/cimi/service/volume_configuration.rb
create mode 100644 server/lib/cimi/service/volume_create.rb
create mode 100644 server/lib/cimi/service/volume_image.rb
create mode 100644 server/lib/cimi/service/volume_image_create.rb
create mode 100644 server/lib/cimi/service/volume_template.rb
create mode 100644 server/lib/cimi/service/volume_template_create.rb
diff --git a/server/lib/cimi/models/action.rb b/server/lib/cimi/models/action.rb
index c1c9908..c83913e 100644
--- a/server/lib/cimi/models/action.rb
+++ b/server/lib/cimi/models/action.rb
@@ -17,8 +17,4 @@ 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
index 57e8be1..453e688 100644
--- a/server/lib/cimi/models/address.rb
+++ b/server/lib/cimi/models/address.rb
@@ -39,42 +39,4 @@ class CIMI::Model::Address < CIMI::Model::Base
scalar :rel, :href
end
- def self.find(id, context)
- if id==:all
- addresses = context.driver.addresses(context.credentials)
- addresses.map{|addr| from_address(addr, context)}
- else
- address = context.driver.address(context.credentials, {:id=>id})
- from_address(address, context)
- end
- end
-
- def self.delete!(id, context)
- context.driver.delete_address(context.credentials, id)
- new(:id => id).destroy
- end
-
- private
-
- def self.from_address(address, context)
- self.new(
- :name => address.id,
- :id => context.address_url(address.id),
- :description => "Address #{address.id}",
- :ip => address.id,
- :allocation => "dynamic",
- :default_gateway => "unknown",
- :dns => "unknown",
- :protocol => protocol_from_address(address.id),
- :mask => "unknown",
- :resource => (address.instance_id) ? {:href=> context.machine_url(address.instance_id)} : nil,
- :network => nil
- )
- end
-
- def self.protocol_from_address(address)
- addr = IPAddr.new(address)
- addr.ipv4? ? "ipv4" : "ipv6"
- end
-
end
diff --git a/server/lib/cimi/models/address_create.rb b/server/lib/cimi/models/address_create.rb
index cf321ce..ffa08c4 100644
--- a/server/lib/cimi/models/address_create.rb
+++ b/server/lib/cimi/models/address_create.rb
@@ -17,35 +17,4 @@ class CIMI::Model::AddressCreate < CIMI::Model::Base
ref :address_template, :required => true
- def create(context)
- validate!
-
- if address_template.href?
- template = address_template.find(context)
- end
-
- params = {
- :name => name,
- :description => description,
- :address_template => template,
- :env => context # FIXME: We should not pass the context to the driver (!)
- }
-
- unless context.driver.respond_to? :create_address
- raise Deltacloud::Exceptions.exception_from_status(
- 501,
- "Creating Address is not supported by the current driver"
- )
- end
-
- address = context.driver.create_address(context.credentials, params)
-
- result = CIMI::Model::Address.from_address(address, context)
- result.name = name if name
- result.description = description if description
- result.property = property if property
- result.save
- result
- end
-
end
diff --git a/server/lib/cimi/models/address_template.rb b/server/lib/cimi/models/address_template.rb
index 9b5000b..bc66ccc 100644
--- a/server/lib/cimi/models/address_template.rb
+++ b/server/lib/cimi/models/address_template.rb
@@ -24,51 +24,4 @@ class CIMI::Model::AddressTemplate < CIMI::Model::Base
array :operations do
scalar :rel, :href
end
-
- def self.find(id, context)
- if id==:all
- if context.driver.respond_to? :address_templates
- context.driver.address_templates(context.credentials, {:env=>context})
- else
- current_db.address_templates.map { |t| from_db(t, context) }
- end
- else
- if context.driver.respond_to? :address_templates
- context.driver.address_templates(context.credentials, {:id=>id, :env=>context})
- else
- template = current_db.address_templates_dataset.first(:id => id)
- raise CIMI::Model::NotFound unless template
- from_db(template, context)
- end
- end
- end
-
- def self.delete!(id, context)
- current_db.address_templates.first(:id => id).destroy
- end
-
- private
-
- def self.from_db(model, context)
- self.new(
- :id => context.address_template_url(model.id),
- :name => model.name,
- :description => model.description,
- :ip => model.ip,
- :hostname => model.hostname,
- :allocation => model.allocation,
- :default_gateway => model.default_gateway,
- :dns => model.dns,
- :protocol => model.protocol,
- :mask => model.mask,
- :property => (model.ent_properties ? JSON::parse(model.ent_properties) : nil),
- :operations => [
- {
- :href => context.destroy_address_template_url(model.id),
- :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
- }
- ]
- )
- end
-
end
diff --git a/server/lib/cimi/models/address_template_create.rb b/server/lib/cimi/models/address_template_create.rb
index e9ce3d3..601154d 100644
--- a/server/lib/cimi/models/address_template_create.rb
+++ b/server/lib/cimi/models/address_template_create.rb
@@ -25,20 +25,4 @@ class CIMI::Model::AddressTemplateCreate < CIMI::Model::Base
href :network
- def create(context)
- validate!
- new_template = context.current_db.add_address_template(
- :name => name,
- :description => description,
- :hostname => hostname,
- :ip => ip,
- :allocation => allocation,
- :default_gateway => default_gateway,
- :dns => dns,
- :protocol => protocol,
- :mask => mask,
- :ent_properties => property.to_json
- )
- CIMI::Model::AddressTemplate.from_db(new_template, context)
- end
end
diff --git a/server/lib/cimi/models/cloud_entry_point.rb b/server/lib/cimi/models/cloud_entry_point.rb
index 6c28e53..a016004 100644
--- a/server/lib/cimi/models/cloud_entry_point.rb
+++ b/server/lib/cimi/models/cloud_entry_point.rb
@@ -37,34 +37,6 @@ class CIMI::Model::CloudEntryPoint < CIMI::Model::Base
href coll.underscore
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",
- :driver => context.driver.name,
- :provider => context.current_provider,
- :id => context.cloudEntryPoint_url,
- :base_uri => context.base_uri + "/",
- :created => Time.now.xmlschema
- }))
- end
-
- # Return an Hash of the CIMI root entities used in CloudEntryPoint
- def self.entities(context)
- CIMI::Collections.modules(:cimi).inject({}) do |supported_entities, m|
- m.collections.each do |c|
- index_operation_capability = c.operation(:index).required_capability
- next if m.settings.respond_to?(:capability) and !m.settings.capability(index_operation_capability)
- supported_entities[c.collection_name.to_s] = { :href => context.send(:"#{c.collection_name}_url") }
- end
- supported_entities
- end
- end
-
- def entities
- @attribute_values.clone.delete_if { |key, value| !value.respond_to? :href }
- end
-
private
def self.href_defined?(resource)
diff --git a/server/lib/cimi/models/credential.rb b/server/lib/cimi/models/credential.rb
index 872248f..e16d64a 100644
--- a/server/lib/cimi/models/credential.rb
+++ b/server/lib/cimi/models/credential.rb
@@ -25,38 +25,4 @@ class CIMI::Model::Credential < CIMI::Model::Base
scalar :rel, :href
end
- def self.find(id, context)
- if id == :all
- return [] unless context.driver.respond_to?(:keys)
- 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)
- credential = Credential.from_xml(body)
- key = context.driver.create_key(context.credentials, :key_name => credential.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.credential_url(key.id),
- :created => Time.now.xmlschema
- )
- end
-
end
diff --git a/server/lib/cimi/models/credential_create.rb b/server/lib/cimi/models/credential_create.rb
index 6479769..c02d68e 100644
--- a/server/lib/cimi/models/credential_create.rb
+++ b/server/lib/cimi/models/credential_create.rb
@@ -17,30 +17,4 @@ class CIMI::Model::CredentialCreate < CIMI::Model::Base
ref :credential_template, :required => true
- def create(context)
- validate!
-
- unless context.driver.respond_to? :create_key
- raise Deltacloud::Exceptions.exception_from_status(
- 501,
- "Creating Credential is not supported by the current driver"
- )
- end
-
- if credential_template.href?
- template = credential_template.find(ctx)
- else
- template = credential_template
- end
-
- key = context.driver.create_key(context.credentials, :key_name => name)
-
- result = CIMI::Model::Credential.from_key(key, context)
- result.name = name if name
- result.description = description if description
- result.property = property if property
- result.save
- result
-
- end
end
diff --git a/server/lib/cimi/models/credential_template.rb b/server/lib/cimi/models/credential_template.rb
index 1148c42..c263cef 100644
--- a/server/lib/cimi/models/credential_template.rb
+++ b/server/lib/cimi/models/credential_template.rb
@@ -19,6 +19,4 @@ class CIMI::Model::CredentialTemplate < CIMI::Model::Base
text :password, :required => true
text :key, :required => true
- # TODO: tbd
-
end
diff --git a/server/lib/cimi/models/disk.rb b/server/lib/cimi/models/disk.rb
index c725721..b358568 100644
--- a/server/lib/cimi/models/disk.rb
+++ b/server/lib/cimi/models/disk.rb
@@ -22,60 +22,4 @@ class CIMI::Model::Disk < CIMI::Model::Base
scalar :rel, :href
end
- def self.find(instance, machine_config, context, id=:all)
- if id == :all
- name = instance.id+"_disk_" #assuming one disk for now...
-
- if machine_config
- mach_config_disks = machine_config.disks
- return mach_config_disks.map do |d|
- self.new(
- :id => context.machine_url(instance.id) + "/disks/#{name}#{d[:capacity]}",
- :name => "#{name}#{d[:capacity]}",
- :description => "Disk for Machine #{instance.id}",
- :created => instance.launch_time.nil? ? Time.now.xmlschema : Time.parse(instance.launch_time).xmlschema,
- :capacity => d[:capacity]
- )
- end
- else
- if instance.instance_profile.override? :storage
- capacity = context.to_kibibyte(instance.instance_profile.storage, 'MB')
- else
- hw_profile = context.driver.hardware_profile(context.credentials, :id => instance.instance_profile.name)
- if hw_profile.storage
- capacity = context.to_kibibyte(hw_profile.storage.value, 'MB')
- end
- end
-
- return [] unless capacity
-
- [self.new(
- :id => context.machine_url(instance.id)+"/disks/#{name}#{capacity}",
- :name => name + capacity.to_s,
- :description => "Disk for Machine #{instance.id}",
- :created => instance.launch_time.nil? ? Time.now.xmlschema : Time.parse(instance.launch_time).xmlschema,
- :capacity => capacity
- )]
- end
- else
- end
- end
-
- def self.collection_for_instance(instance_id, context)
- instance = context.driver.instance(context.credentials, :id => instance_id)
- disks = find(instance, nil, context)
- unless CIMI::Model.const_defined?('DiskCollection')
- collection_class = CIMI::Model::Collection.generate(self)
- else
- collection_class = CIMI::Model::DiskCollection
- end
- collection_class.new(
- :id => context.url("/machines/#{instance_id}/disks"),
- :name => 'default',
- :count => disks.size,
- :description => "Disk collection for Machine #{instance_id}",
- :entries => disks
- )
- end
-
end
diff --git a/server/lib/cimi/models/forwarding_group.rb b/server/lib/cimi/models/forwarding_group.rb
index 221c0b2..ea55de5 100644
--- a/server/lib/cimi/models/forwarding_group.rb
+++ b/server/lib/cimi/models/forwarding_group.rb
@@ -25,12 +25,4 @@ class CIMI::Model::ForwardingGroup < CIMI::Model::Base
scalar :rel, :href
end
- def self.find(id, context)
- if id==:all
- context.driver.forwarding_groups(context.credentials, {:env=>context})
- else
- context.driver.forwarding_groups(context.credentials, {:env=>context, :id=>id})
- end
- end
-
end
diff --git a/server/lib/cimi/models/forwarding_group_template.rb b/server/lib/cimi/models/forwarding_group_template.rb
index fca2f71..ae4c280 100644
--- a/server/lib/cimi/models/forwarding_group_template.rb
+++ b/server/lib/cimi/models/forwarding_group_template.rb
@@ -25,12 +25,4 @@ class CIMI::Model::ForwardingGroupTemplate < CIMI::Model::Base
scalar :rel, :href
end
- def self.find(id, context)
- if id==:all
- context.driver.forwarding_group_templates(context.credentials, {:env=>context})
- else
- context.driver.forwarding_group_templates(context.credentials, {:env=>context, :id=>id})
- end
- end
-
end
diff --git a/server/lib/cimi/models/machine_configuration.rb b/server/lib/cimi/models/machine_configuration.rb
index 69c9eb5..5226582 100644
--- a/server/lib/cimi/models/machine_configuration.rb
+++ b/server/lib/cimi/models/machine_configuration.rb
@@ -30,35 +30,4 @@ class CIMI::Model::MachineConfiguration < CIMI::Model::Base
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 ? context.to_kibibyte((profile.memory.value || profile.memory.default), profile.memory.unit) : nil
- cpu = (profile.cpu ? (profile.cpu.value || profile.cpu.default) : nil )
- storage = profile.storage ? context.to_kibibyte((profile.storage.value || profile.storage.default), profile.storage.unit) : nil
- machine_hash = {
- :name => profile.name,
- :description => "Machine Configuration with #{memory} KiB "+
- "of memory and #{cpu} CPU",
- :cpu => ( cpu.to_i.to_s if cpu ) ,
- :created => Time.now.xmlschema, # FIXME: DC hardware_profile has no mention about created_at
- :memory => (memory if memory),
- :disks => ( [ { :capacity => storage, :format => (profile.storage.respond_to?(:format) ? profile.storage.format : "unknown") } ] if storage ), #no format attr for hwp - may be added if providers support...,
- :id => context.machine_configuration_url(profile.id)
- }
- self.new(machine_hash)
- end
-
end
diff --git a/server/lib/cimi/models/machine_create.rb b/server/lib/cimi/models/machine_create.rb
index 0f04c01..3b3e0d9 100644
--- a/server/lib/cimi/models/machine_create.rb
+++ b/server/lib/cimi/models/machine_create.rb
@@ -14,36 +14,8 @@
# under the License.
class CIMI::Model::MachineCreate < CIMI::Model::Base
+
ref :machine_template
text :realm
- def create(ctx)
- params = {}
- if machine_template.href
- template = machine_template.find(ctx)
- params[:hwp_id] = template.machine_config.ref_id(ctx)
- params[:initial_state] = template.initial_state
- image_id = template.machine_image.ref_id(ctx)
- else
- # FIXME: What if either of these href's isn't there ? What if the user
- # tries to override some aspect of the machine_config/machine_image ?
- params[:hwp_id] = machine_template.machine_config.href.split('/').last
- params[:initial_state] = machine_template.initial_state
- image_id = machine_template.machine_image.href.split('/').last
- if machine_template.credential.href
- params[:keyname] = machine_template.credential.href.split('/').last
- end
- end
-
- params[:name] = name if name
- params[:realm_id] = realm if realm
- instance = ctx.driver.create_instance(ctx.credentials, image_id, params)
-
- result = CIMI::Model::Machine::from_instance(instance, ctx)
- result.name = name if name
- result.description = description if description
- result.property = property if property
- result.save
- result
- end
end
diff --git a/server/lib/cimi/models/machine_image_create.rb b/server/lib/cimi/models/machine_image_create.rb
index 365d640..890241d 100644
--- a/server/lib/cimi/models/machine_image_create.rb
+++ b/server/lib/cimi/models/machine_image_create.rb
@@ -19,23 +19,4 @@ class CIMI::Model::MachineImageCreate < CIMI::Model::Base
text :image_location, :required => true
href :related_image
- def create(context)
- validate!
-
- params = {
- :id => context.href_id(image_location, :machines),
- :name => name,
- :description => description
- }
-
- img = context.driver.create_image(context.credentials, params)
-
- result = CIMI::Model::MachineImage.from_image(img, context)
- result.name = name if name
- result.description = description if description
- result.property = property if property
- result.save
- result
- end
-
end
diff --git a/server/lib/cimi/models/machine_template.rb b/server/lib/cimi/models/machine_template.rb
index eed8fa9..812ad15 100644
--- a/server/lib/cimi/models/machine_template.rb
+++ b/server/lib/cimi/models/machine_template.rb
@@ -43,39 +43,4 @@ class CIMI::Model::MachineTemplate < CIMI::Model::Base
scalar :rel, :href
end
- class << self
- def find(id, context)
- if id == :all
- current_db.machine_templates.map { |t| from_db(t, context) }
- else
- template = current_db.machine_templates_dataset.first(:id => id)
- raise CIMI::Model::NotFound unless template
- from_db(template, context)
- end
- end
-
- def delete!(id, context)
- current_db.machine_templates.first(:id => id).destroy
- end
-
- def from_db(model, context)
- self.new(
- :id => context.machine_template_url(model.id),
- :name => model.name,
- :description => model.description,
- :machine_config => { :href => model.machine_config },
- :machine_image => { :href => model.machine_image },
- :realm => model.realm,
- :property => (model.ent_properties ? JSON::parse(model.ent_properties) : nil),
- :created => Time.parse(model.created_at.to_s).xmlschema,
- :operations => [
- {
- :href => context.destroy_machine_template_url(model.id),
- :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
- }
- ]
- )
- end
- end
-
end
diff --git a/server/lib/cimi/models/machine_template_create.rb b/server/lib/cimi/models/machine_template_create.rb
index 5e5e411..4d46b79 100644
--- a/server/lib/cimi/models/machine_template_create.rb
+++ b/server/lib/cimi/models/machine_template_create.rb
@@ -18,16 +18,4 @@ class CIMI::Model::MachineTemplateCreate < CIMI::Model::Base
href :machine_config, :required => true
href :machine_image, :required => true
- def create(context)
- validate!
- new_template = self.class.current_db.add_machine_template(
- :name => name,
- :description => description,
- :machine_config => machine_config.href,
- :machine_image => machine_image.href,
- :ent_properties => property.to_json
- )
- CIMI::Model::MachineTemplate.from_db(new_template, context)
- end
-
end
diff --git a/server/lib/cimi/models/machine_volume.rb b/server/lib/cimi/models/machine_volume.rb
index 7631138..50b8b76 100644
--- a/server/lib/cimi/models/machine_volume.rb
+++ b/server/lib/cimi/models/machine_volume.rb
@@ -22,69 +22,4 @@ class CIMI::Model::MachineVolume < CIMI::Model::Base
scalar :rel, :href
end
- def self.find(instance_id, context, id=:all)
- if id == :all
- volumes = context.driver.storage_volumes(context.credentials)
- volumes.inject([]) do |attached, vol|
- id = context.machine_url(instance_id)+"/volumes/#{vol.id}"
- attached << self.new(
- :id => id,
- :name => vol.id,
- :description => "MachineVolume #{vol.id} for Machine #{instance_id}",
- :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
- :initial_location => vol.device,
- :volume => {:href=>context.volume_url(vol.id)},
- :operations => [{:href=>id, :rel => "delete" }]
- ) if vol.instance_id == instance_id
- attached
- end
- else
- vol = context.driver.storage_volume(context.credentials, {:id=>id})
- id = context.machine_url(instance_id)+"/volumes/#{vol.id}"
- raise CIMI::Model::NotFound unless vol.instance_id == instance_id
- self.new(
- :id => id,
- :name => vol.id,
- :description => "MachineVolume #{vol.id} for Machine #{instance_id}",
- :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
- :initial_location => vol.device,
- :volume => {:href=>context.volume_url(vol.id)},
- :operations => [{:href=>id, :rel => "delete" }]
- )
- end
- end
-
- def self.find_to_attach_from_xml(xml_in, context)
- xml = XmlSimple.xml_in(xml_in)
- vol_id = xml["volume"].first["href"].split("/").last
- location = xml["initialLocation"].first.strip
- [vol_id, location]
- end
-
- def self.find_to_attach_from_json(json_in, context)
- json = JSON.parse(json_in)
- vol_id = json["volume"]["href"].split("/").last
- location = json["initialLocation"]
- [vol_id, location]
- end
-
-
- def self.collection_for_instance(instance_id, context)
- machine_volumes = self.find(instance_id, context)
- volumes_url = context.url("/machines/#{instance_id}/volumes")
- unless CIMI::Model.const_defined?('MachineVolumeCollection')
- collection_class = CIMI::Model::Collection.generate(self)
- else
- collection_class = CIMI::Model::MachineVolumeCollection
- end
- collection_class.new(
- :id => volumes_url,
- :name => 'default',
- :count => machine_volumes.size,
- :description => "Volume collection for Machine #{instance_id}",
- :entries => machine_volumes,
- :operations => [{ :href => volumes_url.singularize+"_attach", :rel => "add" }]
- )
- end
-
end
diff --git a/server/lib/cimi/models/network.rb b/server/lib/cimi/models/network.rb
index 789e83f..1b8587a 100644
--- a/server/lib/cimi/models/network.rb
+++ b/server/lib/cimi/models/network.rb
@@ -37,36 +37,4 @@ class CIMI::Model::Network < CIMI::Model::Base
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
- if context.expand? :networkPorts
- networks.each do |network|
- network.network_ports = CIMI::Model::NetworkPort.collection_for_network(network.id, context)
- end
- end
- networks
- 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
-
end
diff --git a/server/lib/cimi/models/network_configuration.rb b/server/lib/cimi/models/network_configuration.rb
index 1010d54..c7d37ba 100644
--- a/server/lib/cimi/models/network_configuration.rb
+++ b/server/lib/cimi/models/network_configuration.rb
@@ -27,19 +27,4 @@ class CIMI::Model::NetworkConfiguration < CIMI::Model::Base
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_create.rb b/server/lib/cimi/models/network_create.rb
index 2496269..ea3e170 100644
--- a/server/lib/cimi/models/network_create.rb
+++ b/server/lib/cimi/models/network_create.rb
@@ -17,27 +17,4 @@ class CIMI::Model::NetworkCreate < CIMI::Model::Base
ref :network_template, :required => true
- def create(context)
- validate!
- if network_template.href?
- template = network_template.find(context)
- network_config = template.network_config.find(context)
- forwarding_group = template.forwarding_group.find(context)
- else
- network_config = CIMI::Model::NetworkConfiguration.find(context.href_id(network_template.network_config.href, :network_configurations), context)
- forwarding_group = CIMI::Model::ForwardingGroup.find(context.href_id(network_template.forwarding_group.href, :forwarding_groups), context)
- end
- params = {
- :network_config => network_config,
- :forwarding_group => forwarding_group,
- :name => name,
- :description => description,
- :env => context # FIXME: We should not pass the context to the driver (!)
- }
- network = context.driver.create_network(context.credentials, params)
- network.property = property if property
- network.save
- network
- end
-
end
diff --git a/server/lib/cimi/models/network_port.rb b/server/lib/cimi/models/network_port.rb
index 03b0ca3..3f6b371 100644
--- a/server/lib/cimi/models/network_port.rb
+++ b/server/lib/cimi/models/network_port.rb
@@ -33,77 +33,4 @@ class CIMI::Model::NetworkPort < CIMI::Model::Base
scalar :rel, :href
end
- def self.find(id, context)
- if id==:all
- context.driver.network_ports(context.credentials, {:env=>context})
- else
- context.driver.network_ports(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["networkPortTemplate"]["href"] #template by reference
- network_port_config, network = get_by_reference(input, context)
- else
- if input["networkPortTemplate"]["networkPortConfig"]["href"] # configuration by reference
- network_port_config = CIMI::Model::NetworkPortConfiguration.find(context.href_id(input["networkPortTemplate"]["networkPortConfig"]["href"],:network_port_configurations), context)
- else #configuration by value
- network_port_config = get_by_value(request_body, type)
- end
- network = CIMI::Model::Network.find(context.href_id(input["networkPortTemplate"]["network"]["href"], :networks), context)
- end
- params = {:network_port_config => network_port_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_network_port(context.credentials, params)
- end
-
- def self.delete!(id, context)
- context.driver.delete_network_port(context.credentials, id)
- end
-
- def perform(action, context, &block)
- begin
- if context.driver.send(:"#{action.name}_network_port", context.credentials, self.name)
- block.callback :success
- else
- raise "Operation #{action.name} failed to execute on the NetworkPort #{self.name} "
- end
- rescue => e
- block.callback :failure, e.message
- end
- end
-
- def self.collection_for_network(network_id, context)
- net_url = context.network_url(network_id)
- network_ports = CIMI::Model::NetworkPort.all(context)
- ports_collection = network_ports.inject([]){|res, current| res << current if current.network.href == net_url ; res}
- CIMI::Model::NetworkPortCollection.new(
- :id => net_url+"/network_ports",
- :name => 'default',
- :created => Time.now,
- :description => "#{context.driver.name.capitalize} NetworkPortCollection",
- :count => ports_collection.size,
- :network_ports => ports_collection
- )
- end
-
- private
-
- def self.get_by_reference(input, context)
- network_port_template = CIMI::Model::NetworkPortTemplate.find(context.href_id(input["networkPortTemplate"]["href"], :network_port_templates), context)
- network_port_config = CIMI::Model::NetworkPortConfiguration.find(context.href_id(network_port_template.network_port_config.href, :network_port_configurations), context)
- network = CIMI::Model::Network.find(context.href_id(network_port_template.network.href, :networks), context)
- return network_port_config, network
- end
-
- def self.get_by_value(request_body, type)
- if type == :xml
- xml_arrays = XmlSimple.xml_in(request_body, {"NormaliseSpace"=>2})
- network_port_config = CIMI::Model::NetworkPortConfiguration.from_xml(XmlSimple.xml_out(xml_arrays["networkPortTemplate"][0]["networkPortConfig"][0]))
- else
- json = JSON.parse(request_body)
- network_port_config = CIMI::Model::NetworkPortConfiguration.from_json(JSON.generate(json["networkPortTemplate"]["networkPortConfig"]))
- end
- end
end
diff --git a/server/lib/cimi/models/network_port_configuration.rb b/server/lib/cimi/models/network_port_configuration.rb
index 3789b35..8f505b5 100644
--- a/server/lib/cimi/models/network_port_configuration.rb
+++ b/server/lib/cimi/models/network_port_configuration.rb
@@ -25,12 +25,4 @@ class CIMI::Model::NetworkPortConfiguration < CIMI::Model::Base
scalar :rel, :href
end
- def self.find(id, context)
- if id==:all
- context.driver.network_port_configurations(context.credentials, {:env=>context})
- else
- context.driver.network_port_configurations(context.credentials, {:env=>context, :id=>id})
- end
- end
-
end
diff --git a/server/lib/cimi/models/network_port_template.rb b/server/lib/cimi/models/network_port_template.rb
index 774d6e9..8e7c738 100644
--- a/server/lib/cimi/models/network_port_template.rb
+++ b/server/lib/cimi/models/network_port_template.rb
@@ -25,12 +25,4 @@ class CIMI::Model::NetworkPortTemplate < CIMI::Model::Base
scalar :rel, :href
end
- def self.find(id, context)
- if id==:all
- context.driver.network_port_templates(context.credentials, {:env=>context})
- else
- context.driver.network_port_templates(context.credentials, {:env=>context, :id=>id})
- end
- end
-
end
diff --git a/server/lib/cimi/models/network_template.rb b/server/lib/cimi/models/network_template.rb
index a16c094..4f69f52 100644
--- a/server/lib/cimi/models/network_template.rb
+++ b/server/lib/cimi/models/network_template.rb
@@ -24,14 +24,4 @@ class CIMI::Model::NetworkTemplate < CIMI::Model::Base
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/resource_metadata.rb b/server/lib/cimi/models/resource_metadata.rb
index 3ed88db..2c4ee08 100644
--- a/server/lib/cimi/models/resource_metadata.rb
+++ b/server/lib/cimi/models/resource_metadata.rb
@@ -16,6 +16,7 @@
class CIMI::Model::ResourceMetadata < CIMI::Model::Base
+ # FIXME: Is this property really needed? (Base model include 'name'
text :name
text :type_uri
@@ -51,98 +52,13 @@ class CIMI::Model::ResourceMetadata < CIMI::Model::Base
scalar :rel, :href
end
- def self.find(id, context)
- if id == :all
- resource_metadata = []
- CIMI::Model.root_entities.each do |resource_class|
- meta = resource_metadata_for(resource_class, context)
- resource_metadata << meta unless none_defined(meta)
- end
- return resource_metadata
- else
- resource_class = CIMI::Model.const_get("#{id.camelize}")
- resource_metadata_for(resource_class, context)
- end
- end
-
- def self.resource_metadata_for(resource_class, context)
- attributes = rm_attributes_for(resource_class, context)
- capabilities = rm_capabilities_for(resource_class, context)
- actions = rm_actions_for(resource_class, context)
- cimi_resource = resource_class.name.split("::").last
- self.new({ :id => context.resource_metadata_url(cimi_resource.underscore),
- :name => cimi_resource,
- :type_uri => resource_class.resource_uri,
- :attributes => attributes,
- :capabilities => capabilities,
- :actions => actions
- })
- end
-
- def self.resource_attributes
- @resource_attributes ||= {}
- end
-
def self.add_resource_attribute!(klass, name, opts={})
resource_attributes[klass.name] ||= {}
resource_attributes[klass.name][name] = opts
end
- private
-
- def self.rm_attributes_for(resource_class, context)
- return [] if resource_attributes[resource_class.name].nil?
- resource_attributes[resource_class.name].map do |attr_name, attr_def|
- if attr_def.has_key? :constraints
- constraints = attr_def[:constraints].call(context)
- else
- constraints = []
- end
- {
- :name => attr_name.to_s,
- # TODO: We need to make this URI return description of this 'non-CIMI'
- # attribute
- :namespace => "http://deltacloud.org/cimi/#{resource_class.name.split('::').last}/#{attr_name}",
- :type => translate_attr_type(attr_def[:type]),
- :required => attr_def[:required] ? 'true' : 'false',
- :constraints => constraints.map { |v| { :value => v }}
- }
- end
- end
-
- def self.rm_capabilities_for(resource_class,context)
- cimi_object = resource_class.name.split("::").last.underscore.pluralize.to_sym
- capabilities = (context.driver.class.features[cimi_object] || []).inject([]) do |res, cur|
- feat = CIMI::FakeCollection.feature(cur)
- values = (context.driver.class.constraints[cimi_object][feat.name][:values] || []).inject([]) do |vals, val|
- vals << val
- vals
- end
- res << {:name => feat.name.to_s.camelize,
- :uri => CMWG_NAMESPACE+"/capability/#{cimi_object.to_s.camelize.singularize}/#{feat.name.to_s.camelize}",
- :description => feat.description,
- :value => values.join(",") }
- res
- end
-#cimi_resource.underscore.pluralize.to_sym
- end
-
- def self.rm_actions_for(resource_class, context)
- []
- end
-
- def self.translate_attr_type(type)
- case type
- when :href then 'URI'
- when :text then 'string'
- when :boolean then 'boolean'
- else 'text'
- end
- end
-
- def self.none_defined(metadata)
- return true if metadata.capabilities.empty? && metadata.capabilities.empty? && metadata.attributes.empty?
- return false
+ def self.resource_attributes
+ @resource_attributes ||= {}
end
end
diff --git a/server/lib/cimi/models/system.rb b/server/lib/cimi/models/system.rb
index e238259..118f9f5 100644
--- a/server/lib/cimi/models/system.rb
+++ b/server/lib/cimi/models/system.rb
@@ -19,49 +19,25 @@ class CIMI::Model::System < CIMI::Model::Base
text :state
-# collection :systems, :class => CIMI::Model::SystemSystem
-# collection :machines, :class => CIMI::Model::SystemMachine
-# collection :credentials, :class => CIMI::Model::SystemCredential
-# collection :volumes, :class => CIMI::Model::SystemVolume
-# collection :networks, :class => CIMI::Model::SystemNetwork
-# collection :network_ports, :class => CIMI::Model::SystemNetworkPort
-# collection :addresses, :class => CIMI::Model::SystemAddress
-# collection :forwarding_groups, :class => CIMI::Model::SystemForwardingGroup
+ # FIXME: Any reason for these comments?
-# array :meters do
-# scalar :href
-# end
+ # collection :systems, :class => CIMI::Model::SystemSystem
+ # collection :machines, :class => CIMI::Model::SystemMachine
+ # collection :credentials, :class => CIMI::Model::SystemCredential
+ # collection :volumes, :class => CIMI::Model::SystemVolume
+ # collection :networks, :class => CIMI::Model::SystemNetwork
+ # collection :network_ports, :class => CIMI::Model::SystemNetworkPort
+ # collection :addresses, :class => CIMI::Model::SystemAddress
+ # collection :forwarding_groups, :class => CIMI::Model::SystemForwardingGroup
-# href :event_log
+ # array :meters do
+ # scalar :href
+ # end
+
+ # href :event_log
array :operations do
scalar :rel, :href
end
- def self.find(id, context)
- if id == :all
- systems = context.driver.systems(context.credentials, {:env=>context})
- else
- systems = context.driver.systems(context.credentials, {:env=>context, :id=>id})
- raise CIMI::Model::NotFound unless systems.first
- systems.first
- end
- end
-
- def perform(action, context, &block)
- begin
- if context.driver.send(:"#{action.name}_system", context.credentials, self.id.split("/").last)
- block.callback :success
- else
- raise "Operation failed to execute on given System"
- end
- rescue => e
- block.callback :failure, e.message
- end
- end
-
- def self.delete!(id, context)
- context.driver.destroy_system(context.credentials, id)
- end
-
end
diff --git a/server/lib/cimi/models/system_template.rb b/server/lib/cimi/models/system_template.rb
index 6a6e1f2..82e418b 100644
--- a/server/lib/cimi/models/system_template.rb
+++ b/server/lib/cimi/models/system_template.rb
@@ -21,43 +21,29 @@ class CIMI::Model::SystemTemplate < CIMI::Model::Base
text :name, :description
hash_map :properties
text :type
+
+ # FIXME: Any reasons for these comments?
+
#component_template, comprises:
-# struct :machine_template, :class => CIMI::Model::MachineTemplate
-# struct :system_template, :class => CIMI::Model::SystemTemplate
-# struct :credential_template, :class => CIMI::Model::CredentialTemplate
-# struct :volume_template, :class => CIMI::Model::VolumeTemplate
-# struct :network_template, :class => CIMI::Model::NetworkTemplate
-# struct :network_port_template, :class => CIMI::Model::NetworkPortTemplate
-# struct :forwarding_group_template, :class => CIMI::Model::ForwardingGroupTemplate
-# struct :address_template, :class => CIMI::Model::AddressTemplate
+ # struct :machine_template, :class => CIMI::Model::MachineTemplate
+ # struct :system_template, :class => CIMI::Model::SystemTemplate
+ # struct :credential_template, :class => CIMI::Model::CredentialTemplate
+ # struct :volume_template, :class => CIMI::Model::VolumeTemplate
+ # struct :network_template, :class => CIMI::Model::NetworkTemplate
+ # struct :network_port_template, :class => CIMI::Model::NetworkPortTemplate
+ # struct :forwarding_group_template, :class => CIMI::Model::ForwardingGroupTemplate
+ # struct :address_template, :class => CIMI::Model::AddressTemplate
text :quantity
end
-# array :meter_templates do
-# scalar :href
-# end
+ # array :meter_templates do
+ # scalar :href
+ # end
-# href :event_log_template
+ # href :event_log_template
array :operations do
scalar :rel, :href
end
- class << self
- def find(id, context)
- if id == :all
- templates = context.driver.system_templates(context.credentials, {:env=>context})
- else
- templates = context.driver.system_templates(context.credentials, {:env=>context, :id=>id})
- raise CIMI::Model::NotFound unless templates.first
- templates.first
- end
- end
-
- def delete!(id, context)
- context.driver.destroy_system_template(context.credentials, id)
- end
-
- end
-
end
diff --git a/server/lib/cimi/models/volume.rb b/server/lib/cimi/models/volume.rb
index 888589a..a1b4423 100644
--- a/server/lib/cimi/models/volume.rb
+++ b/server/lib/cimi/models/volume.rb
@@ -37,63 +37,4 @@ class CIMI::Model::Volume < CIMI::Model::Base
scalar :rel, :href
end
- def self.find(id, context)
- creds = context.credentials
- if id == :all
- volumes = context.driver.storage_volumes(creds)
- volumes.collect{ |volume| from_storage_volume(volume, context) }
- else
- volume = context.driver.storage_volumes(creds, :id => id).first
- raise CIMI::Model::NotFound unless volume
- from_storage_volume(volume, context)
- end
- end
-
- def self.all(context); find(:all, context); end
-
- def self.delete!(id, context)
- context.driver.destroy_storage_volume(context.credentials, {:id=>id} )
- new(:id => id).destroy
- end
-
- def self.find_to_attach_from_json(json_in, context)
- json = JSON.parse(json_in)
- json["volumes"].map{|v| {:volume=>self.find(v["volume"]["href"].split("/volumes/").last, context),
- :initial_location=>v["initialLocation"] }}
- end
-
- def self.find_to_attach_from_xml(xml_in, context)
- xml = XmlSimple.xml_in(xml_in)
- xml["volume"].map{|v| {:volume => self.find(v["href"].split("/volumes/").last, context),
- :initial_location=>v["initialLocation"] }}
- end
-
- def self.from_storage_volume(volume, context)
- self.new( { :name => volume.id,
- :created => volume.created.nil? ? nil : Time.parse(volume.created).xmlschema,
- :id => context.volume_url(volume.id),
- :capacity => context.to_kibibyte(volume.capacity, 'GB'),
- :bootable => "false", #fixme ... will vary... ec2 doesn't expose this
- :snapshots => [], #fixme...
- :type => 'http://schemas.dmtf.org/cimi/1/mapped',
- :state => volume.state == 'IN-USE' ? 'AVAILABLE' : volume.state,
- :meters => [],
- :operations => [{:href=> context.volume_url(volume.id), :rel => "delete"}]
- } )
- end
-
- def self.collection_for_instance(instance_id, context)
- instance = context.driver.instance(context.credentials, :id => instance_id)
- volumes = instance.storage_volumes.map do |mappings|
- mappings.keys.map { |volume_id| from_storage_volume(context.driver.storage_volume(context.credentials, :id => volume_id), context) }
- end.flatten
- CIMI::Model::VolumeCollection.new(
- :id => context.url("/machines/#{instance_id}/volumes"),
- :name => 'default',
- :count => volumes.size,
- :description => "Volume collection for Machine #{instance_id}",
- :entries => volumes
- )
- end
-
end
diff --git a/server/lib/cimi/models/volume_configuration.rb b/server/lib/cimi/models/volume_configuration.rb
index bf94a3a..7393b53 100644
--- a/server/lib/cimi/models/volume_configuration.rb
+++ b/server/lib/cimi/models/volume_configuration.rb
@@ -25,67 +25,4 @@ class CIMI::Model::VolumeConfiguration < CIMI::Model::Base
scalar :rel, :href
end
- def self.create_from_json(body, context)
- json = JSON.parse(body)
- new_config = current_db.add_volume_configuration(
- :name => json['name'],
- :description => json['description'],
- :format => json['format'],
- :capacity => json['capacity'],
- :ent_properties => (json['properties'] || {}).to_json
- )
- from_db(new_config, context)
- end
-
- def self.create_from_xml(body, context)
- xml = XmlSimple.xml_in(body)
- xml['property'] ||= []
- new_config = current_db.add_volume_configuration(
- :name => xml['name'].first,
- :description => xml['description'].first,
- :format => xml['format'].first,
- :capacity => xml['capacity'].first,
- :ent_properties => JSON::dump((xml['property'] || {}).inject({}){ |r, p| r[p['key']]=p['content']; r })
- )
- from_db(new_config, context)
- end
-
- def self.delete!(id, context)
- current_db.volume_configurations.first(:id => id).destroy
- end
-
- def self.find(id, context)
- if id==:all
- if context.driver.respond_to? :volume_configurations
- context.driver.volume_configurations(context.credentials, {:env=>context})
- else
- current_db.volume_configurations.map { |t| from_db(t, context) }
- end
- else
- if context.driver.respond_to? :volume_configuration
- context.driver.volume_configuration(context.credentials, id, :env=>context)
- else
- config = current_db.volume_configurations_dataset.first(:id => id)
- raise CIMI::Model::NotFound unless config
- from_db(config, context)
- end
- end
- end
-
- private
-
- def self.from_db(model, context)
- self.new(
- :id => context.volume_configuration_url(model.id),
- :name => model.name,
- :description => model.description,
- :format => model.format,
- :capacity => context.to_kibibyte(model.capacity, "GB"),
- :property => (model.ent_properties ? JSON::parse(model.ent_properties) : nil),
- :operations => [
- { :href => context.destroy_volume_configuration_url(model.id), :rel => 'http://schemas.dmtf.org/cimi/1/action/delete' }
- ]
- )
- end
-
end
diff --git a/server/lib/cimi/models/volume_create.rb b/server/lib/cimi/models/volume_create.rb
index 607c407..1408c77 100644
--- a/server/lib/cimi/models/volume_create.rb
+++ b/server/lib/cimi/models/volume_create.rb
@@ -17,42 +17,4 @@ class CIMI::Model::VolumeCreate < CIMI::Model::Base
ref :volume_template, :required => true
- def create(context)
- validate!
-
- if volume_template.href?
- template = volume_template.find(context)
- else
- template = CIMI::Model::VolumeTemplate.from_xml(volume_template.to_xml)
- end
-
- volume_image = template.volume_image.href? ?
- template.volume_image.find(context) : template.volume_image
-
- volume_config = template.volume_config.href? ?
- template.volume_config.find(context) : template.volume_config
-
- params = {
- :name => name,
- :capacity => volume_config.capacity,
- :snapshot_id => ref_id(volume_image.id),
- }
-
- unless context.driver.respond_to? :create_storage_volume
- raise Deltacloud::Exceptions.exception_from_status(
- 501,
- "Creating Volume is not supported by the current driver"
- )
- end
-
- volume = context.driver.create_storage_volume(context.credentials, params)
-
- result = CIMI::Model::Volume.from_storage_volume(volume, context)
- result.name = name if result.name.nil?
- result.description = description if description
- result.property = property if property
- result.save
- result
- end
-
end
diff --git a/server/lib/cimi/models/volume_image.rb b/server/lib/cimi/models/volume_image.rb
index ef06552..ec94289 100644
--- a/server/lib/cimi/models/volume_image.rb
+++ b/server/lib/cimi/models/volume_image.rb
@@ -24,34 +24,4 @@ class CIMI::Model::VolumeImage < CIMI::Model::Base
array :operations do
scalar :rel, :href
end
-
- def self.find(id, context)
- creds = context.credentials
- if id == :all
- snapshots = context.driver.storage_snapshots(creds)
- snapshots.collect{ |snapshot| from_storage_snapshot(snapshot, context) }
- else
- snapshot = context.driver.storage_snapshots(creds, id => :id).first
- raise CIMI::Model::NotFound unless snapshot
- from_storage_snapshot(snapshot, context)
- end
- end
-
- def self.all(context); find(:all, context); end
-
- def self.delete!(vol_image_id, context)
- context.driver.destroy_storage_snapshot(context.credentials, {:id=>vol_image_id})
- end
-
- def self.from_storage_snapshot(snapshot, context)
- self.new( {
- :name => snapshot.name,
- :description => snapshot.description,
- :created => snapshot.created.nil? ? nil : Time.parse(snapshot.created).xmlschema,
- :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_create.rb b/server/lib/cimi/models/volume_image_create.rb
index f953146..4eb0ed1 100644
--- a/server/lib/cimi/models/volume_image_create.rb
+++ b/server/lib/cimi/models/volume_image_create.rb
@@ -19,29 +19,4 @@ class CIMI::Model::VolumeImageCreate < CIMI::Model::Base
text :image_data
text :bootable, :required => true
- def create(context)
- validate!
-
- params = {
- :volume_id => context.href_id(image_location.href, :volumes),
- :name => name,
- :description => description
- }
-
- unless context.driver.respond_to? :create_storage_snapshot
- raise Deltacloud::Exceptions.exception_from_status(
- 501,
- 'Creating VolumeImage is not supported by the current driver'
- )
- end
-
- new_snapshot = context.driver.create_storage_snapshot(context.credentials, params)
- result = CIMI::Model::VolumeImage.from_storage_snapshot(new_snapshot, context)
- result.name= name unless new_snapshot.name
- result.description = description unless new_snapshot.description
- result.property = property if property
- result.save
- result
- end
-
end
diff --git a/server/lib/cimi/models/volume_template.rb b/server/lib/cimi/models/volume_template.rb
index 15cbcd0..bda4657 100644
--- a/server/lib/cimi/models/volume_template.rb
+++ b/server/lib/cimi/models/volume_template.rb
@@ -29,45 +29,4 @@ class CIMI::Model::VolumeTemplate < CIMI::Model::Base
scalar :rel, :href
end
- def self.find(id, context)
- if id==:all
- if context.driver.respond_to? :volume_templates
- context.driver.volume_templates(context.credentials, {:env=>context})
- else
- current_db.volume_templates.map { |t| from_db(t, context) }
- end
- else
- if context.driver.respond_to? :volume_template
- context.driver.volume_template(context.credentials, id, :env=>context)
- else
- template = current_db.volume_templates_dataset.first(:id => id)
- raise CIMI::Model::NotFound unless template
- from_db(template, context)
- end
- end
- end
-
- def self.delete!(id, context)
- current_db.volume_templates.first(:id => id).destroy
- end
-
- def self.from_db(model, context)
- self.new(
- :id => context.volume_template_url(model.id),
- :name => model.name,
- :description => model.description,
- :volume_config => {:href => model.volume_config},
- :volume_image => {:href => model.volume_image},
- :property => (model.ent_properties ? JSON::parse(model.ent_properties) : nil),
- :operations => [
- {
- :href => context.destroy_volume_template_url(model.id),
- :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
- }
- ]
- )
- end
-
-
-
end
diff --git a/server/lib/cimi/models/volume_template_create.rb b/server/lib/cimi/models/volume_template_create.rb
index b6dbec2..3064ae8 100644
--- a/server/lib/cimi/models/volume_template_create.rb
+++ b/server/lib/cimi/models/volume_template_create.rb
@@ -18,16 +18,4 @@ class CIMI::Model::VolumeTemplateCreate < CIMI::Model::Base
ref :volume_config, :required => true
ref :volume_image, :required => true
- def create(context)
- validate!
- new_template = self.class.current_db.add_volume_template(
- :name => name,
- :description => description,
- :volume_config => volume_config.href,
- :volume_image => volume_image.href,
- :ent_properties => property.to_json
- )
- CIMI::Model::VolumeTemplate.from_db(new_template, context)
- end
-
end
diff --git a/server/lib/cimi/service.rb b/server/lib/cimi/service.rb
index f6b933f..b05efbf 100644
--- a/server/lib/cimi/service.rb
+++ b/server/lib/cimi/service.rb
@@ -27,3 +27,38 @@ require_relative './../db/volume_template'
require_relative './service/base'
require_relative './service/machine'
require_relative './service/machine_image'
+require_relative './service/volume_image'
+require_relative './service/system_template'
+require_relative './service/network_port_configuration'
+require_relative './service/credential_create'
+require_relative './service/machine_template_create'
+require_relative './service/volume_create'
+require_relative './service/network_create'
+require_relative './service/network'
+require_relative './service/forwarding_group'
+require_relative './service/volume_template_create'
+require_relative './service/system'
+require_relative './service/address_template_create'
+require_relative './service/volume'
+require_relative './service/volume_image_create'
+require_relative './service/machine_configuration'
+require_relative './service/volume_template'
+require_relative './service/machine_template'
+require_relative './service/network_port'
+require_relative './service/forwarding_group_template'
+require_relative './service/credential_template'
+require_relative './service/volume_configuration'
+require_relative './service/cloud_entry_point'
+require_relative './service/network_configuration'
+require_relative './service/address_template'
+require_relative './service/action'
+require_relative './service/machine_create'
+require_relative './service/address'
+require_relative './service/credential'
+require_relative './service/network_port_template'
+require_relative './service/machine_image_create'
+require_relative './service/address_create'
+require_relative './service/network_template'
+require_relative './service/disk'
+require_relative './service/machine_volume'
+require_relative './service/resource_metadata'
diff --git a/server/lib/cimi/service/action.rb b/server/lib/cimi/service/action.rb
new file mode 100644
index 0000000..9503704
--- /dev/null
+++ b/server/lib/cimi/service/action.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.
+
+class CIMI::Service::Action < CIMI::Service::Base
+
+ def operation
+ action.split('/').last.strip.intern
+ end
+end
diff --git a/server/lib/cimi/service/address.rb b/server/lib/cimi/service/address.rb
new file mode 100644
index 0000000..f883c15
--- /dev/null
+++ b/server/lib/cimi/service/address.rb
@@ -0,0 +1,56 @@
+# 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::Service::Address < CIMI::Service::Base
+
+ def self.find(id, context)
+ if id==:all
+ addresses = context.driver.addresses(context.credentials)
+ addresses.map{|addr| from_address(addr, context)}
+ else
+ address = context.driver.address(context.credentials, {:id=>id})
+ from_address(address, context)
+ end
+ end
+
+ def self.delete!(id, context)
+ context.driver.delete_address(context.credentials, id)
+ self.new(context, :values => { :id => id }).destroy
+ end
+
+ private
+
+ def self.from_address(address, context)
+ self.new(context, :values => {
+ :name => address.id,
+ :id => context.address_url(address.id),
+ :description => "Address #{address.id}",
+ :ip => address.id,
+ :allocation => "dynamic",
+ :default_gateway => "unknown",
+ :dns => "unknown",
+ :protocol => protocol_from_address(address.id),
+ :mask => "unknown",
+ :resource => (address.instance_id) ? {:href=> context.machine_url(address.instance_id)} : nil,
+ :network => nil
+ })
+ end
+
+ def self.protocol_from_address(address)
+ addr = IPAddr.new(address)
+ addr.ipv4? ? "ipv4" : "ipv6"
+ end
+
+end
diff --git a/server/lib/cimi/service/address_create.rb b/server/lib/cimi/service/address_create.rb
new file mode 100644
index 0000000..20bda09
--- /dev/null
+++ b/server/lib/cimi/service/address_create.rb
@@ -0,0 +1,45 @@
+# 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::Service::AddressCreate < CIMI::Service::Base
+
+ def create
+ template = resolve(address_template)
+
+ params = {
+ :name => name,
+ :description => description,
+ :address_template => template,
+ :env => context # FIXME: We should not pass the context to the driver (!)
+ }
+
+ unless context.driver.respond_to? :create_address
+ raise Deltacloud::Exceptions.exception_from_status(
+ 501,
+ "Creating Address is not supported by the current driver"
+ )
+ end
+
+ address = context.driver.create_address(context.credentials, params)
+
+ result = CIMI::Service::Address.from_address(address, context)
+ result.name = name if name
+ result.description = description if description
+ result.property = property if property
+ result.save
+ result
+ end
+
+end
diff --git a/server/lib/cimi/service/address_template.rb b/server/lib/cimi/service/address_template.rb
new file mode 100644
index 0000000..2a5a0d3
--- /dev/null
+++ b/server/lib/cimi/service/address_template.rb
@@ -0,0 +1,71 @@
+# 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::Service::AddressTemplate < CIMI::Service::Base
+
+ def self.find(id, context)
+ if id==:all
+ if context.driver.respond_to? :address_templates
+ context.driver.address_templates(context.credentials, {:env=>context})
+ else
+ current_db.address_templates.map { |t| from_db(t, context) }
+ end
+ else
+ if context.driver.respond_to? :address_template
+ context.driver.address_template(context.credentials, :id => id, :env=>context)
+ else
+ template = current_db.address_templates_dataset.first(:id => id)
+ raise CIMI::Model::NotFound unless template
+ from_db(template, context)
+ end
+ end
+ end
+
+ def self.delete!(id, context)
+ current_db.address_templates.first(:id => id).destroy
+ end
+
+ protected
+ def attributes_to_copy
+ super + [ :ip, :hostname, :allocation, :default_gateway,
+ :dns, :protocol, :mask ]
+ end
+
+ private
+
+ def self.from_db(model, context)
+ self.new(context, :values => {
+ :id => context.address_template_url(model.id),
+ :name => model.name,
+ :description => model.description,
+ :ip => model.ip,
+ :hostname => model.hostname,
+ :allocation => model.allocation,
+ :default_gateway => model.default_gateway,
+ :dns => model.dns,
+ :protocol => model.protocol,
+ :mask => model.mask,
+ :property => (model.ent_properties ? JSON::parse(model.ent_properties) : nil),
+ :operations => [
+ {
+ :href => context.destroy_address_template_url(model.id),
+ :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
+ }
+ ]
+ })
+ end
+
+
+end
diff --git a/server/lib/cimi/service/address_template_create.rb b/server/lib/cimi/service/address_template_create.rb
new file mode 100644
index 0000000..01566ab
--- /dev/null
+++ b/server/lib/cimi/service/address_template_create.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::Service::AddressTemplateCreate < CIMI::Service::Base
+
+ def create
+ new_template = context.current_db.add_address_template(
+ :name => name,
+ :description => description,
+ :hostname => hostname,
+ :ip => ip,
+ :allocation => allocation,
+ :default_gateway => default_gateway,
+ :dns => dns,
+ :protocol => protocol,
+ :mask => mask,
+ :ent_properties => property.to_json
+ )
+ CIMI::Service::AddressTemplate.from_db(new_template, context)
+ end
+
+end
diff --git a/server/lib/cimi/service/cloud_entry_point.rb b/server/lib/cimi/service/cloud_entry_point.rb
new file mode 100644
index 0000000..5029e12
--- /dev/null
+++ b/server/lib/cimi/service/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::Service::CloudEntryPoint < CIMI::Service::Base
+
+ def self.create(context)
+ self.new(context, :values => entities(context).merge({
+ :name => context.driver.name,
+ :description => "Cloud Entry Point for the Deltacloud #{context.driver.name} driver",
+ :driver => context.driver.name,
+ :provider => context.current_provider,
+ :id => context.cloudEntryPoint_url,
+ :base_uri => context.base_uri + "/",
+ :created => Time.now.xmlschema
+ }))
+ end
+
+ # Return an Hash of the CIMI root entities used in CloudEntryPoint
+ def self.entities(context)
+ CIMI::Collections.modules(:cimi).inject({}) do |supported_entities, m|
+ m.collections.each do |c|
+ index_operation_capability = c.operation(:index).required_capability
+ next if m.settings.respond_to?(:capability) and !m.settings.capability(index_operation_capability)
+ supported_entities[c.collection_name.to_s] = { :href => context.send(:"#{c.collection_name}_url") }
+ end
+ supported_entities
+ end
+ end
+
+ def entities
+ @attribute_values.clone.delete_if { |key, value| !value.respond_to? :href }
+ end
+
+end
diff --git a/server/lib/cimi/service/credential.rb b/server/lib/cimi/service/credential.rb
new file mode 100644
index 0000000..c48f372
--- /dev/null
+++ b/server/lib/cimi/service/credential.rb
@@ -0,0 +1,52 @@
+# 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::Service::Credential < CIMI::Service::Base
+
+ def self.find(id, context)
+ if id == :all
+ return [] unless context.driver.respond_to?(:keys)
+ 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)
+ credential = Credential.from_xml(body)
+ key = context.driver.create_key(context.credentials, :key_name => credential.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(context, :values => {
+ :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.credential_url(key.id),
+ :created => Time.now.xmlschema
+ })
+ end
+
+end
diff --git a/server/lib/cimi/service/credential_create.rb b/server/lib/cimi/service/credential_create.rb
new file mode 100644
index 0000000..3290596
--- /dev/null
+++ b/server/lib/cimi/service/credential_create.rb
@@ -0,0 +1,38 @@
+# 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::Service::CredentialCreate < CIMI::Service::Base
+
+ def create
+ unless context.driver.respond_to? :create_key
+ raise Deltacloud::Exceptions.exception_from_status(
+ 501,
+ "Creating Credential is not supported by the current driver"
+ )
+ end
+
+ template = resolve(credential_template)
+
+ key = context.driver.create_key(context.credentials, :key_name => name)
+
+ result = CIMI::Service::Credential.from_key(key, context)
+ result.name = name if name
+ result.description = description if description
+ result.property = property if property
+ result.save
+ result
+ end
+
+end
diff --git a/server/lib/cimi/service/credential_template.rb b/server/lib/cimi/service/credential_template.rb
new file mode 100644
index 0000000..513160d
--- /dev/null
+++ b/server/lib/cimi/service/credential_template.rb
@@ -0,0 +1,20 @@
+# 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::Service::CredentialTemplate < CIMI::Service::Base
+
+ # FIXME: TBD
+
+end
diff --git a/server/lib/cimi/service/disk.rb b/server/lib/cimi/service/disk.rb
new file mode 100644
index 0000000..1af908e
--- /dev/null
+++ b/server/lib/cimi/service/disk.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.
+
+class CIMI::Service::Disk < CIMI::Service::Base
+
+ def self.find(instance, machine_config, context, id=:all)
+ if id == :all
+ name = instance.id+"_disk_" #assuming one disk for now...
+
+ if machine_config
+ mach_config_disks = machine_config.disks
+ return mach_config_disks.map do |d|
+ self.new(context, :values => {
+ :id => context.machine_url(instance.id) + "/disks/#{name}#{d[:capacity]}",
+ :name => "#{name}#{d[:capacity]}",
+ :description => "Disk for Machine #{instance.id}",
+ :created => instance.launch_time.nil? ?
+ Time.now.xmlschema : Time.parse(instance.launch_time).xmlschema,
+ :capacity => d[:capacity]
+ })
+ end
+ else
+ if instance.instance_profile.override? :storage
+ capacity = context.to_kibibyte(instance.instance_profile.storage, 'MB')
+ else
+ hw_profile = context.driver.hardware_profile(
+ context.credentials,
+ :id => instance.instance_profile.name
+ )
+ if hw_profile.storage
+ capacity = context.to_kibibyte(hw_profile.storage.value, 'MB')
+ end
+ end
+
+ return [] unless capacity
+
+ [self.new(context, :values => {
+ :id => context.machine_url(instance.id)+"/disks/#{name}#{capacity}",
+ :name => name + capacity.to_s,
+ :description => "Disk for Machine #{instance.id}",
+ :created => instance.launch_time.nil? ?
+ Time.now.xmlschema : Time.parse(instance.launch_time).xmlschema,
+ :capacity => capacity
+ })]
+ end
+ else
+ end
+ end
+
+ def self.collection_for_instance(instance_id, context)
+ instance = context.driver.instance(context.credentials, :id => instance_id)
+ disks = find(instance, nil, context)
+ unless CIMI::Model.const_defined?('DiskCollection')
+ collection_class = CIMI::Model::Collection.generate(self)
+ else
+ collection_class = CIMI::Model::DiskCollection
+ end
+ collection_class.new(context, :values => {
+ :id => context.url("/machines/#{instance_id}/disks"),
+ :name => 'default',
+ :count => disks.size,
+ :description => "Disk collection for Machine #{instance_id}",
+ :entries => disks
+ })
+ end
+
+
+end
diff --git a/server/lib/cimi/service/forwarding_group.rb b/server/lib/cimi/service/forwarding_group.rb
new file mode 100644
index 0000000..ef12350
--- /dev/null
+++ b/server/lib/cimi/service/forwarding_group.rb
@@ -0,0 +1,26 @@
+# 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::Service::ForwardingGroup < CIMI::Service::Base
+
+ def self.find(id, context)
+ if id==:all
+ context.driver.forwarding_groups(context.credentials, {:env=>context})
+ else
+ context.driver.forwarding_groups(context.credentials, {:env=>context, :id=>id})
+ end
+ end
+
+end
diff --git a/server/lib/cimi/service/forwarding_group_template.rb b/server/lib/cimi/service/forwarding_group_template.rb
new file mode 100644
index 0000000..32e7388
--- /dev/null
+++ b/server/lib/cimi/service/forwarding_group_template.rb
@@ -0,0 +1,26 @@
+# 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::Service::ForwardingGroupTemplate < CIMI::Service::Base
+
+ def self.find(id, context)
+ if id==:all
+ context.driver.forwarding_group_templates(context.credentials, {:env=>context})
+ else
+ context.driver.forwarding_group_templates(context.credentials, {:env=>context, :id=>id})
+ end
+ end
+
+end
diff --git a/server/lib/cimi/service/machine.rb b/server/lib/cimi/service/machine.rb
index 72e5346..7112486 100644
--- a/server/lib/cimi/service/machine.rb
+++ b/server/lib/cimi/service/machine.rb
@@ -52,19 +52,19 @@ class CIMI::Service::Machine < CIMI::Service::Base
def self.attach_volume(volume, location, context)
context.driver.attach_storage_volume(context.credentials,
{:id=>volume, :instance_id=>context.params[:id], :device=>location})
- CIMI::Model::MachineVolume.find(context.params[:id], context, volume)
+ CIMI::Service::MachineVolume.find(context.params[:id], context, volume)
end
#returns the machine_volume_collection for the given machine
def self.detach_volume(volume, location, context)
context.driver.detach_storage_volume(context.credentials,
{:id=>volume, :instance_id=>context.params[:id], :device=>location})
- CIMI::Model::MachineVolume.collection_for_instance(context.params[:id], context)
+ CIMI::Service::MachineVolume.collection_for_instance(context.params[:id], context)
end
def self.from_instance(instance, context)
cpu = memory = (instance.instance_profile.id == "opaque")? "n/a" : nil
- machine_conf = CIMI::Model::MachineConfiguration.find(instance.instance_profile.name, context)
+ machine_conf = CIMI::Service::MachineConfiguration.find(instance.instance_profile.name, context)
machine_spec = {
:name => instance.name,
:created => instance.launch_time.nil? ? Time.now.xmlschema : Time.parse(instance.launch_time.to_s).xmlschema,
@@ -78,10 +78,10 @@ class CIMI::Service::Machine < CIMI::Service::Base
:operations => convert_instance_actions(instance, context)
}
if context.expand? :disks
- machine_spec[:disks] = CIMI::Model::Disk.find(instance, machine_conf, context, :all)
+ machine_spec[:disks] = CIMI::Service::Disk.find(instance, machine_conf, context, :all)
end
if context.expand? :volumes
- machine_spec[:volumes] = CIMI::Model::MachineVolume.find(instance.id, context, :all)
+ machine_spec[:volumes] = CIMI::Service::MachineVolume.find(instance.id, context, :all)
end
machine_spec[:realm] = instance.realm_id if instance.realm_id
machine_spec[:machine_image] = { :href => context.machine_image_url(instance.image_id) } if instance.image_id
@@ -102,14 +102,14 @@ class CIMI::Service::Machine < CIMI::Service::Base
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
+ CIMI::Service::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)
+ machine_conf = CIMI::Service::MachineConfiguration.find(profile.name, context)
memory_override = profile.overrides.find { |p, v| p == :memory }
memory_override.nil? ? machine_conf.memory.to_i : context.to_kibibyte(memory_override[1].to_i,"MB")
end
diff --git a/server/lib/cimi/service/machine_configuration.rb b/server/lib/cimi/service/machine_configuration.rb
new file mode 100644
index 0000000..d4ddf20
--- /dev/null
+++ b/server/lib/cimi/service/machine_configuration.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::Service::MachineConfiguration < CIMI::Service::Base
+
+ 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 ?
+ context.to_kibibyte((profile.memory.value || profile.memory.default), profile.memory.unit) : nil
+ cpu = (profile.cpu ? (profile.cpu.value || profile.cpu.default) : nil )
+ storage = profile.storage ?
+ context.to_kibibyte((profile.storage.value || profile.storage.default), profile.storage.unit) : nil
+ machine_hash = {
+ :name => profile.name,
+ :description => "Machine Configuration with #{memory} KiB of memory and #{cpu} CPU",
+ :cpu => ( cpu.to_i.to_s if cpu ) ,
+ :created => Time.now.xmlschema, # FIXME: DC hardware_profile has no mention about created_at
+ :memory => (memory if memory),
+ :disks => ( [ {
+ :capacity => storage,
+ :format => (profile.storage.respond_to?(:format) ? profile.storage.format : "unknown") }
+ ] if storage ), # no format attr for hwp - may be added if providers support...,
+ :id => context.machine_configuration_url(profile.id)
+ }
+ self.new(context, :values => machine_hash)
+ end
+
+
+end
diff --git a/server/lib/cimi/service/machine_create.rb b/server/lib/cimi/service/machine_create.rb
new file mode 100644
index 0000000..1e5b637
--- /dev/null
+++ b/server/lib/cimi/service/machine_create.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::Service::MachineCreate < CIMI::Service::Base
+
+ def create
+ params = {}
+ if machine_template.href
+ template = resolve(machine_template)
+ params[:hwp_id] = ref_id(template.machine_config.href)
+ params[:initial_state] = template.initial_state
+ image_id = ref_id(template.machine_image.href)
+ else
+ # FIXME: What if either of these href's isn't there ? What if the user
+ # tries to override some aspect of the machine_config/machine_image ?
+ params[:hwp_id] = ref_id(machine_template.machine_config.href)
+ params[:initial_state] = machine_template.initial_state
+ image_id = ref_id(machine_template.machine_image.href)
+ if machine_template.credential.href
+ params[:keyname] = ref_id(machine_template.credential.href)
+ end
+ end
+
+ params[:name] = name if name
+ params[:realm_id] = realm if realm
+ instance = context.driver.create_instance(context.credentials, image_id, params)
+
+ result = CIMI::Service::Machine::from_instance(instance, context)
+ result.name = name if name
+ result.description = description if description
+ result.property = property if property
+ result.save
+ result
+ end
+
+
+end
diff --git a/server/lib/cimi/service/machine_image.rb b/server/lib/cimi/service/machine_image.rb
index dad26a8..17d9220 100644
--- a/server/lib/cimi/service/machine_image.rb
+++ b/server/lib/cimi/service/machine_image.rb
@@ -15,10 +15,6 @@
class CIMI::Service::MachineImage < CIMI::Service::Base
- def initialize(ctx, opts)
- super
- end
-
def self.find(id, context)
images = []
if id == :all
@@ -44,7 +40,7 @@ class CIMI::Service::MachineImage < CIMI::Service::Base
def self.delete!(image_id, context)
context.driver.destroy_image(context.credentials, image_id)
- new(:id => image_id).destroy
+ self.new(context, :values => { :id => image_id }).destroy
end
diff --git a/server/lib/cimi/service/machine_image_create.rb b/server/lib/cimi/service/machine_image_create.rb
new file mode 100644
index 0000000..7cd1a01
--- /dev/null
+++ b/server/lib/cimi/service/machine_image_create.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::Service::MachineImageCreate < CIMI::Service::Base
+
+ def create
+ params = {
+ :id => context.href_id(image_location, :machines),
+ :name => name,
+ :description => description
+ }
+
+ img = context.driver.create_image(context.credentials, params)
+
+ result = CIMI::Service::MachineImage.from_image(img, context)
+ result.name = name if name
+ result.description = description if description
+ result.property = property if property
+ result.save
+ result
+ end
+
+end
diff --git a/server/lib/cimi/service/machine_template.rb b/server/lib/cimi/service/machine_template.rb
new file mode 100644
index 0000000..e790e89
--- /dev/null
+++ b/server/lib/cimi/service/machine_template.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.
+
+class CIMI::Service::MachineTemplate < CIMI::Service::Base
+
+ def initialize(ctx, opts)
+ super
+ end
+
+ class << self
+ def find(id, context)
+ if id == :all
+ current_db.machine_templates.map { |t| from_db(t, context) }
+ else
+ template = current_db.machine_templates_dataset.first(:id => id)
+ raise CIMI::Model::NotFound unless template
+ from_db(template, context)
+ end
+ end
+
+ def delete!(id, context)
+ current_db.machine_templates.first(:id => id).destroy
+ end
+
+ def from_db(model, context)
+ self.new(context, :values => {
+ :id => context.machine_template_url(model.id),
+ :name => model.name,
+ :description => model.description,
+ :machine_config => { :href => model.machine_config },
+ :machine_image => { :href => model.machine_image },
+ :realm => model.realm,
+ :property => (model.ent_properties ? JSON::parse(model.ent_properties) : nil),
+ :created => Time.parse(model.created_at.to_s).xmlschema,
+ :operations => [
+ {
+ :href => context.destroy_machine_template_url(model.id),
+ :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
+ }
+ ]
+ })
+ end
+ end
+
+ protected
+ def attributes_to_copy
+ super + [ :machine_config, :machine_image ]
+ end
+end
diff --git a/server/lib/cimi/service/machine_template_create.rb b/server/lib/cimi/service/machine_template_create.rb
new file mode 100644
index 0000000..a47aa6c
--- /dev/null
+++ b/server/lib/cimi/service/machine_template_create.rb
@@ -0,0 +1,29 @@
+# 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::Service::MachineTemplateCreate < CIMI::Service::Base
+
+ def create
+ new_template = self.class.current_db.add_machine_template(
+ :name => name,
+ :description => description,
+ :machine_config => machine_config.href,
+ :machine_image => machine_image.href,
+ :ent_properties => property.to_json
+ )
+ CIMI::Service::MachineTemplate.from_db(new_template, context)
+ end
+
+end
diff --git a/server/lib/cimi/service/machine_volume.rb b/server/lib/cimi/service/machine_volume.rb
new file mode 100644
index 0000000..77c545b
--- /dev/null
+++ b/server/lib/cimi/service/machine_volume.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.
+
+class CIMI::Service::MachineVolume < CIMI::Service::Base
+
+ def self.find(instance_id, context, id=:all)
+ if id == :all
+ volumes = context.driver.storage_volumes(context.credentials)
+ volumes.inject([]) do |attached, vol|
+ id = context.machine_url(instance_id)+"/volumes/#{vol.id}"
+ attached << self.new(context, :values => {
+ :id => id,
+ :name => vol.id,
+ :description => "MachineVolume #{vol.id} for Machine #{instance_id}",
+ :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
+ :initial_location => vol.device,
+ :volume => {:href=>context.volume_url(vol.id)},
+ :operations => [{:href=>id, :rel => "delete" }]
+ }) if vol.instance_id == instance_id
+ attached
+ end
+ else
+ vol = context.driver.storage_volume(context.credentials, {:id=>id})
+ id = context.machine_url(instance_id)+"/volumes/#{vol.id}"
+ raise CIMI::Model::NotFound unless vol.instance_id == instance_id
+ self.new(context, :values => {
+ :id => id,
+ :name => vol.id,
+ :description => "MachineVolume #{vol.id} for Machine #{instance_id}",
+ :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
+ :initial_location => vol.device,
+ :volume => {:href=>context.volume_url(vol.id)},
+ :operations => [{:href=>id, :rel => "delete" }]
+ })
+ end
+ end
+
+ def self.find_to_attach_from_xml(xml_in, context)
+ xml = XmlSimple.xml_in(xml_in)
+ vol_id = xml["volume"].first["href"].split("/").last
+ location = xml["initialLocation"].first.strip
+ [vol_id, location]
+ end
+
+ def self.find_to_attach_from_json(json_in, context)
+ json = JSON.parse(json_in)
+ vol_id = json["volume"]["href"].split("/").last
+ location = json["initialLocation"]
+ [vol_id, location]
+ end
+
+
+ def self.collection_for_instance(instance_id, context)
+ machine_volumes = self.find(instance_id, context)
+ volumes_url = context.url("/machines/#{instance_id}/volumes")
+ # FIXME: Really ???
+ attach_url = volumes_url.singularize+"_attach"
+ CIMI::Model::MachineVolume.list(volumes_url, machine_volumes, :add_url => attach_url)
+ end
+
+
+end
diff --git a/server/lib/cimi/service/network.rb b/server/lib/cimi/service/network.rb
new file mode 100644
index 0000000..a58aa1e
--- /dev/null
+++ b/server/lib/cimi/service/network.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.
+
+class CIMI::Service::Network < CIMI::Service::Base
+
+ 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
+ if context.expand? :networkPorts
+ networks.each do |network|
+ network.network_ports = CIMI::Service::NetworkPort.collection_for_network(network.id, context)
+ end
+ end
+ networks
+ 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
+
+
+end
diff --git a/server/lib/cimi/service/network_configuration.rb b/server/lib/cimi/service/network_configuration.rb
new file mode 100644
index 0000000..a133c94
--- /dev/null
+++ b/server/lib/cimi/service/network_configuration.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::Service::NetworkConfiguration < CIMI::Service::Base
+
+ 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)
+ warn "This method should go into NetworkConfigurationCreate model"
+ end
+
+ def self.create_from_json(request_body, context)
+ warn "This method should go into NetworkConfigurationCreate model"
+ end
+
+end
diff --git a/server/lib/cimi/service/network_create.rb b/server/lib/cimi/service/network_create.rb
new file mode 100644
index 0000000..f191833
--- /dev/null
+++ b/server/lib/cimi/service/network_create.rb
@@ -0,0 +1,39 @@
+# 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::Service::NetworkCreate < CIMI::Service::Base
+
+ def create
+ if network_template.href?
+ template = resolve(network_template)
+ network_config = resolve(template.network_config)
+ forwarding_group = resolve(template.forwarding_group)
+ else
+ network_config = CIMI::Service::NetworkConfiguration.find(context.href_id(network_template.network_config.href, :network_configurations), context)
+ forwarding_group = CIMI::Service::ForwardingGroup.find(context.href_id(network_template.forwarding_group.href, :forwarding_groups), context)
+ end
+ params = {
+ :network_config => network_config,
+ :forwarding_group => forwarding_group,
+ :name => name,
+ :description => description,
+ :env => context # FIXME: We should not pass the context to the driver (!)
+ }
+ network = context.driver.create_network(context.credentials, params)
+ network.property = property if property
+ network.save
+ network
+ end
+end
diff --git a/server/lib/cimi/service/network_port.rb b/server/lib/cimi/service/network_port.rb
new file mode 100644
index 0000000..d400411
--- /dev/null
+++ b/server/lib/cimi/service/network_port.rb
@@ -0,0 +1,97 @@
+# 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::Service::NetworkPort < CIMI::Service::Base
+
+ def self.find(id, context)
+ if id==:all
+ context.driver.network_ports(context.credentials, {:env=>context})
+ else
+ context.driver.network_ports(context.credentials, {:id=>id, :env=>context})
+ end
+ end
+
+ # FIXME: This should go into NetworkPortCreate model
+ #
+ 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["networkPortTemplate"]["href"] #template by reference
+ network_port_config, network = get_by_reference(input, context)
+ else
+ if input["networkPortTemplate"]["networkPortConfig"]["href"] # configuration by reference
+ network_port_config = CIMI::Service::NetworkPortConfiguration.find(context.href_id(input["networkPortTemplate"]["networkPortConfig"]["href"],:network_port_configurations), context)
+ else #configuration by value
+ network_port_config = get_by_value(request_body, type)
+ end
+ network = CIMI::Service::Network.find(context.href_id(input["networkPortTemplate"]["network"]["href"], :networks), context)
+ end
+ params = {:network_port_config => network_port_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_network_port(context.credentials, params)
+ end
+
+ def self.delete!(id, context)
+ context.driver.delete_network_port(context.credentials, id)
+ end
+
+ def perform(action, context, &block)
+ begin
+ if context.driver.send(:"#{action.name}_network_port", context.credentials, self.name)
+ block.callback :success
+ else
+ raise "Operation #{action.name} failed to execute on the NetworkPort #{self.name} "
+ end
+ rescue => e
+ block.callback :failure, e.message
+ end
+ end
+
+ def self.collection_for_network(network_id, context)
+ net_url = context.network_url(network_id)
+ network_ports = CIMI::Service::NetworkPort.all(context)
+ ports_collection = network_ports.inject([]){|res, current| res << current if current.network.href == net_url ; res}
+ CIMI::Service::NetworkPortCollection.new(context, :values => {
+ :id => net_url+"/network_ports",
+ :name => 'default',
+ :created => Time.now,
+ :description => "#{context.driver.name.capitalize} NetworkPortCollection",
+ :count => ports_collection.size,
+ :network_ports => ports_collection
+ })
+ end
+
+ private
+
+ # FIXME: Are the methods below really needed???
+
+ def self.get_by_reference(input, context)
+ network_port_template = CIMI::Service::NetworkPortTemplate.find(context.href_id(input["networkPortTemplate"]["href"], :network_port_templates), context)
+ network_port_config = CIMI::Service::NetworkPortConfiguration.find(context.href_id(network_port_template.network_port_config.href, :network_port_configurations), context)
+ network = CIMI::Service::Network.find(context.href_id(network_port_template.network.href, :networks), context)
+ return network_port_config, network
+ end
+
+ def self.get_by_value(request_body, type)
+ if type == :xml
+ xml_arrays = XmlSimple.xml_in(request_body, {"NormaliseSpace"=>2})
+ network_port_config = CIMI::Service::NetworkPortConfiguration.from_xml(XmlSimple.xml_out(xml_arrays["networkPortTemplate"][0]["networkPortConfig"][0]))
+ else
+ json = JSON.parse(request_body)
+ network_port_config = CIMI::Service::NetworkPortConfiguration.from_json(JSON.generate(json["networkPortTemplate"]["networkPortConfig"]))
+ end
+ end
+
+
+end
diff --git a/server/lib/cimi/service/network_port_configuration.rb b/server/lib/cimi/service/network_port_configuration.rb
new file mode 100644
index 0000000..2d5c1ba
--- /dev/null
+++ b/server/lib/cimi/service/network_port_configuration.rb
@@ -0,0 +1,26 @@
+# 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::Service::NetworkPortConfiguration < CIMI::Service::Base
+
+ def self.find(id, context)
+ if id==:all
+ context.driver.network_port_configurations(context.credentials, {:env=>context})
+ else
+ context.driver.network_port_configurations(context.credentials, {:env=>context, :id=>id})
+ end
+ end
+
+end
diff --git a/server/lib/cimi/service/network_port_template.rb b/server/lib/cimi/service/network_port_template.rb
new file mode 100644
index 0000000..9f60493
--- /dev/null
+++ b/server/lib/cimi/service/network_port_template.rb
@@ -0,0 +1,26 @@
+# 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::Service::NetworkPortTemplate < CIMI::Service::Base
+
+ def self.find(id, context)
+ if id==:all
+ context.driver.network_port_templates(context.credentials, {:env=>context})
+ else
+ context.driver.network_port_templates(context.credentials, {:env=>context, :id=>id})
+ end
+ end
+
+end
diff --git a/server/lib/cimi/service/network_template.rb b/server/lib/cimi/service/network_template.rb
new file mode 100644
index 0000000..afe79f6
--- /dev/null
+++ b/server/lib/cimi/service/network_template.rb
@@ -0,0 +1,28 @@
+# 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::Service::NetworkTemplate < CIMI::Service::Base
+
+ 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/service/resource_metadata.rb b/server/lib/cimi/service/resource_metadata.rb
new file mode 100644
index 0000000..23924fb
--- /dev/null
+++ b/server/lib/cimi/service/resource_metadata.rb
@@ -0,0 +1,110 @@
+# 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::Service::ResourceMetadata < CIMI::Service::Base
+
+ def initialize(ctx, opts)
+ super
+ end
+
+ def self.find(id, context)
+ if id == :all
+ resource_metadata = []
+ CIMI::Model.root_entities.each do |resource_class|
+ meta = resource_metadata_for(resource_class, context)
+ resource_metadata << meta unless none_defined(meta)
+ end
+ return resource_metadata
+ else
+ resource_class = CIMI::Model.const_get("#{id.camelize}")
+ resource_metadata_for(resource_class, context)
+ end
+ end
+
+ def self.resource_metadata_for(resource_class, context)
+ attributes = rm_attributes_for(resource_class, context)
+ capabilities = rm_capabilities_for(resource_class, context)
+ actions = rm_actions_for(resource_class, context)
+ cimi_resource = resource_class.name.split("::").last
+ self.new(context, :values => {
+ :id => context.resource_metadata_url(cimi_resource.underscore),
+ :name => cimi_resource,
+ :type_uri => resource_class.resource_uri,
+ :attributes => attributes,
+ :capabilities => capabilities,
+ :actions => actions
+ })
+ end
+
+ private
+
+ def self.rm_attributes_for(resource_class, context)
+ return [] if resource_attributes[resource_class.name].nil?
+ resource_attributes[resource_class.name].map do |attr_name, attr_def|
+ if attr_def.has_key? :constraints
+ constraints = attr_def[:constraints].call(context)
+ else
+ constraints = []
+ end
+ {
+ :name => attr_name.to_s,
+ # TODO: We need to make this URI return description of this 'non-CIMI'
+ # attribute
+ :namespace => "http://deltacloud.org/cimi/#{resource_class.name.split('::').last}/#{attr_name}",
+ :type => translate_attr_type(attr_def[:type]),
+ :required => attr_def[:required] ? 'true' : 'false',
+ :constraints => constraints.map { |v| { :value => v }}
+ }
+ end
+ end
+
+ # FIXME: This method is srsly a nightmare ;-)
+ #
+ def self.rm_capabilities_for(resource_class,context)
+ cimi_object = resource_class.name.split("::").last.underscore.pluralize.to_sym
+ (context.driver.class.features[cimi_object] || []).inject([]) do |res, cur|
+ feat = CIMI::FakeCollection.feature(cur)
+ values = (context.driver.class.constraints[cimi_object][feat.name][:values] || []).inject([]) do |vals, val|
+ vals << val
+ vals
+ end
+ res << {:name => feat.name.to_s.camelize,
+ :uri => CMWG_NAMESPACE+"/capability/#{cimi_object.to_s.camelize.singularize}/#{feat.name.to_s.camelize}",
+ :description => feat.description,
+ :value => values.join(",") }
+ res
+ end
+ end
+
+ def self.rm_actions_for(resource_class, context)
+ []
+ end
+
+ def self.translate_attr_type(type)
+ case type
+ when :href then 'URI'
+ when :text then 'string'
+ when :boolean then 'boolean'
+ else 'text'
+ end
+ end
+
+ def self.none_defined(metadata)
+ return true if metadata.capabilities.empty? && metadata.capabilities.empty? && metadata.attributes.empty?
+ return false
+ end
+
+
+end
diff --git a/server/lib/cimi/service/system.rb b/server/lib/cimi/service/system.rb
new file mode 100644
index 0000000..daad428
--- /dev/null
+++ b/server/lib/cimi/service/system.rb
@@ -0,0 +1,45 @@
+# 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::Service::System < CIMI::Service::Base
+
+ def self.find(id, context)
+ if id == :all
+ systems = context.driver.systems(context.credentials, {:env=>context})
+ else
+ systems = context.driver.systems(context.credentials, {:env=>context, :id=>id})
+ raise CIMI::Model::NotFound unless systems.first
+ systems.first
+ end
+ end
+
+ def perform(action, context, &block)
+ begin
+ if context.driver.send(:"#{action.name}_system", context.credentials, self.id.split("/").last)
+ block.callback :success
+ else
+ raise "Operation failed to execute on given System"
+ end
+ rescue => e
+ block.callback :failure, e.message
+ end
+ end
+
+ def self.delete!(id, context)
+ context.driver.destroy_system(context.credentials, id)
+ end
+
+
+end
diff --git a/server/lib/cimi/service/system_template.rb b/server/lib/cimi/service/system_template.rb
new file mode 100644
index 0000000..785f79d
--- /dev/null
+++ b/server/lib/cimi/service/system_template.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.
+
+class CIMI::Service::SystemTemplate < CIMI::Service::Base
+
+ def self.find(id, context)
+ if id == :all
+ templates = context.driver.system_templates(context.credentials, {:env=>context})
+ else
+ templates = context.driver.system_templates(context.credentials, {:env=>context, :id=>id})
+ raise CIMI::Model::NotFound unless templates.first
+ templates.first
+ end
+ end
+
+ def self.delete!(id, context)
+ context.driver.destroy_system_template(context.credentials, id)
+ end
+
+end
diff --git a/server/lib/cimi/service/volume.rb b/server/lib/cimi/service/volume.rb
new file mode 100644
index 0000000..2e38691
--- /dev/null
+++ b/server/lib/cimi/service/volume.rb
@@ -0,0 +1,81 @@
+# 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::Service::Volume < CIMI::Service::Base
+
+ def self.find(id, context)
+ creds = context.credentials
+ if id == :all
+ volumes = context.driver.storage_volumes(creds)
+ volumes.collect{ |volume| from_storage_volume(volume, context) }
+ else
+ volume = context.driver.storage_volumes(creds, :id => id).first
+ raise CIMI::Model::NotFound unless volume
+ from_storage_volume(volume, context)
+ end
+ end
+
+ def self.all(context); find(:all, context); end
+
+ def self.delete!(id, context)
+ context.driver.destroy_storage_volume(context.credentials, {:id=>id} )
+ new(context, :values => { :id => id }).destroy
+ end
+
+ def self.find_to_attach_from_json(json_in, context)
+ json = JSON.parse(json_in)
+ json["volumes"].map{|v| {:volume=>self.find(v["volume"]["href"].split("/volumes/").last, context),
+ :initial_location=>v["initialLocation"] }}
+ end
+
+ def self.find_to_attach_from_xml(xml_in, context)
+ xml = XmlSimple.xml_in(xml_in)
+ xml["volume"].map{|v| {:volume => self.find(v["href"].split("/volumes/").last, context),
+ :initial_location=>v["initialLocation"] }}
+ end
+
+ def self.from_storage_volume(volume, context)
+ self.new(context, :values => {
+ :name => volume.id,
+ :created => volume.created.nil? ? nil : Time.parse(volume.created).xmlschema,
+ :id => context.volume_url(volume.id),
+ :capacity => context.to_kibibyte(volume.capacity, 'GB'),
+ :bootable => "false", #fixme ... will vary... ec2 doesn't expose this
+ :snapshots => [], #fixme...
+ :type => 'http://schemas.dmtf.org/cimi/1/mapped',
+ :state => volume.state == 'IN-USE' ? 'AVAILABLE' : volume.state,
+ :meters => [],
+ :operations => [{:href=> context.volume_url(volume.id), :rel => "delete"}]
+ })
+ end
+
+ def self.collection_for_instance(instance_id, context)
+ instance = context.driver.instance(context.credentials, :id => instance_id)
+ volumes = instance.storage_volumes.map do |mappings|
+ mappings.keys.map do |volume_id|
+ from_storage_volume(context.driver.storage_volume(context.credentials, :id => volume_id), context)
+ end
+ end.flatten
+ CIMI::Service::VolumeCollection.new(context, :values => {
+ :id => context.url("/machines/#{instance_id}/volumes"),
+ :name => 'default',
+ :count => volumes.size,
+ :description => "Volume collection for Machine #{instance_id}",
+ :entries => volumes
+ })
+ end
+
+
+end
diff --git a/server/lib/cimi/service/volume_configuration.rb b/server/lib/cimi/service/volume_configuration.rb
new file mode 100644
index 0000000..ebb2c7c
--- /dev/null
+++ b/server/lib/cimi/service/volume_configuration.rb
@@ -0,0 +1,92 @@
+# 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::Service::VolumeConfiguration < CIMI::Service::Base
+
+ # FIXME: These two should go into VolumeConfigurationCreate
+ #
+ def self.create_from_json(body, context)
+ json = JSON.parse(body)
+ new_config = current_db.add_volume_configuration(
+ :name => json['name'],
+ :description => json['description'],
+ :format => json['format'],
+ :capacity => json['capacity'],
+ :ent_properties => (json['properties'] || {}).to_json
+ )
+ from_db(new_config, context)
+ end
+
+ def self.create_from_xml(body, context)
+ xml = XmlSimple.xml_in(body)
+ xml['property'] ||= []
+ new_config = current_db.add_volume_configuration(
+ :name => xml['name'].first,
+ :description => xml['description'].first,
+ :format => xml['format'].first,
+ :capacity => xml['capacity'].first,
+ :ent_properties => JSON::dump((xml['property'] || {}).inject({}){ |r, p| r[p['key']]=p['content']; r })
+ )
+ from_db(new_config, context)
+ end
+
+ def self.delete!(id, context)
+ current_db.volume_configurations.first(:id => id).destroy
+ end
+
+ def self.find(id, context)
+ if id==:all
+ if context.driver.respond_to? :volume_configurations
+ context.driver.volume_configurations(context.credentials, {:env=>context})
+ else
+ current_db.volume_configurations.map { |t| from_db(t, context) }
+ end
+ else
+ if context.driver.respond_to? :volume_configuration
+ context.driver.volume_configuration(context.credentials, id, :env=>context)
+ else
+ config = current_db.volume_configurations_dataset.first(:id => id)
+ raise CIMI::Model::NotFound unless config
+ from_db(config, context)
+ end
+ end
+ end
+
+ protected
+ def attributes_to_copy
+ super + [ :format, :capacity ]
+ end
+
+ private
+
+ def self.from_db(model, context)
+ self.new(context, :values => {
+ :id => context.volume_configuration_url(model.id),
+ :name => model.name,
+ :description => model.description,
+ :format => model.format,
+ :capacity => context.to_kibibyte(model.capacity, "GB"),
+ :property => (model.ent_properties ? JSON::parse(model.ent_properties) : nil),
+ :operations => [
+ {
+ :href => context.destroy_volume_configuration_url(model.id),
+ :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
+ }
+ ]
+ })
+ end
+
+
+end
diff --git a/server/lib/cimi/service/volume_create.rb b/server/lib/cimi/service/volume_create.rb
new file mode 100644
index 0000000..6d9f3d0
--- /dev/null
+++ b/server/lib/cimi/service/volume_create.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.
+
+class CIMI::Service::VolumeCreate < CIMI::Service::Base
+
+ def create
+ template = resolve(volume_template)
+ volume_image = resolve(template.volume_image)
+ volume_config = resolve(template.volume_config)
+
+ params = {
+ :name => name,
+ :capacity => volume_config.capacity,
+ :snapshot_id => ref_id(volume_image.id),
+ }
+
+ unless context.driver.respond_to? :create_storage_volume
+ raise Deltacloud::Exceptions.exception_from_status(
+ 501,
+ "Creating Volume is not supported by the current driver"
+ )
+ end
+
+ volume = context.driver.create_storage_volume(context.credentials, params)
+
+ result = CIMI::Service::Volume.from_storage_volume(volume, context)
+ result.name = name if name
+ result.description = description if description
+ result.property = property if property
+ result.save
+ result
+ end
+
+
+end
diff --git a/server/lib/cimi/service/volume_image.rb b/server/lib/cimi/service/volume_image.rb
new file mode 100644
index 0000000..5d57368
--- /dev/null
+++ b/server/lib/cimi/service/volume_image.rb
@@ -0,0 +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.
+
+class CIMI::Service::VolumeImage < CIMI::Service::Base
+
+ def self.find(id, context)
+ creds = context.credentials
+ if id == :all
+ snapshots = context.driver.storage_snapshots(creds)
+ snapshots.collect{ |snapshot| from_storage_snapshot(snapshot, context) }
+ else
+ snapshot = context.driver.storage_snapshots(creds, id => :id).first
+ raise CIMI::Model::NotFound unless snapshot
+ from_storage_snapshot(snapshot, context)
+ end
+ end
+
+ def self.delete!(vol_image_id, context)
+ context.driver.destroy_storage_snapshot(context.credentials, {:id=>vol_image_id})
+ end
+
+ def self.from_storage_snapshot(snapshot, context)
+ self.new( context, :values => {
+ :name => snapshot.name,
+ :description => snapshot.description,
+ :created => snapshot.created.nil? ? nil : Time.parse(snapshot.created).xmlschema,
+ :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/service/volume_image_create.rb b/server/lib/cimi/service/volume_image_create.rb
new file mode 100644
index 0000000..f75b2ef
--- /dev/null
+++ b/server/lib/cimi/service/volume_image_create.rb
@@ -0,0 +1,42 @@
+# 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::Service::VolumeImageCreate < CIMI::Service::Base
+
+ def create
+ params = {
+ :volume_id => context.href_id(image_location.href, :volumes),
+ :name => name,
+ :description => description
+ }
+
+ unless context.driver.respond_to? :create_storage_snapshot
+ raise Deltacloud::Exceptions.exception_from_status(
+ 501,
+ 'Creating VolumeImage is not supported by the current driver'
+ )
+ end
+
+ new_snapshot = context.driver.create_storage_snapshot(context.credentials, params)
+ result = CIMI::Service::VolumeImage.from_storage_snapshot(new_snapshot, context)
+ result.name= name unless new_snapshot.name
+ result.description = description unless new_snapshot.description
+ result.property = property if property
+ result.save
+ result
+ end
+
+
+end
diff --git a/server/lib/cimi/service/volume_template.rb b/server/lib/cimi/service/volume_template.rb
new file mode 100644
index 0000000..d95ba72
--- /dev/null
+++ b/server/lib/cimi/service/volume_template.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.
+
+class CIMI::Service::VolumeTemplate < CIMI::Service::Base
+
+ def self.find(id, context)
+ if id==:all
+ if context.driver.respond_to? :volume_templates
+ context.driver.volume_templates(context.credentials, {:env=>context})
+ else
+ current_db.volume_templates.map { |t| from_db(t, context) }
+ end
+ else
+ if context.driver.respond_to? :volume_template
+ context.driver.volume_template(context.credentials, id, :env=>context)
+ else
+ template = current_db.volume_templates_dataset.first(:id => id)
+ raise CIMI::Model::NotFound unless template
+ from_db(template, context)
+ end
+ end
+ end
+
+ def self.delete!(id, context)
+ current_db.volume_templates.first(:id => id).destroy
+ end
+
+ def self.from_db(model, context)
+ self.new(context, :values => {
+ :id => context.volume_template_url(model.id),
+ :name => model.name,
+ :description => model.description,
+ :volume_config => {:href => model.volume_config},
+ :volume_image => {:href => model.volume_image},
+ :property => (model.ent_properties ? JSON::parse(model.ent_properties) : nil),
+ :operations => [
+ {
+ :href => context.destroy_volume_template_url(model.id),
+ :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
+ }
+ ]
+ })
+ end
+
+ protected
+ def attributes_to_copy
+ super + [ :machine_config, :machine_image ]
+ end
+end
diff --git a/server/lib/cimi/service/volume_template_create.rb b/server/lib/cimi/service/volume_template_create.rb
new file mode 100644
index 0000000..b05e0f4
--- /dev/null
+++ b/server/lib/cimi/service/volume_template_create.rb
@@ -0,0 +1,29 @@
+# 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::Service::VolumeTemplateCreate < CIMI::Service::Base
+
+ def create
+ new_template = self.class.current_db.add_volume_template(
+ :name => name,
+ :description => description,
+ :volume_config => volume_config.href,
+ :volume_image => volume_image.href,
+ :ent_properties => property.to_json
+ )
+ CIMI::Service::VolumeTemplate.from_db(new_template, context)
+ end
+
+end
--
1.8.1.4
[PATCH 14/14] CIMI: remove unused model methods
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
Collection.all and Resource.all_uri do not make sense any more since they
ultimately depend on find, which is now a service method.
---
server/lib/cimi/models/collection.rb | 6 ------
server/lib/cimi/models/resource.rb | 6 ------
2 files changed, 12 deletions(-)
diff --git a/server/lib/cimi/models/collection.rb b/server/lib/cimi/models/collection.rb
index cc95ab7..b06a1e9 100644
--- a/server/lib/cimi/models/collection.rb
+++ b/server/lib/cimi/models/collection.rb
@@ -130,11 +130,5 @@ module CIMI::Model
end
collection_class.new(params)
end
-
- def all(context)
- find :all, context
- end
-
end
-
end
diff --git a/server/lib/cimi/models/resource.rb b/server/lib/cimi/models/resource.rb
index 246b135..9f5bb66 100644
--- a/server/lib/cimi/models/resource.rb
+++ b/server/lib/cimi/models/resource.rb
@@ -89,12 +89,6 @@ module CIMI
end
end
- # Return Array of links to current CIMI object
- #
- def all_uri(context)
- self.all(context).map { |e| { :href => e.id } }
- end
-
# Construct a new object from the XML representation +xml+
def from_xml(text)
xml = XmlSimple.xml_in(text, :force_content => true)
--
1.8.1.4
[PATCH 01/14] CIMI Models: rename hash in DSL to hash_map
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
Since 'hash' is used for putting objects into Hash, overriding it as a
class method causes surprises when a class is used as a hash key.
---
server/lib/cimi/models/base.rb | 2 +-
server/lib/cimi/models/schema.rb | 2 +-
server/lib/cimi/models/system_template.rb | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
index e8c1104..a207bed 100644
--- a/server/lib/cimi/models/base.rb
+++ b/server/lib/cimi/models/base.rb
@@ -121,7 +121,7 @@ module CIMI::Model
# Common attributes for all resources
#
text :id, :name, :description, :created, :updated
- hash :property
+ hash_map :property
def initialize(values = {})
super(values)
diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
index 4ce16b9..b4e9377 100644
--- a/server/lib/cimi/models/schema.rb
+++ b/server/lib/cimi/models/schema.rb
@@ -461,7 +461,7 @@ class CIMI::Model::Schema
add_attributes!([name, opts], Ref)
end
- def hash(name)
+ def hash_map(name)
add_attributes!([name, {}], Hash)
end
diff --git a/server/lib/cimi/models/system_template.rb b/server/lib/cimi/models/system_template.rb
index 09cd9b0..6a6e1f2 100644
--- a/server/lib/cimi/models/system_template.rb
+++ b/server/lib/cimi/models/system_template.rb
@@ -19,7 +19,7 @@ class CIMI::Model::SystemTemplate < CIMI::Model::Base
array :component_descriptors do
text :name, :description
- hash :properties
+ hash_map :properties
text :type
#component_template, comprises:
# struct :machine_template, :class => CIMI::Model::MachineTemplate
--
1.8.1.4
Re: RFC: Separate CIMI (de)serialization from server functionality
(rev 3)
Posted by David Lutterkort <lu...@redhat.com>.
On Wed, 2013-03-13 at 17:33 -0700, lutter@redhat.com wrote:
> This is the third take on splitting server-side functionality out of our
> models. As in previous attempts, CIMI::Model is now solely concerned with
> (se)serialization, whereas CIMI::Service does all the actual server-side
> functionality.
>
> FWIW, the unit and blackbox tests all pass for me with this patch series
> ...
>
> Also recorded as http://tracker.deltacloud.org/set/389
Actually, the RFC in the subject line was a mistake; I would like to
commit these unless there are good reasons not to.
David
[PATCH 07/14] CIMI: Added Service::Base#parse method
Posted by lu...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>
Make possible to call .parse on Service models from
Rabbit collections.
Signed-off-by: Michal fojtik <mf...@redhat.com>
TrackedAt: http://tracker.deltacloud.org/patch/a16895d3bb6ab3596fb77fee96d041e01c3a1747
---
server/lib/cimi/service/base.rb | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/server/lib/cimi/service/base.rb b/server/lib/cimi/service/base.rb
index 8daa183..fa845d0 100644
--- a/server/lib/cimi/service/base.rb
+++ b/server/lib/cimi/service/base.rb
@@ -50,6 +50,13 @@ module CIMI::Service
define_method(:"#{name}=") { |newval| self[name] = newval }
end
end
+
+ def parse(context)
+ req = context.request
+ model = model_class.parse(req.body, req.content_type)
+ new(context, :model => model)
+ end
+
end
def initialize(context, opts)
--
1.8.1.4
[PATCH 12/14] CIMI::Model::Schema::Ref: do not support looking up the referenced object
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
This now depends on service objects and can therefore not be used from models
---
server/lib/cimi/models/schema.rb | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
index b6651a7..5a2049b 100644
--- a/server/lib/cimi/models/schema.rb
+++ b/server/lib/cimi/models/schema.rb
@@ -191,20 +191,6 @@ class CIMI::Model::Schema
else
@klass = Class.new(opts[:class]) do |m|
scalar :href
-
- def ref_id(ctx)
- # FIXME: We should use ctx's routes to split
- # out the :id
- href.split('/').last
- end
-
- def find(ctx)
- klass.find(ref_id(ctx), ctx)
- end
-
- def klass
- self.class.superclass
- end
end
CIMI::Model::const_set(refname, @klass)
end
--
1.8.1.4
[PATCH 13/14] CIMI: a very simple test of volume creation
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
---
server/tests/cimi/collections/volumes_test.rb | 42 +++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
create mode 100644 server/tests/cimi/collections/volumes_test.rb
diff --git a/server/tests/cimi/collections/volumes_test.rb b/server/tests/cimi/collections/volumes_test.rb
new file mode 100644
index 0000000..0b55d06
--- /dev/null
+++ b/server/tests/cimi/collections/volumes_test.rb
@@ -0,0 +1,42 @@
+require 'rubygems'
+require 'require_relative' if RUBY_VERSION < '1.9'
+require 'minitest/autorun'
+require_relative './common.rb'
+
+describe CIMI::Collections::Volumes do
+
+ def create_model(model_class, attr)
+ model = model_class.new(attr)
+ svc_class = CIMI::Service::const_get(model_class.name.split('::').last)
+ svc_class.new(nil, :model => model).save
+ model
+ end
+
+ before do
+ def app; run_frontend(:cimi) end
+ authorize 'mockuser', 'mockpassword'
+
+ @config = create_model CIMI::Model::VolumeConfiguration,
+ :id => "http://localhost:3001/cimi/volume_configurations/1",
+ :name => "volume_config",
+ :format => "ext3",
+ :capacity => 1
+
+ @collection = CIMI::Collections.collection(:volumes)
+ end
+
+ def make_volume_create
+ vt = CIMI::Model::VolumeTemplate.new
+ vt.volume_config.href = @config.id
+ CIMI::Model::VolumeCreate.new(:name => "new_cimi_volume_#{Time.now.to_i}",
+ :volume_template => vt)
+ end
+
+ it 'allows creation of a new volume' do
+ vc = make_volume_create
+ post '/cimi/volumes', vc.to_json, "CONTENT_TYPE" => "application/json"
+
+ last_response.status.must_equal 201
+ model.name.must_equal vc.name
+ end
+end
--
1.8.1.4
[PATCH 09/14] CIMI: Use CIMI::Service namespace in Rabbit collections
Posted by lu...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>
Signed-off-by: Michal fojtik <mf...@redhat.com>
TrackedAt: http://tracker.deltacloud.org/patch/4f61366999285c2dfbc497bdc0581c8b657d9191
---
server/lib/cimi/collections/address_templates.rb | 8 ++---
server/lib/cimi/collections/addresses.rb | 8 ++---
server/lib/cimi/collections/cloud_entry_point.rb | 2 +-
server/lib/cimi/collections/credentials.rb | 4 +--
server/lib/cimi/collections/machine_images.rb | 4 +--
server/lib/cimi/collections/machine_templates.rb | 10 +++---
server/lib/cimi/collections/machines.rb | 36 ++++++++--------------
server/lib/cimi/collections/network_ports.rb | 6 ++--
server/lib/cimi/collections/networks.rb | 4 +--
server/lib/cimi/collections/resource_metadata.rb | 4 +--
server/lib/cimi/collections/system_templates.rb | 10 +++---
server/lib/cimi/collections/systems.rb | 9 +++---
.../lib/cimi/collections/volume_configurations.rb | 8 ++---
server/lib/cimi/collections/volume_images.rb | 6 ++--
server/lib/cimi/collections/volume_templates.rb | 6 ++--
server/lib/cimi/collections/volumes.rb | 4 +--
16 files changed, 58 insertions(+), 71 deletions(-)
diff --git a/server/lib/cimi/collections/address_templates.rb b/server/lib/cimi/collections/address_templates.rb
index 72e167d..99fe745 100644
--- a/server/lib/cimi/collections/address_templates.rb
+++ b/server/lib/cimi/collections/address_templates.rb
@@ -34,7 +34,7 @@ module CIMI::Collections
operation :show do
description 'Show a specific AddressTemplate'
control do
- address_template = CIMI::Model::AddressTemplate.find(params[:id], self)
+ address_template = AddressTemplate.find(params[:id], self)
respond_to do |format|
format.xml {address_template.to_xml}
format.json {address_template.to_json}
@@ -45,8 +45,8 @@ module CIMI::Collections
operation :create do
description "Create new AddressTemplate"
control do
- addr_templ = CIMI::Model::AddressTemplateCreate.parse(request.body, request.content_type)
- new_address_template = addr_templ.create(self)
+ addr_templ = AddressTemplateCreate.parse(self)
+ new_address_template = addr_templ.create
headers_for_create new_address_template
respond_to do |format|
format.json { new_address_template.to_json }
@@ -58,7 +58,7 @@ module CIMI::Collections
operation :destroy do
description "Delete a specified AddressTemplate"
control do
- CIMI::Model::AddressTemplate.delete!(params[:id], self)
+ AddressTemplate.delete!(params[:id], self)
no_content_with_status(200)
end
end
diff --git a/server/lib/cimi/collections/addresses.rb b/server/lib/cimi/collections/addresses.rb
index c34068d..682cce4 100644
--- a/server/lib/cimi/collections/addresses.rb
+++ b/server/lib/cimi/collections/addresses.rb
@@ -36,7 +36,7 @@ module CIMI::Collections
operation :show, :with_capability => :address do
description 'Show a specific Address'
control do
- address = CIMI::Model::Address.find(params[:id], self)
+ address = Address.find(params[:id], self)
respond_to do |format|
format.xml {address.to_xml}
format.json {address.to_json}
@@ -47,8 +47,8 @@ module CIMI::Collections
operation :create, :with_capability => :create_address do
description "Create a new Address"
control do
- addr = CIMI::Model::AddressCreate.parse(request.body, request.content_type)
- address = addr.create(self)
+ addr = AddressCreate.parse(self)
+ address = addr.create
respond_to do |format|
format.xml { address.to_xml }
format.json { address.to_json }
@@ -60,7 +60,7 @@ module CIMI::Collections
description "Delete a specified Address"
param :id, :string, :required
control do
- CIMI::Model::Address.delete!(params[:id], self)
+ Address.delete!(params[:id], self)
no_content_with_status(200)
end
end
diff --git a/server/lib/cimi/collections/cloud_entry_point.rb b/server/lib/cimi/collections/cloud_entry_point.rb
index b1240bc..37b47b2 100644
--- a/server/lib/cimi/collections/cloud_entry_point.rb
+++ b/server/lib/cimi/collections/cloud_entry_point.rb
@@ -28,7 +28,7 @@ module CIMI::Collections
if params[:force_auth]
halt 401 unless driver.valid_credentials?(credentials)
end
- entry_point = CIMI::Model::CloudEntryPoint.create(self)
+ entry_point = CIMI::Service::CloudEntryPoint.create(self)
respond_to do |format|
format.xml { entry_point.to_xml }
format.json { entry_point.to_json }
diff --git a/server/lib/cimi/collections/credentials.rb b/server/lib/cimi/collections/credentials.rb
index 8d90be6..0cd44b9 100644
--- a/server/lib/cimi/collections/credentials.rb
+++ b/server/lib/cimi/collections/credentials.rb
@@ -46,8 +46,8 @@ module CIMI::Collections
operation :create, :with_capability => :create_key do
description "Show specific machine admin"
control do
- c = CIMI::Model::CredentialCreate.parse(request.body, request.content_type)
- new_admin = c.create(self)
+ c = CredentialCreate.parse(self)
+ new_admin = c.create
headers_for_create new_admin
respond_to do |format|
format.json { new_admin.to_json }
diff --git a/server/lib/cimi/collections/machine_images.rb b/server/lib/cimi/collections/machine_images.rb
index ce9fa6a..66c74c2 100644
--- a/server/lib/cimi/collections/machine_images.rb
+++ b/server/lib/cimi/collections/machine_images.rb
@@ -46,8 +46,8 @@ module CIMI::Collections
operation :create, :with_capability => :create_image do
description "Create a new machine image."
control do
- mi = MachineImageCreate.parse(request.body, request.content_type)
- machine_image = mi.create(self)
+ mi = MachineImageCreate.parse(self)
+ machine_image = mi.create
headers_for_create machine_image
respond_to do |format|
format.xml { machine_image.to_xml }
diff --git a/server/lib/cimi/collections/machine_templates.rb b/server/lib/cimi/collections/machine_templates.rb
index 6bdd1f2..fcdafcc 100644
--- a/server/lib/cimi/collections/machine_templates.rb
+++ b/server/lib/cimi/collections/machine_templates.rb
@@ -23,7 +23,7 @@ module CIMI::Collections
operation :index do
description "List all machine templates"
control do
- machine_templates = CIMI::Model::MachineTemplate.list(self).select_by(params['$select'])
+ machine_templates = MachineTemplate.list(self)
respond_to do |format|
format.xml { machine_templates.to_xml }
format.json { machine_templates.to_json }
@@ -34,7 +34,7 @@ module CIMI::Collections
operation :show do
description "Show specific machine template"
control do
- machine_template = CIMI::Model::MachineTemplate.find(params[:id], self)
+ machine_template = MachineTemplate.find(params[:id], self)
respond_to do |format|
format.xml { machine_template.to_xml }
format.json { machine_template.to_json }
@@ -45,8 +45,8 @@ module CIMI::Collections
operation :create do
description "Create new machine template"
control do
- mt = CIMI::Model::MachineTemplateCreate.parse(request.body, request.content_type)
- new_machine_template = mt.create(self)
+ mt = MachineTemplateCreate.parse(self)
+ new_machine_template = mt.create
headers_for_create new_machine_template
respond_to do |format|
format.json { new_machine_template.to_json }
@@ -58,7 +58,7 @@ module CIMI::Collections
operation :destroy do
description "Delete a specified machine template"
control do
- CIMI::Model::MachineTemplate.delete!(params[:id], self)
+ MachineTemplate.delete!(params[:id], self)
no_content_with_status(200)
end
end
diff --git a/server/lib/cimi/collections/machines.rb b/server/lib/cimi/collections/machines.rb
index f3cb62a..f74b02b 100644
--- a/server/lib/cimi/collections/machines.rb
+++ b/server/lib/cimi/collections/machines.rb
@@ -46,8 +46,8 @@ module CIMI::Collections
operation :create, :with_capability => :create_instance do
description "Create a new Machine entity."
control do
- mc = MachineCreate.parse(request.body, request.content_type)
- new_machine = mc.create(self)
+ mc = MachineCreate.parse(self)
+ new_machine = mc.create
headers_for_create new_machine
respond_to do |format|
format.json { new_machine.to_json }
@@ -69,12 +69,8 @@ module CIMI::Collections
param :id, :string, :required
control do
machine = Machine.find(params[:id], self)
- if current_content_type == :json
- action = Action.from_json(request.body.read)
- else
- action = Action.from_xml(request.body.read)
- end
- machine.perform(action, self) do |operation|
+ action = Action.parse(self)
+ machine.perform(action) do |operation|
no_content_with_status(202) if operation.success?
# Handle errors using operation.failure?
end
@@ -86,12 +82,8 @@ module CIMI::Collections
param :id, :string, :required
control do
machine = Machine.find(params[:id], self)
- if current_content_type == :json
- action = Action.from_json(request.body.read.gsub("restart", "reboot"))
- else
- action = Action.from_xml(request.body.read.gsub("restart", "reboot"))
- end
- machine.perform(action, self) do |operation|
+ action = Action.parse(self)
+ machine.perform(action) do |operation|
no_content_with_status(202) if operation.success?
# Handle errors using operation.failure?
end
@@ -103,12 +95,8 @@ module CIMI::Collections
param :id, :string, :required
control do
machine = Machine.find(params[:id], self)
- if current_content_type == :json
- action = Action.from_json(request.body.read)
- else
- action = Action.from_xml(request.body.read)
- end
- machine.perform(action, self) do |operation|
+ action = Action.parse(self)
+ machine.perform(action) do |operation|
no_content_with_status(202) if operation.success?
# Handle errors using operation.failure?
end
@@ -119,7 +107,7 @@ module CIMI::Collections
description "Retrieve the Machine's DiskCollection"
param :id, :string, :required
control do
- disks = CIMI::Model::Disk.collection_for_instance(params[:id], self)
+ disks = Disk.collection_for_instance(params[:id], self)
respond_to do |format|
format.json {disks.to_json}
format.xml {disks.to_xml}
@@ -133,7 +121,7 @@ module CIMI::Collections
operation :index, :with_capability => :storage_volumes do
description "Retrieve the Machine's MachineVolumeCollection"
control do
- volumes = CIMI::Model::MachineVolume.collection_for_instance(params[:id], self)
+ volumes = MachineVolume.collection_for_instance(params[:id], self)
respond_to do |format|
format.json {volumes.to_json}
format.xml {volumes.to_xml}
@@ -144,7 +132,7 @@ module CIMI::Collections
operation :show, :with_capability => :storage_volumes do
description "Retrieve a Machine's specific MachineVolume"
control do
- volume = CIMI::Model::MachineVolume.find(params[:id], self, params[:vol_id])
+ volume = MachineVolume.find(params[:id], self, params[:vol_id])
respond_to do |format|
format.json {volume.to_json}
format.xml {volume.to_xml}
@@ -155,7 +143,7 @@ module CIMI::Collections
operation :destroy, :with_capability => :detach_storage_volume do
description "Remove/detach a volume from the Machine's MachineVolumeCollection"
control do
- machine_volume = CIMI::Model::MachineVolume.find(params[:id], self, params[:vol_id])
+ machine_volume = MachineVolume.find(params[:id], self, params[:vol_id])
location = machine_volume.initial_location
machine_volumes = Machine.detach_volume(params[:vol_id], location, self)
respond_to do |format|
diff --git a/server/lib/cimi/collections/network_ports.rb b/server/lib/cimi/collections/network_ports.rb
index 28c2df4..021ae7b 100644
--- a/server/lib/cimi/collections/network_ports.rb
+++ b/server/lib/cimi/collections/network_ports.rb
@@ -48,9 +48,9 @@ module CIMI::Collections
description "Create a new NetworkPort"
control do
if current_content_type == :json
- network_port = CIMI::Model::NetworkPort.create(request.body.read, self, :json)
+ network_port = NetworkPort.create(request.body.read, self, :json)
else
- network_port = CIMI::Model::NetworkPort.create(request.body.read, self, :xml)
+ network_port = NetworkPort.create(request.body.read, self, :xml)
end
respond_to do |format|
format.xml { network_port.to_xml }
@@ -62,7 +62,7 @@ module CIMI::Collections
operation :destroy, :with_capability => :delete_network_port do
description "Delete a specified NetworkPort"
control do
- CIMI::Model::NetworkPort.delete!(params[:id], self)
+ NetworkPort.delete!(params[:id], self)
no_content_with_status(200)
end
end
diff --git a/server/lib/cimi/collections/networks.rb b/server/lib/cimi/collections/networks.rb
index 0f32827..f3d6fc9 100644
--- a/server/lib/cimi/collections/networks.rb
+++ b/server/lib/cimi/collections/networks.rb
@@ -46,8 +46,8 @@ module CIMI::Collections
operation :create, :with_capability => :create_network do
description "Create a new Network"
control do
- n = CIMI::Model::NetworkCreate.parse(request.body, request.content_type)
- network = n.create(self)
+ n = NetworkCreate.parse(self)
+ network = n.create
respond_to do |format|
format.xml { network.to_xml}
format.json { network.to_json }
diff --git a/server/lib/cimi/collections/resource_metadata.rb b/server/lib/cimi/collections/resource_metadata.rb
index 54de02a..f27ee33 100644
--- a/server/lib/cimi/collections/resource_metadata.rb
+++ b/server/lib/cimi/collections/resource_metadata.rb
@@ -21,7 +21,7 @@ module CIMI::Collections
operation :index do
description "List all resource metadata defined for this provider"
control do
- resource_metadata = CIMI::Model::ResourceMetadata.list(self)
+ resource_metadata = CIMI::Service::ResourceMetadata.list(self)
respond_to do |format|
format.xml{resource_metadata.to_xml}
format.json{resource_metadata.to_json}
@@ -32,7 +32,7 @@ module CIMI::Collections
operation :show do
description "Get the resource metadata for a specific collection"
control do
- resource_metadata = CIMI::Model::ResourceMetadata.find(params[:id], self)
+ resource_metadata = CIMI::Service::ResourceMetadata.find(params[:id], self)
respond_to do |format|
format.xml{resource_metadata.to_xml}
format.json{resource_metadata.to_json}
diff --git a/server/lib/cimi/collections/system_templates.rb b/server/lib/cimi/collections/system_templates.rb
index 7ab0d3e..fe27cd3 100644
--- a/server/lib/cimi/collections/system_templates.rb
+++ b/server/lib/cimi/collections/system_templates.rb
@@ -23,7 +23,7 @@ module CIMI::Collections
operation :index, :with_capability => :system_templates do
description "List all system templates"
control do
- system_templates = CIMI::Model::SystemTemplate.list(self).select_by(params['$select'])
+ system_templates = SystemTemplate.list(self).select_by(params['$select'])
respond_to do |format|
format.xml { system_templates.to_xml }
format.json { system_templates.to_json }
@@ -34,7 +34,7 @@ module CIMI::Collections
operation :show, :with_capability => :system_templates do
description "Show specific system template"
control do
- system_template = CIMI::Model::SystemTemplate.find(params[:id], self)
+ system_template = SystemTemplate.find(params[:id], self)
respond_to do |format|
format.xml { system_template.to_xml }
format.json { system_template.to_json }
@@ -46,9 +46,9 @@ module CIMI::Collections
description "Create new system template"
control do
if grab_content_type(request.content_type, request.body) == :json
- new_system_template = CIMI::Model::SystemTemplate.create_from_json(request.body.read, self)
+ new_system_template = SystemTemplate.create_from_json(request.body.read, self)
else
- new_system_template = CIMI::Model::SystemTemplate.create_from_xml(request.body.read, self)
+ new_system_template = SystemTemplate.create_from_xml(request.body.read, self)
end
headers_for_create new_system_template
respond_to do |format|
@@ -61,7 +61,7 @@ module CIMI::Collections
operation :destroy, :with_capability => :destroy_system_template do
description "Delete a specified system template"
control do
- CIMI::Model::SystemTemplate.delete!(params[:id], self)
+ SystemTemplate.delete!(params[:id], self)
no_content_with_status(200)
end
end
diff --git a/server/lib/cimi/collections/systems.rb b/server/lib/cimi/collections/systems.rb
index ded0aa6..a6adb8d 100644
--- a/server/lib/cimi/collections/systems.rb
+++ b/server/lib/cimi/collections/systems.rb
@@ -72,8 +72,7 @@ module CIMI::Collections
param :id, :string, :required
control do
system = System.find(params[:id], self)
- action = Action.parse(request.body,
- request.content_type)
+ action = Action.parse(self)
system.perform(action, self) do |operation|
no_content_with_status(202) if operation.success?
# Handle errors using operation.failure?
@@ -155,7 +154,7 @@ module CIMI::Collections
operation :index, :with_capability => :storage_volumes do
description "Retrieve the System's SystemVolumeCollection"
control do
- volumes = CIMI::Model::SystemVolume.collection_for_system(params[:id], self)
+ volumes = SystemVolume.collection_for_system(params[:id], self)
respond_to do |format|
format.json {volumes.to_json}
format.xml {volumes.to_xml}
@@ -166,7 +165,7 @@ module CIMI::Collections
operation :show, :with_capability => :storage_volumes do
description "Retrieve a System's specific SystemVolume"
control do
- volume = CIMI::Model::SystemVolume.find(params[:id], self, params[:vol_id])
+ volume = SystemVolume.find(params[:id], self, params[:vol_id])
respond_to do |format|
format.json {volume.to_json}
format.xml {volume.to_xml}
@@ -177,7 +176,7 @@ module CIMI::Collections
operation :destroy, :with_capability => :detach_storage_volume do
description "Remove/detach a volume from the System's SystemVolumeCollection"
control do
- system_volume = CIMI::Model::SystemVolume.find(params[:id], self, params[:vol_id])
+ system_volume = SystemVolume.find(params[:id], self, params[:vol_id])
location = system_volume.initial_location
system_volumes = System.detach_volume(params[:vol_id], location, self)
respond_to do |format|
diff --git a/server/lib/cimi/collections/volume_configurations.rb b/server/lib/cimi/collections/volume_configurations.rb
index 0a33794..45a9d47 100644
--- a/server/lib/cimi/collections/volume_configurations.rb
+++ b/server/lib/cimi/collections/volume_configurations.rb
@@ -23,7 +23,7 @@ module CIMI::Collections
operation :index, :with_capability => :storage_volumes do
description "Get list all VolumeConfigurations"
control do
- volume_configuration = VolumeConfiguration.list(self).select_by(params['$select'])
+ volume_configuration = VolumeConfiguration.list(self)
respond_to do |format|
format.xml { volume_configuration.to_xml }
format.json { volume_configuration.to_json }
@@ -46,9 +46,9 @@ module CIMI::Collections
description "Create new VolumeConfiguration"
control do
if current_content_type == :json
- new_config = CIMI::Model::VolumeConfiguration.create_from_json(request.body.read, self)
+ new_config = VolumeConfiguration.create_from_json(request.body.read, self)
else
- new_config = CIMI::Model::VolumeConfiguration.create_from_xml(request.body.read, self)
+ new_config = VolumeConfiguration.create_from_xml(request.body.read, self)
end
headers_for_create new_config
respond_to do |format|
@@ -61,7 +61,7 @@ module CIMI::Collections
operation :destroy, :with_capability => :destroy_storage_volume do
description "Delete a specified VolumeConfiguration"
control do
- CIMI::Model::VolumeConfiguration.delete!(params[:id], self)
+ VolumeConfiguration.delete!(params[:id], self)
no_content_with_status(200)
end
end
diff --git a/server/lib/cimi/collections/volume_images.rb b/server/lib/cimi/collections/volume_images.rb
index 1596e2d..b9970b4 100644
--- a/server/lib/cimi/collections/volume_images.rb
+++ b/server/lib/cimi/collections/volume_images.rb
@@ -46,8 +46,8 @@ module CIMI::Collections
operation :create, :with_capability => :create_storage_snapshot do
description "Create a new volume image."
control do
- img = CIMI::Model::VolumeImageCreate.parse(request.body, request.content_type)
- volume_image = img.create(self)
+ img = VolumeImageCreate.parse(self)
+ volume_image = img.create
headers_for_create volume_image
respond_to do |format|
format.xml { volume_image.to_xml }
@@ -59,7 +59,7 @@ module CIMI::Collections
operation :destroy, :with_capability => :destroy_storage_snapshot do
description "Delete a specified VolumeImage"
control do
- CIMI::Model::VolumeImage.delete!(params[:id], self)
+ VolumeImage.delete!(params[:id], self)
no_content_with_status 200
end
end
diff --git a/server/lib/cimi/collections/volume_templates.rb b/server/lib/cimi/collections/volume_templates.rb
index b844ed8..556fe96 100644
--- a/server/lib/cimi/collections/volume_templates.rb
+++ b/server/lib/cimi/collections/volume_templates.rb
@@ -46,8 +46,8 @@ module CIMI::Collections
description "Create new VolumeTemplate"
control do
puts request.body
- vol = CIMI::Model::VolumeTemplateCreate.parse(request.body, request.content_type)
- new_template = vol.create(self)
+ vol = VolumeTemplateCreate.parse(self)
+ new_template = vol.create
headers_for_create new_template
respond_to do |format|
format.json { new_template.to_json }
@@ -59,7 +59,7 @@ module CIMI::Collections
operation :destroy, :with_capability => :destroy_storage_volume do
description "Delete a specified VolumeTemplate"
control do
- CIMI::Model::VolumeTemplate.delete!(params[:id], self)
+ VolumeTemplate.delete!(params[:id], self)
no_content_with_status(200)
end
end
diff --git a/server/lib/cimi/collections/volumes.rb b/server/lib/cimi/collections/volumes.rb
index 3f46591..49a58b3 100644
--- a/server/lib/cimi/collections/volumes.rb
+++ b/server/lib/cimi/collections/volumes.rb
@@ -49,8 +49,8 @@ module CIMI::Collections
operation :create, :with_capability => :create_storage_volume do
description "Create a new Volume."
control do
- vol = CIMI::Model::VolumeCreate.parse(request.body, request.content_type)
- new_volume = vol.create(self)
+ vol = VolumeCreate.parse(self)
+ new_volume = vol.create
headers_for_create new_volume
respond_to do |format|
format.json { new_volume.to_json }
--
1.8.1.4
[PATCH 02/14] CIMI (schema): properly generate and track embedded collection classes
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
---
server/lib/cimi/models/schema.rb | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
index b4e9377..9c27c6f 100644
--- a/server/lib/cimi/models/schema.rb
+++ b/server/lib/cimi/models/schema.rb
@@ -302,7 +302,10 @@ class CIMI::Model::Schema
raise "Specify the class of collection entries using :class"
end
params[:embedded] = true
- @collection_class = CIMI::Model::Collection.generate(opts[:class], params)
+ unless opts[:class].collection_class
+ opts[:class].collection_class = CIMI::Model::Collection.generate(opts[:class], params)
+ end
+ @collection_class = opts[:class].collection_class
end
def from_xml(xml, model)
@@ -466,7 +469,7 @@ class CIMI::Model::Schema
end
def collection(name, opts={})
- opts[:scope] = self.class
+ opts[:scope] = self
add_attributes!([name, opts], Collection)
end
end
--
1.8.1.4
[PATCH 04/14] CIMI: split models into model and service objects
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
The current CIMI::Model classes address two concerns:
* serialization/deserialization of CIMI objects
* interaction with the current driver and the DB
This patch splits these two concerns into two separate class hierarchies:
CIMI::Model for (de)serialization and CIMI::Service for interacting with
drivers/db
Besides cleaning up the code, this will make it possible to reuse
CIMI::Model classes as the basis for client code.
---
server/lib/cimi/collections/base.rb | 4 +-
server/lib/cimi/helpers/cimi_helper.rb | 2 +-
server/lib/cimi/helpers/database_helper.rb | 3 +-
server/lib/cimi/models.rb | 9 --
server/lib/cimi/models/base.rb | 74 +--------
server/lib/cimi/models/collection.rb | 27 +---
server/lib/cimi/models/machine.rb | 125 ---------------
server/lib/cimi/service.rb | 28 ++++
server/lib/cimi/service/base.rb | 201 +++++++++++++++++++++++++
server/lib/cimi/service/machine.rb | 147 ++++++++++++++++++
server/tests/cimi/collections/common.rb | 27 ++++
server/tests/cimi/collections/machines_test.rb | 7 +
server/tests/cimi/db/database_helper_test.rb | 11 +-
13 files changed, 430 insertions(+), 235 deletions(-)
create mode 100644 server/lib/cimi/service.rb
create mode 100644 server/lib/cimi/service/base.rb
create mode 100644 server/lib/cimi/service/machine.rb
diff --git a/server/lib/cimi/collections/base.rb b/server/lib/cimi/collections/base.rb
index 1e49ea3..0d1d0ee 100644
--- a/server/lib/cimi/collections/base.rb
+++ b/server/lib/cimi/collections/base.rb
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-require_relative '../models'
+require_relative '../service'
module CIMI::Collections
class Base < Sinatra::Base
@@ -24,7 +24,7 @@ module CIMI::Collections
include Sinatra::Rabbit
include Sinatra::Rabbit::Features
- include CIMI::Model
+ include CIMI::Service
helpers Deltacloud::Helpers::Drivers
helpers Deltacloud::Helpers::Database
diff --git a/server/lib/cimi/helpers/cimi_helper.rb b/server/lib/cimi/helpers/cimi_helper.rb
index e23d819..6d9403e 100644
--- a/server/lib/cimi/helpers/cimi_helper.rb
+++ b/server/lib/cimi/helpers/cimi_helper.rb
@@ -72,7 +72,7 @@ module CIMI
end
def deltacloud_create_method_for(cimi_entity)
- case cimi_entity
+ case cimi_entity.to_s
when "machine" then "create_instance"
when "machine_configuration" then "create_hardware_profile"
when "machine_image" then "create_image"
diff --git a/server/lib/cimi/helpers/database_helper.rb b/server/lib/cimi/helpers/database_helper.rb
index 7e5f99a..b62fbbc 100644
--- a/server/lib/cimi/helpers/database_helper.rb
+++ b/server/lib/cimi/helpers/database_helper.rb
@@ -25,8 +25,7 @@ module Deltacloud
"volume_configuration", "volume_template" ]
def provides?(entity)
- return true if DATABASE_COLLECTIONS.include? entity
- return false
+ DATABASE_COLLECTIONS.include? entity.to_s
end
def current_provider
diff --git a/server/lib/cimi/models.rb b/server/lib/cimi/models.rb
index edfb0e3..8eeb96c 100644
--- a/server/lib/cimi/models.rb
+++ b/server/lib/cimi/models.rb
@@ -37,15 +37,6 @@ end
require 'require_relative' if RUBY_VERSION < '1.9'
-# Database entities
-#
-require_relative './../db/provider'
-require_relative './../db/entity'
-require_relative './../db/machine_template'
-require_relative './../db/address_template'
-require_relative './../db/volume_configuration'
-require_relative './../db/volume_template'
-
require_relative './models/schema'
require_relative './models/resource'
require_relative './models/collection'
diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
index a207bed..fc8cca8 100644
--- a/server/lib/cimi/models/base.rb
+++ b/server/lib/cimi/models/base.rb
@@ -15,8 +15,6 @@
require 'xmlsimple'
-require_relative '../helpers/database_helper'
-
# 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.
@@ -109,86 +107,16 @@ module CIMI::Model
class Base < Resource
- # Extend the base model with database methods
- extend Deltacloud::Helpers::Database
-
# Extend the base model with the collection handling methods
extend CIMI::Model::CollectionMethods
# Include methods needed to handle the $select query parameter
include CIMI::Helpers::SelectBaseMethods
+
#
# Common attributes for all resources
#
text :id, :name, :description, :created, :updated
hash_map :property
-
- def initialize(values = {})
- super(values)
- retrieve_entity
- end
-
- def []=(a, v)
- v = super
- retrieve_entity if a == :id
- v
- end
-
- # Save the common attributes name, description, and properties to the
- # database
- def save
- if @entity
- @entity.name = name
- @entity.description = description
- @entity.properties = property
- @entity.save
- end
- self
- end
-
- # Destroy the database attributes for this model
- def destroy
- @entity.destroy
- self
- end
-
- # FIXME: Kludge around the fact that we do not have proper *Create
- # objects that deserialize properties by themselves
- def extract_properties!(data)
- h = {}
- if data['property']
- # Data came from XML
- h = data['property'].inject({}) do |r,v|
- r[v['key']] = v['content']
- r
- end
- elsif data['properties']
- h = data['properties']
- end
- property ||= {}
- property.merge!(h)
- end
-
- def ref_id(ref_url)
- ref_url.split('/').last if ref_url
- end
-
- private
-
- # Load an existing database entity for this object, or create a new one
- def retrieve_entity
- if self.id
- @entity = Deltacloud::Database::Entity::retrieve(self)
- if @entity.exists?
- self.name = @entity.name
- self.description = @entity.description
- self.property ||= {}
- self.property.merge!(@entity.properties)
- end
- else
- @entity = nil
- end
- end
-
end
end
diff --git a/server/lib/cimi/models/collection.rb b/server/lib/cimi/models/collection.rb
index f36c081..cc95ab7 100644
--- a/server/lib/cimi/models/collection.rb
+++ b/server/lib/cimi/models/collection.rb
@@ -120,26 +120,15 @@ module CIMI::Model
end
# Return a collection of entities
- def list(context)
- entries = find(:all, context)
- desc = "#{self.name.split("::").last} Collection for the #{context.driver.name.capitalize} driver"
- acts_as_root_entity unless collection_class
- id = context.send("#{collection_class.entry_name}_url")
- ops = []
- cimi_entity = collection_class.entry_name.to_s.singularize
- cimi_create = "create_#{cimi_entity}_url"
- dcloud_create = context.deltacloud_create_method_for(cimi_entity)
- if(context.respond_to?(cimi_create) &&
- context.driver.respond_to?(dcloud_create)) ||
- provides?(cimi_entity)
- url = context.send(cimi_create)
- ops << { :rel => "add", :href => url }
+ def list(id, entries, params = {})
+ params[:id] = id
+ params[:entries] = entries
+ params[:count] = params[:entries].size
+ if params[:add_url]
+ params[:operations] ||= []
+ params[:operations] << { :rel => "add", :href => params.delete(:add_url) }
end
- collection_class.new(:id => id,
- :count => entries.size,
- :entries => entries,
- :operations => ops,
- :description => desc)
+ collection_class.new(params)
end
def all(context)
diff --git a/server/lib/cimi/models/machine.rb b/server/lib/cimi/models/machine.rb
index 3beb2f7..6990fb9 100644
--- a/server/lib/cimi/models/machine.rb
+++ b/server/lib/cimi/models/machine.rb
@@ -38,129 +38,4 @@ class CIMI::Model::Machine < CIMI::Model::Base
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 perform(action, context, &block)
- begin
- if context.driver.send(:"#{action.name}_instance", context.credentials, self.id.split("/").last)
- 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)
- new(:id => id).destroy
- end
-
- #returns the newly attach machine_volume
- def self.attach_volume(volume, location, context)
- context.driver.attach_storage_volume(context.credentials,
- {:id=>volume, :instance_id=>context.params[:id], :device=>location})
- CIMI::Model::MachineVolume.find(context.params[:id], context, volume)
- end
-
- #returns the machine_volume_collection for the given machine
- def self.detach_volume(volume, location, context)
- context.driver.detach_storage_volume(context.credentials,
- {:id=>volume, :instance_id=>context.params[:id], :device=>location})
- CIMI::Model::MachineVolume.collection_for_instance(context.params[:id], context)
- end
-
- def self.from_instance(instance, context)
- cpu = memory = (instance.instance_profile.id == "opaque")? "n/a" : nil
- machine_conf = CIMI::Model::MachineConfiguration.find(instance.instance_profile.name, context)
- machine_spec = {
- :name => instance.name,
- :created => instance.launch_time.nil? ? Time.now.xmlschema : Time.parse(instance.launch_time.to_s).xmlschema,
- :description => "No description set for Machine #{instance.name}",
- :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 => { :href => context.machine_url(instance.id)+"/disks"},
- :volumes => { :href=>context.machine_url(instance.id)+"/volumes"},
- :operations => convert_instance_actions(instance, context)
- }
- if context.expand? :disks
- machine_spec[:disks] = CIMI::Model::Disk.find(instance, machine_conf, context, :all)
- end
- if context.expand? :volumes
- machine_spec[:volumes] = CIMI::Model::MachineVolume.find(instance.id, context, :all)
- end
- machine_spec[:realm] = instance.realm_id if instance.realm_id
- machine_spec[:machine_image] = { :href => context.machine_image_url(instance.image_id) } if instance.image_id
- self.new(machine_spec)
- end
-
- # FIXME: This will convert 'RUNNING' state to 'STARTED'
- # which is defined in CIMI (p65)
- #
- def self.convert_instance_state(state)
- case state
- when "RUNNING" then "STARTED"
- when "PENDING" then "CREATING" #aruba only exception... could be "STARTING" here
- else state
- end
- 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 }
- memory_override.nil? ? machine_conf.memory.to_i : context.to_kibibyte(memory_override[1].to_i,"MB")
- 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)
- actions = instance.actions.collect do |action|
- action = :restart if action == :reboot
- name = action
- name = :delete if action == :destroy # In CIMI destroy operation become delete
- { :href => context.send(:"#{action}_machine_url", instance.id), :rel => "http://schemas.dmtf.org/cimi/1/action/#{name}" }
- end
- actions << { :href => context.send(:"machine_images_url"), :rel => "http://schemas.dmtf.org/cimi/1/action/capture" } if instance.can_create_image?
- actions
- 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),
- :initial_location=>vol.values.first} }
- end
-
end
diff --git a/server/lib/cimi/service.rb b/server/lib/cimi/service.rb
new file mode 100644
index 0000000..5231c24
--- /dev/null
+++ b/server/lib/cimi/service.rb
@@ -0,0 +1,28 @@
+# 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.
+#
+
+module CIMI::Service; end
+
+require_relative './models'
+require_relative './../db/provider'
+require_relative './../db/entity'
+require_relative './../db/machine_template'
+require_relative './../db/address_template'
+require_relative './../db/volume_configuration'
+require_relative './../db/volume_template'
+
+require_relative './service/base'
+require_relative './service/machine'
diff --git a/server/lib/cimi/service/base.rb b/server/lib/cimi/service/base.rb
new file mode 100644
index 0000000..7df57f6
--- /dev/null
+++ b/server/lib/cimi/service/base.rb
@@ -0,0 +1,201 @@
+# 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_relative '../helpers/database_helper'
+
+# Service objects implement the server functionality of CIMI resources; in
+# particular, these objects are responsible for interacting with the
+# current driver. They use the CIMI::Model objects for (de)serialization
+module CIMI::Service
+
+ class Base
+
+ # Extend the base model with database methods
+ extend Deltacloud::Helpers::Database
+
+ attr_reader :model, :context
+
+ class << self
+ def model_class
+ CIMI::Model.const_get(name.split('::').last)
+ end
+
+ def model_name
+ name.split('::').last.underscore.to_sym
+ end
+
+ def collection_name
+ name.split('::').last.underscore.pluralize.to_sym
+ end
+
+ def inherited(subclass)
+ # Decorate all the attributes of the model class
+ schema = subclass.model_class.schema
+ schema.attribute_names.each do |name|
+ define_method(name) { self[name] }
+ define_method(:"#{name}=") { |newval| self[name] = newval }
+ end
+ end
+ end
+
+ def initialize(context, opts)
+ if opts[:values]
+ @model = model_class.new(opts[:values])
+ elsif opts[:model]
+ @model = opts[:model]
+ else
+ @model = model_class.new({})
+ end
+ @context = context
+ retrieve_entity
+ end
+
+ def model_class
+ self.class.model_class
+ end
+
+ # Decorate some model methods
+ def []=(a, v)
+ v = (@model[a] = v)
+ retrieve_entity if a == :id
+ v
+ end
+
+ def [](a)
+ @model[a]
+ end
+
+ def to_xml
+ @model.to_xml
+ end
+
+ def to_json
+ @model.to_json
+ end
+
+ def select_attributes(attr_list)
+ @model.select_attributes(attr_list)
+ end
+
+ # Lookup a reference and return the corresponding model
+ def resolve(ref)
+ self.class.resolve(ref, context)
+ end
+
+ def self.resolve(ref, ctx)
+ model = nil
+ if ref.href?
+ name = ref.class.superclass.name.split('::').last
+ service_class = CIMI::Service::const_get(name)
+ id = ref.href.split('/').last
+ model = service_class.find(id, ctx)
+ else
+ # FIXME: if ref.href? we need to overwrite
+ # attributes in model with ones from ref as long as they are present
+ model = ref
+ end
+ model
+ end
+
+ def self.list(ctx)
+ id = ctx.send("#{collection_name}_url")
+ entries = find(:all, ctx)
+ params = {}
+ params[:desc] = "#{self.name.split("::").last} Collection for the #{ctx.driver.name.capitalize} driver"
+ params[:add_url] = create_url(ctx)
+ model_class.list(id, entries, params)
+ end
+
+ def self.create_url(ctx)
+ cimi_create = "create_#{model_name}_url"
+ dcloud_create = ctx.deltacloud_create_method_for(model_name)
+ if(ctx.respond_to?(cimi_create) &&
+ ctx.driver.respond_to?(dcloud_create)) || provides?(model_name)
+ ctx.send(cimi_create)
+ end
+ end
+
+ # Save the common attributes name, description, and properties to the
+ # database
+ def save
+ if @entity
+ before_save
+ @entity.save
+ end
+ self
+ end
+
+ # Destroy the database attributes for this model
+ def destroy
+ @entity.destroy
+ self
+ end
+
+ # FIXME: Kludge around the fact that we do not have proper *Create
+ # objects that deserialize properties by themselves
+ def extract_properties!(data)
+ h = {}
+ if data['property']
+ # Data came from XML
+ h = data['property'].inject({}) do |r,v|
+ r[v['key']] = v['content']
+ r
+ end
+ elsif data['properties']
+ h = data['properties']
+ end
+ property ||= {}
+ property.merge!(h)
+ end
+
+ def ref_id(ref_url)
+ ref_url.split('/').last if ref_url
+ end
+
+ protected
+
+ def attributes_to_copy
+ [:name, :description]
+ end
+
+ def before_save
+ attributes_to_copy.each { |a| @entity[a] = @model[a] }
+ @entity.properties = @model.property
+ end
+
+ def after_retrieve
+ attributes_to_copy.each { |a| @model[a] = @entity[a] }
+ @model.property ||= {}
+ @model.property.merge!(@entity.properties)
+ end
+
+ private
+
+ # Load an existing database entity for this object, or create a new one
+ def retrieve_entity
+ if self.id
+ @entity = Deltacloud::Database::Entity::retrieve(@model)
+ if @entity.exists?
+ after_retrieve
+ end
+ else
+ @entity = nil
+ end
+ end
+
+ end
+end
diff --git a/server/lib/cimi/service/machine.rb b/server/lib/cimi/service/machine.rb
new file mode 100644
index 0000000..72e5346
--- /dev/null
+++ b/server/lib/cimi/service/machine.rb
@@ -0,0 +1,147 @@
+# 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::Service::Machine < CIMI::Service::Base
+
+ 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 perform(action, &block)
+ begin
+ op = action.operation
+ op = :reboot if op == :restart
+ puts "PERFORM #{op.inspect} on #{ref_id(id)}"
+ if context.driver.send(:"#{op}_instance", context.credentials, ref_id(id))
+ block.callback :success
+ else
+ raise "Operation #{op} failed to execute on given Machine #{ref_id(id)}"
+ end
+ rescue => e
+ raise
+ block.callback :failure, e.message
+ end
+ end
+
+ def self.delete!(id, context)
+ context.driver.destroy_instance(context.credentials, id)
+ new(context, :values => { :id => id }).destroy
+ end
+
+ #returns the newly attach machine_volume
+ def self.attach_volume(volume, location, context)
+ context.driver.attach_storage_volume(context.credentials,
+ {:id=>volume, :instance_id=>context.params[:id], :device=>location})
+ CIMI::Model::MachineVolume.find(context.params[:id], context, volume)
+ end
+
+ #returns the machine_volume_collection for the given machine
+ def self.detach_volume(volume, location, context)
+ context.driver.detach_storage_volume(context.credentials,
+ {:id=>volume, :instance_id=>context.params[:id], :device=>location})
+ CIMI::Model::MachineVolume.collection_for_instance(context.params[:id], context)
+ end
+
+ def self.from_instance(instance, context)
+ cpu = memory = (instance.instance_profile.id == "opaque")? "n/a" : nil
+ machine_conf = CIMI::Model::MachineConfiguration.find(instance.instance_profile.name, context)
+ machine_spec = {
+ :name => instance.name,
+ :created => instance.launch_time.nil? ? Time.now.xmlschema : Time.parse(instance.launch_time.to_s).xmlschema,
+ :description => "No description set for Machine #{instance.name}",
+ :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 => { :href => context.machine_url(instance.id)+"/disks"},
+ :volumes => { :href=>context.machine_url(instance.id)+"/volumes"},
+ :operations => convert_instance_actions(instance, context)
+ }
+ if context.expand? :disks
+ machine_spec[:disks] = CIMI::Model::Disk.find(instance, machine_conf, context, :all)
+ end
+ if context.expand? :volumes
+ machine_spec[:volumes] = CIMI::Model::MachineVolume.find(instance.id, context, :all)
+ end
+ machine_spec[:realm] = instance.realm_id if instance.realm_id
+ machine_spec[:machine_image] = { :href => context.machine_image_url(instance.image_id) } if instance.image_id
+ self.new(context, :values => machine_spec)
+ end
+
+ # FIXME: This will convert 'RUNNING' state to 'STARTED'
+ # which is defined in CIMI (p65)
+ #
+ def self.convert_instance_state(state)
+ case state
+ when "RUNNING" then "STARTED"
+ when "PENDING" then "CREATING" #aruba only exception... could be "STARTING" here
+ else state
+ end
+ 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 }
+ memory_override.nil? ? machine_conf.memory.to_i : context.to_kibibyte(memory_override[1].to_i,"MB")
+ 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)
+ actions = instance.actions.collect do |action|
+ action = :restart if action == :reboot
+ name = action
+ name = :delete if action == :destroy # In CIMI destroy operation become delete
+ { :href => context.send(:"#{action}_machine_url", instance.id), :rel => "http://schemas.dmtf.org/cimi/1/action/#{name}" }
+ end
+ actions << { :href => context.send(:"machine_images_url"), :rel => "http://schemas.dmtf.org/cimi/1/action/capture" } if instance.can_create_image?
+ actions
+ 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),
+ :initial_location=>vol.values.first} }
+ end
+
+end
diff --git a/server/tests/cimi/collections/common.rb b/server/tests/cimi/collections/common.rb
index 5948dde..f44f9cd 100644
--- a/server/tests/cimi/collections/common.rb
+++ b/server/tests/cimi/collections/common.rb
@@ -15,3 +15,30 @@ Deltacloud[:cimi].require!
Deltacloud[:cimi].default_frontend!
def formats; [ 'application/xml', 'application/json' ]; end
+
+def model_class
+ resource = nil
+ resp = last_response
+ ct = resp.content_type
+ if ct == "application/json"
+ json = JSON::parse(last_response.body)
+ json["resourceURI"].wont_be_nil
+ resource = json["resourceURI"].split("/").last
+ elsif ct == "application/xml"
+ xml = Nokogiri::XML(last_response.body)
+ if xml.root.name == "Collection"
+ resource = xml.root["resourceURI"].split("/").last
+ else
+ resource = xml.root.name
+ end
+ elsif resp.body.nil? || resp.body.size == 0
+ raise "Can not construct model from empty body"
+ else
+ raise "Unexpected content type #{resp.content_type}"
+ end
+ CIMI::Model::const_get(resource)
+end
+
+def model
+ model_class.parse(last_response.body, last_response.content_type)
+end
diff --git a/server/tests/cimi/collections/machines_test.rb b/server/tests/cimi/collections/machines_test.rb
index b2f7efb..5e8346e 100644
--- a/server/tests/cimi/collections/machines_test.rb
+++ b/server/tests/cimi/collections/machines_test.rb
@@ -35,6 +35,13 @@ describe CIMI::Collections::Machines do
xml.root.name.must_equal 'Machine'
end
+ it 'should have an "add" operation for the machine collection' do
+ get root_url + '/machines'
+ model.operations.wont_be_empty
+ add_ops = model.operations.select { |op| op.rel == "add" }
+ add_ops.size.must_equal 1
+ end
+
describe "$expand" do
def machine(*expand)
url = '/machines/inst1'
diff --git a/server/tests/cimi/db/database_helper_test.rb b/server/tests/cimi/db/database_helper_test.rb
index b474307..43642ec 100644
--- a/server/tests/cimi/db/database_helper_test.rb
+++ b/server/tests/cimi/db/database_helper_test.rb
@@ -16,7 +16,8 @@ describe Deltacloud::Helpers::Database do
before do
@provider = Deltacloud::Database::Provider
@entity = Deltacloud::Database::Entity
- @baseModel = CIMI::Model::Base
+ @baseService = CIMI::Service::Base
+ @baseModel = @baseService.model_class
@db = DatabaseHelper.new
@prov = @provider::lookup
@@ -98,7 +99,7 @@ describe Deltacloud::Helpers::Database do
check_entity_base_attrs new_entity, @entity, @prov
base = @baseModel.new(:id => 'base1')
- base.destroy
+ @baseService.new(nil, :model => base).destroy
entity = @entity.retrieve(base)
entity.wont_be_nil
entity.exists?.must_equal false
@@ -123,10 +124,12 @@ describe Deltacloud::Helpers::Database do
}
}
'
- machine = CIMI::Model::Machine.from_json(json)
+
+ model = CIMI::Model::Machine.from_json(json)
+ machine = CIMI::Service::Machine.new(nil, :model => model)
machine.save
- m2 = CIMI::Model::Machine.new(:id => machine.id)
+ m2 = CIMI::Service::Machine.new(nil, :values => { :id => machine.id })
m2.name.must_equal 'myDatabaseMachine'
m2.description.must_equal 'This is a demo machine'
m2.property.must_be_kind_of Hash
--
1.8.1.4
[PATCH 06/14] CIMI: Migrated MachineImage to services
Posted by lu...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>
Signed-off-by: Michal fojtik <mf...@redhat.com>
TrackedAt: http://tracker.deltacloud.org/patch/ac7d8b3fe7354da3cb2d29400632bfe36694556d
---
server/lib/cimi/collections/machine_images.rb | 6 ++--
server/lib/cimi/models/machine_image.rb | 28 ---------------
server/lib/cimi/service.rb | 1 +
server/lib/cimi/service/machine_image.rb | 51 +++++++++++++++++++++++++++
4 files changed, 55 insertions(+), 31 deletions(-)
create mode 100644 server/lib/cimi/service/machine_image.rb
diff --git a/server/lib/cimi/collections/machine_images.rb b/server/lib/cimi/collections/machine_images.rb
index ee0033c..ce9fa6a 100644
--- a/server/lib/cimi/collections/machine_images.rb
+++ b/server/lib/cimi/collections/machine_images.rb
@@ -24,7 +24,7 @@ module CIMI::Collections
operation :index, :with_capability => :images do
description "List all machine configurations"
control do
- machine_images = MachineImage.list(self).select_by(params['$select'])
+ machine_images = MachineImage.list(self)
respond_to do |format|
format.xml { machine_images.to_xml }
format.json { machine_images.to_json }
@@ -46,7 +46,7 @@ module CIMI::Collections
operation :create, :with_capability => :create_image do
description "Create a new machine image."
control do
- mi = CIMI::Model::MachineImageCreate.parse(request.body, request.content_type)
+ mi = MachineImageCreate.parse(request.body, request.content_type)
machine_image = mi.create(self)
headers_for_create machine_image
respond_to do |format|
@@ -59,7 +59,7 @@ module CIMI::Collections
operation :destroy, :with_capability => :destroy_image do
description "Delete a specified MachineImage"
control do
- CIMI::Model::MachineImage.delete!(params[:id], self)
+ MachineImage.delete!(params[:id], self)
no_content_with_status 200
end
end
diff --git a/server/lib/cimi/models/machine_image.rb b/server/lib/cimi/models/machine_image.rb
index 74f48ef..f900dae 100644
--- a/server/lib/cimi/models/machine_image.rb
+++ b/server/lib/cimi/models/machine_image.rb
@@ -26,32 +26,4 @@ class CIMI::Model::MachineImage < CIMI::Model::Base
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(
- :id => context.machine_image_url(image.id),
- :name => image.id,
- :description => image.description,
- :state => image.state || 'UNKNOWN',
- :type => "IMAGE",
- :created => image.creation_time.nil? ?
- Time.now.xmlschema : Time.parse(image.creation_time.to_s).xmlschema
- )
- end
-
- def self.delete!(image_id, context)
- context.driver.destroy_image(context.credentials, image_id)
- new(:id => image_id).destroy
- end
-
end
diff --git a/server/lib/cimi/service.rb b/server/lib/cimi/service.rb
index 5231c24..f6b933f 100644
--- a/server/lib/cimi/service.rb
+++ b/server/lib/cimi/service.rb
@@ -26,3 +26,4 @@ require_relative './../db/volume_template'
require_relative './service/base'
require_relative './service/machine'
+require_relative './service/machine_image'
diff --git a/server/lib/cimi/service/machine_image.rb b/server/lib/cimi/service/machine_image.rb
new file mode 100644
index 0000000..dad26a8
--- /dev/null
+++ b/server/lib/cimi/service/machine_image.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.
+
+class CIMI::Service::MachineImage < CIMI::Service::Base
+
+ def initialize(ctx, opts)
+ super
+ 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(context, :values => {
+ :id => context.machine_image_url(image.id),
+ :name => image.id,
+ :description => image.description,
+ :state => image.state || 'UNKNOWN',
+ :type => "IMAGE",
+ :created => image.creation_time.nil? ?
+ Time.now.xmlschema : Time.parse(image.creation_time.to_s).xmlschema
+ })
+ end
+
+ def self.delete!(image_id, context)
+ context.driver.destroy_image(context.credentials, image_id)
+ new(:id => image_id).destroy
+ end
+
+
+end
--
1.8.1.4
[PATCH 03/14] DB Entity: make sure we instantiate the correct subclass
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
We only ever instantiated Database::Entity, but never any of its
subclasses. We now keep a map of CIMI::Model => Database::Entity subclass
and call new on the appropriate subclass of Entity.
---
server/lib/db/entity.rb | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/server/lib/db/entity.rb b/server/lib/db/entity.rb
index 45a7f30..7f32161 100644
--- a/server/lib/db/entity.rb
+++ b/server/lib/db/entity.rb
@@ -44,6 +44,7 @@ module Deltacloud
end
def after_initialize
+ super
if ent_properties
self.properties = JSON::parse(ent_properties)
else
@@ -61,11 +62,25 @@ module Deltacloud
entity = Provider::lookup.entities_dataset.first(h)
unless entity
h[:provider_id] = Provider::lookup.id
- entity = Entity.new(h)
+ entity = @@model_entity_map[model.class].new(h)
end
entity
end
+ def self.inherited(subclass)
+ super
+ # Build a map from CIMI::Model class to Entity subclass. This only
+ # works if the two classes have the same name in their respective
+ # modules.
+ # The map is used to determine what Entity subclass to instantiate
+ # for a given model in +retrieve+
+ @@model_entity_map ||= Hash.new(Entity)
+ n = subclass.name.split('::').last
+ if k = CIMI::Model::const_get(n)
+ @@model_entity_map[k] = subclass
+ end
+ end
+
private
def self.model_hash(model)
{ :be_kind => model.class.name,
--
1.8.1.4
[PATCH 05/14] CIMI: Apply $filter and $select in Base#list
Posted by lu...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>
No need to have ugly chained methods in collections.
Signed-off-by: Michal fojtik <mf...@redhat.com>
TrackedAt: http://tracker.deltacloud.org/patch/c2417e1f3383ae4a76e1d40d04440daed149bf95
---
server/lib/cimi/collections/machines.rb | 2 +-
server/lib/cimi/service/base.rb | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/server/lib/cimi/collections/machines.rb b/server/lib/cimi/collections/machines.rb
index 0337f86..f3cb62a 100644
--- a/server/lib/cimi/collections/machines.rb
+++ b/server/lib/cimi/collections/machines.rb
@@ -24,7 +24,7 @@ module CIMI::Collections
operation :index, :with_capability => :instances do
description "List all machines"
control do
- machines = Machine.list(self).select_by(params['$select']).filter_by(params['$filter'])
+ machines = Machine.list(self)
respond_to do |format|
format.xml { machines.to_xml }
format.json { machines.to_json }
diff --git a/server/lib/cimi/service/base.rb b/server/lib/cimi/service/base.rb
index 7df57f6..8daa183 100644
--- a/server/lib/cimi/service/base.rb
+++ b/server/lib/cimi/service/base.rb
@@ -117,7 +117,7 @@ module CIMI::Service
params = {}
params[:desc] = "#{self.name.split("::").last} Collection for the #{ctx.driver.name.capitalize} driver"
params[:add_url] = create_url(ctx)
- model_class.list(id, entries, params)
+ model_class.list(id, entries, params).select_by(ctx.params['$select']).filter_by(ctx.params['$filter'])
end
def self.create_url(ctx)
--
1.8.1.4
[PATCH 11/14] * server/lib/cimi/service/machine_template.rb (delete!): fix 500 error
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
The method was simply busted. Now also allows deletion of nonexisting
templates
---
server/lib/cimi/service/machine_template.rb | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/server/lib/cimi/service/machine_template.rb b/server/lib/cimi/service/machine_template.rb
index 4a3cd4e..837c519 100644
--- a/server/lib/cimi/service/machine_template.rb
+++ b/server/lib/cimi/service/machine_template.rb
@@ -29,7 +29,9 @@ class CIMI::Service::MachineTemplate < CIMI::Service::Base
end
def delete!(id, context)
- current_db.machine_templates.first(:id => id).destroy
+ if mt = current_db.machine_templates_dataset.first(:id => id)
+ mt.destroy
+ end
end
def from_db(model, context)
--
1.8.1.4
Re: RFC: Separate CIMI (de)serialization from server functionality
(rev 3)
Posted by Michal Fojtik <mf...@redhat.com>.
On 03/13, lutter@redhat.com wrote:
Applied cleanly. All tests are green. ACK this series.
I'm for pushing it and fixing small nits/etc later :-)
-- Michal
>
> This is the third take on splitting server-side functionality out of our
> models. As in previous attempts, CIMI::Model is now solely concerned with
> (se)serialization, whereas CIMI::Service does all the actual server-side
> functionality.
>
> FWIW, the unit and blackbox tests all pass for me with this patch series
> ...
>
> Also recorded as http://tracker.deltacloud.org/set/389
>
> David
--
Michal Fojtik <mf...@redhat.com>
Deltacloud API, CloudForms
[PATCH 10/14] CIMI: make ResourceMetadata work with the Model/Service split
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
Extension attributes now need to be mentioned twice: in the model class
they are declared like any other attribute. In the service class, resource
metadata can be added using
metadata attr_name, :type => TYPE, :constraints => PROC
---
server/lib/cimi/models/cloud_entry_point.rb | 4 +-
server/lib/cimi/models/machine.rb | 8 +--
server/lib/cimi/models/machine_template.rb | 3 +-
server/lib/cimi/models/resource_metadata.rb | 10 ---
server/lib/cimi/models/schema.rb | 9 ---
server/lib/cimi/service.rb | 10 ++-
server/lib/cimi/service/base.rb | 58 ++++++++++++++++++
server/lib/cimi/service/cloud_entry_point.rb | 3 +
server/lib/cimi/service/machine.rb | 7 +++
server/lib/cimi/service/machine_template.rb | 4 +-
server/lib/cimi/service/resource_metadata.rb | 92 ++++------------------------
11 files changed, 98 insertions(+), 110 deletions(-)
diff --git a/server/lib/cimi/models/cloud_entry_point.rb b/server/lib/cimi/models/cloud_entry_point.rb
index a016004..a1ec0a7 100644
--- a/server/lib/cimi/models/cloud_entry_point.rb
+++ b/server/lib/cimi/models/cloud_entry_point.rb
@@ -15,8 +15,8 @@
class CIMI::Model::CloudEntryPoint < CIMI::Model::Base
- resource_attr :driver, :required => true
- resource_attr :provider, :required => true
+ text :driver, :required => true
+ text :provider, :required => true
# All possible CIMI collections, in the order in which they should appear
# in the CEP
diff --git a/server/lib/cimi/models/machine.rb b/server/lib/cimi/models/machine.rb
index 6990fb9..3d1369c 100644
--- a/server/lib/cimi/models/machine.rb
+++ b/server/lib/cimi/models/machine.rb
@@ -17,10 +17,10 @@ class CIMI::Model::Machine < CIMI::Model::Base
acts_as_root_entity
- resource_attr :realm, :required => false,
- :constraints => lambda { |c| c.driver.realms(c.credentials).map { |r| r.id } }
-
- resource_attr :machine_image, :required => false, :type => :href
+ # DC-specific Extension
+ text :realm, :required => false
+ # DC-specific extension
+ href :machine_image, :required => false
text :state
text :cpu
diff --git a/server/lib/cimi/models/machine_template.rb b/server/lib/cimi/models/machine_template.rb
index 812ad15..68e865b 100644
--- a/server/lib/cimi/models/machine_template.rb
+++ b/server/lib/cimi/models/machine_template.rb
@@ -22,8 +22,7 @@ class CIMI::Model::MachineTemplate < CIMI::Model::Base
ref :machine_image
ref :credential
- resource_attr :realm, :required => false,
- :constraints => lambda { |c| c.driver.realms(c.credentials).map { |r| r.id }}
+ text :realm, :required => false
array :volumes do
scalar :href, :initial_location
diff --git a/server/lib/cimi/models/resource_metadata.rb b/server/lib/cimi/models/resource_metadata.rb
index 2c4ee08..0a2ab5d 100644
--- a/server/lib/cimi/models/resource_metadata.rb
+++ b/server/lib/cimi/models/resource_metadata.rb
@@ -51,14 +51,4 @@ class CIMI::Model::ResourceMetadata < CIMI::Model::Base
array :operations do
scalar :rel, :href
end
-
- def self.add_resource_attribute!(klass, name, opts={})
- resource_attributes[klass.name] ||= {}
- resource_attributes[klass.name][name] = opts
- end
-
- def self.resource_attributes
- @resource_attributes ||= {}
- end
-
end
diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
index 9c27c6f..b6651a7 100644
--- a/server/lib/cimi/models/schema.rb
+++ b/server/lib/cimi/models/schema.rb
@@ -425,15 +425,6 @@ class CIMI::Model::Schema
# +add_attributes!+ method
module DSL
- def resource_attr(name, opts={})
- CIMI::Model::ResourceMetadata.add_resource_attribute!(self, name, opts)
- if opts[:type]
- send(opts[:type], name)
- else
- text name
- end
- end
-
def href(*args)
opts = args.extract_opts!
args.each { |arg| struct(arg, opts) { scalar :href, :required => opts[:required] } }
diff --git a/server/lib/cimi/service.rb b/server/lib/cimi/service.rb
index b05efbf..8176532 100644
--- a/server/lib/cimi/service.rb
+++ b/server/lib/cimi/service.rb
@@ -14,7 +14,15 @@
# under the License.
#
-module CIMI::Service; end
+module CIMI
+ module Service
+ def self.root_entities
+ CIMI::Model::root_entities.map do |m|
+ CIMI::Service.const_get(m.name.split('::').last)
+ end
+ end
+ end
+end
require_relative './models'
require_relative './../db/provider'
diff --git a/server/lib/cimi/service/base.rb b/server/lib/cimi/service/base.rb
index fa845d0..b829e6a 100644
--- a/server/lib/cimi/service/base.rb
+++ b/server/lib/cimi/service/base.rb
@@ -136,6 +136,64 @@ module CIMI::Service
end
end
+ #
+ # Resource metadata
+ #
+ METADATA_TYPES = [ 'text', 'URI', 'string', 'boolean' ]
+
+ # A hash of the attributes that need to be mentioned in the given
+ # context
+ def self.resource_attributes(context)
+ metadata.keys.map do |k|
+ a = model_class.schema.attributes.find { |a| a.name == k }
+ raise "No attribute named #{k} defined" unless a
+ constr = metadata[k][:constraints].call(context)
+ {
+ :name => a.name,
+ :namespace => "http://deltacloud.org/cimi/#{model_name}/#{a.name}",
+ :type => metadata[k][:type],
+ :required => a.required? ? 'true' : 'false',
+ :constraints => constr.map { |v| { :value => v } }
+ }
+ end
+ end
+
+ def self.resource_capabilities(context)
+ cimi_object = model_name.to_s.pluralize.to_sym
+ driver_class = context.driver.class
+ (driver_class.features[cimi_object] || []).map do |cur|
+ feat = CIMI::FakeCollection.feature(cur)
+ values = driver_class.constraints[cimi_object][feat.name][:values] || []
+ { :name => feat.name.to_s.camelize,
+ :uri => CMWG_NAMESPACE+"/capability/#{cimi_object.to_s.camelize.singularize}/#{feat.name.to_s.camelize}",
+ :description => feat.description,
+ :value => values.join(",")
+ }
+ end
+ end
+
+ # Define the metadata for an attribute; +opts+ must be a Hash that can
+ # contain the following entries:
+ # :type : one of METADATA_TYPES
+ # :constraints : a proc that is passed the current context and
+ # must return a list of values
+ def self.metadata(attr_name = nil, opts = nil)
+ @metadata ||= {}
+ return @metadata if attr_name.nil? && opts.nil?
+
+ opts[:type] ||= 'text'
+ opts[:type] = opts[:type].to_s
+ opts[:constraints] ||= lambda { |_| [] }
+ unless METADATA_TYPES.include?(opts[:type])
+ raise "Metadata type must be one of #{METADATA_TYPES.join(",")}"
+ end
+ metadata[attr_name] = opts
+ end
+
+ #
+ # Database interactions
+ #
+
# Save the common attributes name, description, and properties to the
# database
def save
diff --git a/server/lib/cimi/service/cloud_entry_point.rb b/server/lib/cimi/service/cloud_entry_point.rb
index 5029e12..9491e3d 100644
--- a/server/lib/cimi/service/cloud_entry_point.rb
+++ b/server/lib/cimi/service/cloud_entry_point.rb
@@ -15,6 +15,9 @@
class CIMI::Service::CloudEntryPoint < CIMI::Service::Base
+ metadata :driver, :type => 'text'
+ metadata :provider, :type => 'text'
+
def self.create(context)
self.new(context, :values => entities(context).merge({
:name => context.driver.name,
diff --git a/server/lib/cimi/service/machine.rb b/server/lib/cimi/service/machine.rb
index 7112486..f347cda 100644
--- a/server/lib/cimi/service/machine.rb
+++ b/server/lib/cimi/service/machine.rb
@@ -15,6 +15,13 @@
class CIMI::Service::Machine < CIMI::Service::Base
+ metadata :realm,
+ :constraints => lambda { |c|
+ c.driver.realms(c.credentials).map { |r| r.id }
+ }
+
+ metadata :machine_image, :type => 'URI'
+
def self.find(id, context)
instances = []
if id == :all
diff --git a/server/lib/cimi/service/machine_template.rb b/server/lib/cimi/service/machine_template.rb
index e790e89..4a3cd4e 100644
--- a/server/lib/cimi/service/machine_template.rb
+++ b/server/lib/cimi/service/machine_template.rb
@@ -15,9 +15,7 @@
class CIMI::Service::MachineTemplate < CIMI::Service::Base
- def initialize(ctx, opts)
- super
- end
+ metadata :realm, :constraints => lambda { |c| c.driver.realms(c.credentials).map { |r| r.id }}
class << self
def find(id, context)
diff --git a/server/lib/cimi/service/resource_metadata.rb b/server/lib/cimi/service/resource_metadata.rb
index 23924fb..3a8f09f 100644
--- a/server/lib/cimi/service/resource_metadata.rb
+++ b/server/lib/cimi/service/resource_metadata.rb
@@ -15,96 +15,30 @@
class CIMI::Service::ResourceMetadata < CIMI::Service::Base
- def initialize(ctx, opts)
- super
- end
-
def self.find(id, context)
if id == :all
- resource_metadata = []
- CIMI::Model.root_entities.each do |resource_class|
- meta = resource_metadata_for(resource_class, context)
- resource_metadata << meta unless none_defined(meta)
- end
- return resource_metadata
+ CIMI::Service.root_entities.map do |svc_class|
+ resource_metadata_for(svc_class, context)
+ end.reject { |metadata| metadata.none_defined? }
else
- resource_class = CIMI::Model.const_get("#{id.camelize}")
- resource_metadata_for(resource_class, context)
+ svc_class = CIMI::Service.const_get("#{id.camelize}")
+ resource_metadata_for(svc_class, context)
end
end
- def self.resource_metadata_for(resource_class, context)
- attributes = rm_attributes_for(resource_class, context)
- capabilities = rm_capabilities_for(resource_class, context)
- actions = rm_actions_for(resource_class, context)
- cimi_resource = resource_class.name.split("::").last
+ def self.resource_metadata_for(svc_class, context)
+ cimi_resource = svc_class.name.split("::").last
self.new(context, :values => {
:id => context.resource_metadata_url(cimi_resource.underscore),
:name => cimi_resource,
- :type_uri => resource_class.resource_uri,
- :attributes => attributes,
- :capabilities => capabilities,
- :actions => actions
+ :type_uri => svc_class.model_class.resource_uri,
+ :attributes => svc_class.resource_attributes(context),
+ :capabilities => svc_class.resource_capabilities(context),
+ :actions => []
})
end
- private
-
- def self.rm_attributes_for(resource_class, context)
- return [] if resource_attributes[resource_class.name].nil?
- resource_attributes[resource_class.name].map do |attr_name, attr_def|
- if attr_def.has_key? :constraints
- constraints = attr_def[:constraints].call(context)
- else
- constraints = []
- end
- {
- :name => attr_name.to_s,
- # TODO: We need to make this URI return description of this 'non-CIMI'
- # attribute
- :namespace => "http://deltacloud.org/cimi/#{resource_class.name.split('::').last}/#{attr_name}",
- :type => translate_attr_type(attr_def[:type]),
- :required => attr_def[:required] ? 'true' : 'false',
- :constraints => constraints.map { |v| { :value => v }}
- }
- end
- end
-
- # FIXME: This method is srsly a nightmare ;-)
- #
- def self.rm_capabilities_for(resource_class,context)
- cimi_object = resource_class.name.split("::").last.underscore.pluralize.to_sym
- (context.driver.class.features[cimi_object] || []).inject([]) do |res, cur|
- feat = CIMI::FakeCollection.feature(cur)
- values = (context.driver.class.constraints[cimi_object][feat.name][:values] || []).inject([]) do |vals, val|
- vals << val
- vals
- end
- res << {:name => feat.name.to_s.camelize,
- :uri => CMWG_NAMESPACE+"/capability/#{cimi_object.to_s.camelize.singularize}/#{feat.name.to_s.camelize}",
- :description => feat.description,
- :value => values.join(",") }
- res
- end
- end
-
- def self.rm_actions_for(resource_class, context)
- []
- end
-
- def self.translate_attr_type(type)
- case type
- when :href then 'URI'
- when :text then 'string'
- when :boolean then 'boolean'
- else 'text'
- end
- end
-
- def self.none_defined(metadata)
- return true if metadata.capabilities.empty? && metadata.capabilities.empty? && metadata.attributes.empty?
- return false
+ def none_defined?
+ capabilities.empty? && attributes.empty?
end
-
-
end
--
1.8.1.4