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 2011/11/09 22:18:24 UTC
[PATCH 2/2] CIMI: model for machineTemplate
From: David Lutterkort <lu...@redhat.com>
Signed-off-by: David Lutterkort <lu...@redhat.com>
---
server/lib/cimi/model/machine_template.rb | 36 +++++++++
server/spec/cimi/data/machine_template.json | 30 ++++++++
server/spec/cimi/data/machine_template.xml | 24 ++++++
server/spec/cimi/model/machine_template_spec.rb | 51 +++++++++++++
server/spec/spec_helper.rb | 92 +++++++++++++++++++++++
5 files changed, 233 insertions(+), 0 deletions(-)
create mode 100644 server/lib/cimi/model/machine_template.rb
create mode 100644 server/spec/cimi/data/machine_template.json
create mode 100644 server/spec/cimi/data/machine_template.xml
create mode 100644 server/spec/cimi/model/machine_template_spec.rb
diff --git a/server/lib/cimi/model/machine_template.rb b/server/lib/cimi/model/machine_template.rb
new file mode 100644
index 0000000..458f365
--- /dev/null
+++ b/server/lib/cimi/model/machine_template.rb
@@ -0,0 +1,36 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineTemplate < CIMI::Model::Base
+ href :machine_config
+ href :machine_image
+ href :machine_admin
+ array :volumes do
+ scalar :href
+ scalar :protocol
+ scalar :attachment_point
+ end
+ array :volume_templates do
+ scalar :href, :attachment_point, :protocol
+ end
+ array :network_interfaces do
+ href :vsp
+ text :hostname, :mac_address, :state, :protocol, :allocation
+ text :address, :default_gateway, :dns, :max_transmission_unit
+ end
+ array :operations do
+ scalar :rel, :href
+ end
+end
diff --git a/server/spec/cimi/data/machine_template.json b/server/spec/cimi/data/machine_template.json
new file mode 100644
index 0000000..54de58d
--- /dev/null
+++ b/server/spec/cimi/data/machine_template.json
@@ -0,0 +1,30 @@
+{
+ "uri": "http://cimi.example.org/machine_templates/1",
+ "name": "My First Template",
+ "description": "A template for testing",
+ "created": "2011-11-01",
+ "machineConfig": { "href": "http://cimi.example.org/machine_configs/1" },
+ "machineImage": { "href": "http://cimi.example.org/machine_images/1" },
+ "volumes": [{
+ "href": "http://cimi.example.org/volumes/1",
+ "attachmentPoint": "/dev/sda",
+ "protocol": "nfs"
+ }],
+ "networkInterfaces": [{
+ "vsp": { "href": "http://cimi.example.org/vsps/1" },
+ "hostname": "host.cimi.example.org",
+ "macAddress": "00:11:22:33:44:55",
+ "state": "UP",
+ "protocol": "TCP",
+ "allocation": "static",
+ "address": "192.168.0.17",
+ "defaultGateway": "192.168.0.1",
+ "dns": "192.168.0.1",
+ "maxTransmissionUnit": "1500"
+ }],
+ "operations": [
+ { "rel": "edit",
+ "href": "http://cimi.example.org/machine_templates/1/edit" },
+ { "rel": "delete",
+ "href": "http://cimi.example.org/machine_templates/1/delete" }]
+}
diff --git a/server/spec/cimi/data/machine_template.xml b/server/spec/cimi/data/machine_template.xml
new file mode 100644
index 0000000..160b311
--- /dev/null
+++ b/server/spec/cimi/data/machine_template.xml
@@ -0,0 +1,24 @@
+<MachineTemplate xmlns="http://www.dmtf.org/cimi">
+ <uri>http://cimi.example.org/machine_templates/1</uri>
+ <name>My First Template</name>
+ <description>A template for testing</description>
+ <created>2011-11-01</created>
+ <machineConfig href="http://cimi.example.org/machine_configs/1"/>
+ <machineImage href="http://cimi.example.org/machine_images/1"/>
+ <volume href="http://cimi.example.org/volumes/1"
+ attachmentPoint="/dev/sda" protocol="nfs" />
+ <networkInterface>
+ <vsp href="http://cimi.example.org/vsps/1"/>
+ <hostname>host.cimi.example.org</hostname>
+ <macAddress>00:11:22:33:44:55</macAddress>
+ <state>UP</state>
+ <protocol>TCP</protocol>
+ <allocation>static</allocation>
+ <address>192.168.0.17</address>
+ <defaultGateway>192.168.0.1</defaultGateway>
+ <dns>192.168.0.1</dns>
+ <maxTransmissionUnit>1500</maxTransmissionUnit>
+ </networkInterface>
+ <operation rel="edit" href="http://cimi.example.org/machine_templates/1/edit"/>
+ <operation rel="delete" href="http://cimi.example.org/machine_templates/1/delete"/>
+</MachineTemplate>
diff --git a/server/spec/cimi/model/machine_template_spec.rb b/server/spec/cimi/model/machine_template_spec.rb
new file mode 100644
index 0000000..d7028a6
--- /dev/null
+++ b/server/spec/cimi/model/machine_template_spec.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.
+#
+
+require 'spec_helper'
+
+require 'cimi/model'
+
+describe "MachineTemplate model" do
+
+ DATA_DIR = File::join(File::dirname(__FILE__), '..', 'data')
+
+ before(:all) do
+ @xml = IO::read(File::join(DATA_DIR, "machine_template.xml"))
+ @json = IO::read(File::join(DATA_DIR, "machine_template.json"))
+ end
+
+ it "can be constructed from XML" do
+ templ = CIMI::Model::MachineTemplate.from_xml(@xml)
+ templ.should_not be_nil
+ templ.created.should == "2011-11-01"
+ templ.volumes.size.should == 1
+ templ.should serialize_to @xml, :fmt => :xml
+ end
+
+ it "should convert strings in keys to symbols when contructed from XML" do
+ templ = CIMI::Model::MachineTemplate.from_xml(@xml)
+ templ.should_not be_nil
+ templ.attribute_values.keys.each { |key| key.should be_a(Symbol) }
+ end
+
+ it "can be constructed from JSON" do
+ templ = CIMI::Model::MachineTemplate.from_json(@json)
+ templ.should_not be_nil
+
+ templ.created.should == "2011-11-01"
+ templ.should serialize_to @json, :fmt => :json
+ end
+end
diff --git a/server/spec/spec_helper.rb b/server/spec/spec_helper.rb
index 1e0dd87..d9a51f5 100644
--- a/server/spec/spec_helper.rb
+++ b/server/spec/spec_helper.rb
@@ -25,3 +25,95 @@ def parse_xml(xml, opts = {})
opts[:keep_root] = true unless opts.has_key?(:keep_root)
XmlSimple.xml_in(xml, opts)
end
+
+class HashCmp
+ def initialize(exp, act)
+ @exp = exp
+ @act = act
+ @io = StringIO.new
+ end
+
+ def match?
+ @equal = true
+ compare_values(@exp, @act, [])
+ @equal
+ end
+
+ def errors
+ @io.string
+ end
+
+ private
+ def compare_values(exp, act, path)
+ if exp.is_a?(String)
+ mismatch("entries differ", exp, act, path) unless exp == act
+ elsif exp.is_a?(Array)
+ mismatch("expected array", exp, act, path) unless act.is_a?(Array)
+ unless act.size == exp.size
+ mismatch("different array lengths", exp, act, path)
+ end
+ name = path.pop
+ 0.upto(exp.size-1) do |i|
+ compare_values(exp[i], act[i], path + [ "#{name}[#{i}]" ])
+ end
+ elsif exp.is_a?(Hash)
+ unless act.is_a?(Hash)
+ mismatch("expected Hash", exp, act, path)
+ return
+ end
+ unless (missing = exp.keys - act.keys).empty?
+ error "Missing key(s) at /#{path.join("/")}: #{missing.inspect}"
+ end
+ unless (excess = act.keys - exp.keys).empty?
+ error "Excess key(s) at /#{path.join("/")}: #{excess.inspect}"
+ end
+ (exp.keys - missing - excess).each do |k|
+ compare_values(exp[k], act[k], path + [ k ])
+ end
+ end
+ end
+
+ def mismatch(msg, exp, act, path)
+ error "#{msg}[#{fmt(path)}]: #{exp.inspect} != #{act.inspect}"
+ end
+
+ def error(msg)
+ @equal = false
+ @io.puts msg
+ end
+
+ def fmt(path)
+ "/#{path.join("/")}"
+ end
+end
+
+RSpec::Matchers.define :serialize_to do |exp, opts|
+ match do |act|
+ matcher(exp, act, opts[:fmt]).match?
+ end
+
+ failure_message_for_should do |act|
+ m = matcher(exp, act, opts[:fmt])
+ m.match?
+ "#{opts[:fmt].to_s.upcase} documents do not match\n" + m.errors
+ end
+
+ def matcher(exp, act, fmt)
+ raise "missing format; use :fmt => [:xml || :json]" if fmt.nil?
+ exp, act = [exp, act].map { |x| convert(x, fmt) }
+ HashCmp.new(exp, act)
+ end
+
+ def convert(x, fmt)
+ if fmt == :json
+ x = x.to_json if x.is_a?(CIMI::Model::Base)
+ x = JSON.parse(x) if x.is_a?(String)
+ elsif fmt == :xml
+ x = x.to_xml if x.is_a?(CIMI::Model::Base)
+ x = parse_xml(x) if x.is_a?(String)
+ else
+ raise "Invalid format #{fmt}"
+ end
+ x
+ end
+end
--
1.7.6.4