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 2012/10/06 02:52:04 UTC
RFC: embedded CIMI collections
These series of patches adds support for embedded collections for CIMI
models. It's not quite perfect yet, since it doesn't produce the exactly
right XML yet, nor is it possible to parse objects with embedded
collections.
The main reason I like this better than the way Michal did it is because it
makes it unnecessary to have XXXCollection classes for
collections. Instead, you can just write
collection :things, :class => CIMI::Model::Thing
For example, for the disks collection in machine, we simply have
class CIMI::Model::Machine < CIMI::Model::Base
...
collection :disks, :class => CIMI::Model::Disk
...
end
The interesting stuff are the last three patches in the series. The other
ones can probably be acked and committed as they are.
David
[PATCH 3/7] CIMI models: let the schema convert raw values for model objects
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
This is a noop for now
---
server/lib/cimi/models/base.rb | 9 +++++++--
server/lib/cimi/models/schema.rb | 10 ++++++++++
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
index 4c9b2dc..eefa868 100644
--- a/server/lib/cimi/models/base.rb
+++ b/server/lib/cimi/models/base.rb
@@ -161,14 +161,19 @@ class CIMI::Model::Base
end
def []=(a, v)
- @attribute_values[a] = v
+ @attribute_values[a] = self.class.schema.convert(a, v)
+ end
end
#
# Factory methods
#
def initialize(values = {})
- @attribute_values = values
+ names = self.class.schema.attribute_names
+ @attribute_values = names.inject({}) do |hash, name|
+ hash[name] = self.class.schema.convert(name, values[name])
+ hash
+ end
end
# Construct a new object from the XML representation +xml+
diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
index ed3541a..e679b2e 100644
--- a/server/lib/cimi/models/schema.rb
+++ b/server/lib/cimi/models/schema.rb
@@ -46,6 +46,10 @@ class CIMI::Model::Schema
def to_json(model, json)
json[@json_name] = model[@name] if model and model[@name]
end
+
+ def convert(value)
+ value
+ end
end
class Scalar < Attribute
@@ -222,6 +226,12 @@ class CIMI::Model::Schema
@attributes = []
end
+ def convert(name, value)
+ attr = @attributes.find { |a| a.name == name }
+ raise "Unknown attribute #{name}" unless attr
+ attr.convert(value)
+ end
+
def from_xml(xml, model = {})
@attributes.freeze
@attributes.each { |attr| attr.from_xml(xml, model) }
--
1.7.7.6
[PATCH 5/7] CIMI: add collection support to model DSL
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
We reuse the CIMI::Model::Collection class that is also used for toplevel
collections. With that, we won't need special purpose XXXCollection
classes.
---
server/lib/cimi/models/base.rb | 3 ++
server/lib/cimi/models/schema.rb | 45 +++++++++++++++++++++++++++++++++----
2 files changed, 43 insertions(+), 5 deletions(-)
diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
index 2a27a8f..2e66694 100644
--- a/server/lib/cimi/models/base.rb
+++ b/server/lib/cimi/models/base.rb
@@ -66,6 +66,9 @@ require 'json'
# [array(name, opts, &block)]
# An array of structured subobjects; the block defines the schema of
# the subobjects.
+# [collection(name, opts)]
+# A collection of associated objects; use the +:class+ option to
+# specify the type of the collection entries
module CIMI::Model
diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
index e679b2e..d8ba13b 100644
--- a/server/lib/cimi/models/schema.rb
+++ b/server/lib/cimi/models/schema.rb
@@ -216,6 +216,41 @@ class CIMI::Model::Schema
end
end
+ class Collection < Attribute
+ def initialize(name, opts = {})
+ super(name, opts)
+ unless opts[:class]
+ raise "Specify the class of collection entries using :class"
+ end
+ @collection_class = CIMI::Model::Collection.generate(opts[:class])
+ end
+
+ def from_xml(xml, model)
+ raise "Parsing collections (#{name}) not supported"
+ end
+
+ def from_json(json, model)
+ raise "Parsing collections (#{name}) not supported"
+ end
+
+ def to_xml(model, xml)
+ xml[xml_name] = @collection_class.schema.to_xml(model[name])
+ end
+
+ def to_json(model, json)
+ json[json_name] = @collection_class.schema.to_json(model[name])
+ end
+
+ # Convert a Hash or Array to an instance of the collection class
+ def convert(value)
+ if value.is_a?(::Array)
+ @collection_class.new(:entries => value)
+ else
+ @collection_class.new(value || {})
+ end
+ end
+ end
+
#
# The actual Schema class
#
@@ -226,6 +261,10 @@ class CIMI::Model::Schema
@attributes = []
end
+ def collections
+ @attributes.select { |a| a.is_a?(Collection) }
+ end
+
def convert(name, value)
attr = @attributes.find { |a| a.name == name }
raise "Unknown attribute #{name}" unless attr
@@ -303,11 +342,7 @@ class CIMI::Model::Schema
end
def collection(name, opts={})
- text :count
-
- array :operations do
- scalar :rel, :href
- end
+ add_attributes!([name, opts], Collection)
end
end
--
1.7.7.6
[PATCH 2/7] CIMI (Model::Base): make generated attr methods go through the [] methods
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
---
server/lib/cimi/models/base.rb | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
index bb4a055..4c9b2dc 100644
--- a/server/lib/cimi/models/base.rb
+++ b/server/lib/cimi/models/base.rb
@@ -143,8 +143,8 @@ class CIMI::Model::Base
base_schema.add_attributes!(names, attr_klass, &block)
end
names.each do |name|
- define_method(name) { @attribute_values[name] }
- define_method(:"#{name}=") { |newval| @attribute_values[name] = newval }
+ define_method(name) { self[name] }
+ define_method(:"#{name}=") { |newval| self[name] = newval }
end
end
--
1.7.7.6
Re: RFC: embedded CIMI collections
Posted by Michal Fojtik <mi...@mifo.sk>.
On Oct 6, 2012, at 2:52 AM, lutter@redhat.com wrote:
ACK. I rebased the $expand patches and make them work with this
collections.
-- Michal
>
> These series of patches adds support for embedded collections for CIMI
> models. It's not quite perfect yet, since it doesn't produce the exactly
> right XML yet, nor is it possible to parse objects with embedded
> collections.
>
> The main reason I like this better than the way Michal did it is because it
> makes it unnecessary to have XXXCollection classes for
> collections. Instead, you can just write
>
> collection :things, :class => CIMI::Model::Thing
>
> For example, for the disks collection in machine, we simply have
>
> class CIMI::Model::Machine < CIMI::Model::Base
> ...
> collection :disks, :class => CIMI::Model::Disk
> ...
> end
>
> The interesting stuff are the last three patches in the series. The other
> ones can probably be acked and committed as they are.
>
> David
[PATCH 4/7] CIMI::Model::Base: remove unused methods acts_as_root_entity and all
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
---
server/lib/cimi/models/base.rb | 11 -----------
1 files changed, 0 insertions(+), 11 deletions(-)
diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
index eefa868..2a27a8f 100644
--- a/server/lib/cimi/models/base.rb
+++ b/server/lib/cimi/models/base.rb
@@ -235,17 +235,6 @@ class CIMI::Model::Base
hash :property
- def self.acts_as_root_entity(name=nil)
- if name
- name = name.to_s.camelize.pluralize
- else
- name = xml_tag_name.pluralize.uncapitalize
- end
- CIMI::Model.register_as_root_entity! name
- end
-
- def self.all(_self); find(:all, _self); end
-
def filter_by(filter_opts)
return self if filter_opts.nil?
return filter_attributes(filter_opts.split(',').map{ |a| a.intern }) if filter_opts.include? ','
--
1.7.7.6
[PATCH 1/7] CIMI::Model::Collection: fix typo in entries method
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
---
server/lib/cimi/models/collection.rb | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/server/lib/cimi/models/collection.rb b/server/lib/cimi/models/collection.rb
index 47c92f2..cae5e69 100644
--- a/server/lib/cimi/models/collection.rb
+++ b/server/lib/cimi/models/collection.rb
@@ -31,7 +31,8 @@ module CIMI::Model
end
def entries
- self[entry_name]
+ self[self.class.entry_name]
+ end
end
def [](a)
--
1.7.7.6
[PATCH 6/7] CIMI: call a 'prepare' method on models before serializing
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
This gives us an opportunity to
* set the count of collections to the number of entries
* generate id's for collections embedded in other objects
---
server/lib/cimi/models/base.rb | 6 ++++++
server/lib/cimi/models/collection.rb | 6 ++++++
server/lib/cimi/models/schema.rb | 4 ++++
3 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
index 2e66694..d238135 100644
--- a/server/lib/cimi/models/base.rb
+++ b/server/lib/cimi/models/base.rb
@@ -166,6 +166,12 @@ class CIMI::Model::Base
def []=(a, v)
@attribute_values[a] = self.class.schema.convert(a, v)
end
+
+ # Prepare to serialize
+ def prepare
+ self.class.schema.collections.map { |coll| coll.name }.each do |n|
+ self[n].id = "#{self.id}/#{n}"
+ end
end
#
diff --git a/server/lib/cimi/models/collection.rb b/server/lib/cimi/models/collection.rb
index cae5e69..f56efc5 100644
--- a/server/lib/cimi/models/collection.rb
+++ b/server/lib/cimi/models/collection.rb
@@ -27,12 +27,18 @@ module CIMI::Model
if values[:entries]
values[self.class.entry_name] = values.delete(:entries)
end
+ values[self.class.entry_name] ||= []
super(values)
end
def entries
self[self.class.entry_name]
end
+
+ # Prepare to serialize
+ def prepare
+ self.count = self.entries.size
+ self.count = nil if self.count == 0
end
def [](a)
diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
index d8ba13b..a8f76f9 100644
--- a/server/lib/cimi/models/schema.rb
+++ b/server/lib/cimi/models/schema.rb
@@ -234,10 +234,12 @@ class CIMI::Model::Schema
end
def to_xml(model, xml)
+ model[name].prepare
xml[xml_name] = @collection_class.schema.to_xml(model[name])
end
def to_json(model, json)
+ model[name].prepare
json[json_name] = @collection_class.schema.to_json(model[name])
end
@@ -286,6 +288,7 @@ class CIMI::Model::Schema
def to_xml(model, xml = nil)
xml ||= OrderedHash.new
@attributes.freeze
+ model.prepare if model.respond_to?(:prepare)
@attributes.each { |attr| attr.to_xml(model, xml) }
xml
end
@@ -301,6 +304,7 @@ class CIMI::Model::Schema
def to_json(model, json = {})
@attributes.freeze
+ model.prepare if model.respond_to?(:prepare)
@attributes.each { |attr| attr.to_json(model, json) }
json
end
--
1.7.7.6
[PATCH 7/7] CIMI: use embedded collection for Machine.disks and Machine.volumes
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
---
server/lib/cimi/models.rb | 2 -
server/lib/cimi/models/disk_collection.rb | 37 --------------------
server/lib/cimi/models/machine.rb | 13 +++----
.../lib/cimi/models/machine_volume_collection.rb | 34 ------------------
4 files changed, 5 insertions(+), 81 deletions(-)
delete mode 100644 server/lib/cimi/models/disk_collection.rb
delete mode 100644 server/lib/cimi/models/machine_volume_collection.rb
diff --git a/server/lib/cimi/models.rb b/server/lib/cimi/models.rb
index df328f5..1eae2c9 100644
--- a/server/lib/cimi/models.rb
+++ b/server/lib/cimi/models.rb
@@ -25,9 +25,7 @@ require_relative './models/collection'
require_relative './models/errors'
require_relative './models/action'
require_relative './models/disk'
-require_relative './models/disk_collection'
require_relative './models/machine_volume'
-require_relative './models/machine_volume_collection'
# Toplevel entities; order matters as it determines the order
# in which the entities appear in the CEP
diff --git a/server/lib/cimi/models/disk_collection.rb b/server/lib/cimi/models/disk_collection.rb
deleted file mode 100644
index 7dbff39..0000000
--- a/server/lib/cimi/models/disk_collection.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership. The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-class CIMI::Model::DiskCollection < CIMI::Model::Base
- text :count
-
- #add disks array:
- self << CIMI::Model::Disk
-
- array :operations do
- scalar :rel, :href
- end
-
- def self.default(instance_id, context)
- instance = context.driver.instance(context.credentials, :id=>instance_id)
- machine_conf = CIMI::Model::MachineConfiguration.find(instance.instance_profile.name, context)
- disks = CIMI::Model::Disk.find(instance, machine_conf, context, :all)
- self.new(
- :id => context.machine_url(instance_id)+"/disks",
- :description => "DiskCollection for Machine #{instance_id}",
- :created => instance.launch_time,
- :count => disks.size,
- :disks => disks
- )
- end
-end
diff --git a/server/lib/cimi/models/machine.rb b/server/lib/cimi/models/machine.rb
index c605d2a..a15fa81 100644
--- a/server/lib/cimi/models/machine.rb
+++ b/server/lib/cimi/models/machine.rb
@@ -24,11 +24,8 @@ class CIMI::Model::Machine < CIMI::Model::Base
href :event_log
- href :disks
-
- href :volumes
-
- href :network_interfaces
+ collection :disks, :class => CIMI::Model::Disk
+ collection :volumes, :class => CIMI::Model::MachineVolume
array :meters do
scalar :href
@@ -118,6 +115,7 @@ class CIMI::Model::Machine < CIMI::Model::Base
private
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)
self.new(
:name => instance.id,
:description => instance.name,
@@ -126,10 +124,9 @@ class CIMI::Model::Machine < CIMI::Model::Base
: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"},
- :network_interfaces => {:href => context.machine_url(instance.id+"/network_interfaces")},
+ :disks => CIMI::Model::Disk.find(instance, machine_conf, context, :all),
:operations => convert_instance_actions(instance, context),
- :volumes=>{:href=>context.machine_url(instance.id)+"/volumes"},
+ :volumes => CIMI::Model::MachineVolume.find(instance.id, context, :all),
:property => convert_instance_properties(instance, context)
)
end
diff --git a/server/lib/cimi/models/machine_volume_collection.rb b/server/lib/cimi/models/machine_volume_collection.rb
deleted file mode 100644
index b9dfcad..0000000
--- a/server/lib/cimi/models/machine_volume_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership. The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-class CIMI::Model::MachineVolumeCollection < CIMI::Model::Base
-
- text :count
-
- self << CIMI::Model::MachineVolume
-
- array :operations do
- scalar :rel, :href
- end
-
- def self.default(instance_id, context)
- volumes = CIMI::Model::MachineVolume.find(instance_id, context)
- self.new(
- :id => context.machine_url(instance_id)+"/volumes",
- :description => "MachineVolumeCollection for Machine #{instance_id}",
- :count => volumes.size,
- :machine_volumes => volumes
- )
- end
-end
--
1.7.7.6