1
0
mirror of https://github.com/OpenNebula/one.git synced 2024-12-22 13:33:52 +03:00

Bug #1595: Store a collection of Image IDs that are currently cloning an Image

This commit is contained in:
Carlos Martín 2012-10-31 17:50:16 +01:00
parent c2eec65475
commit 2d68cb5fdb
9 changed files with 210 additions and 37 deletions

View File

@ -292,14 +292,24 @@ public:
return cloning_ops;
}
int dec_cloning()
int dec_cloning(int img_id)
{
return --cloning_ops;
if ( img_clone_collection.del_collection_id(img_id) == 0 )
{
cloning_ops--;
}
return cloning_ops;
}
int inc_cloning()
int inc_cloning(int img_id)
{
return ++cloning_ops;
if ( img_clone_collection.add_collection_id(img_id) == 0 )
{
cloning_ops++;
}
return cloning_ops;
}
/**
@ -553,6 +563,11 @@ private:
*/
ObjectCollection vm_collection;
/**
* Stores a collection with the Images cloning this image
*/
ObjectCollection img_clone_collection;
// *************************************************************************
// DataBase implementation (Private)
// *************************************************************************

View File

@ -107,8 +107,9 @@ public:
/**
* Closes any cloning operation on the image, updating the state if needed
* @param iid image id of the image to be released
* @param clone_img_id image id of the image that was being cloned
*/
void release_cloning_image(int iid);
void release_cloning_image(int iid, int clone_img_id);
/**
* Enables the image

View File

@ -1001,6 +1001,7 @@ ONEDB_MIGRATOR_FILES="src/onedb/2.0_to_2.9.80.rb \
src/onedb/3.6.0_to_3.7.80.rb \
src/onedb/3.7.80_to_3.8.0.rb \
src/onedb/3.8.0_to_3.8.1.rb \
src/onedb/3.8.1_to_3.9.80.rb \
src/onedb/fsck.rb \
src/onedb/onedb.rb \
src/onedb/onedb_backend.rb"

View File

@ -57,6 +57,13 @@
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="CLONES">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="TEMPLATE" type="xs:anyType"/>
</xs:sequence>
</xs:complexType>

View File

@ -53,7 +53,8 @@ Image::Image(int _uid,
cloning_id(-1),
ds_id(-1),
ds_name(""),
vm_collection("VMS")
vm_collection("VMS"),
img_clone_collection("CLONES")
{
if (_image_template != 0)
{
@ -318,6 +319,7 @@ string& Image::to_xml(string& xml) const
string perms_xml;
ostringstream oss;
string vm_collection_xml;
string clone_collection_xml;
oss <<
"<IMAGE>" <<
@ -343,6 +345,7 @@ string& Image::to_xml(string& xml) const
"<DATASTORE_ID>" << ds_id << "</DATASTORE_ID>"<<
"<DATASTORE>" << ds_name << "</DATASTORE>" <<
vm_collection.to_xml(vm_collection_xml) <<
img_clone_collection.to_xml(clone_collection_xml) <<
obj_template->to_xml(template_xml) <<
"</IMAGE>";
@ -427,6 +430,21 @@ int Image::from_xml(const string& xml)
ObjectXML::free_nodes(content);
content.clear();
ObjectXML::get_nodes("/IMAGE/CLONES", content);
if (content.empty())
{
return -1;
}
rc += img_clone_collection.from_xml_node(content[0]);
ObjectXML::free_nodes(content);
if (rc != 0)
{
return -1;

View File

@ -225,7 +225,7 @@ void ImageManager::release_image(int vm_id, int iid, bool failed)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void ImageManager::release_cloning_image(int iid)
void ImageManager::release_cloning_image(int iid, int clone_img_id)
{
Image * img;
@ -238,24 +238,18 @@ void ImageManager::release_cloning_image(int iid)
return;
}
int cloning = img->dec_cloning(clone_img_id);
switch (img->get_state())
{
case Image::CLONE:
img->dec_cloning();
img->set_state(Image::READY);
ipool->update(img);
img->unlock();
break;
case Image::USED:
if ( img->dec_cloning() == 0 && img->get_running() == 0 )
case Image::CLONE:
if ( cloning == 0 && img->get_running() == 0 )
{
img->set_state(Image::READY);
}
ipool->update(img);
img->unlock();
break;
case Image::DELETE:
@ -275,6 +269,9 @@ void ImageManager::release_cloning_image(int iid)
img->unlock();
break;
}
ipool->update(img);
img->unlock();
}
/* -------------------------------------------------------------------------- */
@ -439,7 +436,7 @@ int ImageManager::delete_image(int iid, const string& ds_data)
if ( cloning_id != -1 )
{
release_cloning_image(cloning_id);
release_cloning_image(cloning_id, iid);
}
return 0;
@ -524,7 +521,7 @@ int ImageManager::clone_image(int new_id,
switch(img->get_state())
{
case Image::READY:
img->inc_cloning();
img->inc_cloning(new_id);
if (img->isPersistent())
{
@ -541,7 +538,7 @@ int ImageManager::clone_image(int new_id,
break;
case Image::USED:
img->inc_cloning();
img->inc_cloning(new_id);
ipool->update(img);

View File

@ -279,7 +279,7 @@ static void clone_action(istringstream& is,
NebulaLog::log("ImM", Log::INFO, "Image cloned and ready to use.");
im ->release_cloning_image(cloning_id);
im->release_cloning_image(cloning_id, id);
return;
@ -304,7 +304,7 @@ error:
image->unlock();
im ->release_cloning_image(cloning_id);
im->release_cloning_image(cloning_id, id);
return;
}

View File

@ -0,0 +1,105 @@
# -------------------------------------------------------------------------- #
# 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 'set'
require "rexml/document"
include REXML
module Migrator
def db_version
"3.9.80"
end
def one_version
"OpenNebula 3.9.80"
end
def up
########################################################################
# Add Cloning Image ID collection to Images
########################################################################
counters = {}
counters[:image] = {}
# Init image counters
@db.fetch("SELECT oid,body FROM image_pool") do |row|
if counters[:image][row[:oid]].nil?
counters[:image][row[:oid]] = {
:clones => Set.new
}
end
doc = Document.new(row[:body])
doc.root.each_element("CLONING_ID") do |e|
img_id = e.text.to_i
if counters[:image][img_id].nil?
counters[:image][img_id] = {
:clones => Set.new
}
end
counters[:image][img_id][:clones].add(row[:oid])
end
end
########################################################################
# Image
#
# IMAGE/CLONING_OPS
# IMAGE/CLONES/ID
########################################################################
@db.run "CREATE TABLE image_pool_new (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name,uid) );"
@db[:image_pool].each do |row|
doc = Document.new(row[:body])
oid = row[:oid]
n_cloning_ops = counters[:image][oid][:clones].size
# Rewrite number of clones
doc.root.each_element("CLONING_OPS") { |e|
if e.text != n_cloning_ops.to_s
warn("Image #{oid} CLONING_OPS has #{e.text} \tis\t#{n_cloning_ops}")
e.text = n_cloning_ops
end
}
# re-do list of Images cloning this one
clones_new_elem = doc.root.add_element("CLONES")
counters[:image][oid][:clones].each do |id|
clones_new_elem.add_element("ID").text = id.to_s
end
row[:body] = doc.to_s
# commit
@db[:image_pool_new].insert(row)
end
# Rename table
@db.run("DROP TABLE image_pool")
@db.run("ALTER TABLE image_pool_new RENAME TO image_pool")
return true
end
end

View File

@ -21,11 +21,11 @@ require 'set'
module OneDBFsck
def db_version
"3.8.1"
"4.0.0"
end
def one_version
"OpenNebula 3.8.1"
"OpenNebula 4.0.0"
end
IMAGE_STATES=%w{INIT READY USED DISABLED LOCKED ERROR CLONE DELETE USED_PERS}
@ -530,8 +530,6 @@ module OneDBFsck
counters[:image] = {}
counters[:vnet] = {}
cloning_ops = {}
# Initialize all the host counters to 0
@db.fetch("SELECT oid FROM host_pool") do |row|
counters[:host][row[:oid]] = {
@ -543,18 +541,26 @@ module OneDBFsck
# Init image counters
@db.fetch("SELECT oid,body FROM image_pool") do |row|
counters[:image][row[:oid]] = Set.new
if counters[:image][row[:oid]].nil?
counters[:image][row[:oid]] = {
:vms => Set.new,
:clones => Set.new
}
end
doc = Document.new(row[:body])
cloning_ops[row[:oid]] = [] if cloning_ops[row[:oid]].nil?
doc.root.each_element("CLONING_ID") do |e|
img_id = e.text.to_i
cloning_ops[img_id] = [] if cloning_ops[img_id].nil?
cloning_ops[img_id] << row[:oid]
if counters[:image][img_id].nil?
counters[:image][img_id] = {
:vms => Set.new,
:clones => Set.new
}
end
counters[:image][img_id][:clones].add(row[:oid])
end
end
@ -584,7 +590,7 @@ module OneDBFsck
if counters[:image][img_id].nil?
log_error("VM #{row[:oid]} is using Image #{img_id}, but it does not exist")
else
counters[:image][img_id].add(row[:oid])
counters[:image][img_id][:vms].add(row[:oid])
end
end
@ -733,6 +739,8 @@ module OneDBFsck
# IMAGE/VMS/ID
#
# IMAGE/CLONING_OPS
# IMAGE/CLONES/ID
#
# IMAGE/CLONING_ID
#
# IMAGE/STATE
@ -750,8 +758,8 @@ module OneDBFsck
persistent = ( doc.root.get_text('PERSISTENT').to_s == "1" )
current_state = doc.root.get_text('STATE').to_s.to_i
rvms = counters[:image][oid].size
n_cloning_ops = cloning_ops[row[:oid]].size
rvms = counters[:image][oid][:vms].size
n_cloning_ops = counters[:image][oid][:clones].size
# rewrite running_vms
doc.root.each_element("RUNNING_VMS") {|e|
@ -766,7 +774,7 @@ module OneDBFsck
vms_new_elem = doc.root.add_element("VMS")
counters[:image][oid].each do |id|
counters[:image][oid][:vms].each do |id|
id_elem = vms_elem.elements.delete("ID[.=#{id}]")
if id_elem.nil?
@ -783,6 +791,7 @@ module OneDBFsck
if ( persistent && rvms > 0 )
n_cloning_ops = 0
counters[:image][oid][:clones] = Set.new
end
# Check number of clones
@ -793,6 +802,26 @@ module OneDBFsck
end
}
# re-do list of Images cloning this one
clones_elem = doc.root.elements.delete("CLONES")
clones_new_elem = doc.root.add_element("CLONES")
counters[:image][oid][:clones].each do |id|
id_elem = clones_elem.elements.delete("ID[.=#{id}]")
if id_elem.nil?
log_error("Image #{id} is missing fom Image #{oid} CLONES id list")
end
clones_new_elem.add_element("ID").text = id.to_s
end
clones_elem.each_element("ID") do |id_elem|
log_error("Image #{id_elem.text} is in Image #{oid} CLONES id list, but it should not")
end
# Check state
state = current_state