Migrate VN_MAD from the Host to the Network

This commit is contained in:
Jaime Melis committed 2016-04-13 15:53:38 +02:00
1 parent be59195bf8
commit fc3ab2d7ab
3 files changed
+403 -1

No files matched your search

+2 -1
View File
@@ -1217,7 +1217,8 @@ ONEDB_LOCAL_MIGRATOR_FILES="src/onedb/local/4.5.80_to_4.7.80.rb \
src/onedb/local/4.13.85_to_4.90.0.rb"
ONEDB_PATCH_FILES="src/onedb/patches/4.14_monitoring.rb \
src/onedb/patches/history_times.rb"
src/onedb/patches/history_times.rb \
src/onedb/patches/vnmad.rb"
#-------------------------------------------------------------------------------
# Configuration files for OpenNebula, to be installed under $ETC_LOCATION
+207
View File
@@ -14,6 +14,8 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'set'
require 'opennebula'
include OpenNebula
@@ -471,6 +473,211 @@ module Migrator
log_time()
# Move HOST/VN_MAD --> VNET/VN_MAD
log_time()
# Build net_vnmad
net_vnmad = {}
@db.transaction do
@db.fetch("SELECT * FROM vm_pool") do |row|
doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
state = row[:state].to_i
if state != 6
vnmads = Set.new
doc.root.xpath("HISTORY_RECORDS/HISTORY/VNMMAD").collect{|v| vnmads << v.text }
doc.root.xpath("TEMPLATE/NIC/NETWORK_ID").each do |net_id|
net_id = net_id.text.to_i
net_vnmad[net_id] ||= Set.new
net_vnmad[net_id] += vnmads
end
end
end
end
# Build cluster_vnmad and fix hosts
@db.run "ALTER TABLE host_pool RENAME TO old_host_pool;"
@db.run "CREATE TABLE host_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, state INTEGER, last_mon_time INTEGER, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, cid INTEGER);"
cluster_vnmad = {}
@db.transaction do
@db.fetch("SELECT * FROM old_host_pool") do |row|
doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
# Get cluster
cluster_id = doc.root.xpath('CLUSTER_ID').text.to_i
# Store VN_MAD
vnmad = doc.root.xpath('VN_MAD').text
cluster_vnmad[cluster_id] ||= Set.new
cluster_vnmad[cluster_id] << vnmad
# Remove VN_MAD
doc.root.xpath('//VN_MAD').remove
row[:body] = doc.root.to_s
@db[:host_pool].insert(row)
end
end
@db.run "DROP TABLE old_host_pool;"
# Fix Networks
# So far we have two hashes: net_vnmad, which lists the specific vnmad found
# for each network, based on the nics of the VMs, and cluster_vnmad, with
# the vnmad found in the hosts.
#
# We will report a warning if either the cluster or the network has more
# than one vnmad. We will automatically choose one vnmad from the network
# list, or if empty from the cluster list.
#
# That vnmad may be changed through onedb patch.
#
# It could happen that no network is found in the net or in the cluster, in
# which case the admin **must** run the onedb patch, it's not optional any
# more.
@db.run "ALTER TABLE network_pool RENAME TO old_network_pool;"
@db.run "CREATE TABLE network_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, pid INTEGER, UNIQUE(name,uid));"
suggest_patch = false
final_net_vnmad = {}
@db.transaction do
@db.fetch("SELECT * FROM old_network_pool") do |row|
doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
net_id = row[:oid]
cluster_id = doc.root.xpath('CLUSTERS/ID').first.text.to_i
net_vnmad_len = net_vnmad[net_id].length rescue 0
cluster_vnmad_len = cluster_vnmad[cluster_id].length rescue 0
if (vlan = doc.root.xpath('VLAN'))
vlan = vlan.text
if !vlan.empty? && vlan.to_i == 0
dummy_net = true
end
end
doc.root.xpath('//VLAN').remove
if dummy_net
vnmad = "fw"
else
vnmad = nil
other_vnmads = nil
# net_vnmad_len == 1 => that one
# net_vnmad_len > 1 => get first one and show warning
# net_vnmad_len == 0 && cluster_vnmad_len == 1 => that one
# net_vnmad_len == 0 && cluster_vnmad_len > 1 => first one and show warning
# net_vnmad_len == 0 && cluster_vnmad_len == 0 => force onedb patch
if net_vnmad_len == 1
vnmad = net_vnmad[net_id].first
elsif net_vnmad_len > 1
vnmad = net_vnmad[net_id].first
other_vnmads = net_vnmad[net_id] - Set[vnmad]
elsif net_vnmad_len == 0 && cluster_vnmad_len == 1
vnmad = cluster_vnmad[cluster_id].first
elsif net_vnmad_len == 0 && cluster_vnmad_len > 1
vnmad = cluster_vnmad[cluster_id].first
other_vnmads = cluster_vnmad[cluster_id] - Set[vnmad]
end
if vnmad && other_vnmads
if !suggest_patch
puts
puts "**************************************************************"
puts "* WARNING WARNING WARNING WARNING WARNING WARNING WARNING *"
puts "**************************************************************"
end
suggest_patch = true
puts "* Net ##{net_id} assigned VN_MAD=#{vnmad}. " <<
"Other options: #{other_vnmads.to_a.join(', ')}"
end
end
final_net_vnmad[net_id] = vnmad
if vnmad
doc.root.add_child(doc.create_element("VN_MAD")).content = vnmad
end
row[:body] = doc.root.to_s
@db[:network_pool].insert(row)
end
end
patch_cmd = "onedb patch [opts] /usr/lib/one/ruby/onedb/patches/vnmad.rb"
if suggest_patch
puts
puts "If you want to change the above assignments, please run:"
puts patch_cmd
end
net_unassigned = final_net_vnmad.select{|k,v| v.nil?}.keys
if !net_unassigned.empty?
puts
puts "**************************************************************"
puts "* ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR *"
puts "**************************************************************"
puts
puts "You **must** run:"
puts patch_cmd
puts
puts "to assign a vnmad to the following networks:"
net_unassigned.each{|n| puts " - #{n}"}
puts
end
@db.run "DROP TABLE old_network_pool;"
# Fix VMs
@db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
@db.run "CREATE TABLE IF NOT EXISTS vm_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, last_poll INTEGER, state INTEGER, lcm_state INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER)"
@db.transaction do
@db.fetch("SELECT * FROM old_vm_pool") do |row|2
doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
state = row[:state].to_i
if state != 6
# Remove vnmad from the history records
doc.root.xpath("HISTORY_RECORDS//VNMMAD").remove
doc.root.xpath("HISTORY_RECORDS//DS_LOCATION").remove
# Rename VMMMAD -> VM_MAD and TMMAD -> TM_MAD
doc.root.xpath("HISTORY_RECORDS//VMMMAD").each {|e| e.name = "VM_MAD"}
doc.root.xpath("HISTORY_RECORDS//TMMAD").each {|e| e.name = "TM_MAD"}
# Add vnmad to the nics
doc.root.xpath('TEMPLATE/NIC').each do |nic|
net_id = nic.xpath("NETWORK_ID").text.to_i rescue nil # NICs without network may exist
next unless net_id
vnmad = final_net_vnmad[net_id]
if vnmad
nic.add_child(doc.create_element("VN_MAD")).content = vnmad
end
end
row[:body] = doc.root.to_s
end
@db[:vm_pool].insert(row)
end
end
@db.run "DROP TABLE old_vm_pool;"
return true
end
+194
View File
@@ -0,0 +1,194 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2015, 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 = "4.90.0"
LOCAL_VERSION = "4.90.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()
all_nets = {}
fix_nets = {}
@db.transaction do
@db.fetch("SELECT * FROM network_pool") do |row|
doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
vnmad = doc.root.xpath("VN_MAD").text rescue ""
all_nets[row[:oid]] = {:name => row[:name], :vnmad => vnmad}
if vnmad.empty?
fix_nets[row[:oid]] = ""
end
end
end
if !fix_nets.empty?
puts "You need to input a VN_MAD for the following networks:"
fix_nets.each do |net_id, vnmad|
input = ""
while ( input.empty? ) do
name = all_nets[net_id][:name]
puts "##{net_id} (#{name}) => VN_MAD:"
input = STDIN.gets.chomp.strip
end
fix_nets[net_id] = input
end
end
puts
puts "Change additional networks:"
input = ""
while (input != "c")
puts
puts "Input the ID of the network to change or 'c' to continue"
input = STDIN.gets.chomp.strip
if input.match(/^\d+$/)
net_id = input.to_i
if all_nets[net_id].nil?
puts "Error: Net ##{net_id} not found."
next
end
input_vnmad = ""
while ( input_vnmad.empty? ) do
name = all_nets[net_id][:name]
current_vnmad = all_nets[net_id][:vnmad]
puts "##{net_id} (#{name}) (current VN_MAD='#{current_vnmad}') => VN_MAD:"
input_vnmad = STDIN.gets.chomp.strip
end
fix_nets[net_id] = input_vnmad
end
end
puts "Review these assignemnts:"
fix_nets.keys.sort.each do |net_id|
name = all_nets[net_id][:name]
vnmad = fix_nets[net_id]
current_vnmad = all_nets[net_id][:vnmad]
msg = "* ##{net_id} (#{name}) => VN_MAD='#{vnmad}'"
if !current_vnmad.empty?
msg << " (current VN_MAD='#{current_vnmad}')"
end
puts msg
end
puts
input = ""
while ( !input.match(/^(y|n)$/)) do
puts "Do you wish to apply the above? (y/n)"
input = STDIN.gets.chomp.strip.downcase
end
if input == "n"
puts "Quitting without changing anything."
raise "Execution canceled by user"
end
@db.run "ALTER TABLE network_pool RENAME TO old_network_pool;"
@db.run "CREATE TABLE network_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, pid INTEGER, UNIQUE(name,uid));"
@db.transaction do
@db.fetch("SELECT * FROM old_network_pool") do |row|
doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
net_id = row[:oid]
vnmad = fix_nets[net_id]
if vnmad
doc.root.add_child(doc.create_element("VN_MAD")).content = vnmad
end
row[:body] = doc.root.to_s
@db[:network_pool].insert(row)
end
end
@db.run "DROP TABLE old_network_pool;"
@db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
@db.run "CREATE TABLE IF NOT EXISTS vm_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, last_poll INTEGER, state INTEGER, lcm_state INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER)"
@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}
state = row[:state].to_i
if state != 6
doc.root.xpath('TEMPLATE/NIC').each do |nic|
net_id = nic.xpath("NETWORK_ID").text.to_i rescue nil # NICs without network may exist
next unless net_id
vnmad = fix_nets[net_id]
if vnmad
nic.add_child(doc.create_element("VN_MAD")).content = vnmad
end
end
row[:body] = doc.root.to_s
end
@db[:vm_pool].insert(row)
end
end
@db.run "DROP TABLE old_vm_pool;"
log_time()
return true
end
end