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:
parent
c2eec65475
commit
2d68cb5fdb
@ -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)
|
||||
// *************************************************************************
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
105
src/onedb/3.8.1_to_3.9.80.rb
Normal file
105
src/onedb/3.8.1_to_3.9.80.rb
Normal 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
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user