From e97040d3e5b68be31c220661a7e33bf204ae3916 Mon Sep 17 00:00:00 2001 From: Daniel Molina Date: Wed, 22 Feb 2012 17:16:39 +0100 Subject: [PATCH] Add more OCCI tests --- .../occi/test/fixtures/compute/empty.xml | 1 + .../test/fixtures/compute/first_compute.xml | 20 ++ .../fixtures/compute/first_compute_done.xml | 20 ++ .../test/fixtures/compute/second_compute.xml | 20 ++ .../fixtures/compute/second_compute_done.xml | 20 ++ .../test/fixtures/instance_type/extended.xml | 20 ++ .../occi/test/fixtures/instance_type/list.xml | 5 + .../occi/test/fixtures/network/empty.xml | 1 + .../occi/test/fixtures/network/first_net.xml | 11 + .../occi/test/fixtures/network/second_net.xml | 11 + src/cloud/occi/test/fixtures/root.xml | 7 + .../occi/test/fixtures/storage/empty.xml | 1 + .../test/fixtures/storage/first_storage.xml | 13 + .../test/fixtures/storage/second_storage.xml | 13 + src/cloud/occi/test/spec/occi_spec.rb | 283 ++++++++++++++++++ src/cloud/occi/test/spec/spec.opts | 4 + src/cloud/occi/test/spec/spec_helper.rb | 152 ++++++++++ 17 files changed, 602 insertions(+) create mode 100644 src/cloud/occi/test/fixtures/compute/empty.xml create mode 100644 src/cloud/occi/test/fixtures/compute/first_compute.xml create mode 100644 src/cloud/occi/test/fixtures/compute/first_compute_done.xml create mode 100644 src/cloud/occi/test/fixtures/compute/second_compute.xml create mode 100644 src/cloud/occi/test/fixtures/compute/second_compute_done.xml create mode 100644 src/cloud/occi/test/fixtures/instance_type/extended.xml create mode 100644 src/cloud/occi/test/fixtures/instance_type/list.xml create mode 100644 src/cloud/occi/test/fixtures/network/empty.xml create mode 100644 src/cloud/occi/test/fixtures/network/first_net.xml create mode 100644 src/cloud/occi/test/fixtures/network/second_net.xml create mode 100644 src/cloud/occi/test/fixtures/root.xml create mode 100644 src/cloud/occi/test/fixtures/storage/empty.xml create mode 100644 src/cloud/occi/test/fixtures/storage/first_storage.xml create mode 100644 src/cloud/occi/test/fixtures/storage/second_storage.xml create mode 100644 src/cloud/occi/test/spec/occi_spec.rb create mode 100644 src/cloud/occi/test/spec/spec.opts diff --git a/src/cloud/occi/test/fixtures/compute/empty.xml b/src/cloud/occi/test/fixtures/compute/empty.xml new file mode 100644 index 0000000000..17ef393d05 --- /dev/null +++ b/src/cloud/occi/test/fixtures/compute/empty.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/cloud/occi/test/fixtures/compute/first_compute.xml b/src/cloud/occi/test/fixtures/compute/first_compute.xml new file mode 100644 index 0000000000..4824a2b00e --- /dev/null +++ b/src/cloud/occi/test/fixtures/compute/first_compute.xml @@ -0,0 +1,20 @@ + + 0 + + oneadmin + 1 + 1024 + Compute + small + PENDING + + + DISK + hde + + + + 192.168.1.1 + 02:00:c0:a8:01:01 + + diff --git a/src/cloud/occi/test/fixtures/compute/first_compute_done.xml b/src/cloud/occi/test/fixtures/compute/first_compute_done.xml new file mode 100644 index 0000000000..46bd2c8352 --- /dev/null +++ b/src/cloud/occi/test/fixtures/compute/first_compute_done.xml @@ -0,0 +1,20 @@ + + 0 + + oneadmin + 1 + 1024 + Compute + small + DONE + + + DISK + hde + + + + 192.168.1.1 + 02:00:c0:a8:01:01 + + diff --git a/src/cloud/occi/test/fixtures/compute/second_compute.xml b/src/cloud/occi/test/fixtures/compute/second_compute.xml new file mode 100644 index 0000000000..ee057ed43e --- /dev/null +++ b/src/cloud/occi/test/fixtures/compute/second_compute.xml @@ -0,0 +1,20 @@ + + 1 + + users + 1 + 1024 + Compute2 + small + PENDING + + + DISK + hde + + + + 192.168.2.1 + 02:00:c0:a8:02:01 + + diff --git a/src/cloud/occi/test/fixtures/compute/second_compute_done.xml b/src/cloud/occi/test/fixtures/compute/second_compute_done.xml new file mode 100644 index 0000000000..e73c28ba3b --- /dev/null +++ b/src/cloud/occi/test/fixtures/compute/second_compute_done.xml @@ -0,0 +1,20 @@ + + 1 + + users + 1 + 1024 + Compute2 + small + DONE + + + DISK + hde + + + + 192.168.2.1 + 02:00:c0:a8:02:01 + + diff --git a/src/cloud/occi/test/fixtures/instance_type/extended.xml b/src/cloud/occi/test/fixtures/instance_type/extended.xml new file mode 100644 index 0000000000..f774763320 --- /dev/null +++ b/src/cloud/occi/test/fixtures/instance_type/extended.xml @@ -0,0 +1,20 @@ + + + large + large + 8 + 8192 + + + medium + medium + 4 + 4096 + + + small + small + 1 + 1024 + + diff --git a/src/cloud/occi/test/fixtures/instance_type/list.xml b/src/cloud/occi/test/fixtures/instance_type/list.xml new file mode 100644 index 0000000000..135ae70491 --- /dev/null +++ b/src/cloud/occi/test/fixtures/instance_type/list.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/cloud/occi/test/fixtures/network/empty.xml b/src/cloud/occi/test/fixtures/network/empty.xml new file mode 100644 index 0000000000..c96d82e6ed --- /dev/null +++ b/src/cloud/occi/test/fixtures/network/empty.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/cloud/occi/test/fixtures/network/first_net.xml b/src/cloud/occi/test/fixtures/network/first_net.xml new file mode 100644 index 0000000000..24b388783d --- /dev/null +++ b/src/cloud/occi/test/fixtures/network/first_net.xml @@ -0,0 +1,11 @@ + + 0 + Network + + oneadmin + Network of the user my_first_occi_user +
192.168.1.1
+ 125 + 0 + NO +
diff --git a/src/cloud/occi/test/fixtures/network/second_net.xml b/src/cloud/occi/test/fixtures/network/second_net.xml new file mode 100644 index 0000000000..9cad2d9594 --- /dev/null +++ b/src/cloud/occi/test/fixtures/network/second_net.xml @@ -0,0 +1,11 @@ + + 1 + Network2 + + users + Network of the user my_second_occi_user +
192.168.2.1
+ 125 + 0 + NO +
diff --git a/src/cloud/occi/test/fixtures/root.xml b/src/cloud/occi/test/fixtures/root.xml new file mode 100644 index 0000000000..38843f0418 --- /dev/null +++ b/src/cloud/occi/test/fixtures/root.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/cloud/occi/test/fixtures/storage/empty.xml b/src/cloud/occi/test/fixtures/storage/empty.xml new file mode 100644 index 0000000000..622d314777 --- /dev/null +++ b/src/cloud/occi/test/fixtures/storage/empty.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/cloud/occi/test/fixtures/storage/first_storage.xml b/src/cloud/occi/test/fixtures/storage/first_storage.xml new file mode 100644 index 0000000000..c24bea57ae --- /dev/null +++ b/src/cloud/occi/test/fixtures/storage/first_storage.xml @@ -0,0 +1,13 @@ + + 0 + Storage + + oneadmin + READY + DATABLOCK + Storage of the user my_first_occi_user + 100 + ext3 + NO + NO + diff --git a/src/cloud/occi/test/fixtures/storage/second_storage.xml b/src/cloud/occi/test/fixtures/storage/second_storage.xml new file mode 100644 index 0000000000..defd5b1a56 --- /dev/null +++ b/src/cloud/occi/test/fixtures/storage/second_storage.xml @@ -0,0 +1,13 @@ + + 1 + Storage2 + + users + READY + DATABLOCK + Storage of the user my_second_occi_user + 100 + ext3 + NO + NO + diff --git a/src/cloud/occi/test/spec/occi_spec.rb b/src/cloud/occi/test/spec/occi_spec.rb new file mode 100644 index 0000000000..ba35ae94dd --- /dev/null +++ b/src/cloud/occi/test/spec/occi_spec.rb @@ -0,0 +1,283 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed 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 File.expand_path(File.dirname(__FILE__) + '/spec_helper') + +# The following methods are helpers defined in spec_helper +# - compare_xml +# - get_fixture +# - network_template +# - storage_template +# - compute_template + +describe 'OCCI tests' do + before(:all) do + @user_oneadmin = "my_first_occi_user" + `oneuser create #{@user_oneadmin} my_pass`.scan(/^ID: (\d+)/) { |uid| + `oneuser show #{uid.first}`.scan(/PASSWORD\s*:\s*(\w*)/) { |password| + @user_pass = password.first.strip + } + + `oneuser chgrp #{uid.first} 0` + } + + @user_users = "my_second_occi_user" + `oneuser create #{@user_users} my_pass2`.scan(/^ID: (\d+)/) { |uid| + `oneuser show #{uid.first}`.scan(/PASSWORD\s*:\s*(\w*)/) { |password| + @user_pass2 = password.first.strip + } + } + + # Define BRIDGE attirbute in network.erb, otherwise the NETWORK creation will + `sed -i.bck "s%^#\\(BRIDGE = \\).*$%\\1 br0%" $ONE_LOCATION/etc/occi_templates/network.erb` + end + + describe "with a user of the oneadmin group" do + before(:each) do + basic_authorize(@user_oneadmin, @user_pass) + end + + it "should retrieve the list of collections" do + get '/' + compare_xml(last_response.body, get_fixture('/root.xml')) + last_response.status.should == 200 + end + + it "should retrieve the list of INSTANCE_TYPEs" do + get '/instance_type' + compare_xml(last_response.body, get_fixture('/instance_type/list.xml')) + last_response.status.should == 200 + end + + it "should retrieve the extended list of INSTANCE_TYPEs" do + get '/instance_type', {'verbose'=>true} + compare_xml(last_response.body, get_fixture('/instance_type/extended.xml')) + last_response.status.should == 200 + end + + context "for NETWORK" do + it "should retrieve the empty list" do + get '/network' + compare_xml(last_response.body, get_fixture('/network/empty.xml')) + last_response.status.should == 200 + end + + it "should create a new NETWORK" do + network = { + :name => "Network", + :description => "Network of the user #{@user_oneadmin}", + :address => "192.168.1.0", + :size => "100", + :pubic => "YES" + } + + post '/network', network_template(network) + compare_xml(last_response.body, get_fixture('/network/first_net.xml')) + last_response.status.should == 201 + end + + it "should retrieve the NETWORK with ID 0" do + get '/network/0' + compare_xml(last_response.body, get_fixture('/network/first_net.xml')) + last_response.status.should == 200 + end + end + + context "for STORAGE" do + it "should retrieve the empty list" do + get '/storage' + compare_xml(last_response.body, get_fixture('/storage/empty.xml')) + last_response.status.should == 200 + end + + it "should create a new STORAGE, type DATABLOCK. This request waits until the IMAGE is ready in OpenNebula" do + storage = { + :name => "Storage", + :description => "Storage of the user #{@user_oneadmin}", + :type => "DATABLOCK", + :size => "100", + :fstype => "ext3" + } + + post '/storage', {'occixml' => storage_template(storage)} + compare_xml(last_response.body, get_fixture('/storage/first_storage.xml')) + last_response.status.should == 201 + end + + it "should retrieve the STORAGE with ID 0" do + get '/storage/0' + compare_xml(last_response.body, get_fixture('/storage/first_storage.xml')) + last_response.status.should == 200 + end + end + + context "for COMPUTE" do + it "should retrieve the empty list" do + get '/compute' + compare_xml(last_response.body, get_fixture('/compute/empty.xml')) + last_response.status.should == 200 + end + + it "should create a new COMPUTE using the previous NETWORK (ID=0) and STORAGE(ID=0)" do + compute = { + :name => "Compute", + :instance_type => "small", + :disk => [ {:storage => '0'} ], + :nic => [ {:network => '0'} ] + } + + post '/compute', compute_template(compute) + compare_xml(last_response.body, get_fixture('/compute/first_compute.xml')) + last_response.status.should == 201 + end + + it "should retrieve the COMPUTE with ID 0" do + get '/compute/0' + compare_xml(last_response.body, get_fixture('/compute/first_compute.xml')) + last_response.status.should == 200 + end + + it "should terminate (DONE) the COMPUTE with ID 0" do + compute = { + :id => "0", + :state => "DONE" + } + + put '/compute/0', compute_action(compute) + compare_xml(last_response.body, get_fixture('/compute/first_compute_done.xml')) + last_response.status.should == 202 + end + end + end + + describe "with a user of the users group" do + before(:each) do + basic_authorize(@user_users, @user_pass2) + end + + it "should retrieve the list of collections" do + get '/' + compare_xml(last_response.body, get_fixture('/root.xml')) + last_response.status.should == 200 + end + + it "should retrieve the list of INSTANCE_TYPEs" do + get '/instance_type' + compare_xml(last_response.body, get_fixture('/instance_type/list.xml')) + last_response.status.should == 200 + end + + it "should retrieve the extended list of INSTANCE_TYPEs" do + get '/instance_type', {'verbose'=>true} + compare_xml(last_response.body, get_fixture('/instance_type/extended.xml')) + last_response.status.should == 200 + end + + context "for NETWORK" do + it "should retrieve the empty list" do + get '/network' + compare_xml(last_response.body, get_fixture('/network/empty.xml')) + last_response.status.should == 200 + end + + it "should create a new NETWORK" do + network = { + :name => "Network2", + :description => "Network of the user #{@user_users}", + :address => "192.168.2.0", + :size => "100", + :pubic => "YES" + } + + post '/network', network_template(network) + compare_xml(last_response.body, get_fixture('/network/second_net.xml')) + last_response.status.should == 201 + end + + it "should retrieve the NETWORK with ID 1" do + get '/network/1' + compare_xml(last_response.body, get_fixture('/network/second_net.xml')) + last_response.status.should == 200 + end + end + + context "for STORAGE" do + it "should retrieve the empty list" do + get '/storage' + compare_xml(last_response.body, get_fixture('/storage/empty.xml')) + last_response.status.should == 200 + end + + it "should create a new STORAGE, type DATABLOCK. This request waits until the IMAGE is ready in OpenNebula" do + storage = { + :name => "Storage2", + :description => "Storage of the user #{@user_users}", + :type => "DATABLOCK", + :size => "100", + :fstype => "ext3" + } + + post '/storage', {'occixml' => storage_template(storage)} + compare_xml(last_response.body, get_fixture('/storage/second_storage.xml')) + last_response.status.should == 201 + end + + it "should retrieve the STORAGE with ID 1" do + get '/storage/1' + compare_xml(last_response.body, get_fixture('/storage/second_storage.xml')) + last_response.status.should == 200 + end + end + + context "for COMPUTE" do + it "should retrieve the empty list" do + get '/compute' + compare_xml(last_response.body, get_fixture('/compute/empty.xml')) + last_response.status.should == 200 + end + + it "should create a new COMPUTE using the previous NETWORK (ID=1) and STORAGE(ID=1)" do + compute = { + :name => "Compute2", + :instance_type => "small", + :disk => [ {:storage => '1'} ], + :nic => [ {:network => '1'} ] + } + + post '/compute', compute_template(compute) + compare_xml(last_response.body, get_fixture('/compute/second_compute.xml')) + last_response.status.should == 201 + end + + it "should retrieve the COMPUTE with ID 1" do + get '/compute/1' + compare_xml(last_response.body, get_fixture('/compute/second_compute.xml')) + last_response.status.should == 200 + end + + it "should terminate (DONE) the COMPUTE with ID 1" do + compute = { + :id => "1", + :state => "DONE" + } + + put '/compute/1', compute_action(compute) + compare_xml(last_response.body, get_fixture('/compute/second_compute_done.xml')) + last_response.status.should == 202 + end + end + end +end \ No newline at end of file diff --git a/src/cloud/occi/test/spec/spec.opts b/src/cloud/occi/test/spec/spec.opts new file mode 100644 index 0000000000..ad561bd258 --- /dev/null +++ b/src/cloud/occi/test/spec/spec.opts @@ -0,0 +1,4 @@ +--colour +--format progress +--loadby mtime +--reverse \ No newline at end of file diff --git a/src/cloud/occi/test/spec/spec_helper.rb b/src/cloud/occi/test/spec/spec_helper.rb index b2a2917a97..0d7423a2fc 100644 --- a/src/cloud/occi/test/spec/spec_helper.rb +++ b/src/cloud/occi/test/spec/spec_helper.rb @@ -24,6 +24,8 @@ require 'rubygems' require 'rspec' require 'rack/test' +require 'rexml/document' + # Load the Sinatra app require 'occi-server' @@ -39,3 +41,153 @@ set :environment, :test def app Sinatra::Application end + + + +def get_fixture(path) + File.read(FIXTURES_PATH + path).strip +end + + +def compare_xml(a, b) + a = REXML::Document.new(a.to_s) + b = REXML::Document.new(b.to_s) + + normalized = Class.new(REXML::Formatters::Pretty) do + def write_text(node, output) + super(node.to_s.strip, output) + end + end + + normalized.new(indentation=0,ie_hack=false).write(node=a, a_normalized='') + normalized.new(indentation=0,ie_hack=false).write(node=b, b_normalized='') + + a_normalized.should == b_normalized +end + + +OCCI_NETWORK = %q{ + + <% if hash[:name] %> + <%= hash[:name] %> + <% end %> + + <% if hash[:description] %> + <%= hash[:description] %> + <% end %> + + <% if hash[:address] %> +
<%= hash[:address] %>
+ <% end %> + + <% if hash[:size] %> + <%= hash[:size] %> + <% end %> + + <% if hash[:public] %> + <%= hash[:public] %> + <% end %> +
+} + +def network_template(hash) + ERB.new(OCCI_NETWORK).result(binding) +end + +OCCI_IMAGE = %q{ + + <% if hash[:name] %> + <%= hash[:name] %> + <% end %> + + <% if hash[:type] %> + <%= hash[:type] %> + <% end %> + + <% if hash[:description] %> + <%= hash[:description] %> + <% end %> + + <% if hash[:size] %> + <%= hash[:size] %> + <% end %> + + <% if hash[:fstype] %> + <%= hash[:fstype] %> + <% end %> + + <% if hash[:public] %> + <%= hash[:public] %> + <% end %> + + <% if hash[:persistent] %> + <%= hash[:persistent] %> + <% end %> + +} + +def storage_template(hash) + ERB.new(OCCI_IMAGE).result(binding) +end + +OCCI_VM = %q{ + + <% if hash[:name] %> + <%= hash[:name] %> + <% end %> + + <% if hash[:instance_type] %> + + <% end %> + + <% if hash[:disk] %> + <% hash[:disk].each { |disk| %> + + <% if disk[:storage] %> + + <% end %> + + <% } %> + <% end %> + + <% if hash[:nic] %> + <% hash[:nic].each { |nic| %> + + <% if nic[:network] %> + + <% end %> + <% if nic[:ip] %> + <%= nic[:ip] %> + <% end %> + + <% } %> + <% end %> + + <% if hash[:context] %> + + <% hash[:context].each { |key, value| %> + <<%= key.to_s.upcase %>><%= value %>> + <% } %> + + <% end %> + +} + +OCCI_VM_ACTION = %q{ + + <% if hash[:id] %> + <%= hash[:id] %> + <% end %> + <% if hash[:state] %> + <%= hash[:state] %> + <% end %> + +} + +def compute_template(hash) + ERB.new(OCCI_VM).result(binding) +end + +def compute_action(hash) + ERB.new(OCCI_VM_ACTION).result(binding) +end