From 7618a5c1acf65a41a994e265e75a14ee8ee89105 Mon Sep 17 00:00:00 2001 From: Vlastimil Holer Date: Wed, 19 Dec 2018 14:55:00 +0100 Subject: [PATCH] B #2687: Disk snapshots dissapearing (#2739) --- src/onedb/local/5.6.0_to_5.7.80.rb | 79 +++++++++++++++++ src/onedb/patches/next_snapshot.rb | 131 +++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 src/onedb/patches/next_snapshot.rb diff --git a/src/onedb/local/5.6.0_to_5.7.80.rb b/src/onedb/local/5.6.0_to_5.7.80.rb index 3b15a76899..b220620991 100644 --- a/src/onedb/local/5.6.0_to_5.7.80.rb +++ b/src/onedb/local/5.6.0_to_5.7.80.rb @@ -36,6 +36,7 @@ module Migrator end def up + bug_2687 # MUST be run before 2489, which generates short body feature_2253 feature_2489 feature_826 @@ -238,4 +239,82 @@ module Migrator create_table(:vn_template_pool) end + def bug_2687 + @db.run "DROP TABLE IF EXISTS old_image_pool;" + @db.run "ALTER TABLE image_pool RENAME TO old_image_pool;" + + create_table(:image_pool) + + @db.transaction do + @db.fetch("SELECT * FROM old_image_pool") do |row| + doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){ + |c| c.default_xml.noblanks + } + + next_snapshot = doc.at_xpath("//SNAPSHOTS/NEXT_SNAPSHOT") + + unless next_snapshot + max = doc.xpath("//SNAPSHOTS/SNAPSHOT/ID").max + + if max + next_snapshot = max.text.to_i + 1 + else + next_snapshot = 0 + end + + sxml = doc.xpath("//SNAPSHOTS") + + if sxml + ns = doc.create_element("NEXT_SNAPSHOT") + ns.content = next_snapshot + sxml = sxml.first.add_child(ns) + end + end + + row[:body] = doc.root.to_s + + @db[:image_pool].insert(row) + end + end + + @db.run "DROP TABLE old_image_pool;" + + @db.run "DROP TABLE IF EXISTS old_vm_pool;" + @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;" + + create_table(:vm_pool) + + @db.transaction do + @db.fetch("SELECT * FROM old_vm_pool") do |row| + doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){ |c| + c.default_xml.noblanks + } + + # evaluate each disk snapshot individually + doc.xpath("//SNAPSHOTS").each do |disk| + next_snapshot = disk.at_xpath("NEXT_SNAPSHOT") + + next if next_snapshot + + max = disk.xpath("SNAPSHOT/ID").max + + if max + next_snapshot = max.text.to_i + 1 + else + next_snapshot = 0 + end + + ns = doc.create_element("NEXT_SNAPSHOT") + ns.content = next_snapshot + disk.add_child(ns) + end + + row[:body] = doc.root.to_s + + @db[:vm_pool].insert(row) + end + end + + @db.run "DROP TABLE old_vm_pool;" + end end diff --git a/src/onedb/patches/next_snapshot.rb b/src/onedb/patches/next_snapshot.rb new file mode 100644 index 0000000000..1b61cf437a --- /dev/null +++ b/src/onedb/patches/next_snapshot.rb @@ -0,0 +1,131 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems # +# # +# 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. # +#--------------------------------------------------------------------------- # + +if !ONE_LOCATION + LOG_LOCATION = "/var/log/one" +else + LOG_LOCATION = ONE_LOCATION + "/var" +end + +LOG = LOG_LOCATION + "/onedb-fsck.log" + +require 'nokogiri' + +module OneDBPatch + VERSION = "5.6.0" + LOCAL_VERSION = "5.6.0" + + def is_hot_patch(ops) + return false + end + + def check_db_version(ops) + db_version = read_db_version() + + if ( db_version[:version] != VERSION || + db_version[:local_version] != LOCAL_VERSION ) + + raise <<-EOT +Version mismatch: patch file is for version +Shared: #{VERSION}, Local: #{LOCAL_VERSION} + +Current database is version +Shared: #{db_version[:version]}, Local: #{db_version[:local_version]} +EOT + end + end + + def patch(ops) + init_log_time() + + puts "This patch updates images and VMs with missing NEXT_SNAPSHOT parameter." + puts + + # BUG #2687: Disk snapshots dissapearing + # https://github.com/OpenNebula/one/issues/2687 + + @db.transaction do + @db.fetch("SELECT * FROM image_pool") do |row| + doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){ + |c| c.default_xml.noblanks + } + + next_snapshot = doc.at_xpath("//SNAPSHOTS/NEXT_SNAPSHOT") + + next if next_snapshot + + max = doc.xpath("//SNAPSHOTS/SNAPSHOT/ID").max + + if max + next_snapshot = max.text.to_i + 1 + else + next_snapshot = 0 + end + + sxml = doc.xpath("//SNAPSHOTS") + + if sxml + ns = doc.create_element("NEXT_SNAPSHOT") + ns.content = next_snapshot + sxml = sxml.first.add_child(ns) + + puts "Image #{row[:oid]} updated with NEXT_SNAPSHOT #{next_snapshot}" + + @db[:image_pool].where(:oid => row[:oid]).update( + :body => doc.root.to_s) + end + end + + log_time() + + @db.fetch("SELECT * FROM vm_pool") do |row| + doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){ |c| + c.default_xml.noblanks + } + + # evaluate each disk snapshot individually + doc.xpath("//SNAPSHOTS").each do |disk| + next_snapshot = disk.at_xpath("NEXT_SNAPSHOT") + + next if next_snapshot + + max = disk.xpath("SNAPSHOT/ID").max + + if max + next_snapshot = max.text.to_i + 1 + else + next_snapshot = 0 + end + + puts "VM #{row[:oid]}, DISK #{disk.at_xpath('DISK_ID').text} updated with NEXT_SNAPSHOT #{next_snapshot}" + + ns = doc.create_element("NEXT_SNAPSHOT") + ns.content = next_snapshot + disk.add_child(ns) + end + + @db[:vm_pool].where(:oid => row[:oid]).update( + :body => doc.root.to_s) + end + + log_time() + end + + log_time() + + return true + end +end