You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltacloud.apache.org by lu...@apache.org on 2013/03/14 19:19:03 UTC
[8/15] git commit: CIMI: split models into model and service objects
CIMI: split models into model and service objects
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.
Project: http://git-wip-us.apache.org/repos/asf/deltacloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltacloud/commit/cc6f9198
Tree: http://git-wip-us.apache.org/repos/asf/deltacloud/tree/cc6f9198
Diff: http://git-wip-us.apache.org/repos/asf/deltacloud/diff/cc6f9198
Branch: refs/heads/master
Commit: cc6f919824f1c682a63cc383c1b2f8eb6841480c
Parents: d86e066
Author: David Lutterkort <lu...@redhat.com>
Authored: Thu Feb 28 16:15:27 2013 -0800
Committer: David Lutterkort <lu...@redhat.com>
Committed: Wed Mar 13 17:28:13 2013 -0700
----------------------------------------------------------------------
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(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/cc6f9198/server/lib/cimi/collections/base.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
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/cc6f9198/server/lib/cimi/helpers/cimi_helper.rb
----------------------------------------------------------------------
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"
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/cc6f9198/server/lib/cimi/helpers/database_helper.rb
----------------------------------------------------------------------
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
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/cc6f9198/server/lib/cimi/models.rb
----------------------------------------------------------------------
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'
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/cc6f9198/server/lib/cimi/models/base.rb
----------------------------------------------------------------------
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
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/cc6f9198/server/lib/cimi/models/collection.rb
----------------------------------------------------------------------
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)
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/cc6f9198/server/lib/cimi/models/machine.rb
----------------------------------------------------------------------
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
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/cc6f9198/server/lib/cimi/service.rb
----------------------------------------------------------------------
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'
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/cc6f9198/server/lib/cimi/service/base.rb
----------------------------------------------------------------------
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
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/cc6f9198/server/lib/cimi/service/machine.rb
----------------------------------------------------------------------
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
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/cc6f9198/server/tests/cimi/collections/common.rb
----------------------------------------------------------------------
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
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/cc6f9198/server/tests/cimi/collections/machines_test.rb
----------------------------------------------------------------------
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'
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/cc6f9198/server/tests/cimi/db/database_helper_test.rb
----------------------------------------------------------------------
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