diff --git a/install.sh b/install.sh
index 422f501fdf..1038958f39 100755
--- a/install.sh
+++ b/install.sh
@@ -511,6 +511,8 @@ INSTALL_FILES=(
MAD_SH_LIB_FILES:$VAR_LOCATION/remotes
ONEDB_FILES:$LIB_LOCATION/ruby/onedb
ONEDB_PATCH_FILES:$LIB_LOCATION/ruby/onedb/patches
+ ONEDB_SHARED_MIGRATOR_FILES:$LIB_LOCATION/ruby/onedb/shared
+ ONEDB_LOCAL_MIGRATOR_FILES:$LIB_LOCATION/ruby/onedb/local
MADS_LIB_FILES:$LIB_LOCATION/mads
IM_PROBES_FILES:$VAR_LOCATION/remotes/im
IM_PROBES_LIB_FILES:$VAR_LOCATION/remotes/im/lib
@@ -1898,6 +1900,68 @@ ONEDB_FILES="src/onedb/fsck.rb \
ONEDB_PATCH_FILES="src/onedb/patches/4.14_monitoring.rb \
src/onedb/patches/history_times.rb"
+ONEDB_SHARED_MIGRATOR_FILES="src/onedb/shared/2.0_to_2.9.80.rb \
+ src/onedb/shared/2.9.80_to_2.9.85.rb \
+ src/onedb/shared/2.9.85_to_2.9.90.rb \
+ src/onedb/shared/2.9.90_to_3.0.0.rb \
+ src/onedb/shared/3.0.0_to_3.1.0.rb \
+ src/onedb/shared/3.1.0_to_3.1.80.rb \
+ src/onedb/shared/3.1.80_to_3.2.0.rb \
+ src/onedb/shared/3.2.0_to_3.2.1.rb \
+ src/onedb/shared/3.2.1_to_3.3.0.rb \
+ src/onedb/shared/3.3.0_to_3.3.80.rb \
+ src/onedb/shared/3.3.80_to_3.4.0.rb \
+ src/onedb/shared/3.4.0_to_3.4.1.rb \
+ src/onedb/shared/3.4.1_to_3.5.80.rb \
+ src/onedb/shared/3.5.80_to_3.6.0.rb \
+ src/onedb/shared/3.6.0_to_3.7.80.rb \
+ src/onedb/shared/3.7.80_to_3.8.0.rb \
+ src/onedb/shared/3.8.0_to_3.8.1.rb \
+ src/onedb/shared/3.8.1_to_3.8.2.rb \
+ src/onedb/shared/3.8.2_to_3.8.3.rb \
+ src/onedb/shared/3.8.3_to_3.8.4.rb \
+ src/onedb/shared/3.8.4_to_3.8.5.rb \
+ src/onedb/shared/3.8.5_to_3.9.80.rb \
+ src/onedb/shared/3.9.80_to_3.9.90.rb \
+ src/onedb/shared/3.9.90_to_4.0.0.rb \
+ src/onedb/shared/4.0.0_to_4.0.1.rb \
+ src/onedb/shared/4.0.1_to_4.1.80.rb \
+ src/onedb/shared/4.1.80_to_4.2.0.rb \
+ src/onedb/shared/4.2.0_to_4.3.80.rb \
+ src/onedb/shared/4.3.80_to_4.3.85.rb \
+ src/onedb/shared/4.3.85_to_4.3.90.rb \
+ src/onedb/shared/4.3.90_to_4.4.0.rb \
+ src/onedb/shared/4.4.0_to_4.4.1.rb \
+ src/onedb/shared/4.4.1_to_4.5.80.rb\
+ src/onedb/shared/4.5.80_to_4.6.0.rb \
+ src/onedb/shared/4.6.0_to_4.11.80.rb \
+ src/onedb/shared/4.11.80_to_4.90.0.rb \
+ src/onedb/shared/4.90.0_to_5.2.0.rb \
+ src/onedb/shared/5.2.0_to_5.3.80.rb \
+ src/onedb/shared/5.3.80_to_5.4.0.rb \
+ src/onedb/shared/5.4.0_to_5.4.1.rb \
+ src/onedb/shared/5.4.1_to_5.5.80.rb \
+ src/onedb/shared/5.5.80_to_5.6.0.rb \
+ src/onedb/shared/5.6.0_to_5.10.0.rb \
+ src/onedb/shared/5.10.0_to_5.12.0.rb"
+
+ONEDB_LOCAL_MIGRATOR_FILES="src/onedb/local/4.5.80_to_4.7.80.rb \
+ src/onedb/local/4.7.80_to_4.9.80.rb \
+ src/onedb/local/4.9.80_to_4.10.3.rb \
+ src/onedb/local/4.10.3_to_4.11.80.rb \
+ src/onedb/local/4.11.80_to_4.13.80.rb \
+ src/onedb/local/4.13.80_to_4.13.85.rb \
+ src/onedb/local/4.13.85_to_4.90.0.rb \
+ src/onedb/local/4.90.0_to_5.3.80.rb \
+ src/onedb/local/5.3.80_to_5.4.0.rb \
+ src/onedb/local/5.4.0_to_5.4.1.rb \
+ src/onedb/local/5.4.1_to_5.5.80.rb \
+ src/onedb/local/5.5.80_to_5.6.0.rb \
+ src/onedb/local/5.6.0_to_5.7.80.rb \
+ src/onedb/local/5.7.80_to_5.8.0.rb \
+ src/onedb/local/5.8.0_to_5.10.0.rb \
+ src/onedb/local/5.10.0_to_5.12.0.rb"
+
#-------------------------------------------------------------------------------
# Configuration files for OpenNebula, to be installed under $ETC_LOCATION
#-------------------------------------------------------------------------------
diff --git a/src/onedb/local/4.10.3_to_4.11.80.rb b/src/onedb/local/4.10.3_to_4.11.80.rb
new file mode 100644
index 0000000000..4ff3f1d314
--- /dev/null
+++ b/src/onedb/local/4.10.3_to_4.11.80.rb
@@ -0,0 +1,183 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'nokogiri'
+
+module Migrator
+ def db_version
+ "4.11.80"
+ end
+
+ def one_version
+ "OpenNebula 4.11.80"
+ end
+
+ def up
+
+ init_log_time()
+
+ ########################################################################
+ # Showback
+ ########################################################################
+
+ @db.run "CREATE TABLE vm_showback (vmid INTEGER, year INTEGER, month INTEGER, body MEDIUMTEXT, PRIMARY KEY(vmid, year, month));"
+
+ log_time()
+
+ ########################################################################
+ # Security Groups
+ ########################################################################
+
+ oneadmin_uname = nil
+
+ @db.fetch("SELECT name FROM user_pool WHERE oid=0") do |row|
+ oneadmin_uname = row[:name]
+ end
+
+ if oneadmin_uname == nil
+ puts "Error trying to read oneadmin's user name ('SELECT name FROM user_pool WHERE oid=0')"
+ return false
+ end
+
+ oneadmin_gname = nil
+
+ @db.fetch("SELECT name FROM group_pool WHERE oid=0") do |row|
+ oneadmin_gname = row[:name]
+ end
+
+ if oneadmin_gname == nil
+ puts "Error trying to read oneadmin's group name ('SELECT name FROM group_pool WHERE oid=0')"
+ return false
+ end
+
+ @db.run "CREATE TABLE secgroup_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name,uid));"
+ @db.run "INSERT INTO secgroup_pool VALUES(0,'default','000#{oneadmin_uname}#{oneadmin_gname}default111100100',0,0,1,1,1);"
+
+ @db.run "INSERT INTO pool_control VALUES('secgroup_pool',99);"
+
+
+ @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, cid INTEGER, pid INTEGER, UNIQUE(name,uid));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_network_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_network_pool')
+
+ template = doc.root.at_xpath("TEMPLATE")
+
+ # The cleaner doc.create_cdata(txt) is not supported in
+ # old versions of nokogiri
+ template.add_child(doc.create_element("SECURITY_GROUPS")).
+ add_child(Nokogiri::XML::CDATA.new(doc,"0"))
+
+ @db[:network_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :cid => row[:cid],
+ :pid => row[:pid])
+ end
+ end
+
+ @db.run "DROP TABLE old_network_pool;"
+
+ log_time()
+
+ ########################################################################
+ # Datastore status
+ ########################################################################
+
+ @db.run "ALTER TABLE datastore_pool RENAME TO old_datastore_pool;"
+ @db.run "CREATE TABLE datastore_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, cid INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_datastore_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_datastore_pool')
+
+ doc.root.add_child(doc.create_element("STATE")).content = "0"
+
+ @db[:datastore_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :cid => row[:cid])
+ end
+ end
+
+ @db.run "DROP TABLE old_datastore_pool;"
+
+ log_time()
+
+ ########################################################################
+ # VM previous status
+ ########################################################################
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE 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.run "INSERT INTO vm_pool SELECT * FROM old_vm_pool WHERE state = 6;"
+
+ log_time()
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_vm_pool WHERE state<>6") do |row|
+ doc = nokogiri_doc(row[:body], 'old_vm_pool')
+
+ ["STATE", "LCM_STATE"].each do |ename|
+ prev_elem = doc.root.at_xpath("PREV_#{ename}")
+
+ if prev_elem.nil?
+ prev_elem = doc.root.add_child(
+ doc.create_element("PREV_#{ename}"))
+
+ prev_elem.content = doc.root.at_xpath(ename).text
+ end
+ end
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+
+ end
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+ log_time()
+
+ return true
+ end
+end
diff --git a/src/onedb/local/4.11.80_to_4.13.80.rb b/src/onedb/local/4.11.80_to_4.13.80.rb
new file mode 100644
index 0000000000..322003ded8
--- /dev/null
+++ b/src/onedb/local/4.11.80_to_4.13.80.rb
@@ -0,0 +1,257 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "4.13.80"
+ end
+
+ def one_version
+ "OpenNebula 4.13.80"
+ end
+
+ def up
+ #3654
+ puts "**************************************************************"
+ puts "* WARNING WARNING WARNING WARNING WARNING WARNING WARNING *"
+ puts "**************************************************************"
+ puts
+ puts "#{one_version} improves the management of FAILED VMs "
+ puts "Please remove (onevm delete) any FAILED VM before continuing. "
+ puts
+
+ #2742
+ puts "**************************************************************"
+ puts "* WARNING WARNING WARNING WARNING WARNING WARNING WARNING *"
+ puts "**************************************************************"
+ puts
+ puts
+ puts "The scheduler (and oned) has been update to enforce access "
+ puts "rights on system datastores. This new version also checks that"
+ puts "the user can access the System DS."
+ puts "This *may require* to update system DS rights of your cloud"
+ puts
+ printf "Do you want to proceed ? [y/N]"
+
+ ans = STDIN.gets.strip.downcase
+
+ return false if ans != "y"
+
+ init_log_time()
+
+ # 3805
+ @db.run "ALTER TABLE document_pool RENAME TO old_document_pool;"
+ @db.run "CREATE TABLE document_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, type INTEGER, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_document_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_document_pool')
+
+ lock_elem = doc.create_element("LOCK")
+ lock_elem.add_child(doc.create_element("LOCKED")).content = "0"
+ lock_elem.add_child(doc.create_element("OWNER")).content = ""
+ lock_elem.add_child(doc.create_element("EXPIRES")).content = "0"
+
+ doc.root.add_child(lock_elem)
+
+ @db[:document_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :type => row[:type],
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_document_pool;"
+
+ log_time()
+
+ # 3718
+
+ # Move monitoring attributes in VM pool table. VMs in the DONE state
+ # will be processed by the onedb patch command.
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE 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.run "INSERT INTO vm_pool SELECT * FROM old_vm_pool WHERE state=6;"
+
+ log_time()
+
+ @db.transaction do
+ #@db.fetch("SELECT * FROM old_vm_pool WHERE state<>6") do |row|
+ @db.fetch("SELECT * FROM old_vm_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_vm_pool')
+
+ update_monitoring(doc.root.at_xpath("/VM"))
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+ log_time()
+
+ # Move monitoring attributes in the history table. Closed records
+ # will be processed by the onedb patch command.
+
+ @db.run "ALTER TABLE history RENAME TO old_history;"
+ @db.run "CREATE TABLE history (vid INTEGER, seq INTEGER, body MEDIUMTEXT, stime INTEGER, etime INTEGER,PRIMARY KEY(vid,seq));"
+
+ @db.run "INSERT INTO history SELECT * FROM old_history WHERE etime<>0;"
+
+ log_time()
+
+ @db.transaction do
+ #@db.fetch("SELECT * FROM old_history WHERE etime=0") do |row|
+ @db.fetch("SELECT * FROM old_history") do |row|
+ doc = nokogiri_doc(row[:body], 'old_history')
+
+ elem = doc.root.at_xpath("/HISTORY/VM")
+ if !elem.nil?
+ update_monitoring(elem)
+ end
+
+ @db[:history].insert(
+ :vid => row[:vid],
+ :seq => row[:seq],
+ :body => doc.root.to_s,
+ :stime => row[:stime],
+ :etime => row[:etime])
+ end
+ end
+
+ @db.run "DROP TABLE old_history;"
+
+ log_time()
+
+ # 3782
+
+ @db.run "ALTER TABLE image_pool RENAME TO old_image_pool;"
+ @db.run "CREATE TABLE image_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name,uid) );"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_image_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_image_pool')
+
+ doc.root.add_child(doc.create_element("TARGET_SNAPSHOT")).content = "-1"
+ doc.root.add_child(doc.create_element("SNAPSHOTS"))
+
+ @db[:image_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_image_pool;"
+
+ log_time()
+
+ return true
+ end
+
+ def mv_monitoring(vm_elem, prev_name, new_name)
+ elem = vm_elem.at_xpath(prev_name)
+
+ if (!elem.nil?)
+ vm_elem.at_xpath("MONITORING").add_child(
+ vm_elem.document.create_element(new_name)).content = elem.text
+
+ elem.remove
+ end
+ end
+
+ def update_monitoring(vm_elem)
+ vm_elem.add_child(vm_elem.document.create_element("MONITORING"))
+
+ mv_monitoring(vm_elem, "CPU", "CPU")
+ mv_monitoring(vm_elem, "MEMORY", "MEMORY")
+ mv_monitoring(vm_elem, "NET_RX", "NETRX")
+ mv_monitoring(vm_elem, "NET_TX", "NETTX")
+
+ mv_monitoring(vm_elem, "AZ_AVAILABILITY_SET_NAME", "AZ_AVAILABILITY_SET_NAME")
+ mv_monitoring(vm_elem, "AZ_CLOUD_SERVICE_NAME", "AZ_CLOUD_SERVICE_NAME")
+ mv_monitoring(vm_elem, "AZ_DATA_DISKS", "AZ_DATA_DISKS")
+ mv_monitoring(vm_elem, "AZ_DEPLOYMENT_NAME", "AZ_DEPLOYMENT_NAME")
+ mv_monitoring(vm_elem, "AZ_DISK_NAME", "AZ_DISK_NAME")
+ mv_monitoring(vm_elem, "AZ_HOSTNAME", "AZ_HOSTNAME")
+ mv_monitoring(vm_elem, "AZ_IMAGE", "AZ_IMAGE")
+ mv_monitoring(vm_elem, "AZ_IPADDRESS", "AZ_IPADDRESS")
+ mv_monitoring(vm_elem, "AZ_MEDIA_LINK", "AZ_MEDIA_LINK")
+ mv_monitoring(vm_elem, "AZ_OS_TYPE", "AZ_OS_TYPE")
+ mv_monitoring(vm_elem, "AZ_ROLE_SIZE", "AZ_ROLE_SIZE")
+ mv_monitoring(vm_elem, "AZ_TCP_ENDPOINTS", "AZ_TCP_ENDPOINTS")
+ mv_monitoring(vm_elem, "AZ_UDP_ENDPOINTS", "AZ_UDP_ENDPOINTS")
+ mv_monitoring(vm_elem, "AZ_VIRTUAL_NETWORK_NAME", "AZ_VIRTUAL_NETWORK_NAME")
+
+ mv_monitoring(vm_elem, "SL_CRED_PASSWORD", "SL_CRED_PASSWORD")
+ mv_monitoring(vm_elem, "SL_CRED_USER", "SL_CRED_USER")
+ mv_monitoring(vm_elem, "SL_DOMAIN", "SL_DOMAIN")
+ mv_monitoring(vm_elem, "SL_FULLYQUALIFIEDDOMAINNAME", "SL_FULLYQUALIFIEDDOMAINNAME")
+ mv_monitoring(vm_elem, "SL_GLOBALIDENTIFIER", "SL_GLOBALIDENTIFIER")
+ mv_monitoring(vm_elem, "SL_HOSTNAME", "SL_HOSTNAME")
+ mv_monitoring(vm_elem, "SL_ID", "SL_ID")
+ mv_monitoring(vm_elem, "SL_MAXCPU", "SL_MAXCPU")
+ mv_monitoring(vm_elem, "SL_MAXMEMORY", "SL_MAXMEMORY")
+ mv_monitoring(vm_elem, "SL_PRIMARYBACKENDIPADDRESS", "SL_PRIMARYBACKENDIPADDRESS")
+ mv_monitoring(vm_elem, "SL_PRIMARYIPADDRESS", "SL_PRIMARYIPADDRESS")
+ mv_monitoring(vm_elem, "SL_STARTCPUS", "SL_STARTCPUS")
+ mv_monitoring(vm_elem, "SL_UUID", "SL_UUID")
+
+ mv_monitoring(vm_elem, "AWS_DNS_NAME", "AWS_DNS_NAME")
+ mv_monitoring(vm_elem, "AWS_PRIVATE_DNS_NAME", "AWS_PRIVATE_DNS_NAME")
+ mv_monitoring(vm_elem, "AWS_KEY_NAME", "AWS_KEY_NAME")
+ mv_monitoring(vm_elem, "AWS_AVAILABILITY_ZONE", "AWS_AVAILABILITY_ZONE")
+ mv_monitoring(vm_elem, "AWS_PLATFORM", "AWS_PLATFORM")
+ mv_monitoring(vm_elem, "AWS_VPC_ID", "AWS_VPC_ID")
+ mv_monitoring(vm_elem, "AWS_PRIVATE_IP_ADDRESS", "AWS_PRIVATE_IP_ADDRESS")
+ mv_monitoring(vm_elem, "AWS_IP_ADDRESS", "AWS_IP_ADDRESS")
+ mv_monitoring(vm_elem, "AWS_SUBNET_ID", "AWS_SUBNET_ID")
+ mv_monitoring(vm_elem, "AWS_SECURITY_GROUPS", "AWS_SECURITY_GROUPS")
+ mv_monitoring(vm_elem, "AWS_INSTANCE_TYPE", "AWS_INSTANCE_TYPE")
+
+ mv_monitoring(vm_elem, "ESX_HOST", "ESX_HOST")
+ mv_monitoring(vm_elem, "GUEST_IP", "GUEST_IP")
+ mv_monitoring(vm_elem, "GUEST_STATE", "GUEST_STATE")
+ mv_monitoring(vm_elem, "VMWARETOOLS_RUNNING_STATUS", "VMWARETOOLS_RUNNING_STATUS")
+ mv_monitoring(vm_elem, "VMWARETOOLS_VERSION", "VMWARETOOLS_VERSION")
+ mv_monitoring(vm_elem, "VMWARETOOLS_VERSION_STATUS", "VMWARETOOLS_VERSION_STATUS")
+ end
+end
diff --git a/src/onedb/local/4.13.80_to_4.13.85.rb b/src/onedb/local/4.13.80_to_4.13.85.rb
new file mode 100644
index 0000000000..945e15bb7a
--- /dev/null
+++ b/src/onedb/local/4.13.80_to_4.13.85.rb
@@ -0,0 +1,239 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "4.13.85"
+ end
+
+ def one_version
+ "OpenNebula 4.13.85"
+ end
+
+ def up
+ init_log_time()
+
+ # 1727
+
+ @db.run "ALTER TABLE user_quotas RENAME TO old_user_quotas;"
+ @db.run "CREATE TABLE user_quotas (user_oid INTEGER PRIMARY KEY, body MEDIUMTEXT);"
+
+ @db.transaction do
+ # oneadmin does not have quotas
+ @db.fetch("SELECT * FROM old_user_quotas WHERE user_oid=0") do |row|
+ @db[:user_quotas].insert(row)
+ end
+
+ @db.fetch("SELECT * FROM old_user_quotas WHERE user_oid>0") do |row|
+ doc = nokogiri_doc(row[:body], 'old_user_quotas')
+
+ calculate_quotas(doc, "uid=#{row[:user_oid]}", "User")
+
+ @db[:user_quotas].insert(
+ :user_oid => row[:user_oid],
+ :body => doc.root.to_s)
+ end
+ end
+
+ @db.run "DROP TABLE old_user_quotas;"
+
+ log_time()
+
+ @db.run "ALTER TABLE group_quotas RENAME TO old_group_quotas;"
+ @db.run "CREATE TABLE group_quotas (group_oid INTEGER PRIMARY KEY, body MEDIUMTEXT);"
+
+ @db.transaction do
+ # oneadmin does not have quotas
+ @db.fetch("SELECT * FROM old_group_quotas WHERE group_oid=0") do |row|
+ @db[:group_quotas].insert(row)
+ end
+
+ @db.fetch("SELECT * FROM old_group_quotas WHERE group_oid>0") do |row|
+ doc = nokogiri_doc(row[:body], 'old_group_quotas')
+
+ calculate_quotas(doc, "gid=#{row[:group_oid]}", "Group")
+
+ @db[:group_quotas].insert(
+ :group_oid => row[:group_oid],
+ :body => doc.root.to_s)
+ end
+ end
+
+ @db.run "DROP TABLE old_group_quotas;"
+
+ log_time()
+
+ default_user_quotas = nil
+ default_group_quotas = nil
+
+ @db.fetch("SELECT * FROM system_attributes WHERE name = 'DEFAULT_USER_QUOTAS'") do |row|
+ default_user_quotas = nokogiri_doc(row[:body], 'system_attributes')
+
+ vm_elem = default_user_quotas.root.at_xpath("VM_QUOTA/VM")
+
+ if !vm_elem.nil?
+ vm_elem.at_xpath("VOLATILE_SIZE").name = "SYSTEM_DISK_SIZE"
+ vm_elem.at_xpath("VOLATILE_SIZE_USED").name = "SYSTEM_DISK_SIZE_USED"
+ end
+ end
+
+ @db.fetch("SELECT * FROM system_attributes WHERE name = 'DEFAULT_GROUP_QUOTAS'") do |row|
+ default_group_quotas = nokogiri_doc(row[:body], 'system_attributes')
+
+ vm_elem = default_group_quotas.root.at_xpath("VM_QUOTA/VM")
+
+ if !vm_elem.nil?
+ vm_elem.at_xpath("VOLATILE_SIZE").name = "SYSTEM_DISK_SIZE"
+ vm_elem.at_xpath("VOLATILE_SIZE_USED").name = "SYSTEM_DISK_SIZE_USED"
+ end
+ end
+
+ if !default_user_quotas.nil?
+ @db[:system_attributes].where(:name => "DEFAULT_USER_QUOTAS").update(
+ :body => default_user_quotas.root.to_s)
+ end
+
+ if !default_group_quotas.nil?
+ @db[:system_attributes].where(:name => "DEFAULT_GROUP_QUOTAS").update(
+ :body => default_group_quotas.root.to_s)
+ end
+
+ log_time()
+
+ @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);"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_host_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_host_pool')
+
+ doc.root.at_xpath("HOST_SHARE").add_child(doc.create_element("PCI_DEVICES"))
+
+ @db[:host_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :state => row[:state],
+ :last_mon_time => row[:last_mon_time],
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :cid => row[:cid])
+ end
+ end
+
+ @db.run "DROP TABLE old_host_pool;"
+
+ log_time()
+
+ @db.transaction do
+ @db.run "ALTER TABLE datastore_pool RENAME TO old_datastore_pool;"
+ @db.run "CREATE TABLE datastore_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, cid INTEGER);"
+
+ @db.run "INSERT INTO datastore_pool SELECT * FROM old_datastore_pool;"
+
+ @db.run "DROP TABLE old_datastore_pool;"
+ end
+
+ log_time()
+
+ return true
+ end
+
+ # Copied from fsck file, this method only recalculates the SYSTEM_DISK quotas
+ def calculate_quotas(doc, where_filter, resource)
+
+ oid = doc.root.at_xpath("ID").text.to_i
+
+ sys_used = 0
+
+ @db.fetch("SELECT body FROM vm_pool WHERE #{where_filter} AND state<>6") do |vm_row|
+ vmdoc = nokogiri_doc(row[:body], 'vm_pool')
+
+ vmdoc.root.xpath("TEMPLATE/DISK").each { |e|
+ type = ""
+
+ e.xpath("TYPE").each { |t_elem|
+ type = t_elem.text.upcase
+ }
+
+ size = 0
+
+ if !e.at_xpath("SIZE").nil?
+ size = e.at_xpath("SIZE").text.to_i
+ end
+
+ if ( type == "SWAP" || type == "FS")
+ sys_used += size
+ else
+ if !e.at_xpath("CLONE").nil?
+ clone = (e.at_xpath("CLONE").text.upcase == "YES")
+
+ target = nil
+
+ if clone
+ target = e.at_xpath("CLONE_TARGET").text if !e.at_xpath("CLONE_TARGET").nil?
+ else
+ target = e.at_xpath("LN_TARGET").text if !e.at_xpath("LN_TARGET").nil?
+ end
+
+ if !target.nil? && target != "NONE" # self or system
+ sys_used += size
+
+ if !e.at_xpath("DISK_SNAPSHOT_TOTAL_SIZE").nil?
+ sys_used += e.at_xpath("DISK_SNAPSHOT_TOTAL_SIZE").text.to_i
+ end
+ end
+ end
+ end
+ }
+ end
+
+ vm_elem = doc.root.at_xpath("VM_QUOTA/VM")
+
+ if !vm_elem.nil?
+ vm_elem.at_xpath("VOLATILE_SIZE").name = "SYSTEM_DISK_SIZE"
+ vm_elem.at_xpath("VOLATILE_SIZE_USED").name = "SYSTEM_DISK_SIZE_USED"
+ else
+ doc.root.xpath("VM_QUOTA").each { |e| e.remove }
+
+ vm_quota = doc.root.add_child(doc.create_element("VM_QUOTA"))
+ vm_elem = vm_quota.add_child(doc.create_element("VM"))
+
+ vm_elem.add_child(doc.create_element("CPU")).content = "-1"
+ vm_elem.add_child(doc.create_element("CPU_USED")).content = "0"
+
+ vm_elem.add_child(doc.create_element("MEMORY")).content = "-1"
+ vm_elem.add_child(doc.create_element("MEMORY_USED")).content = "0"
+
+ vm_elem.add_child(doc.create_element("VMS")).content = "-1"
+ vm_elem.add_child(doc.create_element("VMS_USED")).content = "0"
+
+ vm_elem.add_child(doc.create_element("SYSTEM_DISK_SIZE")).content = "-1"
+ vm_elem.add_child(doc.create_element("SYSTEM_DISK_SIZE_USED")).content = "0"
+ end
+
+ vm_elem.xpath("SYSTEM_DISK_SIZE_USED").each { |e|
+ if e.text != sys_used.to_s
+ #puts("#{resource} #{oid} quotas: SYSTEM_DISK_SIZE_USED has #{e.text} \tis\t#{sys_used}")
+ e.content = sys_used.to_s
+ end
+ }
+ end
+end
diff --git a/src/onedb/local/4.13.85_to_4.90.0.rb b/src/onedb/local/4.13.85_to_4.90.0.rb
new file mode 100644
index 0000000000..d06f38101f
--- /dev/null
+++ b/src/onedb/local/4.13.85_to_4.90.0.rb
@@ -0,0 +1,972 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'base64'
+require 'zlib'
+require 'pathname'
+
+require 'opennebula'
+
+include OpenNebula
+
+module Migrator
+ def db_version
+ "4.90.0"
+ end
+
+ def one_version
+ "OpenNebula 4.90.0"
+ end
+
+ TEMPLATE_TRANSFORM_ATTRS = {
+ 'SUNSTONE_NETWORK_SELECT' => 'NETWORK_SELECT'
+ }
+
+ def up
+ init_log_time()
+
+ ############################################################################
+ # 4369
+ ############################################################################
+
+ @db.run "CREATE TABLE cluster_datastore_relation (cid INTEGER, oid INTEGER, PRIMARY KEY(cid, oid));"
+ @db.run "CREATE TABLE cluster_network_relation (cid INTEGER, oid INTEGER, PRIMARY KEY(cid, oid));"
+
+
+ @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);"
+
+ host_ids = []
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_host_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_host_pool')
+
+ cid_elem = doc.root.at_xpath("CLUSTER_ID")
+ cid = cid_elem.text.to_i
+
+ if (cid == -1)
+ cid = 0
+ cid_elem.content = "0"
+ doc.root.at_xpath("CLUSTER").content = "default"
+
+ host_ids << row[:oid]
+ end
+
+ @db[:host_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :state => row[:state],
+ :last_mon_time => row[:last_mon_time],
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :cid => cid)
+ end
+ end
+
+ @db.run "DROP TABLE old_host_pool;"
+
+ log_time()
+
+ @db.run "ALTER TABLE datastore_pool RENAME TO old_datastore_pool;"
+ @db.run "CREATE TABLE datastore_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ ds_ids = []
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_datastore_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_datastore_pool')
+
+ doc.root.at_xpath("CLUSTER").remove
+
+ cid_elem = doc.root.at_xpath("CLUSTER_ID")
+ cid = cid_elem.text.to_i
+
+ cid_elem.remove
+
+ if (cid == -1)
+ cid = 0
+ ds_ids << row[:oid]
+ end
+
+ cluster_ids_elem = doc.create_element("CLUSTERS")
+ cluster_ids_elem.add_child(doc.create_element("ID")).content = cid.to_s
+
+ doc.root.add_child(cluster_ids_elem)
+
+ @db[:datastore_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+
+ @db[:cluster_datastore_relation].insert(
+ :cid => cid,
+ :oid => row[:oid])
+ end
+ end
+
+ @db.run "DROP TABLE old_datastore_pool;"
+
+ log_time()
+
+ @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));"
+
+ vnet_ids = []
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_network_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_network_pool')
+
+ doc.root.at_xpath("CLUSTER").remove
+
+ cid_elem = doc.root.at_xpath("CLUSTER_ID")
+ cid = cid_elem.text.to_i
+
+ cid_elem.remove
+
+ if (cid == -1)
+ cid = 0
+ vnet_ids << row[:oid]
+ end
+
+ cluster_ids_elem = doc.create_element("CLUSTERS")
+ cluster_ids_elem.add_child(doc.create_element("ID")).content = cid.to_s
+
+ doc.root.add_child(cluster_ids_elem)
+
+ @db[:network_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :pid => row[:pid])
+
+ @db[:cluster_network_relation].insert(
+ :cid => cid,
+ :oid => row[:oid])
+ end
+ end
+
+ @db.run "DROP TABLE old_network_pool;"
+
+ log_time()
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE 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|
+ if row[:state] != 6
+ doc = nokogiri_doc(row[:body], 'old_vm_pool')
+
+ cid = doc.root.at_xpath("HISTORY_RECORDS/HISTORY[last()]/CID").text.to_i rescue nil
+
+ if cid == -1
+ doc.root.at_xpath("HISTORY_RECORDS/HISTORY[last()]/CID").content = 0
+ end
+
+ # Bug #4467
+
+ elem = doc.at_xpath("/VM/USER_TEMPLATE/EC2")
+
+ if (!elem.nil?)
+ elem.name = "PUBLIC_CLOUD"
+
+ if elem.at_xpath("TYPE").nil?
+ elem.add_child(doc.create_element("TYPE")).content = "ec2"
+ 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()
+
+ default_cl_xml = '0default'
+ doc = Nokogiri::XML(default_cl_xml,nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
+
+ hosts_elem = doc.root.at_xpath("HOSTS")
+ host_ids.each { |id|
+ hosts_elem.add_child(doc.create_element("ID")).content = id.to_s
+ }
+
+ ds_elem = doc.root.at_xpath("DATASTORES")
+ ds_ids.each { |id|
+ ds_elem.add_child(doc.create_element("ID")).content = id.to_s
+ }
+
+ vnets_elem = doc.root.at_xpath("VNETS")
+ vnet_ids.each { |id|
+ vnets_elem.add_child(doc.create_element("ID")).content = id.to_s
+ }
+
+ @db[:cluster_pool].insert(
+ :oid => 0,
+ :name => 'default',
+ :body => doc.root.to_s,
+ :uid => 0,
+ :gid => 0,
+ :owner_u => 1,
+ :group_u => 0,
+ :other_u => 0)
+
+ log_time()
+
+ ############################################################################
+ # 4215
+ ############################################################################
+
+ @db.run "CREATE TABLE vrouter_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @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_doc(row[:body], 'old_network_pool')
+
+ doc.root.add_child(doc.create_element("VROUTERS"))
+
+ @db[:network_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :pid => row[:pid])
+ end
+ end
+
+ @db.run "DROP TABLE old_network_pool;"
+
+ log_time()
+
+ @db.run "ALTER TABLE template_pool RENAME TO old_template_pool;"
+ @db.run "CREATE TABLE template_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_template_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_template_pool')
+
+ # Feature #3671
+
+ TEMPLATE_TRANSFORM_ATTRS.each do |old_name, new_name|
+ elem = doc.at_xpath("/VMTEMPLATE/TEMPLATE/#{old_name}")
+
+ if (!elem.nil?)
+ elem.remove
+
+ elem.name = new_name
+
+ if (doc.at_xpath("/VMTEMPLATE/TEMPLATE/SUNSTONE").nil?)
+ doc.at_xpath("/VMTEMPLATE/TEMPLATE").add_child(
+ doc.create_element("SUNSTONE"))
+ end
+
+ doc.at_xpath("/VMTEMPLATE/TEMPLATE/SUNSTONE").add_child(elem)
+ end
+ end
+
+ # Feature #4317
+
+ elem = doc.at_xpath("/VMTEMPLATE/TEMPLATE/SUNSTONE_CAPACITY_SELECT")
+
+ if elem.nil?
+ capacity_edit = true
+ else
+ elem.remove
+ capacity_edit = (elem.text != "NO")
+ end
+
+ if !capacity_edit
+ cpu_e = doc.at_xpath("/VMTEMPLATE/TEMPLATE/CPU")
+ memory_e = doc.at_xpath("/VMTEMPLATE/TEMPLATE/MEMORY")
+ vcpu_e = doc.at_xpath("/VMTEMPLATE/TEMPLATE/VCPU")
+
+ cpu = cpu_e != nil ? cpu_e.text : ""
+ memory = memory_e != nil ? memory_e.text : ""
+ vcpu = vcpu_e != nil ? vcpu_e.text : ""
+
+ user_inputs = doc.at_xpath("/VMTEMPLATE/TEMPLATE/USER_INPUTS")
+
+ if user_inputs.nil?
+ user_inputs = doc.create_element("USER_INPUTS")
+ doc.at_xpath("/VMTEMPLATE/TEMPLATE").add_child(user_inputs)
+ end
+
+ user_inputs.add_child(doc.create_element("CPU")).content = "O|fixed|||#{cpu}"
+ user_inputs.add_child(doc.create_element("MEMORY")).content = "O|fixed|||#{memory}"
+ user_inputs.add_child(doc.create_element("VCPU")).content = "O|fixed|||#{vcpu}"
+ end
+
+ # Bug #4467
+
+ elem = doc.at_xpath("/VMTEMPLATE/TEMPLATE/EC2")
+
+ if (!elem.nil?)
+ elem.name = "PUBLIC_CLOUD"
+
+ if elem.at_xpath("TYPE").nil?
+ elem.add_child(doc.create_element("TYPE")).content = "ec2"
+ end
+ end
+
+ @db[:template_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_template_pool;"
+
+ log_time()
+
+ ############################################################################
+ # Feature #4217
+ ############################################################################
+
+ @db.run "ALTER TABLE image_pool RENAME TO old_image_pool;"
+ @db.run "CREATE TABLE image_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name,uid) );"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_image_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_image_pool')
+
+ doc.root.add_child(doc.create_element("APP_CLONES"))
+
+ @db[:image_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_image_pool;"
+
+ log_time()
+
+ ############################################################################
+ # Feature #3204
+ ############################################################################
+
+ @db.run "ALTER TABLE secgroup_pool RENAME TO old_secgroup_pool;"
+ @db.run "CREATE TABLE secgroup_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name,uid));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_secgroup_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_secgroup_pool')
+
+ doc.root.at_xpath("VMS").name = "UPDATED_VMS"
+ doc.root.add_child(doc.create_element("OUTDATED_VMS"))
+ doc.root.add_child(doc.create_element("UPDATING_VMS"))
+ doc.root.add_child(doc.create_element("ERROR_VMS"))
+
+ @db[:secgroup_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_secgroup_pool;"
+
+ log_time()
+
+ # Bug #4248 - Remove Firewall Drivers
+
+ vms_with_fw = []
+ @db.transaction do
+ @db.fetch("SELECT * FROM vm_pool WHERE state != 6") do |row|
+ doc = nokogiri_doc(row[:body], 'vm_pool')
+
+ has_fw_attrs = !doc.root.xpath("TEMPLATE/NIC[ICMP|WHITE_PORTS_TCP|WHITE_PORTS_UDP|BLACK_PORTS_TCP|BLACK_PORTS_UDP]").empty?
+
+ vms_with_fw << row[:oid].to_i if has_fw_attrs
+ end
+ end
+
+ if !vms_with_fw.empty?
+ puts "**************************************************************"
+ puts "* WARNING WARNING WARNING WARNING WARNING WARNING WARNING *"
+ puts "**************************************************************"
+ puts
+ puts "The old driver 'fw' has been removed from OpenNebula. It was "
+ puts "deprecated in 4.12: "
+ puts "http://docs.opennebula.org/4.12/release_notes/release_notes/compatibility.html"
+ puts
+ puts "We have detected that you still have active VMs with these "
+ puts "attributes: ICMP, WHITE_PORTS_TCP, WHITE_PORTS_UDP, "
+ puts "BLACK_PORTS_TCP, BLACK_PORTS_UDP. "
+ puts
+ puts "The list of affected VMs is: "
+ vms_with_fw.each{|vm| puts "- #{vm}"}
+ puts
+ puts "Please note that OpenNebula will not modify the current "
+ puts "iptables rules, so you will need to manually clean them when "
+ puts "any of VMs is removed."
+ puts
+ puts "Please consider switching to Security Groups "
+ end
+
+ log_time()
+
+ ############################################################################
+ # Remove Xen, VMware and SoftLayer Drivers
+ ############################################################################
+
+ @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);"
+
+ has_xen_hosts = false
+ has_vmware_hosts = false
+ has_sl_hosts = false
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_host_pool") do |row|
+ do_disable = false
+
+ doc = nokogiri_doc(row[:body], 'old_host_pool')
+
+ vm_mad = doc.root.at_xpath("VM_MAD").text
+ im_mad = doc.root.at_xpath("IM_MAD").text
+
+ if vm_mad.match(/xen/) || im_mad.match(/xen/)
+ do_disable = true
+ has_xen_hosts = true
+ end
+
+ if vm_mad.match(/vmware/) || im_mad.match(/vmware/)
+ do_disable = true
+ has_vmware_hosts = true
+ end
+
+
+ if vm_mad.match(/sl/) || im_mad.match(/sl/)
+ do_disable = true
+ has_sl_hosts = true
+ end
+
+ if do_disable
+ doc.root.at_xpath('STATE').content = 4
+
+ row[:state] = 4
+ row[:body] = doc.root.to_s
+ end
+
+ @db[:host_pool].insert(row)
+ end
+ end
+
+ @db.run "DROP TABLE old_host_pool;"
+
+ if has_xen_hosts
+ puts "**************************************************************"
+ puts "* WARNING WARNING WARNING WARNING WARNING WARNING WARNING *"
+ puts "**************************************************************"
+ puts
+ puts "Xen is no longer included in the core distribution. It is"
+ puts "however available as an addon which must be manually installed:"
+ puts "https://github.com/OpenNebula/addon-xen"
+ puts
+ puts "Note that the host has been automatically disabled. After installing"
+ puts "the addon you can manually enable it."
+ puts
+ end
+
+ if has_vmware_hosts
+ puts "**************************************************************"
+ puts "* WARNING WARNING WARNING WARNING WARNING WARNING WARNING *"
+ puts "**************************************************************"
+ puts
+ puts "VMware is no longer supported. You are encouraged to migrate"
+ puts "to the vCenter driver:"
+ puts "http://docs.opennebula.org/stable/administration/virtualization/vcenterg.html"
+ puts
+ puts "Note that the host has been automatically disabled, but not removed."
+ puts
+ end
+
+ if has_sl_hosts
+ puts "**************************************************************"
+ puts "* WARNING WARNING WARNING WARNING WARNING WARNING WARNING *"
+ puts "**************************************************************"
+ puts
+ puts "SoftLayer is no longer included in the core distribution. It is"
+ puts "however available as an addon which must be manually installed:"
+ puts "https://github.com/OpenNebula/addon-softlayer"
+ puts
+ puts "Note that the host has been automatically disabled. After installing"
+ puts "the addon you can manually enable it."
+ puts
+ end
+
+ log_time()
+
+ ############################################################################
+ # Move HOST/VN_MAD --> VNET/VN_MAD
+ ############################################################################
+
+ # Build net_vnmad
+ net_vnmad = {}
+ @db.transaction do
+ @db.fetch("SELECT * FROM vm_pool WHERE state != 6") do |row|
+ doc = nokogiri_doc(row[:body], 'vm_pool')
+ state = row[:state].to_i
+
+ 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
+
+ # 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_doc(row[:body], 'old_host_pool')
+
+ # 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));"
+
+ reserved_vlan_ids = Set.new
+ final_net_vnmad = {}
+ manual_intervention = false
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_network_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_network_pool')
+
+ net_id = row[:oid]
+ net_name = row[:name]
+
+ cluster_id = doc.root.xpath('CLUSTERS/ID').first.text.to_i
+
+ # Get possible VN_MADs
+ net_vnmad_len = net_vnmad[net_id].length rescue 0
+ cluster_vnmad_len = cluster_vnmad[cluster_id].length rescue 0
+
+ # Check if the network has VLAN=NO
+ vlan = doc.root.xpath('VLAN').text rescue nil
+ vlan_no = (vlan == "0")
+
+ # Remove the VLAN attributes
+ doc.root.xpath('//VLAN').remove
+
+ vnmad = nil
+ other_vnmads = nil
+
+ # Get vnmad
+ #
+ # net_vnmad_len == 1 => that one
+ # net_vnmad_len > 1 => interactive
+ # net_vnmad_len == 0 && cluster_vnmad_len == 1 => that one
+ # net_vnmad_len == 0 && cluster_vnmad_len > 1 => interactive
+ # net_vnmad_len == 0 && cluster_vnmad_len == 0 => interactive
+
+ if net_vnmad_len == 1
+ vnmad = net_vnmad[net_id].first
+ elsif net_vnmad_len > 1
+ other_vnmads = net_vnmad[net_id]
+ elsif net_vnmad_len == 0 && cluster_vnmad_len == 1
+ vnmad = cluster_vnmad[cluster_id].first
+ elsif net_vnmad_len == 0 && cluster_vnmad_len > 1
+ other_vnmads = cluster_vnmad[cluster_id]
+ end
+
+ # Ambiguous vnmad, require user input (TODO)
+ if vnmad.nil?
+
+ if !manual_intervention
+ manual_intervention = true
+ puts
+ puts "Manual Intervention required. Please input the VN_MAD " <<
+ " for the following networks:"
+ puts
+ end
+
+ suggested = if other_vnmads
+ " (suggested: [#{other_vnmads.to_a.join(', ')}])"
+ else
+ ""
+ end
+
+ input = ""
+ while (input.empty?) do
+ puts "* Net ##{net_id} (#{net_name}) VN_MAD#{suggested}:"
+ input = STDIN.gets.chomp.strip
+
+ if input.match(/[^\w\-.]/)
+ puts "Invalid char found."
+ input = ""
+ end
+ end
+
+ vnmad = input
+ end
+
+ # If VLAN = NO => don't use isolated VN_MADs
+ if vlan_no && vnmad && ["802.1q", "ovswitch", "vxlan", "ebtables"].include?(vnmad.downcase)
+ input = ""
+ while (input.empty?) do
+ puts "Net ##{net_id} (#{net_name}) has VN_MAD='#{vnmad}' but it also has VLAN=NO. Change to 'fw'? (y/n)"
+
+ input = STDIN.gets.chomp.strip
+
+ case input
+ when 'y'
+ vnmad = 'fw'
+ when 'n'
+ else
+ puts "Invalid value."
+ input = ""
+ end
+ end
+ end
+
+ if vnmad.nil?
+ STDERR.puts "Error getting VN_MAD for Network #{net_id}."
+ exit 1
+ end
+
+ # Create the VN_MAD element:
+ final_net_vnmad[net_id] = vnmad
+ doc.root.add_child(doc.create_element("VN_MAD")).content = vnmad
+
+ # Create/Move the VLAN_ID and VLAN_ID_AUTOMATIC attributes:
+ #
+ # Manual => VLAN_ID exists
+ # Automatic => VLAN_ID does not exist
+ #
+ # If VLAN has been set automatically,
+ #
+ # top-level
+ # top-level 1
+ # remove VLAN_ID from
+ #
+ # If VLAN has been set manually,
+ #
+ # top-level
+ # top-level 0
+ # keep VLAN_ID in
+ #
+ if vnmad && ["802.1q", "ovswitch", "vxlan"].include?(vnmad.downcase)
+ vlan_id = doc.root.xpath('TEMPLATE/VLAN_ID').text rescue nil
+
+ if vlan_id && !vlan_id.empty?
+ vlan_id_automatic = false
+ else
+ # TODO: get from configuration?
+ start_vlan = 2
+
+ vlan_id = start_vlan + (net_id % (4095 - start_vlan))
+ vlan_id_automatic = true
+
+ # Only automatic vlans will be reserved
+ if ["802.1q", "ovswitch"].include?(vnmad.downcase)
+ reserved_vlan_ids << vlan_id
+ end
+
+ doc.root.xpath("//VLAN_ID[not(parent::AR)]").each {|e| e.remove }
+ end
+
+ doc.root.add_child(doc.create_element("VLAN_ID")).content = vlan_id
+ doc.root.add_child(doc.create_element("VLAN_ID_AUTOMATIC")).content = vlan_id_automatic ? "1" : "0"
+ end
+
+ row[:body] = doc.root.to_s
+ @db[:network_pool].insert(row)
+ end
+ 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 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_doc(row[:body], 'old_vm_pool')
+ state = row[:state].to_i
+
+ if state != 6
+ # Remove vnmad from the history records
+ doc.root.xpath("HISTORY_RECORDS//VNMMAD").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
+
+ # Remove DS_LOCATION (Feature #4316 - Remove BASE_PATH)
+ doc.root.xpath("HISTORY_RECORDS//DS_LOCATION").remove
+
+ row[:body] = doc.root.to_s
+ end
+
+ @db[:vm_pool].insert(row)
+ end
+ end
+ @db.run "DROP TABLE old_vm_pool;"
+
+ log_time()
+
+ ############################################################################
+ # Bug #4376 - VLAN IDs Bitmap
+ ############################################################################
+
+ ## Create and bootstrap 'vlan_bitmap' table
+
+ # Create Table
+ @db.run "CREATE TABLE network_vlan_bitmap (id INTEGER, map LONGTEXT, PRIMARY KEY(id));"
+
+ size = 4096
+
+ map = ""
+ size.times.each do |i|
+ map << (reserved_vlan_ids.include?(size - 1 - i) ? "1" : "0")
+ end
+
+ map_encoded = Base64::strict_encode64(Zlib::Deflate.deflate(map))
+
+ @db[:network_vlan_bitmap].insert(
+ :id => 0,
+ :map => map_encoded
+ )
+
+ log_time()
+
+ ############################################################################
+ # VNC Bitmap
+ ############################################################################
+
+ cluster_vnc = {}
+ @db.transaction do
+ @db.fetch("SELECT * FROM vm_pool WHERE state != 6") do |row|
+ doc = nokogiri_doc(row[:body], 'vm_pool')
+
+ port = doc.root.at_xpath('TEMPLATE/GRAPHICS[translate(TYPE,"vnc","VNC")="VNC"]/PORT').text.to_i rescue nil
+ cluster_id = doc.root.at_xpath('HISTORY_RECORDS/HISTORY[last()]/CID').text.to_i rescue nil
+
+ # skip if no port is defined or if it's not assigned to a cluster (not deployed yet!)
+ next if cluster_id.nil? || port.nil?
+
+ cluster_id = 0 if cluster_id == -1
+
+ cluster_vnc[cluster_id] ||= Set.new
+ cluster_vnc[cluster_id] << port
+ end
+ end
+
+ # Create Table
+ @db.run "CREATE TABLE cluster_vnc_bitmap (id INTEGER, map LONGTEXT, PRIMARY KEY(id));"
+
+ vnc_pool_size = 65536
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM cluster_pool") do |row|
+ cluster_id = row[:oid]
+
+ if cluster_vnc[cluster_id]
+ map = ""
+ vnc_pool_size.times.each do |i|
+ map << (cluster_vnc[cluster_id].include?(vnc_pool_size - 1 - i) ? "1" : "0")
+ end
+
+ map_encoded = Base64::strict_encode64(Zlib::Deflate.deflate(map))
+ else
+ map_encoded = "eJztwYEAAAAAgCCl/ekWqQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABqFo8C0Q=="
+ end
+
+ @db[:cluster_vnc_bitmap].insert(
+ :id => cluster_id,
+ :map => map_encoded
+ )
+ end
+ end
+
+ log_time()
+
+ ############################################################################
+ # Feature #4316 - Remove BASE_PATH
+ ############################################################################
+
+ conf_datastore_location = File.read(File.join(VAR_LOCATION, 'config')).match(/DATASTORE_LOCATION=(.*)$/)[1] rescue nil
+
+ @db.run "ALTER TABLE datastore_pool RENAME TO old_datastore_pool;"
+ @db.run "CREATE TABLE datastore_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ has_lvm = false
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_datastore_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_datastore_pool')
+
+ ds_id = row[:oid]
+ ds_name = row[:name]
+
+ base_path = doc.root.at_xpath("TEMPLATE/BASE_PATH").remove rescue nil
+
+ if base_path
+ base_path = base_path.text
+
+ if Pathname(base_path).cleanpath != Pathname(conf_datastore_location).cleanpath
+ puts "**************************************************************"
+ puts "* WARNING WARNING WARNING WARNING WARNING WARNING WARNING *"
+ puts "**************************************************************"
+ puts
+ puts "The Datastore Attribute BASE_PATH has been deprecated. It has been removed from"
+ puts "the Datastore template."
+ puts
+ puts "We have detected that for the datastore ##{ds_id} (#{ds_name}), it does not match"
+ puts "the global DATASTORE_LOCATION."
+ puts
+ puts "You **MUST** create a symbolic link in the nodes to link them:"
+ puts "$ ln -s #{base_path} #{conf_datastore_location}"
+ puts
+ end
+
+ row[:body] = doc.root.to_s
+ end
+
+ ds_mad = doc.root.at_xpath("DS_MAD").text rescue nil
+ has_lvm = true if ds_mad.upcase == "LVM"
+
+ @db[:datastore_pool].insert(row)
+ end
+ end
+
+ @db.run "DROP TABLE old_datastore_pool;"
+
+ if has_lvm
+ puts "**************************************************************"
+ puts "* WARNING WARNING WARNING WARNING WARNING WARNING WARNING *"
+ puts "**************************************************************"
+ puts
+ puts "The LVM driver is no longer included in the core distribution. It is"
+ puts "however available as an addon which must be manually installed:"
+ puts "https://github.com/OpenNebula/addon-lvm"
+ puts
+ puts "You have LVM datastores which will not work until you install the"
+ puts "add-on."
+ puts
+ puts "Note that OpenNebula officially recommends using the fs_lvm drivers:"
+ puts "http://docs.opennebula.org/5.0/deployment/open_cloud_storage_setup/lvm_drivers.html"
+ puts
+ end
+
+ log_time()
+
+ return true
+ end
+
+end
diff --git a/src/onedb/local/4.5.80_to_4.7.80.rb b/src/onedb/local/4.5.80_to_4.7.80.rb
new file mode 100644
index 0000000000..59b4c750b2
--- /dev/null
+++ b/src/onedb/local/4.5.80_to_4.7.80.rb
@@ -0,0 +1,448 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'nokogiri'
+require 'ipaddr'
+
+ONEDCONF_MAC_PREFIX = "02:00"
+
+module Migrator
+ def db_version
+ "4.7.80"
+ end
+
+ def one_version
+ "OpenNebula 4.7.80"
+ end
+
+ def up
+
+ init_log_time()
+
+ @db.run "ALTER TABLE user_quotas RENAME TO old_user_quotas;"
+ @db.run "CREATE TABLE user_quotas (user_oid INTEGER PRIMARY KEY, body MEDIUMTEXT);"
+
+ @db.transaction do
+ # oneadmin does not have quotas
+ @db.fetch("SELECT * FROM old_user_quotas WHERE user_oid=0") do |row|
+ @db[:user_quotas].insert(row)
+ end
+
+ @db.fetch("SELECT * FROM old_user_quotas WHERE user_oid>0") do |row|
+ doc = nokogiri_doc(row[:body], 'old_user_quotas')
+
+ redo_quota_limits(doc)
+
+ @db[:user_quotas].insert(
+ :user_oid => row[:user_oid],
+ :body => doc.root.to_s)
+ end
+ end
+
+ @db.run "DROP TABLE old_user_quotas;"
+
+ log_time()
+
+ @db.run "ALTER TABLE group_quotas RENAME TO old_group_quotas;"
+ @db.run "CREATE TABLE group_quotas (group_oid INTEGER PRIMARY KEY, body MEDIUMTEXT);"
+
+ @db.transaction do
+ # oneadmin does not have quotas
+ @db.fetch("SELECT * FROM old_group_quotas WHERE group_oid=0") do |row|
+ @db[:group_quotas].insert(row)
+ end
+
+ @db.fetch("SELECT * FROM old_group_quotas WHERE group_oid>0") do |row|
+ doc = nokogiri_doc(row[:body], 'old_group_quotasl')
+
+ redo_quota_limits(doc)
+
+ @db[:group_quotas].insert(
+ :group_oid => row[:group_oid],
+ :body => doc.root.to_s)
+ end
+ end
+
+ @db.run "DROP TABLE old_group_quotas;"
+
+ log_time()
+
+ default_user_quotas = nil
+ default_group_quotas = nil
+
+ @db.fetch("SELECT * FROM system_attributes WHERE name = 'DEFAULT_USER_QUOTAS'") do |row|
+ default_user_quotas = nokogiri_doc(row[:body], 'system_attributes')
+
+ redo_quota_limits(default_user_quotas)
+ end
+
+ @db.fetch("SELECT * FROM system_attributes WHERE name = 'DEFAULT_GROUP_QUOTAS'") do |row|
+ default_group_quotas = nokogiri_doc(row[:body], 'system_attributes')
+
+ redo_quota_limits(default_group_quotas)
+ end
+
+ @db[:system_attributes].where(:name => "DEFAULT_USER_QUOTAS").update(
+ :body => default_user_quotas.root.to_s)
+
+ @db[:system_attributes].where(:name => "DEFAULT_GROUP_QUOTAS").update(
+ :body => default_group_quotas.root.to_s)
+
+ log_time()
+
+ ########################################################################
+ # Networks
+ ########################################################################
+
+ @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, cid INTEGER, UNIQUE(name,uid));"
+
+ @db.fetch("SELECT * FROM old_network_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_network_pool')
+
+ ranged = doc.root.at_xpath("TYPE").text == "0"
+ doc.root.at_xpath("TYPE").remove
+
+ global_prefix = doc.root.at_xpath("GLOBAL_PREFIX").text
+ site_prefix = doc.root.at_xpath("SITE_PREFIX").text
+
+ doc.root.at_xpath("GLOBAL_PREFIX").remove
+ doc.root.at_xpath("SITE_PREFIX").remove
+
+ doc.root.add_child(doc.create_element("PARENT_NETWORK_ID"))
+ ar_pool = doc.root.add_child(doc.create_element("AR_POOL"))
+
+ doc.root.at_xpath("TOTAL_LEASES").name = "USED_LEASES"
+
+ type = "IP4"
+
+ if(global_prefix != "" || site_prefix != "")
+ force_e = doc.root.at_xpath("TEMPLATE/CONTEXT_FORCE_IPV4")
+
+ if !force_e.nil? && force_e.text.upcase == "YES"
+ type = "IP4_6"
+ else
+ type = "IP6"
+ end
+ end
+
+ if ranged
+ ip_start_s = doc.root.at_xpath("RANGE/IP_START").text
+ ip_end_s = doc.root.at_xpath("RANGE/IP_END").text
+
+ doc.root.at_xpath("RANGE").remove
+
+ ip_start = IPAddr.new(ip_start_s, Socket::AF_INET)
+ range_ip_end = IPAddr.new(ip_end_s, Socket::AF_INET)
+
+ mac_prefix = ONEDCONF_MAC_PREFIX.gsub(":","").to_i(16)
+
+ @db.fetch("SELECT body FROM leases WHERE oid=#{row[:oid]} ORDER BY ip ASC LIMIT 1") do |lease_row|
+ lease = nokogiri_doc(lease_row[:body], 'leases')
+
+ mac_prefix = lease.root.at_xpath("MAC_PREFIX").text.to_i
+ end
+
+ mac_start_s = mac_to_s(mac_prefix, ip_start.to_i)
+ mac_start = mac_prefix | ip_start.to_i
+
+ ar_id = 0
+
+ ar = add_element(ar_pool, "AR")
+ add_cdata(ar, "AR_ID", ar_id.to_s)
+ add_cdata(ar, "MAC", mac_start_s)
+ add_cdata(ar, "TYPE", type)
+
+ if type == "IP4" || type == "IP4_6"
+ add_cdata(ar, "IP", ip_start_s)
+ end
+
+ if type == "IP6" || type == "IP4_6"
+ if global_prefix != ""
+ add_cdata(ar, "GLOBAL_PREFIX", global_prefix)
+ end
+
+ if site_prefix != ""
+ add_cdata(ar, "ULA_PREFIX", site_prefix)
+ end
+ end
+
+ allocated_str = ""
+
+ @db.fetch("SELECT body FROM leases WHERE oid=#{row[:oid]} ORDER BY ip ASC") do |lease_row|
+ lease = nokogiri_doc(lease_row[:body], 'leases')
+
+ # For ranged, all leases are used
+
+ ip = lease.root.at_xpath("IP").text
+
+ mac_p = lease.root.at_xpath("MAC_PREFIX").text.to_i
+ mac_s = lease.root.at_xpath("MAC_SUFFIX").text.to_i
+ mac = mac_p | mac_s
+
+ vid = lease.root.at_xpath("VID").text.to_i
+
+ index = ip.to_i - ip_start.to_i
+
+ # If mac + index does not match, open a new AR with
+ # a different MAC start
+ if (mac_start + index != mac)
+ # Close current AR
+ ip_end = ip.to_i - 1
+
+ size = ip_end.to_i - ip_start.to_i + 1
+ add_cdata(ar, "SIZE", size.to_s)
+ add_cdata(ar, "ALLOCATED", allocated_str)
+
+ # Create a new AR
+ ar_id += 1
+
+ ip_start = ip.to_i
+ ip_start_s = ip_to_s(ip_start)
+
+ mac_start = mac
+ mac_start_s = mac_to_s(mac_p, mac_s)
+
+ ar = add_element(ar_pool, "AR")
+ add_cdata(ar, "AR_ID", ar_id.to_s)
+ add_cdata(ar, "MAC", mac_start_s)
+ add_cdata(ar, "SIZE", size.to_s)
+ add_cdata(ar, "TYPE", type)
+
+ if type == "IP4" || type == "IP4_6"
+ add_cdata(ar, "IP", ip_start_s)
+ end
+
+ if type == "IP6" || type == "IP4_6"
+ if global_prefix != ""
+ add_cdata(ar, "GLOBAL_PREFIX", global_prefix)
+ end
+
+ if site_prefix != ""
+ add_cdata(ar, "ULA_PREFIX", site_prefix)
+ end
+ end
+
+ allocated_str = ""
+
+ # Recalculate index from new ip_start
+ index = ip.to_i - ip_start.to_i
+ end
+
+ binary_magic = 0x0000001000000000 | (vid & 0xFFFFFFFF)
+
+ allocated_str << " #{index} #{binary_magic}"
+ end
+
+ # Close the last AR
+ size = range_ip_end.to_i - ip_start.to_i + 1
+ add_cdata(ar, "SIZE", size.to_s)
+ add_cdata(ar, "ALLOCATED", allocated_str)
+ else
+ ar_id = 0
+
+ @db.fetch("SELECT body FROM leases WHERE oid=#{row[:oid]}") do |lease_row|
+ lease = nokogiri_doc(lease_row[:body], 'leases')
+
+ # For fixed, IP != MAC_SUFFIX
+
+ ip = lease.root.at_xpath("IP").text
+ mac_p = lease.root.at_xpath("MAC_PREFIX").text
+ mac_s = lease.root.at_xpath("MAC_SUFFIX").text
+ used = lease.root.at_xpath("USED").text
+ vid = lease.root.at_xpath("VID").text.to_i
+
+ mac = mac_to_s(mac_p, mac_s)
+
+ allocated_str = ""
+
+ if used == "1"
+ binary_magic = 0x0000001000000000 | (vid & 0xFFFFFFFF)
+ allocated_str << " 0 #{binary_magic}"
+ end
+
+ ar = add_element(ar_pool, "AR")
+
+ add_cdata(ar, "AR_ID", ar_id.to_s)
+ add_cdata(ar, "MAC", mac)
+ add_cdata(ar, "SIZE", "1")
+ add_cdata(ar, "TYPE", type)
+ add_cdata(ar, "ALLOCATED", allocated_str)
+
+ if type == "IP4" || type == "IP4_6"
+ add_cdata(ar, "IP", ip_to_s(ip))
+ end
+
+ if type == "IP6" || type == "IP4_6"
+ if global_prefix != ""
+ add_cdata(ar, "GLOBAL_PREFIX", global_prefix)
+ end
+
+ if site_prefix != ""
+ add_cdata(ar, "ULA_PREFIX", site_prefix)
+ end
+ end
+
+ ar_id += 1
+ end
+ end
+
+ @db[:network_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :cid => row[:cid])
+ end
+
+ @db.run "DROP TABLE old_network_pool;"
+ @db.run "DROP TABLE leases;"
+
+ log_time()
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE 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.run "INSERT INTO vm_pool SELECT * FROM old_vm_pool WHERE state = 6;"
+
+ log_time()
+
+ @db.fetch("SELECT * FROM old_vm_pool WHERE state<>6") do |row|
+ doc = nokogiri_doc(row[:body], 'old_vm_pool')
+
+ doc.root.xpath("TEMPLATE/NIC/IP6_SITE").each {|e|
+ e.name = "IP6_ULA"
+ }
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+ log_time()
+
+ return true
+ end
+
+ ############################################################################
+
+ def add_element(elem, name)
+ return elem.add_child(elem.document.create_element(name))
+ end
+
+ def add_cdata(elem, name, text)
+ # The cleaner doc.create_cdata(txt) is not supported in
+ # old versions of nokogiri
+ return add_element(elem, name).add_child(
+ Nokogiri::XML::CDATA.new(elem.document(), text))
+ end
+
+ def mac_to_s(prefix, suffix)
+ hex_p = prefix.to_i.to_s(16).rjust(4, "0")
+ hex_s = suffix.to_i.to_s(16).rjust(8, "0")
+
+ mac = hex_p.insert(2,":").insert(5,":") <<
+ hex_s.insert(2,":").insert(5,":").insert(8,":")
+ end
+
+ def ip_to_s(ip)
+ hex = ip.to_i.to_s(16).rjust(8, "0")
+ return "#{hex[0..1].hex}.#{hex[2..3].hex}.#{hex[4..5].hex}.#{hex[6..7].hex}"
+ end
+
+ ############################################################################
+
+ def redo_quota_limits(doc)
+ # VM quotas
+
+ vm_elem = nil
+ doc.root.xpath("VM_QUOTA/VM").each { |e| vm_elem = e }
+
+ if !vm_elem.nil?
+ ["CPU", "MEMORY", "VMS", "VOLATILE_SIZE"].each do |q_name|
+ vm_elem.xpath(q_name).each do |e|
+ if e.text.to_i == 0
+ e.content = "-2"
+ end
+ end
+ end
+ end
+
+ # VNet quotas
+
+ net_quota = nil
+ doc.root.xpath("NETWORK_QUOTA").each { |e| net_quota = e }
+
+ if !net_quota.nil?
+ net_quota.xpath("NETWORK").each do |net_elem|
+ net_elem.xpath("LEASES").each do |e|
+ if e.text.to_i == 0
+ e.content = "-2"
+ end
+ end
+ end
+ end
+
+ # Image quotas
+
+ img_quota = nil
+ doc.root.xpath("IMAGE_QUOTA").each { |e| img_quota = e }
+
+ if !img_quota.nil?
+ img_quota.xpath("IMAGE").each do |img_elem|
+ img_elem.xpath("RVMS").each do |e|
+ if e.text.to_i == 0
+ e.content = "-2"
+ end
+ end
+ end
+ end
+
+ # Datastore quotas
+
+ ds_quota = nil
+ doc.root.xpath("DATASTORE_QUOTA").each { |e| ds_quota = e }
+
+ if !ds_quota.nil?
+ ds_quota.xpath("DATASTORE").each do |ds_elem|
+ ["IMAGES", "SIZE"].each do |q_name|
+ ds_elem.xpath(q_name).each do |e|
+ if e.text.to_i == 0
+ e.content = "-2"
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/src/onedb/local/4.7.80_to_4.9.80.rb b/src/onedb/local/4.7.80_to_4.9.80.rb
new file mode 100644
index 0000000000..7e021d52c6
--- /dev/null
+++ b/src/onedb/local/4.7.80_to_4.9.80.rb
@@ -0,0 +1,69 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'nokogiri'
+
+module Migrator
+ def db_version
+ "4.9.80"
+ end
+
+ def one_version
+ "OpenNebula 4.9.80"
+ end
+
+ def up
+
+ init_log_time()
+
+ ########################################################################
+ # Networks
+ ########################################################################
+
+ @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, cid INTEGER, pid INTEGER, UNIQUE(name,uid));"
+
+ @db.fetch("SELECT * FROM old_network_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_network_pool')
+
+ parent_st = doc.root.at_xpath("PARENT_NETWORK_ID").text
+ parent_i = -1
+
+ if parent_st != ""
+ parent_i = parent_st.to_i
+ end
+
+ @db[:network_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => row[:body],
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :cid => row[:cid],
+ :pid => parent_i)
+ end
+
+ @db.run "DROP TABLE old_network_pool;"
+
+ log_time()
+
+ return true
+ end
+end
diff --git a/src/onedb/local/4.9.80_to_4.10.3.rb b/src/onedb/local/4.9.80_to_4.10.3.rb
new file mode 100644
index 0000000000..1b06482e6f
--- /dev/null
+++ b/src/onedb/local/4.9.80_to_4.10.3.rb
@@ -0,0 +1,37 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "4.10.3"
+ end
+
+ def one_version
+ "OpenNebula 4.10.3"
+ end
+
+ def up
+
+ init_log_time()
+
+ @db.run "CREATE TABLE IF NOT EXISTS vm_import (deploy_id VARCHAR(128), vmid INTEGER, PRIMARY KEY(deploy_id));"
+
+ log_time()
+
+ return true
+ end
+end
diff --git a/src/onedb/local/4.90.0_to_5.3.80.rb b/src/onedb/local/4.90.0_to_5.3.80.rb
new file mode 100644
index 0000000000..c39b0c06d3
--- /dev/null
+++ b/src/onedb/local/4.90.0_to_5.3.80.rb
@@ -0,0 +1,325 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'base64'
+require 'zlib'
+require 'pathname'
+require 'yaml'
+require 'opennebula'
+
+$: << File.dirname(__FILE__)
+
+include OpenNebula
+
+module Migrator
+ def db_version
+ "5.3.80"
+ end
+
+ def one_version
+ "OpenNebula 5.3.80"
+ end
+
+ def up
+ init_log_time()
+
+ feature_5136()
+
+ feature_4901()
+
+ feature_5005()
+
+ feature_2347()
+
+ bug_3705()
+
+ feature_4809()
+
+ log_time()
+
+ return true
+ end
+
+ private
+
+ def xpath(doc, sxpath)
+ element = doc.root.at_xpath(sxpath)
+ if !element.nil?
+ element.text
+ else
+ ""
+ end
+ end
+
+ def delete_element(doc, element)
+ doc.search("//#{element}").each do |node|
+ node.remove
+ end
+ end
+
+ ############################################################################
+ # Feature 5136. Improve ec2 keys_ids_security
+ #
+ ############################################################################
+ def feature_5136
+ ec2_driver_conf = "#{ETC_LOCATION}/ec2_driver.conf.old"
+ token = File.read(VAR_LOCATION+'/.one/one_key')
+ to_encrypt = {}
+
+ if !File.exist?(ec2_driver_conf)
+ STDERR.puts " > Old EC2 file not found, skipping EC2 host migration"
+ return
+ end
+
+ begin
+ ec2_conf = YAML::load(File.read(ec2_driver_conf))
+ rescue Exception => e
+ str_error="ec2_driver.conf invalid syntax!"
+ raise str_error
+ end
+
+ regions = ec2_conf["regions"]
+
+ if !regions
+ STDERR.puts " > Regions not found in EC2 config file, skipping migration"
+ return
+ end
+
+ @db.run "DROP TABLE IF EXISTS old_host_pool;"
+ @db.run "ALTER TABLE host_pool RENAME TO old_host_pool;"
+ create_table(:host_pool)
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_host_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_host_pool')
+
+ template = doc.root.at_xpath("TEMPLATE")
+
+ if xpath(doc, "TEMPLATE/HYPERVISOR").to_s == "ec2"
+ host_name = xpath(doc, "NAME").to_s
+ host_info = ( regions[host_name].nil? ? regions["default"] : regions[host_name] )
+
+ to_encrypt["EC2_ACCESS"]=host_info["access_key_id"]
+ to_encrypt["EC2_SECRET"]=host_info["secret_access_key"]
+
+ OpenNebula.encrypt(to_encrypt, token).each { |k, v|
+ delete_element(template, k)
+ template.add_child(doc.create_element(k, v))
+ }
+
+ capacity = doc.create_element("CAPACITY")
+ host_info["capacity"].each { |k, v|
+ name = k.gsub(".", "_")
+ capacity.add_child(doc.create_element(name.upcase, v))
+ }
+
+ delete_element(template, "CAPACITY")
+ template.add_child(capacity)
+
+ delete_element(template, "REGION_NAME")
+ template.add_child(doc.create_element "REGION_NAME", host_info["region_name"])
+ end
+
+ row[:body] = doc.root.to_s
+ @db[:host_pool].insert(row)
+ end
+ end
+
+ @db.run "DROP TABLE old_host_pool;"
+
+ STDERR.puts " > You can now delete #{ec2_driver_conf} file"
+ end
+
+ ############################################################################
+ # Feature 4921. Adds TOTAL_CPU and TOTAL_MEM to HOST/HOST_SHARE to compute
+ # MAX_CPU and MAX_MEM when RESERVED_CPU/MEM is updated
+ ############################################################################
+ def feature_4901
+ @db.run "DROP TABLE IF EXISTS old_host_pool;"
+ @db.run "ALTER TABLE host_pool RENAME TO old_host_pool;"
+ create_table(:host_pool)
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_host_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_host_pool')
+
+ rcpu = xpath(doc, "TEMPLATE/RESERVED_CPU").to_i
+ rmem = xpath(doc, "TEMPLATE/RESERVED_MEM").to_i
+
+ total_cpu = xpath(doc, "HOST_SHARE/MAX_CPU").to_i + rcpu
+ total_mem = xpath(doc, "HOST_SHARE/MAX_MEM").to_i + rmem
+
+ total_cpu_e = doc.create_element "TOTAL_CPU", total_cpu
+ total_mem_e = doc.create_element "TOTAL_MEM", total_mem
+
+ host_share = doc.root.at_xpath("HOST_SHARE")
+ host_share.add_child(total_cpu_e)
+ host_share.add_child(total_mem_e)
+
+ row[:body] = doc.root.to_s
+
+ @db[:host_pool].insert(row)
+ end
+ end
+
+ @db.run "DROP TABLE old_host_pool;"
+ end
+
+ ############################################################################
+ # Feature 5005.
+ # Adds UID, GID and REQUEST_ID to history records
+ # It also changes the old naming for mads from 4.x to 5.x
+ ############################################################################
+ def feature_5005
+ @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_doc(row[:body], 'old_vm_pool')
+
+ doc.root.xpath("HISTORY_RECORDS/HISTORY").each do |h|
+ reason = h.xpath("REASON")
+ reason.unlink if !reason.nil?
+
+ uid = doc.create_element "UID", -1
+ gid = doc.create_element "GID", -1
+ rid = doc.create_element "REQUEST_ID", -1
+
+ h.add_child(uid)
+ h.add_child(gid)
+ h.add_child(rid)
+ end
+
+ row[:body] = doc.root.to_s
+
+ @db[:vm_pool].insert(row)
+ end
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+ @db.run "DROP TABLE IF EXISTS old_history;"
+ @db.run "ALTER TABLE history RENAME TO old_history;"
+ create_table(:history)
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_history") do |row|
+ doc = nokogiri_doc(row[:body], 'old_history')
+
+ h = doc.root
+
+ reason = h.xpath("REASON")
+ reason.unlink if !reason.nil?
+
+ uid = doc.create_element "UID", -1
+ gid = doc.create_element "GID", -1
+ rid = doc.create_element "REQUEST_ID", -1
+
+ h.add_child(uid)
+ h.add_child(gid)
+ h.add_child(rid)
+
+ # This section is unrelated to Feature 5005. It renames
+ # attributes in the history with the nomenclature that was in
+ # use before OpenNebula 5.0.
+ vm_mad = h.at_xpath("VMMMAD")
+ vm_mad.node_name = "VM_MAD" if vm_mad
+
+ tm_mad = h.at_xpath("TMMAD")
+ tm_mad.node_name = "TM_MAD" if tm_mad
+
+ vn_mad = h.at_xpath("VNMMAD")
+ vn_mad.remove if vn_mad
+
+ row[:body] = doc.root.to_s
+
+ @db[:history].insert(row)
+ end
+ end
+
+ @db.run "DROP TABLE old_history;"
+ end
+
+ def feature_2347
+ create_table(:vmgroup_pool)
+ end
+
+ ############################################################################
+ # Bug 3705
+ # Adds DRIVER to CEPH and LVM image datastores
+ ############################################################################
+ def bug_3705
+ @db.run "DROP TABLE IF EXISTS old_datastore_pool;"
+ @db.run "ALTER TABLE datastore_pool RENAME TO old_datastore_pool;"
+ create_table(:datastore_pool)
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_datastore_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_datastore_pool')
+
+ type = xpath(doc, 'TYPE').to_i
+ tm_mad = xpath(doc, 'TM_MAD')
+
+ if (type == 0) && (["ceph", "fs_lvm"].include?(tm_mad))
+ doc.root.xpath("TEMPLATE/DRIVER").each do |d|
+ d.remove
+ end
+
+ driver = doc.create_element "DRIVER", "raw"
+ doc.root.at_xpath("TEMPLATE").add_child(driver)
+
+ row[:body] = doc.root.to_s
+ end
+
+ @db[:datastore_pool].insert(row)
+ end
+ end
+
+ @db.run "DROP TABLE old_datastore_pool;"
+ end
+
+ ############################################################################
+ # Feature 4809
+ # Simplify HA management in OpenNebula
+ ############################################################################
+ def feature_4809
+ create_table(:logdb)
+
+ @db.run "DROP TABLE IF EXISTS old_zone_pool;"
+ @db.run "ALTER TABLE zone_pool RENAME TO old_zone_pool;"
+ create_table(:zone_pool)
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_zone_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_zone_pool')
+
+ server_pool = doc.create_element "SERVER_POOL"
+ doc.root.add_child(server_pool)
+
+ row[:body] = doc.root.to_s
+
+ @db[:zone_pool].insert(row)
+ end
+ end
+
+ @db.run "DROP TABLE old_zone_pool;"
+ end
+end
diff --git a/src/onedb/local/5.10.0_to_5.12.0.rb b/src/onedb/local/5.10.0_to_5.12.0.rb
new file mode 100644
index 0000000000..bd019f0138
--- /dev/null
+++ b/src/onedb/local/5.10.0_to_5.12.0.rb
@@ -0,0 +1,223 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'json'
+require 'nokogiri'
+
+$LOAD_PATH << File.dirname(__FILE__)
+include OpenNebula
+
+module Migrator
+
+ def db_version
+ '5.12.0'
+ end
+
+ def one_version
+ 'OpenNebula 5.12.0'
+ end
+
+ def up
+ feature_4132
+ feature_3859
+ true
+ end
+
+ private
+
+ def feature_4132
+ @db.run 'DROP TABLE IF EXISTS old_document_pool;'
+ @db.run 'ALTER TABLE document_pool RENAME TO old_document_pool;'
+
+ create_table(:document_pool)
+
+ # VM information to get
+ info = %w[ID UID GID UNAME GNAME NAME]
+
+ STDERR.puts 'All custom_attrs will be used as networks'
+
+ @db.transaction do
+ @db.fetch('SELECT * FROM old_document_pool') do |row|
+ doc = nokogiri_doc(row[:body], 'old_document_pool')
+
+ json = JSON.parse(doc.xpath('//BODY').text)
+
+ json['networks'] = json['custom_attrs'] || {}
+ json['custom_attrs'] = {}
+
+ # services
+ if row[:type] == 100
+ json['networks_values'] = json['custom_attrs_values'] || {}
+ json['custom_attrs_values'] = {}
+
+ # remove unneeded VM information
+ json['roles'].each do |role|
+ role['nodes'].each do |node|
+ node['vm_info']['VM'] = node['vm_info']['VM'].select do |v|
+ info.include?(v)
+ end
+ end
+ end
+ end
+
+ doc.xpath('DOCUMENT/TEMPLATE/BODY')[0].children[0].content = json.to_json
+
+ row[:body] = doc.root.to_s
+
+ @db[:document_pool].insert(row)
+ end
+ end
+
+ @db.run 'DROP TABLE IF EXISTS old_documentpool;'
+ end
+
+ def feature_3859
+ # host monitoring
+ @db.run 'DROP TABLE IF EXISTS old_host_monitoring;'
+ @db.run 'ALTER TABLE host_monitoring RENAME TO old_host_monitoring;'
+
+ create_table(:host_monitoring)
+
+ db.transaction do
+ # Adjust host monitoring
+ @db.fetch('SELECT * FROM old_host_monitoring') do |row|
+ doc_old = nokogiri_doc(row[:body], 'old_host_monitoring')
+
+ doc = nokogiri_doc('', 'old_host_monitoring')
+
+ # id and timestamp
+ monitoring = doc.create_element('MONITORING');
+ monitoring.add_child(doc_old.xpath('HOST/ID'))
+ monitoring.add_child(doc.create_element(
+ 'TIMESTAMP', doc_old.xpath('HOST/LAST_MON_TIME').text))
+
+ # capacity
+ capacity = doc.create_element('CAPACITY')
+ capacity.add_child(doc_old.xpath('HOST/HOST_SHARE/FREE_CPU'))
+ capacity.add_child(doc.create_element(
+ 'FREE_MEMORY', doc_old.xpath('HOST/HOST_SHARE/FREE_MEM').text))
+ capacity.add_child(doc_old.xpath('HOST/HOST_SHARE/USED_CPU'))
+ capacity.add_child(doc.create_element(
+ 'USED_MEMORY', doc_old.xpath('HOST/HOST_SHARE/USED_MEM').text))
+ monitoring.add_child(capacity)
+
+ # system
+ system = doc.create_element('SYSTEM')
+ system.add_child(doc_old.xpath('HOST/TEMPLATE/NETRX'))
+ system.add_child(doc_old.xpath('HOST/TEMPLATE/NETTX'))
+ monitoring.add_child(system)
+
+ doc.root = monitoring
+
+ row[:body] = doc.root.to_s
+
+ @db[:host_monitoring].insert(row)
+ end
+ end
+
+ @db.run 'DROP TABLE IF EXISTS old_host_monitoring;'
+
+ # host pool
+ @db.run 'DROP TABLE IF EXISTS old_host_pool;'
+ @db.run 'ALTER TABLE host_pool RENAME TO old_host_pool;'
+
+ create_table(:host_pool)
+
+ db.transaction do
+ # Adjust host pool
+ @db.fetch('SELECT * FROM old_host_pool') do |row|
+ doc = nokogiri_doc(row[:body], 'old_host_pool')
+
+ doc.xpath('HOST/LAST_MON_TIME').remove
+ doc.xpath('HOST/TEMPLATE/NETRX').remove
+ doc.xpath('HOST/TEMPLATE/NETTX').remove
+ hs = doc.xpath('HOST/HOST_SHARE').pop
+ hs.xpath('FREE_MEM').remove
+ hs.xpath('FREE_CPU').remove
+ hs.xpath('USED_MEM').remove
+ hs.xpath('USED_CPU').remove
+
+ disk_usage = hs.xpath('DISK_USAGE').remove.pop
+ max_disk = hs.xpath('MAX_DISK').remove.pop
+ free_disk = hs.xpath('FREE_DISK').remove.pop
+ used_disk = hs.xpath('USED_DISK').remove.pop
+
+ ds = doc.xpath('HOST/HOST_SHARE/DATASTORES').pop
+ ds.add_child(disk_usage)
+ ds.add_child(max_disk)
+ ds.add_child(free_disk)
+ ds.add_child(used_disk)
+
+ row[:body] = doc.root.to_s
+ row.delete(:last_mon_time)
+
+ @db[:host_pool].insert(row)
+ end
+ end
+
+ @db.run 'DROP TABLE IF EXISTS old_host_pool;'
+
+ # VM monitoring
+ @db.run 'DROP TABLE IF EXISTS old_vm_monitoring;'
+ @db.run 'ALTER TABLE vm_monitoring RENAME TO old_vm_monitoring;'
+
+ create_table(:vm_monitoring)
+
+ db.transaction do
+ # Adjust VM monitoring
+ @db.fetch('SELECT * FROM old_vm_monitoring') do |row|
+ doc = nokogiri_doc(row[:body], 'old_vm_monitoring')
+
+ doc.xpath('VM/STATE').remove
+ doc.xpath('VM/TEMPLATE').remove
+ doc.xpath('VM/LAST_POLL').pop.name = 'TIMESTAMP'
+ doc.xpath('VM').pop.name = 'MONITORING'
+
+ row[:body] = doc.root.to_s
+
+ @db[:vm_monitoring].insert(row)
+ end
+ end
+
+ @db.run 'DROP TABLE IF EXISTS old_vm_monitoring;'
+
+ # VM 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
+ # Adjust host pool
+ @db.fetch('SELECT * FROM old_vm_pool') do |row|
+ doc = nokogiri_doc(row[:body], 'old_vm_pool')
+
+ doc.xpath('VM/LAST_POLL').remove
+ doc.xpath('VM/MONITORING').remove
+ doc.root.add_child(doc.create_element('MONITORING'))
+
+ row[:body] = doc.root.to_s
+ row.delete(:last_poll)
+
+ @db[:vm_pool].insert(row)
+ end
+ end
+
+ @db.run 'DROP TABLE IF EXISTS old_vm_pool;'
+ end
+
+end
diff --git a/src/onedb/local/5.3.80_to_5.4.0.rb b/src/onedb/local/5.3.80_to_5.4.0.rb
new file mode 100644
index 0000000000..63217baaed
--- /dev/null
+++ b/src/onedb/local/5.3.80_to_5.4.0.rb
@@ -0,0 +1,41 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'base64'
+require 'zlib'
+require 'pathname'
+require 'yaml'
+require 'opennebula'
+
+$: << File.dirname(__FILE__)
+
+include OpenNebula
+
+module Migrator
+ def db_version
+ "5.4.0"
+ end
+
+ def one_version
+ "OpenNebula 5.4.0"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/local/5.4.0_to_5.4.1.rb b/src/onedb/local/5.4.0_to_5.4.1.rb
new file mode 100644
index 0000000000..acfbc1f2b3
--- /dev/null
+++ b/src/onedb/local/5.4.0_to_5.4.1.rb
@@ -0,0 +1,52 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'base64'
+require 'zlib'
+require 'pathname'
+require 'yaml'
+require 'opennebula'
+
+$: << File.dirname(__FILE__)
+
+include OpenNebula
+
+module Migrator
+ def db_version
+ "5.4.1"
+ end
+
+ def one_version
+ "OpenNebula 5.4.1"
+ end
+
+ def up
+ add_ha_indexes
+
+ return true
+ end
+
+ def add_ha_indexes
+ indexes = @db.indexes(:logdb)
+
+ @db.alter_table(:logdb) do
+ add_index :fed_index, name: :fed_index_idx if !indexes[:fed_index_idx]
+ add_index :timestamp, name: :timestamp_idx if !indexes[:timestamp_idx]
+ end
+ end
+end
diff --git a/src/onedb/local/5.4.1_to_5.5.80.rb b/src/onedb/local/5.4.1_to_5.5.80.rb
new file mode 100644
index 0000000000..d09fe01134
--- /dev/null
+++ b/src/onedb/local/5.4.1_to_5.5.80.rb
@@ -0,0 +1,256 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'yaml'
+require 'opennebula'
+
+include OpenNebula
+
+module Migrator
+ def db_version
+ "5.5.80"
+ end
+
+ def one_version
+ "OpenNebula 5.5.80"
+ end
+
+ def up
+ init_log_time()
+
+ feature_5189()
+
+ feature_1709()
+
+ feature_1377()
+
+ bug_2189()
+
+ log_time()
+
+ return true
+ end
+
+ private
+
+ def xpath(doc, sxpath)
+ element = doc.root.at_xpath(sxpath)
+ if !element.nil?
+ element.text
+ else
+ ""
+ end
+ end
+
+ def delete_element(doc, element)
+ doc.search("//#{element}").each do |node|
+ node.remove
+ end
+ end
+
+ def feature_1377()
+ @db.run "DROP TABLE IF EXISTS old_document_pool;"
+ @db.run "ALTER TABLE document_pool RENAME TO old_document_pool;"
+
+ create_table(:document_pool)
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_document_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_document_pool')
+
+ delete_element(doc, "LOCK")
+
+ @db[:document_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :type => row[:type],
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u]
+ )
+ end
+ end
+
+ @db.run "DROP TABLE old_document_pool;"
+ end
+
+ def feature_1709()
+ indexes = @db.indexes(:vm_pool)
+
+ @db.alter_table(:vm_pool) do
+ add_index :state, name: :state_idx if !indexes[:state_idx]
+ end
+ end
+
+ def feature_5189()
+ az_driver_conf = "#{ETC_LOCATION}/az_driver.conf.old"
+ token = File.read(VAR_LOCATION+'/.one/one_key')
+ to_encrypt = {}
+
+ if !File.exist?(az_driver_conf)
+ STDERR.puts " > Old Az file not found, skipping Az host migration"
+ return
+ end
+
+ begin
+ az_conf = YAML::load(File.read(az_driver_conf))
+ rescue Exception => e
+ str_error="az_driver.conf invalid syntax!"
+ raise str_error
+ end
+
+ regions = az_conf["regions"]
+
+ if !regions
+ STDERR.puts " > Regions not found in Az config file, " <<
+ "skipping migration"
+ return
+ end
+
+ @db.run "DROP TABLE IF EXISTS old_host_pool;"
+ @db.run "ALTER TABLE host_pool RENAME TO old_host_pool;"
+ create_table(:host_pool)
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_host_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_host_pool')
+
+ template = doc.root.at_xpath("TEMPLATE")
+
+ if xpath(doc, "TEMPLATE/HYPERVISOR").to_s == "AZURE"
+ host_name = xpath(doc, "NAME").to_s
+ host_info = ( regions[host_name].nil? ? regions["default"] : regions[host_name] )
+
+ to_encrypt["AZ_ID"]=host_info["subscription_id"]
+ to_encrypt["AZ_CERT"] = File.read(host_info["pem_management_cert"])
+
+ OpenNebula.encrypt(to_encrypt, token).each { |k, v|
+ delete_element(template, k)
+ template.add_child(doc.create_element(k, v))
+ }
+
+ capacity = doc.create_element("CAPACITY")
+ host_info["capacity"].each { |k, v|
+ capacity.add_child(doc.create_element(k.upcase, v))
+ }
+
+ delete_element(template, "CAPACITY")
+ template.add_child(capacity)
+
+ delete_element(template, "REGION_NAME")
+ template.add_child(doc.create_element "REGION_NAME", host_info["region_name"])
+ end
+
+ row[:body] = doc.root.to_s
+ @db[:host_pool].insert(row)
+ end
+ end
+ @db.run "DROP TABLE old_host_pool;"
+
+ STDERR.puts " > You can now delete #{az_driver_conf} file"
+ end
+
+ def bug_2189()
+ @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_doc(row[:body], 'old_image_pool')
+
+ 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
+
+ @db[:image_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ 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_doc(row[:body], 'old_vm_pool')
+
+ 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
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+ end
+end
diff --git a/src/onedb/local/5.5.80_to_5.6.0.rb b/src/onedb/local/5.5.80_to_5.6.0.rb
new file mode 100644
index 0000000000..1569b2163d
--- /dev/null
+++ b/src/onedb/local/5.5.80_to_5.6.0.rb
@@ -0,0 +1,41 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'base64'
+require 'zlib'
+require 'pathname'
+require 'yaml'
+require 'opennebula'
+
+$: << File.dirname(__FILE__)
+
+include OpenNebula
+
+module Migrator
+ def db_version
+ "5.6.0"
+ end
+
+ def one_version
+ "OpenNebula 5.6.0"
+ end
+
+ def up
+ return true
+ end
+end
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
new file mode 100644
index 0000000000..ea9bf08613
--- /dev/null
+++ b/src/onedb/local/5.6.0_to_5.7.80.rb
@@ -0,0 +1,483 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'base64'
+require 'zlib'
+require 'pathname'
+require 'yaml'
+require 'opennebula'
+require 'vcenter_driver'
+
+$LOAD_PATH << File.dirname(__FILE__)
+
+include OpenNebula
+
+module Migrator
+
+ def db_version
+ '5.7.80'
+ end
+
+ def one_version
+ 'OpenNebula 5.7.80'
+ end
+
+ def up
+ feature_2944
+ GC.start
+ bug_2687 # MUST be run before 2489, which generates short body
+ GC.start
+ feature_2253
+ GC.start
+ feature_2489_2671
+ GC.start
+ feature_826
+ GC.start
+ feature_2966
+ true
+ end
+
+ private
+
+ def feature_2944
+ vclient =->(hid){
+ row = @db.fetch("SELECT * FROM host_pool WHERE oid = #{hid}").first
+ raise "Host #{hid} not found in the OpenNebula DB" if !row[:body]
+ xml = row[:body]
+
+ doc = nokogiri_doc(xml, 'host_pool').root.at_xpath('/HOST/TEMPLATE')
+
+ rp = doc.xpath("VCENTER_RESOURCE_POOL").first
+ rp = rp.text if rp
+
+ token = File.read(VAR_LOCATION+'/.one/one_key')
+ password = doc.xpath("VCENTER_PASSWORD").first.text
+ password = VCenterDriver::VIClient::decrypt(password, token)
+
+ connection = {
+ :host => doc.xpath("VCENTER_HOST").first.text,
+ :user => doc.xpath("VCENTER_USER").first.text,
+ :rp => rp,
+ :ccr => doc.xpath("VCENTER_CCR_REF").first.text,
+ :password => password
+ }
+
+ VCenterDriver::VIClient.new(connection)
+ }
+
+ @db.fetch('SELECT * FROM vm_pool') do |row|
+ begin
+ doc = nokogiri_doc(row[:body], 'vm_pool')
+
+ one_vm = OpenNebula::XMLElement.new(doc.root.at_xpath('/VM'))
+
+ next unless one_vm["USER_TEMPLATE/HYPERVISOR"] == 'vcenter'
+
+ vmid = one_vm['ID']
+ hid = one_vm['HISTORY_RECORDS/HISTORY/HID[last()]']
+ vmref = one_vm['DEPLOY_ID']
+
+ next if !vmref || one_vm['STATE'] == '6'
+
+ vi_client = vclient.call(hid)
+
+ puts
+ puts "one Machine #{vmid} vCenter ref: #{vmref}"
+ vm = VCenterDriver::VirtualMachine.new(vi_client, vmref, vmid).tap do |i|
+ i.one_item = one_vm
+ end
+
+ extraconfig = []
+ vm.disks_each(:managed?) do |disk|
+ begin
+ k = "opennebula.mdisk.#{disk.id}"
+ v = "#{disk.key}"
+ rescue StandardError => e
+ puts " disk:#{disk.id}"
+ puts " #{e.message} (No action needed)"
+ next
+ end
+
+ extraconfig << {key: k, value: v}
+ puts " write #{k} : #{v}"
+ end
+
+ spec = RbVmomi::VIM.VirtualMachineConfigSpec(
+ { :extraConfig => extraconfig }
+ )
+ vm.item.ReconfigVM_Task(:spec => spec).wait_for_completion
+ rescue StandardError => e
+ if e.message.include? 'reference does not exist'
+ STDERR.puts " This machine does not exist in vCenter"
+ else
+ STDERR.puts "Couldn't process VM #{vmid}." if vmid
+ STDERR.puts e.message
+ end
+ end
+ end
+ end
+
+ def feature_2253
+ @db.run 'DROP TABLE IF EXISTS old_network_pool;'
+ @db.run 'ALTER TABLE network_pool RENAME TO old_network_pool;'
+ create_table(:network_pool)
+
+ @db.transaction do
+ # update virtual networks
+ @db.fetch('SELECT * FROM old_network_pool') do |row|
+ doc = nokogiri_doc(row[:body], 'old_network_pool')
+
+ if doc.root.at_xpath('BRIDGE_TYPE').to_s.empty?
+ vn_mad = doc.root.at_xpath('/VNET/VN_MAD').text
+
+ bridge_type = doc.create_element('BRIDGE_TYPE')
+ bridge_type.add_child(bridge_type_by_vn_mad(vn_mad))
+ doc.root.at_xpath('/VNET').add_child(bridge_type)
+ row[:body] = doc.root.to_s
+ end
+
+ @db[:network_pool].insert(row)
+ end
+ end
+
+ @db.run 'DROP TABLE old_network_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
+ # updates VM's nics
+ @db.fetch('SELECT * FROM old_vm_pool') do |row|
+ doc = nokogiri_doc(row[:body], 'old_vm_pool')
+
+ if !doc.root.at_xpath('TEMPLATE/NIC').to_s.empty?
+ doc.root.xpath('//NIC').map do |nic|
+ next unless nic.xpath('BRIDGE_TYPE').to_s.empty?
+
+ vn_mad = nic.xpath('VN_MAD').text
+
+ bridge_type = doc.create_element('BRIDGE_TYPE')
+ bridge_type.add_child(bridge_type_by_vn_mad(vn_mad))
+ nic.add_child(bridge_type)
+ end
+
+ row[:body] = doc.root.to_s
+ end
+
+ @db[:vm_pool].insert(row)
+ end
+ end
+
+ @db.run 'DROP TABLE old_vm_pool;'
+ end
+
+ def feature_2489_2671
+ @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_doc(row[:body], 'old_vm_pool')
+
+ row[:short_body] = gen_short_body(doc)
+ row[:search_token] = gen_search_body(doc)
+
+ @db[:vm_pool].insert(row)
+ end
+ end
+
+ @db.run 'DROP TABLE old_vm_pool;'
+ end
+
+ def bridge_type_by_vn_mad(vn_mad)
+ case vn_mad
+ when 'vcenter'
+ return 'vcenter_port_groups'
+ when 'ovswitch', 'ovswitch_vxlan'
+ return 'openvswitch'
+ else
+ return 'linux'
+ end
+ end
+
+ def gen_search_body(body)
+
+ search_body = "UNAME=" + escape_token(body.root.xpath('UNAME').text) + "\n" +
+ "GNAME=" + escape_token(body.root.xpath('GNAME').text) + "\n" +
+ "NAME=" + escape_token(body.root.xpath('NAME').text) + "\n" +
+ "LAST_POLL=" + escape_token(body.root.xpath('LAST_POLL').text) + "\n" +
+ "PREV_STATE=" + escape_token(body.root.xpath('PREV_STATE').text) + "\n" +
+ "PREV_LCM_STATE=" + escape_token(body.root.xpath('PREV_LCM_STATE').text) + "\n" +
+ "RESCHED=" + escape_token(body.root.xpath('RESCHED').text) + "\n" +
+ "STIME=" + escape_token(body.root.xpath('STIME').text) + "\n" +
+ "ETIME=" + escape_token(body.root.xpath('ETIME').text) + "\n" +
+ "DEPLOY_ID=" + escape_token(body.root.xpath('DEPLOY_ID').text) + "\n"
+
+ body.root.xpath("//TEMPLATE/*").each do |node|
+ search_body += to_token(node)
+ end
+
+ node = Nokogiri::XML(body.root.xpath("//HISTORY_RECORDS/HISTORY[last()]").to_s)
+
+ if !node.root.nil?
+ search_body += history_to_token(node)
+ end
+
+ return search_body
+ end
+
+ def to_token(node)
+ search_body = ""
+ if node.children.size > 1
+ node.children.each do |child|
+ search_body += to_token(child)
+ end
+ elsif
+ search_body += node.name + "=" + escape_token(node.children.text) + "\n"
+ end
+
+ return search_body
+ end
+
+ def history_to_token(hr)
+ hr_token = "HOSTNAME=" + escape_token(hr.xpath("//HOSTNAME").text) + "\n" +
+ "HID=" + hr.xpath("//HID").text + "\n" +
+ "CID=" + hr.xpath("//CID").text + "\n" +
+ "DS_ID=" + hr.xpath("//DS_ID").text + "\n"
+ end
+
+ def escape_token(str)
+ str_scaped = ""
+
+ str.split("").each do |c|
+ case c
+ when '-', '_', '.', ':'
+ str_scaped += '_'
+ else
+ str_scaped += c
+ end
+ end
+
+ return str_scaped
+ end
+
+ def gen_short_body(body)
+ short_body = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
+ xml.VM{
+ xml.ID body.root.xpath('ID').text
+ xml.UID body.root.xpath('UID').text
+ xml.GID body.root.xpath('GID').text
+ xml.UNAME body.root.xpath('UNAME').text
+ xml.GNAME body.root.xpath('GNAME').text
+ xml.NAME body.root.xpath('NAME').text
+ xml.LAST_POLL body.root.xpath('LAST_POLL').text
+ xml.STATE body.root.xpath('STATE').text
+ xml.LCM_STATE body.root.xpath('LCM_STATE').text
+ xml.RESCHED body.root.xpath('RESCHED').text
+ xml.STIME body.root.xpath('STIME').text
+ xml.ETIME body.root.xpath('ETIME').text
+ xml.DEPLOY_ID body.root.xpath('DEPLOY_ID').text
+
+ xml.LOCK {
+ xml.LOCKED body.root.xpath('LOCK/LOCKED').text unless body.root.xpath('LOCK/LOCKED').text.empty?
+ } unless body.root.xpath('LOCK').text.empty?
+
+ xml.TEMPLATE {
+ xml.AUTOMATIC_REQUIREMENTS body.root.xpath('TEMPLATE/AUTOMATIC_REQUIREMENTS').text
+ xml.AUTOMATIC_DS_REQUIREMENTS body.root.xpath('TEMPLATE/AUTOMATIC_DS_REQUIREMENTS').text unless body.root.xpath('TEMPLATE/AUTOMATIC_DS_REQUIREMENTS').text.empty?
+ xml.CPU body.root.xpath('TEMPLATE/CPU').text
+
+ body.root.xpath('TEMPLATE//DISK').each do |disk|
+ xml.DISK {
+ xml.DATASTORE disk.xpath('DATASTORE').text unless disk.xpath('DATASTORE').text.empty?
+ xml.DATASTORE_ID disk.xpath('DATASTORE_ID').text unless disk.xpath('DATASTORE_ID').text.empty?
+ xml.DISK_ID disk.xpath('DISK_ID').text unless disk.xpath('DISK_ID').text.empty?
+ xml.IMAGE disk.xpath('IMAGE').text unless disk.xpath('IMAGE').text.empty?
+ xml.IMAGE_ID disk.xpath('IMAGE_ID').text unless disk.xpath('IMAGE_ID').text.empty?
+ xml.SIZE disk.xpath('SIZE').text unless disk.xpath('SIZE').text.empty?
+ xml.TARGET disk.xpath('TARGET').text unless disk.xpath('TARGET').text.empty?
+ xml.TYPE disk.xpath('TYPE').text unless disk.xpath('TYPE').text.empty?
+ xml.CLONE disk.xpath('CLONE').text unless disk.xpath('CLONE').text.empty?
+ xml.CLONE_TARGET disk.xpath('CLONE_TARGET').text unless disk.xpath('CLONE_TARGET').text.empty?
+ xml.LN_TARGET disk.xpath('LN_TARGET').text unless disk.xpath('LN_TARGET').text.empty?
+ xml.DISK_SNAPSHOT_TOTAL_SIZE disk.xpath('DISK_SNAPSHOT_TOTAL_SIZE').text unless disk.xpath('DISK_SNAPSHOT_TOTAL_SIZE').text.empty?
+ }
+ end
+
+ xml.GRAPHICS {
+ xml.LISTEN body.root.xpath('TEMPLATE/GRAPHICS/LISTEN').text unless body.root.xpath('TEMPLATE/GRAPHICS/LISTEN').text.empty?
+ xml.PASSWD body.root.xpath('TEMPLATE/GRAPHICS/PASSWD').text unless body.root.xpath('TTEMPLATE/GRAPHICS/PASSWD').text.empty?
+ xml.PORT body.root.xpath('TEMPLATE/GRAPHICS/PORT').text unless body.root.xpath('TEMPLATE/GRAPHICS/PORT').text.empty?
+ xml.RANDOM_PASSWD body.root.xpath('TEMPLATE/GRAPHICS/RANDOM_PASSWD').text unless body.root.xpath('TEMPLATE/GRAPHICS/RANDOM_PASSWD').text.empty?
+ xml.TYPE body.root.xpath('TEMPLATE/GRAPHICS/TYPE').text unless body.root.xpath('TEMPLATE/GRAPHICS/TYPE').text.empty?
+ } unless body.root.xpath('TEMPLATE/GRAPHICS').text.empty?
+
+ xml.MEMORY body.root.xpath('TEMPLATE/MEMORY').text unless body.root.xpath('TEMPLATE/MEMORY').text.empty?
+
+ body.root.xpath("TEMPLATE//NIC").each do |nic|
+ xml.NIC {
+ xml.IP nic.xpath('IP').text unless nic.xpath('IP').text.empty?
+ xml.IP6 nic.xpath('IP6').text unless nic.xpath('IP6').text.empty?
+ xml.IP6_ULA nic.xpath('IP6_ULA').text unless nic.xpath('IP6_ULA').text.empty?
+ xml.IP6_LINK nic.xpath('IP6_LINK').text unless nic.xpath('IP6_LINK').text.empty?
+ xml.IP6_GLOBAL nic.xpath('IP6_GLOBAL').text unless nic.xpath('IP6_GLOBAL').text.empty?
+ xml.MAC nic.xpath('MAC').text unless nic.xpath('MAC').text.empty?
+ xml.NETWORK nic.xpath('NETWORK').text unless nic.xpath('NETWORK').text.empty?
+ xml.NETWORK_ID nic.xpath('NETWORK_ID').text unless nic.xpath('NETWORK_ID').text.empty?
+ xml.NIC_ID nic.xpath('NIC_ID').text unless nic.xpath('NIC_ID').text.empty?
+ xml.SECURITY_GROUPS nic.xpath('SECURITY_GROUPS').text unless nic.xpath('SECURITY_GROUPS').text.empty?
+ }
+ end
+ }
+
+ xml.MONITORING {
+ xml.CPU body.root.xpath('MONITORING/CPU').text unless body.root.xpath('MONITORING/CPU').text.empty?
+ xml.MEMORY body.root.xpath('MONITORING/MEMORY').text unless body.root.xpath('MONITORING/MEMORY').text.empty?
+ xml.STATE body.root.xpath('MONITORING/STATE').text unless body.root.xpath('MONITORING/STATE').text.empty?
+ }
+
+ xml.USER_TEMPLATE {
+ xml.LABELS body.root.xpath('USER_TEMPLATE/LABELS').text unless body.root.xpath('USER_TEMPLATE/LABELS').text.empty?
+ xml.SCHED_RANK body.root.xpath('USER_TEMPLATE/SCHED_RANK').text unless body.root.xpath('USER_TEMPLATE/SCHED_RANK').text.empty?
+ xml.RANK body.root.xpath('USER_TEMPLATE/RANK').text unless body.root.xpath('USER_TEMPLATE/RANK').text.empty?
+ xml.SCHED_DS_RANK body.root.xpath('USER_TEMPLATE/SCHED_DS_RANK').text unless body.root.xpath('USER_TEMPLATE/SCHED_DS_RANK').text.empty?
+ xml.PUBLIC_CLOUD body.root.xpath('USER_TEMPLATE/PUBLIC_CLOUD').text unless body.root.xpath('USER_TEMPLATE/PUBLIC_CLOUD').text.empty?
+ xml.EC2 body.root.xpath('USER_TEMPLATE/EC2').text unless body.root.xpath('USER_TEMPLATE/EC2').text.empty?
+ xml.SCHED_REQUIREMENTS body.root.xpath('USER_TEMPLATE/SCHED_REQUIREMENTS').text unless body.root.xpath('USER_TEMPLATE/SCHED_REQUIREMENTS').text.empty?
+ xml.SCHED_DS_REQUIREMENTS body.root.xpath('USER_TEMPLATE/SCHED_DS_REQUIREMENTS').text unless body.root.xpath('USER_TEMPLATE/SCHED_DS_REQUIREMENTS').text.empty?
+ xml.SCHED_MESSAGE body.root.xpath('USER_TEMPLATE/SCHED_MESSAGE').text unless body.root.xpath('USER_TEMPLATE/SCHED_MESSAGE').text.empty?
+ xml.USER_PRIORITY body.root.xpath('USER_TEMPLATE/USER_PRIORITY').text unless body.root.xpath('USER_TEMPLATE/USER_PRIORITY').text.empty?
+ }
+
+ xml.HISTORY_RECORDS {
+ body.root.xpath('HISTORY_RECORDS//HISTORY').last do |hr|
+ xml.HISTORY {
+ xml.OID hr.xpath('OID').text
+ xml.SEQ hr.xpath('SEQ').text
+ xml.HOSTNAME hr.xpath('HOSTNAME').text
+ xml.HID hr.xpath('HID').text
+ xml.CID hr.xpath('CID').text
+ xml.DS_ID hr.xpath('DS_ID').text
+ xml.ACTION hr.xpath('ACTION').text
+ }
+ end
+ }
+ }
+ end
+
+ Nokogiri::XML(short_body.to_xml).root.to_s
+ end
+
+ def feature_826
+ 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_doc(row[:body], 'old_image_pool')
+
+ 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_doc(row[:body], 'old_vm_pool')
+
+ # 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
+
+ def feature_2966
+ @db.run "ALTER TABLE logdb ADD applied BOOLEAN DEFAULT 1;"
+ @db.run "UPDATE logdb SET applied = 0 WHERE timestamp = 0;"
+
+ if @db.adapter_scheme == :sqlite
+ @db.run "DROP INDEX IF EXISTS timestamp_idx"
+ else
+ begin
+ @db.run "ALTER TABLE logdb DROP INDEX timestamp_idx;"
+ rescue Sequel::DatabaseError
+ end
+ @db.run "ALTER TABLE logdb ALTER COLUMN applied DROP DEFAULT"
+ end
+ end
+end
diff --git a/src/onedb/local/5.7.80_to_5.8.0.rb b/src/onedb/local/5.7.80_to_5.8.0.rb
new file mode 100644
index 0000000000..b65bd5b8ce
--- /dev/null
+++ b/src/onedb/local/5.7.80_to_5.8.0.rb
@@ -0,0 +1,44 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'base64'
+require 'zlib'
+require 'pathname'
+require 'yaml'
+require 'opennebula'
+
+$LOAD_PATH << File.dirname(__FILE__)
+
+# OpenNebula DB migrator to 5.8
+module Migrator
+
+ include OpenNebula
+
+ def db_version
+ '5.8.0'
+ end
+
+ def one_version
+ 'OpenNebula 5.8.0'
+ end
+
+ def up
+ true
+ end
+
+end
diff --git a/src/onedb/local/5.8.0_to_5.10.0.rb b/src/onedb/local/5.8.0_to_5.10.0.rb
new file mode 100644
index 0000000000..281a4af1bd
--- /dev/null
+++ b/src/onedb/local/5.8.0_to_5.10.0.rb
@@ -0,0 +1,106 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'base64'
+require 'zlib'
+require 'pathname'
+require 'yaml'
+require 'opennebula'
+require 'vcenter_driver'
+
+$LOAD_PATH << File.dirname(__FILE__)
+
+include OpenNebula
+
+module Migrator
+
+ def db_version
+ '5.10.0'
+ end
+
+ def one_version
+ 'OpenNebula 5.9.80'
+ end
+
+ def up
+ feature_2722
+ feature_3380
+ true
+ end
+
+ private
+
+ def feature_2722
+ @db.run 'DROP TABLE IF EXISTS old_logdb;'
+ @db.run 'ALTER TABLE logdb RENAME TO old_logdb;'
+
+ create_table(:logdb)
+
+ @db.run 'INSERT INTO system_attributes (name, body)' <<
+ 'SELECT \'RAFT_STATE\', sqlcmd FROM old_logdb WHERE log_index = -1;'
+
+ @db.run 'DELETE FROM old_logdb WHERE log_index = -1;'
+
+ db.transaction do
+ # update virtual networks
+ @db.fetch('SELECT * FROM old_logdb') do |row|
+ row[:fed_index] = 18446744073709551615 if row[:fed_index] < 0
+
+ @db[:logdb].insert(row)
+ end
+ end
+
+ @db.run 'DROP TABLE IF EXISTS old_logdb;'
+ end
+
+ def feature_3380
+ @db.run 'DROP TABLE IF EXISTS old_host_pool;'
+ @db.run 'ALTER TABLE host_pool RENAME TO old_host_pool;'
+
+ create_table(:host_pool)
+
+ db.transaction do
+ # Add PREV_STATE to each host
+ @db.fetch('SELECT * FROM old_host_pool') do |row|
+ doc = nokogiri_doc(row[:body], 'old_host_pool')
+
+ state = doc.xpath('//STATE').text
+
+ prev_state = doc.create_element('PREV_STATE', state)
+ doc.root.at_xpath('//HOST').add_child(prev_state)
+
+ row[:body] = doc.root.to_s
+
+ @db[:host_pool].insert(row)
+ end
+ end
+
+ @db.run 'DROP TABLE IF EXISTS old_host_pool;'
+
+ @db.run 'CREATE TABLE IF NOT EXISTS hook_pool '\
+ '(oid INTEGER PRIMARY KEY,name VARCHAR(128), '\
+ 'body MEDIUMTEXT, uid INTEGER, gid INTEGER, '\
+ 'owner_u INTEGER, group_u INTEGER, other_u INTEGER, '\
+ 'type INTEGER);'
+
+ @db.run 'CREATE TABLE IF NOT EXISTS hook_log'\
+ '(hkid INTEGER, exeid INTEGER, timestamp INTEGER, rc INTEGER,'\
+ ' body MEDIUMTEXT,PRIMARY KEY(hkid, exeid))'
+ end
+
+end
diff --git a/src/onedb/shared/2.0_to_2.9.80.rb b/src/onedb/shared/2.0_to_2.9.80.rb
new file mode 100644
index 0000000000..e4f4ffc9ec
--- /dev/null
+++ b/src/onedb/shared/2.0_to_2.9.80.rb
@@ -0,0 +1,339 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 "rexml/document"
+
+module Migrator
+ def db_version
+ "2.9.80"
+ end
+
+ def one_version
+ "OpenNebula 2.9.80"
+ end
+
+ def up
+ ########################################################################
+ # Users
+ ########################################################################
+
+ # 2.2 Schema
+ # CREATE TABLE user_pool (oid INTEGER PRIMARY KEY, user_name VARCHAR(256), password TEXT,enabled INTEGER, UNIQUE(user_name));
+
+ # Move table user_pool
+ @db.run "ALTER TABLE user_pool RENAME TO old_user_pool;"
+
+ # Create new user_pool
+ @db.run "CREATE TABLE user_pool (oid INTEGER PRIMARY KEY, name VARCHAR(256), body TEXT, UNIQUE(name));"
+
+ user_group_ids = ""
+
+ # Read each entry in the old user_pool, and insert into new user_pool
+ @db.fetch("SELECT * FROM old_user_pool") do |row|
+ oid = row[:oid]
+
+ if( oid == 0 )
+ gid = 0
+ groupname = "oneadmin"
+ else
+ gid = 1
+ groupname = "users"
+ user_group_ids += "#{oid}"
+ end
+
+ name = row[:user_name]
+
+ body = "#{oid}#{gid}#{groupname}#{name}#{row[:password]}#{row[:enabled]}"
+
+ @db[:user_pool].insert(
+ :oid => oid,
+ :name => name,
+ :body => body)
+ end
+
+ # Delete old user_pool
+ @db.run "DROP TABLE old_user_pool"
+
+ ########################################################################
+ # Hosts
+ ########################################################################
+
+ # 2.2 Schema
+ # CREATE TABLE host_pool (oid INTEGER PRIMARY KEY,host_name VARCHAR(256), state INTEGER,im_mad VARCHAR(128),vm_mad VARCHAR(128),tm_mad VARCHAR(128),last_mon_time INTEGER, cluster VARCHAR(128), template TEXT, UNIQUE(host_name));
+ # CREATE TABLE host_shares(hid INTEGER PRIMARY KEY,disk_usage INTEGER, mem_usage INTEGER, cpu_usage INTEGER,max_disk INTEGER, max_mem INTEGER, max_cpu INTEGER,free_disk INTEGER, free_mem INTEGER, free_cpu INTEGER,used_disk INTEGER, used_mem INTEGER, used_cpu INTEGER,running_vms INTEGER);
+
+ # Move table
+ @db.run "ALTER TABLE host_pool RENAME TO old_host_pool;"
+
+ # Create new table
+ @db.run "CREATE TABLE host_pool (oid INTEGER PRIMARY KEY, name VARCHAR(256), body TEXT, state INTEGER, last_mon_time INTEGER, UNIQUE(name));"
+
+ # Read each entry in the old table, and insert into new table
+ @db.fetch("SELECT * FROM old_host_pool") do |row|
+ oid = row[:oid]
+ name = row[:host_name]
+ state = row[:state]
+ last_mon_time = row[:last_mon_time]
+
+ # There is one host share for each host
+ host_share = ""
+ @db.fetch("SELECT * FROM host_shares WHERE hid=#{oid}") do |share|
+ host_share = "#{share[:disk_usage]}#{share[:mem_usage]}#{share[:cpu_usage]}#{share[:max_disk]}#{share[:max_mem]}#{share[:max_cpu]}#{share[:free_disk]}#{share[:free_mem]}#{share[:free_cpu]}#{share[:used_disk]}#{share[:used_mem]}#{share[:used_cpu]}#{share[:running_vms]}"
+ end
+
+ # OpenNebula 2.X stored the cluster name, in 3.0 the cluster pool
+ # disappears. The cluster name is added to the Host template, this
+ # way the old VMs with REQUIREMENTS will keep working
+
+ template_doc = REXML::Document.new( row[:template] )
+ cluster_elem = template_doc.root.add_element("CLUSTER")
+ cluster_elem.text = REXML::CData.new( row[:cluster] )
+
+ body = "#{oid}#{name}#{state}#{row[:im_mad]}#{row[:vm_mad]}#{row[:tm_mad]}#{last_mon_time}#{host_share}#{ template_doc.to_s }"
+
+ @db[:host_pool].insert(
+ :oid => oid,
+ :name => name,
+ :body => body,
+ :state => state,
+ :last_mon_time => last_mon_time)
+ end
+
+ # Delete old table
+ @db.run "DROP TABLE old_host_pool"
+ @db.run "DROP TABLE host_shares"
+
+ ########################################################################
+ # Clusters
+ ########################################################################
+
+ # Clusters do not exist any more
+ @db.run "DROP TABLE cluster_pool"
+
+ ########################################################################
+ # Images
+ ########################################################################
+
+ # 2.2 Schema
+ # CREATE TABLE image_pool (oid INTEGER PRIMARY KEY, uid INTEGER, name VARCHAR(128), type INTEGER, public INTEGER, persistent INTEGER, regtime INTEGER, source TEXT, state INTEGER, running_vms INTEGER, template TEXT, UNIQUE(name) );
+
+ # Move table
+ @db.run "ALTER TABLE image_pool RENAME TO old_image_pool;"
+
+ # Create new table
+ @db.run "CREATE TABLE image_pool (oid INTEGER PRIMARY KEY, name VARCHAR(256), body TEXT, uid INTEGER, gid INTEGER, public INTEGER, UNIQUE(name,uid) );"
+
+ # Read each entry in the old table, and insert into new table
+ @db.fetch("SELECT * FROM old_image_pool") do |row|
+ oid = row[:oid]
+ name = row[:name]
+ uid = row[:uid]
+ gid = (uid == 0) ? 0 : 1
+ group = (uid == 0) ? "oneadmin" : "users"
+ public = row[:public]
+
+ # In OpenNebula 2.0 Image States go from 0 to 3, in 3.0 go
+ # from 0 to 5, but the meaning is the same for states 0 to 3
+ body = "#{oid}#{row[:uid]}#{gid}#{get_username(row[:uid])}#{group}#{name}#{row[:type]}#{public}#{row[:persistent]}#{row[:regtime]}#{row[:source]}#{row[:state]}#{row[:running_vms]}#{row[:template]}"
+
+ @db[:image_pool].insert(
+ :oid => oid,
+ :name => name,
+ :body => body,
+ :uid => uid,
+ :gid => gid,
+ :public => public)
+ end
+
+ # Delete old table
+ @db.run "DROP TABLE old_image_pool"
+
+ ########################################################################
+ # VMs
+ ########################################################################
+
+ # 2.2 Schema
+ # CREATE TABLE vm_pool (oid INTEGER PRIMARY KEY,uid INTEGER,name TEXT,last_poll INTEGER, state INTEGER,lcm_state INTEGER,stime INTEGER,etime INTEGER,deploy_id TEXT,memory INTEGER,cpu INTEGER,net_tx INTEGER,net_rx INTEGER, last_seq INTEGER, template TEXT);
+ # CREATE TABLE history (vid INTEGER,seq INTEGER,host_name TEXT,vm_dir TEXT,hid INTEGER,vm_mad TEXT,tm_mad TEXT,stime INTEGER,etime INTEGER,pstime INTEGER,petime INTEGER,rstime INTEGER,retime INTEGER,estime INTEGER,eetime INTEGER,reason INTEGER,PRIMARY KEY(vid,seq));
+
+ # Move tables
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "ALTER TABLE history RENAME TO old_history;"
+
+ # Create new tables
+ @db.run "CREATE TABLE vm_pool (oid INTEGER PRIMARY KEY, name TEXT, body TEXT, uid INTEGER, gid INTEGER, last_poll INTEGER, state INTEGER, lcm_state INTEGER);"
+ @db.run "CREATE TABLE history (vid INTEGER, seq INTEGER, body TEXT, PRIMARY KEY(vid,seq));"
+
+
+ # Read each entry in the old history table, and insert into new table
+ @db.fetch("SELECT * FROM old_history") do |row|
+ vid = row[:vid]
+ seq = row[:seq]
+
+ body = "#{seq}#{row[:host_name]}#{row[:vm_dir]}#{row[:hid]}#{row[:stime]}#{row[:etime]}#{row[:vm_mad]}#{row[:tm_mad]}#{row[:pstime]}#{row[:petime]}#{row[:rstime]}#{row[:retime]}#{row[:estime]}#{row[:eetime]}#{row[:reason]}"
+
+ @db[:history].insert(
+ :vid => vid,
+ :seq => seq,
+ :body => body)
+ end
+
+
+ # Read each entry in the old vm table, and insert into new table
+ @db.fetch("SELECT * FROM old_vm_pool") do |row|
+ oid = row[:oid]
+ name = row[:name]
+ uid = row[:uid]
+ gid = (uid == 0) ? 0 : 1
+ group = (uid == 0) ? "oneadmin" : "users"
+ last_poll = row[:last_poll]
+ state = row[:state]
+ lcm_state = row[:lcm_state]
+
+ # If the VM has History items, the last one is included in the XML
+ history = ""
+ @db.fetch("SELECT body FROM history WHERE vid=#{oid} AND seq=(SELECT MAX(seq) FROM history WHERE vid=#{oid})") do |history_row|
+ history = history_row[:body]
+ end
+
+ if ( history != "" )
+ history = "#{history}"
+ end
+
+ body = "#{oid}#{uid}#{gid}#{get_username(uid)}#{group}#{name}#{last_poll}#{state}#{lcm_state}#{row[:stime]}#{row[:etime]}#{row[:deploy_id]}#{row[:memory]}#{row[:cpu]}#{row[:net_tx]}#{row[:net_rx]}#{row[:template]}#{history}"
+
+ @db[:vm_pool].insert(
+ :oid => oid,
+ :name => name,
+ :body => body,
+ :uid => uid,
+ :gid => gid,
+ :last_poll => last_poll,
+ :state => state,
+ :lcm_state => lcm_state)
+ end
+
+
+ # Delete old tables
+ @db.run "DROP TABLE old_vm_pool"
+ @db.run "DROP TABLE old_history"
+
+
+ ########################################################################
+ # Virtual Networks
+ ########################################################################
+
+ # 2.2 Schema
+ # CREATE TABLE network_pool (oid INTEGER PRIMARY KEY, uid INTEGER, name VARCHAR(256), type INTEGER, bridge TEXT, public INTEGER, template TEXT, UNIQUE(name));
+ # CREATE TABLE leases (oid INTEGER, ip BIGINT, mac_prefix BIGINT, mac_suffix BIGINT,vid INTEGER, used INTEGER, PRIMARY KEY(oid,ip));
+
+ # Move tables
+ @db.run "ALTER TABLE network_pool RENAME TO old_network_pool;"
+ @db.run "ALTER TABLE leases RENAME TO old_leases;"
+
+ # Create new tables
+ @db.run "CREATE TABLE network_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, public INTEGER, UNIQUE(name,uid));"
+ @db.run "CREATE TABLE leases (oid INTEGER, ip BIGINT, body TEXT, PRIMARY KEY(oid,ip));"
+
+ # Read each entry in the old table, and insert into new table
+ @db.fetch("SELECT * FROM old_network_pool") do |row|
+ oid = row[:oid]
+ name = row[:name]
+ uid = row[:uid]
+ gid = (uid == 0) ? 0 : 1
+ group = (uid == 0) ? "oneadmin" : "users"
+ public = row[:public]
+
+ total_leases = 0
+ @db.fetch("SELECT COUNT(ip) FROM old_leases WHERE (oid=#{oid} AND used=1)") do |r|
+ total_leases = r[:"COUNT(ip)"]
+ end
+
+
+ # is stored in the DB, but it is not used to rebuild
+ # the VirtualNetwork object, and it is generated each time the
+ # network is listed. So setting it to 0 is safe
+ body = "#{oid}#{uid}#{gid}#{get_username(uid)}#{group}#{name}#{row[:type]}#{row[:bridge]}#{public}#{total_leases}#{row[:template]}"
+
+ @db[:network_pool].insert(
+ :oid => oid,
+ :name => name,
+ :body => body,
+ :uid => uid,
+ :gid => gid,
+ :public => public)
+ end
+
+ # Read each entry in the old table, and insert into new table
+ @db.fetch("SELECT * FROM old_leases") do |row|
+ oid = row[:oid]
+ ip = row[:ip]
+
+ body = "#{ip}#{row[:mac_prefix]}#{row[:mac_suffix]}#{row[:used]}#{row[:vid]}"
+
+ @db[:leases].insert(
+ :oid => oid,
+ :ip => ip,
+ :body => body)
+ end
+
+ # Delete old tables
+ @db.run "DROP TABLE old_network_pool"
+ @db.run "DROP TABLE old_leases"
+
+
+ ########################################################################
+ # New tables in DB version 1
+ ########################################################################
+
+ @db.run "CREATE TABLE db_versioning (oid INTEGER PRIMARY KEY, version VARCHAR(256), timestamp INTEGER, comment VARCHAR(256));"
+ @db.run "CREATE TABLE template_pool (oid INTEGER PRIMARY KEY, name VARCHAR(256), body TEXT, uid INTEGER, gid INTEGER, public INTEGER);"
+ @db.run "CREATE TABLE acl (oid INT PRIMARY KEY, user BIGINT, resource BIGINT, rights BIGINT);"
+
+ # The group pool has two default ones
+ @db.run "CREATE TABLE group_pool (oid INTEGER PRIMARY KEY, name VARCHAR(256), body TEXT, UNIQUE(name));"
+ @db.run "INSERT INTO group_pool VALUES(0,'oneadmin','0oneadmin0');"
+ @db.run "INSERT INTO group_pool VALUES(1,'users','1users#{user_group_ids}');"
+
+ # New pool_control table contains the last_oid used, must be rebuilt
+ @db.run "CREATE TABLE pool_control (tablename VARCHAR(32) PRIMARY KEY, last_oid BIGINT UNSIGNED)"
+
+ for table in ["user_pool", "host_pool", "image_pool", "vm_pool", "network_pool"] do
+ @db.fetch("SELECT MAX(oid) FROM #{table}") do |row|
+ if( row[:"MAX(oid)"] != nil )
+ @db.run "INSERT INTO pool_control (tablename, last_oid) VALUES ('#{table}', #{row[:"MAX(oid)"]});"
+ end
+ end
+ end
+
+ # First 100 group Ids are reserved for system groups.
+ # Regular ones start from ID 100
+ @db.run "INSERT INTO pool_control (tablename, last_oid) VALUES ('group_pool', 99);"
+
+ return true
+ end
+
+ def get_username(uid)
+ username = ""
+
+ @db.fetch("SELECT name FROM user_pool WHERE oid=#{uid}") do |user|
+ username = user[:name]
+ end
+
+ return username
+ end
+end
diff --git a/src/onedb/shared/2.9.80_to_2.9.85.rb b/src/onedb/shared/2.9.80_to_2.9.85.rb
new file mode 100644
index 0000000000..517d142e9b
--- /dev/null
+++ b/src/onedb/shared/2.9.80_to_2.9.85.rb
@@ -0,0 +1,69 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 "rexml/document"
+include REXML
+
+module Migrator
+ def db_version
+ "2.9.85"
+ end
+
+ def one_version
+ "OpenNebula 2.9.85"
+ end
+
+ def up
+ # There are no DB schema changes from 2.9.80 to 2.9.85, but the Images
+ # now have a element
+
+ # Image pool table:
+ # CREATE TABLE image_pool (oid INTEGER PRIMARY KEY, name VARCHAR(256), body TEXT, uid INTEGER, gid INTEGER, public INTEGER, UNIQUE(name,uid) );
+
+ @db.run "ALTER TABLE image_pool RENAME TO old_image_pool;"
+ @db.run "CREATE TABLE image_pool (oid INTEGER PRIMARY KEY, name VARCHAR(256), body TEXT, uid INTEGER, gid INTEGER, public INTEGER, UNIQUE(name,uid) );"
+
+ @db.fetch("SELECT * FROM old_image_pool") do |row|
+ doc = Document.new(row[:body])
+
+ source = nil
+ doc.root.each_element("SOURCE") { |e|
+ source = e.text
+ }
+
+ du_output = `du -m #{source} 2>/dev/null`
+ size = du_output.split[0]
+
+ size = "0" if ( size == nil )
+
+ size_elem = doc.root.add_element("SIZE")
+ size_elem.text = size
+
+ @db[:image_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :public => row[:public])
+ end
+
+ @db.run "DROP TABLE old_image_pool;"
+
+ return true
+ end
+end
diff --git a/src/onedb/shared/2.9.85_to_2.9.90.rb b/src/onedb/shared/2.9.85_to_2.9.90.rb
new file mode 100644
index 0000000000..1921c17a3b
--- /dev/null
+++ b/src/onedb/shared/2.9.85_to_2.9.90.rb
@@ -0,0 +1,33 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 "rexml/document"
+include REXML
+
+module Migrator
+ def db_version
+ "2.9.90"
+ end
+
+ def one_version
+ "OpenNebula 2.9.90"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/2.9.90_to_3.0.0.rb b/src/onedb/shared/2.9.90_to_3.0.0.rb
new file mode 100644
index 0000000000..d55a2181d2
--- /dev/null
+++ b/src/onedb/shared/2.9.90_to_3.0.0.rb
@@ -0,0 +1,56 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 "rexml/document"
+include REXML
+
+module Migrator
+ def db_version
+ "3.0.0"
+ end
+
+ def one_version
+ "OpenNebula 3.0.0"
+ end
+
+ def up
+ # The tm_nfs driver has been renamed to tm_shared
+ # CREATE TABLE host_pool (oid INTEGER PRIMARY KEY, name VARCHAR(256), body TEXT, state INTEGER, last_mon_time INTEGER, UNIQUE(name));
+
+ @db.run "ALTER TABLE host_pool RENAME TO old_host_pool;"
+ @db.run "CREATE TABLE host_pool (oid INTEGER PRIMARY KEY, name VARCHAR(256), body TEXT, state INTEGER, last_mon_time INTEGER, UNIQUE(name));"
+ @db.run "INSERT INTO host_pool SELECT * FROM old_host_pool;"
+
+ @db.fetch("SELECT * FROM old_host_pool") do |row|
+ doc = Document.new(row[:body])
+
+ source = nil
+ doc.root.each_element("TM_MAD") { |e|
+ if e.text.downcase == "tm_nfs"
+ e.text = "tm_shared"
+
+ @db[:host_pool].filter(:oid => row[:oid]).update(
+ :body => doc.root.to_s)
+ end
+ }
+ end
+
+ @db.run "DROP TABLE old_host_pool;"
+
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.0.0_to_3.1.0.rb b/src/onedb/shared/3.0.0_to_3.1.0.rb
new file mode 100644
index 0000000000..0e18766e84
--- /dev/null
+++ b/src/onedb/shared/3.0.0_to_3.1.0.rb
@@ -0,0 +1,268 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'digest/sha1'
+require "rexml/document"
+include REXML
+
+module Migrator
+ def db_version
+ "3.1.0"
+ end
+
+ def one_version
+ "OpenNebula 3.1.0"
+ end
+
+ def up
+ ########################################################################
+ # Update table definitions
+ ########################################################################
+
+ puts " > Users need to have an authentication driver defined.\n"<<
+ " If you have AUTH_MAD uncommented in oned.conf, enter the driver name,\n"<<
+ " or press enter to use the default value.\n\n"
+ print " Driver name (x509, ssh, ldap): "
+ auth_driver = gets.chomp
+
+ [ [:group_pool, "group"],
+ [:host_pool, "host"],
+ [:image_pool, "image"],
+ [:network_pool, "network"],
+ [:template_pool,"template"],
+ [:user_pool, "user"],
+ [:vm_pool, "vm"]
+ ].each { |pair|
+ # Check that all objects have names shorter that 128
+ check_names(pair[0], pair[1])
+
+ # Change the name column to 128 chars. In SQLite, ALTER COLUMN is
+ # not supported, but since the char limit is ignored,
+ # VARCHAR(128) and VARCHAR(256) are the same type
+ if ( self.class == BackEndMySQL )
+ @db.run "ALTER TABLE #{pair[0]} CHANGE name name VARCHAR(128);"
+ end
+ }
+
+ ########################################################################
+ # Add new attributes to images
+ ########################################################################
+
+ @db.run "ALTER TABLE image_pool RENAME TO old_image_pool;"
+ @db.run "CREATE TABLE image_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, public INTEGER, UNIQUE(name,uid) );"
+
+ @db.fetch("SELECT * FROM old_image_pool") do |row|
+ doc = Document.new(row[:body])
+
+ fstype = ""
+ doc.root.each_element("TEMPLATE/FSTYPE") { |e|
+ fstype = e.text
+ }
+
+ fstype_elem = doc.root.add_element("FSTYPE")
+ fstype_elem.text = fstype
+
+ path = ""
+ doc.root.each_element("TEMPLATE/PATH") { |e|
+ path = e.text
+ }
+
+ path_elem = doc.root.add_element("PATH")
+ path_elem.text = path
+
+ @db[:image_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :public => row[:public])
+ end
+
+ @db.run "DROP TABLE old_image_pool;"
+
+ ########################################################################
+ # Add new attributes to users
+ ########################################################################
+
+ @db.run "ALTER TABLE user_pool RENAME TO old_user_pool;"
+ @db.run "CREATE TABLE user_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, UNIQUE(name));"
+
+ @db.fetch("SELECT * FROM old_user_pool") do |row|
+ doc = Document.new(row[:body])
+
+ # TODO: Try to guess if the password contains a DN and set the
+ # driver to 'x509', or assume ssh if the password is not hex
+ auth_elem = doc.root.add_element("AUTH_DRIVER")
+
+ pass = ""
+ doc.root.each_element("PASSWORD") { |e|
+ pass = e.text
+ }
+
+ if ( auth_driver.empty? || pass =~ /^(\d|[a-fA-F]){40}$/ )
+ auth_elem.text = "core"
+ else
+ auth_elem.text = auth_driver
+ end
+
+ doc.root.add_element("TEMPLATE")
+
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s)
+ end
+
+ @db.run "DROP TABLE old_user_pool;"
+
+ ########################################################################
+ # Create new serveradmin user
+ ########################################################################
+
+ username = "serveradmin"
+ found = false
+ oneadmin_row = nil
+ user_oid = nil
+
+ @db.fetch("SELECT * FROM user_pool WHERE name='#{username}'") do |row|
+ found = true
+ end
+
+ if ( found )
+ puts " > Trying to create user '#{username}' "<<
+ "for Sunstone and public servers operation;\n"<<
+ " but a user with that name already exists. "<<
+ "You will need to create manually a new user, visit\n"<<
+ " http://opennebula.org/documentation:rel3.2:upgrade"
+ else
+ @db.fetch("SELECT * FROM user_pool WHERE oid=0") do |row|
+ oneadmin_row = row
+ end
+
+ @db.fetch("SELECT last_oid FROM pool_control WHERE tablename='user_pool'") do |row|
+ user_oid = (row[:last_oid].to_i + 1)
+ end
+
+ doc = Document.new(oneadmin_row[:body])
+
+ doc.root.each_element("ID") { |e|
+ e.text = (user_oid).to_s
+ }
+
+ doc.root.each_element("GID") { |e|
+ e.text = "0"
+ }
+
+ doc.root.each_element("NAME") { |e|
+ e.text = username
+ }
+
+ doc.root.each_element("AUTH_DRIVER") { |e|
+ e.text = "server_cipher"
+ }
+
+ pass = Digest::SHA1.hexdigest( rand(10000).to_s )
+
+ doc.root.each_element("PASSWORD") { |e|
+ e.text = Digest::SHA1.hexdigest( pass )
+ }
+
+ # Insert new user
+ @db[:user_pool].insert(
+ :oid => user_oid,
+ :name => username,
+ :body => doc.root.to_s)
+
+ # Update last oid in pool_control
+ @db.run("UPDATE pool_control SET last_oid=#{user_oid} WHERE tablename='user_pool';")
+
+ # Insert new user ID in oneadmin group
+
+ @db.fetch("SELECT body FROM group_pool WHERE oid=0") do |row|
+ doc = Document.new(row[:body])
+ end
+
+ doc.root.each_element("USERS"){ |e|
+ new_elem = e.add_element("ID")
+ new_elem.text = user_oid
+ }
+
+ @db.run("UPDATE group_pool SET body='#{doc.root.to_s}' WHERE oid=0;")
+
+ # Create new config files
+
+ new_auth = "#{username}:#{pass}\n"
+
+ begin
+ dir = "#{VAR_LOCATION}/.one"
+ if ( !File.directory?(dir) )
+ Dir.mkdir(dir, 0700)
+ end
+
+ ["sunstone_auth", "occi_auth", "ec2_auth"].each { |name|
+ File.open("#{dir}/#{name}", 'w', 0600) {|f|
+ f.write(new_auth)
+ }
+ }
+ rescue
+ puts "Error trying to create new configuration files in #{dir}"
+ return false
+ end
+
+ puts " > New user '#{username}' created "<<
+ "for Sunstone and public servers operation.\n"<<
+ " You have three new authentication files in #{dir}.\n"<<
+ " For more information, visit\n"<<
+ " http://opennebula.org/documentation:rel3.2:upgrade"
+ end
+
+ return true
+ end
+
+ def check_names(table, elem)
+ @db.run "CREATE TABLE migrator_tmp (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT);"
+
+ @db.fetch("SELECT * FROM #{table}") do |row|
+ if ( row[:name].length > 128 )
+ # Element name is bigger than 128 chars
+ new_name = "#{elem}-#{row[:oid]}-#{row[:name][0..99]}"
+
+ doc = Document.new(row[:body])
+
+ doc.root.each_element("NAME") { |e|
+ e.text = new_name
+ }
+
+ @db[:migrator_tmp].insert(
+ :oid => row[:oid],
+ :name => new_name,
+ :body => doc.root.to_s)
+
+ puts " > #{elem} ##{row[:oid]} had a name bigger than 128 chars and has been renamed to #{new_name[0..10]}..."
+ end
+ end
+
+ @db.fetch("SELECT * FROM migrator_tmp") do |row|
+ @db[table].filter(:oid => row[:oid]).update(
+ :name => row[:name],
+ :body => row[:body])
+ end
+
+ @db.run "DROP TABLE migrator_tmp"
+ end
+end
diff --git a/src/onedb/shared/3.1.0_to_3.1.80.rb b/src/onedb/shared/3.1.0_to_3.1.80.rb
new file mode 100644
index 0000000000..48ed26f1ba
--- /dev/null
+++ b/src/onedb/shared/3.1.0_to_3.1.80.rb
@@ -0,0 +1,220 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'digest/sha1'
+require "rexml/document"
+include REXML
+require 'ipaddr'
+
+module Migrator
+ def db_version
+ "3.1.80"
+ end
+
+ def one_version
+ "OpenNebula 3.1.80"
+ end
+
+ def up
+ puts " > Networking isolation hooks have been moved to Host drivers.\n"<<
+ " If you were using a networking hook, enter its name, or press enter\n"<<
+ " to use the default dummy vn_mad driver.\n\n"
+
+ vn_mad = ""
+
+ while !( ["802.1Q", "dummy", "ebtables", "ovswitch", "fw"].include?(vn_mad) ) do
+ print " Driver name (802.1Q, dummy, ebtables, ovswitch, fw): "
+ vn_mad = gets.chomp
+ vn_mad = "dummy" if vn_mad.empty?
+ end
+
+ # 0 = all, 1 = none, 2 = interactive
+ vlan_option = 1
+
+ if ( vn_mad == "ebtables" || vn_mad == "ovswitch" )
+ puts
+ puts " > A new attribute, VLAN = YES/NO will be added to each VNET.\n"<<
+ " For driver '#{vn_mad}', please choose if you want to isolate all networks (all),\n"<<
+ " none (none), or be asked individually for each VNET (interactive)\n"
+
+ vlan = ""
+ while !( ["all", "none", "interactive"].include?(vlan) ) do
+ print " Isolate VNETs (all, none, interactive): "
+ vlan = gets.chomp
+ end
+
+ case vlan
+ when "all"
+ vlan_option = 0
+ when "none"
+ vlan_option = 1
+ when "interactive"
+ vlan_option = 2
+ end
+ end
+
+ # New VN_MAD element for 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 TEXT, state INTEGER, last_mon_time INTEGER, UNIQUE(name));"
+
+ @db.fetch("SELECT * FROM old_host_pool") do |row|
+ doc = Document.new(row[:body])
+
+ vn_mad_elem = doc.root.add_element("VN_MAD")
+ vn_mad_elem.text = vn_mad
+
+ @db[:host_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :state => row[:state],
+ :last_mon_time => row[:last_mon_time])
+ end
+
+ @db.run "DROP TABLE old_host_pool;"
+
+ # New VLAN and RANGE for vnets
+
+ @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 TEXT, uid INTEGER, gid INTEGER, public INTEGER, UNIQUE(name,uid));"
+
+ @db.fetch("SELECT * FROM old_network_pool") do |row|
+ doc = Document.new(row[:body])
+
+ type = ""
+ doc.root.each_element("TYPE") { |e|
+ type = e.text
+ }
+
+ if type == "0" # RANGED
+ range_elem = doc.root.add_element("RANGE")
+ ip_start_elem = range_elem.add_element("IP_START")
+ ip_end_elem = range_elem.add_element("IP_END")
+
+ net_address = ""
+ doc.root.each_element("TEMPLATE/NETWORK_ADDRESS") { |e|
+ net_address = e.text
+ }
+
+ net_valid = false
+ while !net_valid do
+ begin
+ net_address = IPAddr.new(net_address, Socket::AF_INET)
+ net_valid = true
+ rescue ArgumentError
+ puts
+ puts " > Error processing VNET ##{row[:oid]} '#{row[:name]}'\n"<<
+ " This network address is invalid: '#{net_address}'\n"
+ print " Please enter a valid network address: "
+ net_address = gets.chomp
+ end
+ end
+
+
+ st_size = ""
+ doc.root.each_element("TEMPLATE/NETWORK_SIZE") { |e|
+ st_size = e.text
+ }
+
+ if ( st_size == "C" || st_size == "c" )
+ host_bits = 8
+ elsif ( st_size == "B" || st_size == "b" )
+ host_bits = 16
+ elsif ( st_size == "A" || st_size == "a" )
+ host_bits = 24
+ else
+ size = st_size.to_i
+ host_bits = (Math.log(size+2)/Math.log(2)).ceil
+ end
+
+ net_mask = 0xFFFFFFFF << host_bits
+
+ net_address = net_address.to_i & net_mask
+
+ ip_start_elem.text = IPAddr.new((net_address + 1), Socket::AF_INET).to_s
+ ip_end_elem.text = IPAddr.new((net_address + (1 << host_bits) - 2), Socket::AF_INET).to_s
+ end
+
+ phydev_present = false
+ doc.root.each_element("PHYDEV") { |e|
+ phydev_present = true
+ }
+
+ vlan_elem = doc.root.add_element("VLAN")
+
+ if phydev_present
+ vlan_elem.text = "1"
+ else
+ case vlan_option
+ when 0
+ vlan_elem.text = "1"
+ when 1
+ vlan_elem.text = "0"
+ when 2
+ vlan = ""
+ while !( ["y", "n"].include?(vlan) ) do
+ print " > Isolate VNET ##{row[:oid]} '#{row[:name]}'? (y/n) : "
+ vlan = gets.chomp
+ end
+
+ if ( vlan == "y" )
+ vlan_elem.text = "1"
+ else
+ vlan_elem.text = "0"
+ end
+ end
+ end
+
+ @db[:network_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :public => row[:public])
+ end
+
+ @db.run "DROP TABLE old_network_pool;"
+
+ # Add empty HISTORY_RECORDS element to VMs without any records
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE vm_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, last_poll INTEGER, state INTEGER, lcm_state INTEGER);"
+ @db.run "INSERT INTO vm_pool SELECT * FROM old_vm_pool;"
+
+ @db.fetch("SELECT * FROM old_vm_pool") do |row|
+ doc = Document.new(row[:body])
+
+ found = false
+ doc.root.each_element("HISTORY_RECORDS") { |e|
+ found = true
+ }
+
+ if !found
+ doc.root.add_element("HISTORY_RECORDS")
+
+ @db[:vm_pool].filter(:oid=>row[:oid]).update(
+ :body => doc.root.to_s)
+ end
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.1.80_to_3.2.0.rb b/src/onedb/shared/3.1.80_to_3.2.0.rb
new file mode 100644
index 0000000000..321334248d
--- /dev/null
+++ b/src/onedb/shared/3.1.80_to_3.2.0.rb
@@ -0,0 +1,312 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 "rexml/document"
+include REXML
+
+module Migrator
+ def db_version
+ "3.2.0"
+ end
+
+ def one_version
+ "OpenNebula 3.2.0"
+ end
+
+ HOST_RIGHTS =
+ {
+ 0x1 => 0x8, # "CREATE" => "CREATE"
+ 0x2 => 0x4, # "DELETE" => "ADMIN"
+ 0x4 => 0x2, # "USE" => "MANAGE"
+ 0x8 => 0x4, # "MANAGE" => "ADMIN"
+ 0x10 => 0x1 # "INFO" => "USE"
+# 0x20 "INFO_POOL"
+# 0x40 "INFO_POOL_MINE"
+# 0x80 "INSTANTIATE"
+# 0x100 "CHOWN"
+# 0x200 "DEPLOY"
+# 0x400 "CHAUTH"
+ }
+
+ USER_GROUP_RIGHTS =
+ {
+ 0x1 => 0x8, # "CREATE" => "CREATE"
+ 0x2 => 0x4, # "DELETE" => "ADMIN"
+ 0x4 => 0x1, # "USE" => "USE"
+ 0x8 => 0x2, # "MANAGE" => "MANAGE"
+ 0x10 => 0x1, # "INFO" => "USE"
+# 0x20 "INFO_POOL"
+# 0x40 "INFO_POOL_MINE"
+ 0x80 => 0x1, # "INSTANTIATE" => "USE"
+ 0x100 => 0x2, # "CHOWN" => "MANAGE"
+ 0x200 => 0x4, # "DEPLOY" => "ADMIN"
+ 0x400 => 0x4 # "CHAUTH" => "ADMIN"
+ }
+
+ RIGHTS =
+ {
+ 0x1 => 0x8, # "CREATE" => "CREATE"
+ 0x2 => 0x2, # "DELETE" => "MANAGE"
+ 0x4 => 0x1, # "USE" => "USE"
+ 0x8 => 0x2, # "MANAGE" => "MANAGE"
+ 0x10 => 0x1, # "INFO" => "USE"
+# 0x20 "INFO_POOL"
+# 0x40 "INFO_POOL_MINE"
+ 0x80 => 0x1, # "INSTANTIATE" => "USE"
+ 0x100 => 0x2, # "CHOWN" => "MANAGE"
+ 0x200 => 0x4, # "DEPLOY" => "ADMIN"
+ 0x400 => 0x4 # "CHAUTH" => "ADMIN"
+ }
+
+
+ def up
+
+ ########################################################################
+ # Update ACL Rules
+ ########################################################################
+
+ @db.run "ALTER TABLE acl RENAME TO old_acl;"
+ @db.run "CREATE TABLE acl (oid INT PRIMARY KEY, user BIGINT, resource BIGINT, rights BIGINT);"
+
+ @db.fetch("SELECT * FROM old_acl") do |row|
+
+ rights = row[:rights].to_i
+ new_rights = 0
+
+ rights_hash = nil
+
+ if ( row[:resource] & 0x2000000000 != 0 ) # Resource contains HOST
+ rights_hash = HOST_RIGHTS
+ elsif ( row[:resource] & 0x0000050000000000 != 0 ) # Resource contains USER or GROUP
+ rights_hash = USER_GROUP_RIGHTS
+ else
+ rights_hash = RIGHTS
+ end
+
+ rights_hash.each { |k,v|
+ if ( rights & k != 0 )
+ new_rights = new_rights | v
+ end
+ }
+
+ if ( new_rights != 0 )
+ @db[:acl].insert(
+ :oid => row[:oid],
+ :user => row[:user],
+ :resource => row[:resource],
+ :rights => new_rights.to_s)
+ else
+ puts " > ACL Rule ##{row[:oid]} will be deleted because it\n" <<
+ " only contained deprecated rights INFO_POOL or INFO_POOL_MINE"
+ end
+ end
+
+ @db.run "DROP TABLE old_acl;"
+
+
+ ########################################################################
+ # Add new permission attributes to resources
+ ########################################################################
+
+ @db.run "ALTER TABLE group_pool RENAME TO old_group_pool;"
+ @db.run "CREATE TABLE group_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.fetch("SELECT * FROM old_group_pool") do |row|
+ @db[:group_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => row[:body],
+ :uid => "0",
+ :gid => row[:oid],
+ :owner_u => "1",
+ :group_u => "1",
+ :other_u => "0")
+ end
+
+ @db.run "DROP TABLE old_group_pool;"
+
+
+ @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 TEXT, state INTEGER, last_mon_time INTEGER, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.fetch("SELECT * FROM old_host_pool") do |row|
+ @db[:host_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => row[:body],
+ :state => row[:state],
+ :last_mon_time => row[:last_mon_time],
+ :uid => "0",
+ :gid => row[:oid],
+ :owner_u => "1",
+ :group_u => "0",
+ :other_u => "0")
+ end
+
+ @db.run "DROP TABLE old_host_pool;"
+
+
+ @db.run "ALTER TABLE user_pool RENAME TO old_user_pool;"
+ @db.run "CREATE TABLE IF NOT EXISTS user_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.fetch("SELECT * FROM old_user_pool") do |row|
+ doc = Document.new(row[:body])
+
+ gid = "1"
+ doc.root.each_element("GID") { |e|
+ gid = e.text
+ }
+
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => row[:body],
+ :uid => row[:oid],
+ :gid => gid,
+ :owner_u => "1",
+ :group_u => "0",
+ :other_u => "0")
+ end
+
+ @db.run "DROP TABLE old_user_pool;"
+
+
+ @db.run "ALTER TABLE image_pool RENAME TO old_image_pool;"
+ @db.run "CREATE TABLE image_pool (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.fetch("SELECT * FROM old_image_pool") do |row|
+ doc = Document.new(row[:body])
+
+ # Delete PUBLIC elem
+ pub_elem = doc.root.delete_element("PUBLIC")
+ public_value = pub_elem.text
+
+ add_permissions(doc, public_value)
+
+ @db[:image_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => "1",
+ :group_u => public_value,
+ :other_u => "0")
+ end
+
+ @db.run "DROP TABLE old_image_pool;"
+
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE vm_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, last_poll INTEGER, state INTEGER, lcm_state INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.fetch("SELECT * FROM old_vm_pool") do |row|
+ doc = Document.new(row[:body])
+
+ # There is no PUBLIC elem
+ public_value = "0"
+
+ add_permissions(doc, public_value)
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => "1",
+ :group_u => public_value,
+ :other_u => "0")
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+
+ @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 TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name,uid));"
+
+ @db.fetch("SELECT * FROM old_network_pool") do |row|
+ doc = Document.new(row[:body])
+
+ # Delete PUBLIC elem
+ pub_elem = doc.root.delete_element("PUBLIC")
+ public_value = pub_elem.text
+
+ add_permissions(doc, public_value)
+
+ @db[:network_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => "1",
+ :group_u => public_value,
+ :other_u => "0")
+ end
+
+ @db.run "DROP TABLE old_network_pool;"
+
+
+ @db.run "ALTER TABLE template_pool RENAME TO old_template_pool;"
+ @db.run "CREATE TABLE template_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.fetch("SELECT * FROM old_template_pool") do |row|
+ doc = Document.new(row[:body])
+
+ # Delete PUBLIC elem
+ pub_elem = doc.root.delete_element("PUBLIC")
+ public_value = pub_elem.text
+
+ add_permissions(doc, public_value)
+
+ @db[:template_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => "1",
+ :group_u => public_value,
+ :other_u => "0")
+ end
+
+ @db.run "DROP TABLE old_template_pool;"
+
+
+ return true
+ end
+
+ def add_permissions(doc, public_value)
+ perm_elem = doc.root.add_element("PERMISSIONS")
+
+ perm_elem.add_element("OWNER_U").text = "1"
+ perm_elem.add_element("OWNER_M").text = "1"
+ perm_elem.add_element("OWNER_A").text = "0"
+
+ perm_elem.add_element("GROUP_U").text = public_value
+ perm_elem.add_element("GROUP_M").text = "0"
+ perm_elem.add_element("GROUP_A").text = "0"
+
+ perm_elem.add_element("OTHER_U").text = "0"
+ perm_elem.add_element("OTHER_M").text = "0"
+ perm_elem.add_element("OTHER_A").text = "0"
+ end
+end
diff --git a/src/onedb/shared/3.2.0_to_3.2.1.rb b/src/onedb/shared/3.2.0_to_3.2.1.rb
new file mode 100644
index 0000000000..6bfcf513b3
--- /dev/null
+++ b/src/onedb/shared/3.2.0_to_3.2.1.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "3.2.1"
+ end
+
+ def one_version
+ "OpenNebula 3.2.1"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.2.1_to_3.3.0.rb b/src/onedb/shared/3.2.1_to_3.3.0.rb
new file mode 100644
index 0000000000..6ebb0cd9cb
--- /dev/null
+++ b/src/onedb/shared/3.2.1_to_3.3.0.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "3.3.0"
+ end
+
+ def one_version
+ "OpenNebula 3.3.0"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.3.0_to_3.3.80.rb b/src/onedb/shared/3.3.0_to_3.3.80.rb
new file mode 100644
index 0000000000..da371c8a42
--- /dev/null
+++ b/src/onedb/shared/3.3.0_to_3.3.80.rb
@@ -0,0 +1,313 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 "rexml/document"
+include REXML
+
+module Migrator
+ def db_version
+ "3.3.80"
+ end
+
+ def one_version
+ "OpenNebula 3.3.80"
+ end
+
+ SHORT_VM_STATES=%w{init pend hold actv stop susp done fail}
+
+ SHORT_LCM_STATES=%w{prol boot runn migr save save save migr prol,
+ epil epil shut shut fail clea unkn}
+
+ def up
+
+ header_done = false
+
+ @db.fetch("SELECT oid,name,state,lcm_state FROM vm_pool WHERE ( state <> 1 AND state <> 6 )") do |row|
+ if ( !header_done )
+ puts "You can't have active VMs. Please shutdown or delete the following VMs:"
+ puts
+ puts " ID STAT NAME"
+
+ header_done = true
+ end
+
+ if row[:state] != 3
+ state_str = SHORT_VM_STATES[row[:state]]
+ else
+ state_str = SHORT_LCM_STATES[row[:lcm_state]]
+ end
+
+ puts "#{'%6.6s' % row[:oid].to_s} #{state_str} #{row[:name]}"
+ end
+
+ if ( header_done )
+ puts
+ return false
+ end
+
+ one_location = ENV["ONE_LOCATION"]
+
+ if !one_location
+ var_location = "/var/lib/one"
+ else
+ var_location = one_location + "/var"
+ end
+
+ ########################################################################
+ # Get oneadmin user and group names
+ ########################################################################
+
+ oneadmin_uname = nil
+
+ @db.fetch("SELECT name FROM user_pool WHERE oid=0") do |row|
+ oneadmin_uname = row[:name]
+ end
+
+ if oneadmin_uname == nil
+ puts "Error trying to read oneadmin's user name ('SELECT name FROM user_pool WHERE oid=0')"
+ return false
+ end
+
+ oneadmin_gname = nil
+
+ @db.fetch("SELECT name FROM group_pool WHERE oid=0") do |row|
+ oneadmin_gname = row[:name]
+ end
+
+ if oneadmin_gname == nil
+ puts "Error trying to read oneadmin's group name ('SELECT name FROM group_pool WHERE oid=0')"
+ return false
+ end
+
+ ########################################################################
+ # Create the cluster and datastore tables
+ ########################################################################
+
+ # New table for Clusters
+ @db.run "CREATE TABLE cluster_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ # New table for Datastores
+ @db.run "CREATE TABLE datastore_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ # Insert system datastore
+
+ xml =
+ "" <<
+ " 0" <<
+ " 0" <<
+ " 0" <<
+ " #{oneadmin_uname}" <<
+ " #{oneadmin_gname}" <<
+ " system" <<
+ " " <<
+ " 1" <<
+ " 1" <<
+ " 0" <<
+ " 1" <<
+ " 0" <<
+ " 0" <<
+ " 0" <<
+ " 0" <<
+ " 0" <<
+ " " <<
+ " -" <<
+ " shared" <<
+ " #{var_location}/datastores/0" <<
+ " -1" <<
+ " " <<
+ " " <<
+ " " <<
+ " " <<
+ " " <<
+ " " <<
+ ""
+
+ @db[:datastore_pool].insert(
+ :oid => 0,
+ :name => 'system',
+ :body => xml,
+ :uid => 0,
+ :gid => 0,
+ :owner_u => 1,
+ :group_u => 1,
+ :other_u => 0)
+
+ # Last oid for cluster_pool and datastore_pool
+
+ @db[:pool_control].insert(
+ :tablename => 'cluster_pool',
+ :last_oid => 99)
+
+ @db[:pool_control].insert(
+ :tablename => 'datastore_pool',
+ :last_oid => 99)
+
+ ########################################################################
+ # Add each Host to Cluster -1 (none)
+ ########################################################################
+
+ @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 TEXT, state INTEGER, last_mon_time INTEGER, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.fetch("SELECT * FROM old_host_pool") do |row|
+ doc = Document.new(row[:body])
+
+ # Delete TM_MAD elem
+ doc.root.delete_element("TM_MAD")
+
+ # Add Cluster elements
+ doc.root.add_element("CLUSTER_ID").text = "-1"
+ doc.root.add_element("CLUSTER").text = ""
+
+ @db[:host_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :state => row[:state],
+ :last_mon_time => row[:last_mon_time],
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_host_pool;"
+
+ ########################################################################
+ # Add each VNet to Cluster -1 (none)
+ ########################################################################
+
+ @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 TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name,uid));"
+
+ @db.fetch("SELECT * FROM old_network_pool") do |row|
+ doc = Document.new(row[:body])
+
+ # Add Cluster elements
+ doc.root.add_element("CLUSTER_ID").text = "-1"
+ doc.root.add_element("CLUSTER").text = ""
+
+ @db[:network_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_network_pool;"
+
+ ########################################################################
+ # Add each Image to Datastore 1 (default)
+ ########################################################################
+
+ images_element = ""
+
+ @db.run "ALTER TABLE image_pool RENAME TO old_image_pool;"
+ @db.run "CREATE TABLE image_pool (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.fetch("SELECT * FROM old_image_pool") do |row|
+ doc = Document.new(row[:body])
+
+ # Add Cluster elements
+ doc.root.add_element("DATASTORE_ID").text = "1"
+ doc.root.add_element("DATASTORE").text = "default"
+
+ images_element << "#{row[:oid]}"
+
+ # Update SOURCE
+ doc.root.each_element("SOURCE") { |e|
+ previous_source = e.text
+
+ if previous_source.nil?
+ next
+ end
+
+ hash = previous_source.split('/')[-1]
+
+ if ( hash.length == 32 && hash =~ /^[0-9A-F]+$/i )
+ e.text = "#{var_location}/datastores/1/#{hash}"
+
+ `ln -s #{previous_source} #{e.text}`
+ end
+ }
+
+ @db[:image_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_image_pool;"
+
+ images_element << ""
+
+ # Insert default datastore
+
+ xml =
+ "" <<
+ " 1" <<
+ " 0" <<
+ " 0" <<
+ " #{oneadmin_uname}" <<
+ " #{oneadmin_gname}" <<
+ " default" <<
+ " " <<
+ " 1" <<
+ " 1" <<
+ " 0" <<
+ " 1" <<
+ " 0" <<
+ " 0" <<
+ " 1" <<
+ " 0" <<
+ " 0" <<
+ " " <<
+ " fs" <<
+ " shared" <<
+ " #{var_location}/datastores/1" <<
+ " -1" <<
+ " " <<
+ images_element <<
+ " " <<
+ " " <<
+ " " <<
+ " " <<
+ ""
+
+ @db[:datastore_pool].insert(
+ :oid => 1,
+ :name => 'default',
+ :body => xml,
+ :uid => 0,
+ :gid => 0,
+ :owner_u => 1,
+ :group_u => 1,
+ :other_u => 1)
+
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.3.80_to_3.4.0.rb b/src/onedb/shared/3.3.80_to_3.4.0.rb
new file mode 100644
index 0000000000..788831800b
--- /dev/null
+++ b/src/onedb/shared/3.3.80_to_3.4.0.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "3.4.0"
+ end
+
+ def one_version
+ "OpenNebula 3.4.0"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.4.0_to_3.4.1.rb b/src/onedb/shared/3.4.0_to_3.4.1.rb
new file mode 100644
index 0000000000..4d0e44d366
--- /dev/null
+++ b/src/onedb/shared/3.4.0_to_3.4.1.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "3.4.1"
+ end
+
+ def one_version
+ "OpenNebula 3.4.1"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.4.1_to_3.5.80.rb b/src/onedb/shared/3.4.1_to_3.5.80.rb
new file mode 100644
index 0000000000..afce01582e
--- /dev/null
+++ b/src/onedb/shared/3.4.1_to_3.5.80.rb
@@ -0,0 +1,421 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 "rexml/document"
+include REXML
+
+module Migrator
+ def db_version
+ "3.5.80"
+ end
+
+ def one_version
+ "OpenNebula 3.5.80"
+ end
+
+ def up
+
+ oneadmin_row = nil
+ @db.fetch("SELECT * FROM user_pool WHERE oid = 0") do |row|
+ oneadmin_row = row
+ end
+
+ if oneadmin_row[:gid] != 0
+
+ puts " > Oneadmin user will be moved to the oneadmin group"
+
+ # Change user group
+
+ doc = Document.new(oneadmin_row[:body])
+
+ doc.root.each_element("GID") { |e|
+ e.text = "0"
+ }
+
+ doc.root.each_element("GNAME") { |e|
+ e.text = "oneadmin"
+ }
+
+ @db[:user_pool].filter(:oid=>0).delete
+
+ @db[:user_pool].insert(
+ :oid => oneadmin_row[:oid],
+ :name => oneadmin_row[:name],
+ :body => doc.root.to_s,
+ :uid => oneadmin_row[:oid],
+ :gid => 0,
+ :owner_u => oneadmin_row[:owner_u],
+ :group_u => oneadmin_row[:group_u],
+ :other_u => oneadmin_row[:other_u])
+
+ # Remove oneadmin's id from previous group
+
+ group_row = nil
+
+ @db.fetch("SELECT * FROM group_pool WHERE oid = #{oneadmin_row[:gid]}") do |row|
+ group_row = row
+ end
+
+ doc = Document.new(group_row[:body])
+
+ doc.root.delete_element("USERS/ID[.=0]")
+
+ @db[:group_pool].filter(:oid=>group_row[:oid]).delete
+
+ @db[:group_pool].insert(
+ :oid => group_row[:oid],
+ :name => group_row[:name],
+ :body => doc.root.to_s,
+ :uid => group_row[:oid],
+ :gid => group_row[:gid],
+ :owner_u => group_row[:owner_u],
+ :group_u => group_row[:group_u],
+ :other_u => group_row[:other_u])
+
+ # Add oneadmin's id to oneadmin group
+
+ @db.fetch("SELECT * FROM group_pool WHERE oid = 0") do |row|
+ group_row = row
+ end
+
+ doc = Document.new(group_row[:body])
+
+ doc.root.get_elements("USERS")[0].add_element("ID").text = "0"
+
+ @db[:group_pool].filter(:oid=>group_row[:oid]).delete
+
+ @db[:group_pool].insert(
+ :oid => group_row[:oid],
+ :name => group_row[:name],
+ :body => doc.root.to_s,
+ :uid => group_row[:oid],
+ :gid => group_row[:gid],
+ :owner_u => group_row[:owner_u],
+ :group_u => group_row[:group_u],
+ :other_u => group_row[:other_u])
+ end
+
+
+ @db.run "ALTER TABLE datastore_pool RENAME TO old_datastore_pool;"
+ @db.run "CREATE TABLE datastore_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.fetch("SELECT * FROM old_datastore_pool") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("DISK_TYPE").text = "0"
+
+ @db[:datastore_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_datastore_pool;"
+
+
+ @db.run "ALTER TABLE image_pool RENAME TO old_image_pool;"
+ @db.run "CREATE TABLE image_pool (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.fetch("SELECT * FROM old_image_pool") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("DISK_TYPE").text = "0"
+ doc.root.add_element("CLONING_ID").text = "-1"
+ doc.root.add_element("CLONING_OPS").text = "0"
+
+ @db[:image_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_image_pool;"
+
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE vm_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, last_poll INTEGER, state INTEGER, lcm_state INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.fetch("SELECT * FROM old_vm_pool") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("RESCHED").text = "0"
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+
+ @db.run "ALTER TABLE history RENAME TO old_history;"
+ @db.run "CREATE TABLE history (vid INTEGER, seq INTEGER, body TEXT, stime INTEGER, etime INTEGER, PRIMARY KEY(vid,seq));"
+
+ @db.fetch("SELECT * FROM old_history") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("OID").text = row[:vid].to_s
+
+ stime = "0"
+ doc.root.each_element("STIME") { |e|
+ stime = e.text
+ }
+
+ etime = "0"
+ doc.root.each_element("ETIME") { |e|
+ etime = e.text
+ }
+
+ @db.fetch("SELECT body FROM vm_pool WHERE oid = #{row[:vid]}") do |vm_row|
+ vm_doc = Document.new(vm_row[:body])
+
+ vm_doc.root.delete_element( '/VM/HISTORY_RECORDS/HISTORY' )
+
+ ["MEMORY", "CPU", "NET_TX", "NET_RX"].each { |elem_name|
+ vm_doc.root.each_element(elem_name) { |e|
+ e.text = "0"
+ }
+ }
+
+ doc.root.add_element( vm_doc )
+ end
+
+ @db[:history].insert(
+ :vid => row[:vid],
+ :seq => row[:seq],
+ :body => doc.root.to_s,
+ :stime => stime,
+ :etime => etime)
+ end
+
+ @db.run "DROP TABLE old_history;"
+
+
+ @db.run "ALTER TABLE user_pool RENAME TO old_user_pool;"
+ @db.run "CREATE TABLE user_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ # oneadmin does not have quotas
+ @db.fetch("SELECT * FROM old_user_pool WHERE oid=0") do |row|
+ doc = Document.new(row[:body])
+
+ ds_quota = doc.root.add_element("DATASTORE_QUOTA")
+ net_quota = doc.root.add_element("NETWORK_QUOTA")
+ vm_quota = doc.root.add_element("VM_QUOTA")
+ img_quota = doc.root.add_element("IMAGE_QUOTA")
+
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:oid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.fetch("SELECT * FROM old_user_pool WHERE oid>0") do |row|
+ doc = Document.new(row[:body])
+
+ calculate_quotas(doc, "uid=#{row[:oid]}")
+
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:oid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_user_pool;"
+
+
+ @db.run "ALTER TABLE group_pool RENAME TO old_group_pool;"
+ @db.run "CREATE TABLE group_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+
+ # oneadmin group does not have quotas
+ @db.fetch("SELECT * FROM old_group_pool WHERE oid=0") do |row|
+ doc = Document.new(row[:body])
+
+ ds_quota = doc.root.add_element("DATASTORE_QUOTA")
+ net_quota = doc.root.add_element("NETWORK_QUOTA")
+ vm_quota = doc.root.add_element("VM_QUOTA")
+ img_quota = doc.root.add_element("IMAGE_QUOTA")
+
+ @db[:group_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:oid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.fetch("SELECT * FROM old_group_pool WHERE oid>0") do |row|
+ doc = Document.new(row[:body])
+
+ calculate_quotas(doc, "gid=#{row[:oid]}")
+
+ @db[:group_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:oid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_group_pool;"
+
+
+ @db.run "CREATE TABLE document_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, type INTEGER, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.run "CREATE TABLE host_monitoring (hid INTEGER, last_mon_time INTEGER, body TEXT, PRIMARY KEY(hid, last_mon_time));"
+ @db.run "CREATE TABLE vm_monitoring (vmid INTEGER, last_poll INTEGER, body TEXT, PRIMARY KEY(vmid, last_poll));"
+
+ return true
+ end
+
+ def calculate_quotas(doc, where_filter)
+ ds_quota = doc.root.add_element("DATASTORE_QUOTA")
+ net_quota = doc.root.add_element("NETWORK_QUOTA")
+ vm_quota = doc.root.add_element("VM_QUOTA")
+ img_quota = doc.root.add_element("IMAGE_QUOTA")
+
+ # VM quotas
+ cpu_used = 0
+ mem_used = 0
+ vms_used = 0
+
+ # VNet quotas
+ vnet_usage = {}
+
+ # Image quotas
+ img_usage = {}
+
+ @db.fetch("SELECT body FROM vm_pool WHERE #{where_filter} AND state!=6") do |vm_row|
+ vmdoc = Document.new(vm_row[:body])
+
+ # VM quotas
+ vmdoc.root.each_element("TEMPLATE/CPU") { |e|
+ cpu_used += e.text.to_i
+ }
+
+ vmdoc.root.each_element("TEMPLATE/MEMORY") { |e|
+ mem_used += e.text.to_i
+ }
+
+ vms_used += 1
+
+ # VNet quotas
+ vmdoc.root.each_element("TEMPLATE/NIC/NETWORK_ID") { |e|
+ vnet_usage[e.text] = 0 if vnet_usage[e.text].nil?
+ vnet_usage[e.text] += 1
+ }
+
+ # Image quotas
+ vmdoc.root.each_element("TEMPLATE/DISK/IMAGE_ID") { |e|
+ img_usage[e.text] = 0 if img_usage[e.text].nil?
+ img_usage[e.text] += 1
+ }
+ end
+
+ # VM quotas
+ vm_elem = vm_quota.add_element("VM")
+
+ vm_elem.add_element("CPU").text = "0"
+ vm_elem.add_element("CPU_USED").text = cpu_used.to_s
+
+ vm_elem.add_element("MEMORY").text = "0"
+ vm_elem.add_element("MEMORY_USED").text = mem_used.to_s
+
+ vm_elem.add_element("VMS").text = "0"
+ vm_elem.add_element("VMS_USED").text = vms_used.to_s
+
+ # VNet quotas
+ vnet_usage.each { |vnet_id, usage|
+ new_elem = net_quota.add_element("NETWORK")
+
+ new_elem.add_element("ID").text = vnet_id
+ new_elem.add_element("LEASES").text = "0"
+ new_elem.add_element("LEASES_USED").text = usage.to_s
+ }
+
+ # Image quotas
+ img_usage.each { |img_id, usage|
+ new_elem = img_quota.add_element("IMAGE")
+
+ new_elem.add_element("ID").text = img_id
+ new_elem.add_element("RVMS").text = "0"
+ new_elem.add_element("RVMS_USED").text = usage.to_s
+ }
+
+ # Datastore quotas
+ ds_usage = {}
+
+ @db.fetch("SELECT body FROM image_pool WHERE #{where_filter}") do |img_row|
+ img_doc = Document.new(img_row[:body])
+
+ img_doc.root.each_element("DATASTORE_ID") { |e|
+ ds_usage[e.text] = [0,0] if ds_usage[e.text].nil?
+ ds_usage[e.text][0] += 1
+
+ img_doc.root.each_element("SIZE") { |size|
+ ds_usage[e.text][1] += size.text.to_i
+ }
+ }
+ end
+
+ ds_usage.each { |ds_id, usage|
+ new_elem = ds_quota.add_element("DATASTORE")
+
+ new_elem.add_element("ID").text = ds_id
+ new_elem.add_element("IMAGES").text = "0"
+ new_elem.add_element("IMAGES_USED").text = usage[0].to_s
+ new_elem.add_element("SIZE").text = "0"
+ new_elem.add_element("SIZE_USED").text = usage[1].to_s
+ }
+
+ end
+end
diff --git a/src/onedb/shared/3.5.80_to_3.6.0.rb b/src/onedb/shared/3.5.80_to_3.6.0.rb
new file mode 100644
index 0000000000..21c8b1459b
--- /dev/null
+++ b/src/onedb/shared/3.5.80_to_3.6.0.rb
@@ -0,0 +1,147 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 "rexml/document"
+include REXML
+
+module Migrator
+ def db_version
+ "3.6.0"
+ end
+
+ def one_version
+ "OpenNebula 3.6.0"
+ end
+
+ def up
+
+ @db.run "ALTER TABLE cluster_pool RENAME TO old_cluster_pool;"
+ @db.run "CREATE TABLE cluster_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.fetch("SELECT * FROM old_cluster_pool") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("TEMPLATE")
+
+ @db[:cluster_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_cluster_pool;"
+
+
+ @db.run "ALTER TABLE datastore_pool RENAME TO old_datastore_pool;"
+ @db.run "CREATE TABLE datastore_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ system_tm = ""
+
+ @db.fetch("SELECT * FROM old_datastore_pool WHERE oid = 0") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.each_element("TM_MAD") { |e|
+ system_tm = e.text
+ }
+
+ doc.root.add_element("SYSTEM").text = "1"
+
+ @db[:datastore_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.fetch("SELECT * FROM old_datastore_pool WHERE oid > 0") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("SYSTEM").text = "0"
+
+ @db[:datastore_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_datastore_pool;"
+
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE vm_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, last_poll INTEGER, state INTEGER, lcm_state INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.fetch("SELECT * FROM old_vm_pool") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.each_element("HISTORY_RECORDS/HISTORY") { |e|
+ e.add_element("TMMAD").text = system_tm
+ e.add_element("DS_ID").text = "0"
+ }
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+
+ @db.run "ALTER TABLE history RENAME TO old_history;"
+ @db.run "CREATE TABLE history (vid INTEGER, seq INTEGER, body TEXT, stime INTEGER, etime INTEGER, PRIMARY KEY(vid,seq));"
+
+ @db.fetch("SELECT * FROM old_history") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("TMMAD").text = system_tm
+ doc.root.add_element("DS_ID").text = "0"
+
+ @db[:history].insert(
+ :vid => row[:vid],
+ :seq => row[:seq],
+ :body => doc.root.to_s,
+ :stime => row[:stime],
+ :etime => row[:etime])
+ end
+
+ @db.run "DROP TABLE old_history;"
+
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.6.0_to_3.7.80.rb b/src/onedb/shared/3.6.0_to_3.7.80.rb
new file mode 100644
index 0000000000..0b3ce4227c
--- /dev/null
+++ b/src/onedb/shared/3.6.0_to_3.7.80.rb
@@ -0,0 +1,340 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 "rexml/document"
+include REXML
+
+module Migrator
+ def db_version
+ "3.7.80"
+ end
+
+ def one_version
+ "OpenNebula 3.7.80"
+ end
+
+ def up
+
+ puts " > Please enter the DATASTORE_LOCATION set in your oned.conf,\n"<<
+ " Press enter to use the default /var/lib/one/datastores/\n"
+ print " DATASTORE_LOCATION: "
+ ds_location = gets.chomp
+
+ ds_location = "/var/lib/one/datastores/" if ds_location.empty?
+
+ ########################################################################
+ # Feature #1522: Allow users to create Documents by default
+ ########################################################################
+
+ # Insert rule "* DOCUMENT/* CREATE"
+
+ last_oid = 0
+ @db.fetch("SELECT last_oid FROM pool_control WHERE tablename='acl'") do |row|
+ last_oid = row[:last_oid].to_i
+ end
+
+ @db[:acl].insert(
+ :oid => (last_oid + 1).to_s,
+ :user => 0x400000000.to_s,
+ :resource => 0x400400000000.to_s,
+ :rights => 0x8.to_s)
+
+ @db.run("UPDATE pool_control SET last_oid=#{last_oid + 1} WHERE tablename='acl';")
+
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE vm_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, last_poll INTEGER, state INTEGER, lcm_state INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.fetch("SELECT * FROM old_vm_pool") do |row|
+ vm_doc = Document.new(row[:body])
+
+ ####################################################################
+ # Feature #1393: DATASTORE_LOCATION for each system datastore
+ ####################################################################
+
+ vm_doc.root.each_element("HISTORY_RECORDS/HISTORY") { |e|
+ e.add_element("DS_LOCATION").text = ds_location
+ }
+
+ ####################################################################
+ # Bug #1363: Make sure all VMs have CPU (float) & MEM (int)
+ ####################################################################
+
+ # NOTE: The VM memory and CPU are modified, but the sum in
+ # HOST/HOST_SHARE is not. A onedb fsck is required
+
+ # If state != DONE
+ if ( row[:state] != 6 )
+ memory = nil
+ vm_doc.root.each_element("TEMPLATE/MEMORY") { |e|
+ memory = e.text.to_i
+ memory = 0 if memory < 0
+
+ e.text = memory.to_s
+ }
+
+ if memory.nil?
+ vm_doc.root.each_element("TEMPLATE") { |e|
+ e.add_element("MEMORY").text = "0"
+ }
+ end
+
+ cpu = nil
+ vm_doc.root.each_element("TEMPLATE/CPU") { |e|
+ # truncate to 2 decimals
+ cpu = (e.text.to_f * 100).to_i / 100.0
+ cpu = 0 if cpu < 0
+
+ e.text = cpu.to_s
+ }
+
+ if cpu.nil?
+ vm_doc.root.each_element("TEMPLATE") { |e|
+ e.add_element("CPU").text = "0"
+ }
+ end
+ end
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => vm_doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+
+ ####################################################################
+ # Feature #1393: DATASTORE_LOCATION for each system datastore
+ ####################################################################
+
+ @db.run "ALTER TABLE history RENAME TO old_history;"
+ @db.run "CREATE TABLE history (vid INTEGER, seq INTEGER, body TEXT, stime INTEGER, etime INTEGER,PRIMARY KEY(vid,seq));"
+
+ @db.fetch("SELECT * FROM old_history") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("DS_LOCATION").text = ds_location
+
+ @db[:history].insert(
+ :vid => row[:vid],
+ :seq => row[:seq],
+ :body => doc.root.to_s,
+ :stime => row[:stime],
+ :etime => row[:etime])
+ end
+
+ @db.run "DROP TABLE old_history;"
+
+
+ ########################################################################
+ # Bug #1335: Add suspended VMs resoureces to Host usage
+ ########################################################################
+ @db.fetch("SELECT * FROM vm_pool WHERE state = 5") do |row|
+
+ vm_doc = Document.new(row[:body])
+
+ memory = 0
+ vm_doc.root.each_element("TEMPLATE/MEMORY") { |e|
+ memory = e.text.to_i
+ }
+
+ cpu = 0
+ vm_doc.root.each_element("TEMPLATE/CPU") { |e|
+ cpu = e.text.to_f
+ }
+
+ hid = -1
+ vm_doc.root.each_element("HISTORY_RECORDS/HISTORY[last()]/HID") { |e|
+ hid = e.text.to_i
+ }
+
+
+ host_row = nil
+ @db.fetch("SELECT * FROM host_pool WHERE oid = #{hid}") do |hrow|
+ host_row = hrow
+ end
+
+ host_doc = Document.new(host_row[:body])
+
+ host_doc.root.each_element("HOST_SHARE/MEM_USAGE") { |e|
+ mem_usage = e.text.to_i
+ e.text = (mem_usage + (memory * 1024)).to_s
+ }
+
+ host_doc.root.each_element("HOST_SHARE/CPU_USAGE") { |e|
+ cpu_usage = e.text.to_i
+ e.text = (cpu_usage + (cpu * 100)).to_s
+ }
+
+ host_doc.root.each_element("HOST_SHARE/RUNNING_VMS") { |e|
+ e.text = (e.text.to_i + 1).to_s
+ }
+
+ @db.run("DELETE FROM host_pool WHERE oid = #{host_row[:oid]}")
+
+ @db[:host_pool].insert(
+ :oid => host_row[:oid],
+ :name => host_row[:name],
+ :body => host_doc.root.to_s,
+ :state => host_row[:state],
+ :last_mon_time => host_row[:last_mon_time],
+ :uid => host_row[:uid],
+ :gid => host_row[:gid],
+ :owner_u => host_row[:owner_u],
+ :group_u => host_row[:group_u],
+ :other_u => host_row[:other_u])
+ end
+
+ ########################################################################
+ # Bugs #1347 & #1363: re-calculate CPU & MEM quotas
+ ########################################################################
+
+ @db.run "ALTER TABLE user_pool RENAME TO old_user_pool;"
+ @db.run "CREATE TABLE user_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ # oneadmin does not have quotas
+ @db.fetch("SELECT * FROM old_user_pool WHERE oid=0") do |row|
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => row[:body],
+ :uid => row[:oid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.fetch("SELECT * FROM old_user_pool WHERE oid>0") do |row|
+ doc = Document.new(row[:body])
+
+ redo_vm_quotas(doc, "uid=#{row[:oid]}")
+
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:oid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_user_pool;"
+
+
+ @db.run "ALTER TABLE group_pool RENAME TO old_group_pool;"
+ @db.run "CREATE TABLE group_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+
+ # oneadmin group does not have quotas
+ @db.fetch("SELECT * FROM old_group_pool WHERE oid=0") do |row|
+ @db[:group_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => row[:body],
+ :uid => row[:oid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.fetch("SELECT * FROM old_group_pool WHERE oid>0") do |row|
+ doc = Document.new(row[:body])
+
+ redo_vm_quotas(doc, "gid=#{row[:oid]}")
+
+ @db[:group_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:oid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_group_pool;"
+
+ return true
+ end
+
+ def redo_vm_quotas(doc, where_filter)
+ cpu_limit = "0"
+ mem_limit = "0"
+ vms_limit = "0"
+
+ doc.root.each_element("VM_QUOTA/VM/CPU") { |e|
+ cpu_limit = e.text
+ }
+
+ doc.root.each_element("VM_QUOTA/VM/MEMORY") { |e|
+ mem_limit = e.text
+ }
+
+ doc.root.each_element("VM_QUOTA/VM/VMS") { |e|
+ vms_limit = e.text
+ }
+
+ doc.root.delete_element("VM_QUOTA")
+ vm_quota = doc.root.add_element("VM_QUOTA")
+
+ # VM quotas
+ cpu_used = 0
+ mem_used = 0
+ vms_used = 0
+
+ @db.fetch("SELECT body FROM vm_pool WHERE #{where_filter} AND state<>6") do |vm_row|
+ vmdoc = Document.new(vm_row[:body])
+
+ # VM quotas
+ vmdoc.root.each_element("TEMPLATE/CPU") { |e|
+ cpu_used += e.text.to_f
+ }
+
+ vmdoc.root.each_element("TEMPLATE/MEMORY") { |e|
+ mem_used += e.text.to_i
+ }
+
+ vms_used += 1
+ end
+
+ # VM quotas
+ vm_elem = vm_quota.add_element("VM")
+
+ vm_elem.add_element("CPU").text = cpu_limit
+ vm_elem.add_element("CPU_USED").text = sprintf('%.2f', cpu_used)
+
+ vm_elem.add_element("MEMORY").text = mem_limit
+ vm_elem.add_element("MEMORY_USED").text = mem_used.to_s
+
+ vm_elem.add_element("VMS").text = vms_limit
+ vm_elem.add_element("VMS_USED").text = vms_used.to_s
+ end
+end
diff --git a/src/onedb/shared/3.7.80_to_3.8.0.rb b/src/onedb/shared/3.7.80_to_3.8.0.rb
new file mode 100644
index 0000000000..c0501a57e9
--- /dev/null
+++ b/src/onedb/shared/3.7.80_to_3.8.0.rb
@@ -0,0 +1,79 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 "rexml/document"
+include REXML
+
+module Migrator
+ def db_version
+ "3.8.0"
+ end
+
+ def one_version
+ "OpenNebula 3.8.0"
+ end
+
+ def up
+
+ ########################################################################
+ # Bug #1480 Add new attribute CONTEXT/DISK_ID
+ ########################################################################
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE vm_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, last_poll INTEGER, state INTEGER, lcm_state INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.fetch("SELECT * FROM old_vm_pool") do |row|
+ if ( row[:state] != 6 ) # DONE
+ doc = Document.new(row[:body])
+
+ # Get max ID
+ max_id = -1
+
+ doc.root.each_element("TEMPLATE/DISK/DISK_ID") { |e|
+ disk_id = e.text.to_i
+
+ max_id = disk_id if disk_id > max_id
+ }
+
+ doc.root.each_element("TEMPLATE/CONTEXT") { |e|
+ e.delete_element("DISK_ID")
+ e.add_element("DISK_ID").text = (max_id + 1).to_s
+ }
+
+ row[:body] = doc.root.to_s
+ end
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => row[:body],
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.8.0_to_3.8.1.rb b/src/onedb/shared/3.8.0_to_3.8.1.rb
new file mode 100644
index 0000000000..ea658ba2d4
--- /dev/null
+++ b/src/onedb/shared/3.8.0_to_3.8.1.rb
@@ -0,0 +1,196 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'nokogiri'
+require "rexml/document"
+include REXML
+
+module Migrator
+ def db_version
+ "3.8.1"
+ end
+
+ def one_version
+ "OpenNebula 3.8.1"
+ end
+
+ def up
+
+ init_log_time()
+
+ ########################################################################
+ # Bug : Add VM IDs Collection to Hosts & Images
+ ########################################################################
+
+ counters = {}
+ counters[:host] = {}
+ counters[:image] = {}
+
+ # Initialize all the host counters
+ @db.fetch("SELECT oid FROM host_pool") do |row|
+ counters[:host][row[:oid]] = {
+ :rvms => Set.new
+ }
+ end
+
+ # Init image counters
+ @db.fetch("SELECT oid FROM image_pool") do |row|
+ counters[:image][row[:oid]] = Set.new
+ end
+
+ log_time()
+
+ # Aggregate information of the RUNNING vms
+ @db.fetch("SELECT oid,body FROM vm_pool WHERE state<>6") do |row|
+ vm_doc = nokogiri_doc(row[:body], 'vm_pool')
+
+ state = vm_doc.root.at_xpath('STATE').text.to_i
+ lcm_state = vm_doc.root.at_xpath('LCM_STATE').text.to_i
+
+ # Images used by this VM
+ vm_doc.root.xpath("TEMPLATE/DISK/IMAGE_ID").each do |e|
+ img_id = e.text.to_i
+
+ if counters[:image][img_id].nil?
+ warn("VM #{row[:oid]} is using Image #{img_id}, but it does not exist")
+ else
+ counters[:image][img_id].add(row[:oid])
+ end
+ end
+
+
+ # Host resources
+
+ # Only states that add to Host resources consumption are
+ # ACTIVE, SUSPENDED, POWEROFF
+ next if !([3,5,8].include? state)
+
+ # Get hostid
+ hid = -1
+ vm_doc.root.xpath("HISTORY_RECORDS/HISTORY[last()]/HID").each { |e|
+ hid = e.text.to_i
+ }
+
+ if counters[:host][hid].nil?
+ warn("VM #{row[:oid]} is using Host #{hid}, but it does not exist")
+ else
+ counters[:host][hid][:rvms].add(row[:oid])
+ end
+ end
+
+ log_time()
+
+ ########################################################################
+ # Hosts
+ #
+ # HOST/HOST_SHARE/RUNNING_VMS
+ # HOST/VMS/ID
+ ########################################################################
+
+ @db.run "CREATE TABLE host_pool_new (oid INTEGER PRIMARY KEY, " <<
+ "name VARCHAR(128), body TEXT, state INTEGER, " <<
+ "last_mon_time INTEGER, uid INTEGER, gid INTEGER, " <<
+ "owner_u INTEGER, group_u INTEGER, other_u INTEGER, " <<
+ "UNIQUE(name));"
+
+ # Calculate the host's xml and write them to host_pool_new
+ @db.transaction do
+ @db[:host_pool].each do |row|
+ host_doc = Document.new(row[:body])
+
+ hid = row[:oid]
+
+ rvms = counters[:host][hid][:rvms].size
+
+ # rewrite running_vms
+ host_doc.root.each_element("HOST_SHARE/RUNNING_VMS") {|e|
+ if e.text != rvms.to_s
+ warn("Host #{hid} RUNNING_VMS has #{e.text} \tis\t#{rvms}")
+ e.text = rvms
+ end
+ }
+
+ # re-do list of VM IDs
+ vms_new_elem = host_doc.root.add_element("VMS")
+
+ counters[:host][hid][:rvms].each do |id|
+ vms_new_elem.add_element("ID").text = id.to_s
+ end
+
+ row[:body] = host_doc.to_s
+
+ # commit
+ @db[:host_pool_new].insert(row)
+ end
+ end
+
+ # Rename table
+ @db.run("DROP TABLE host_pool")
+ @db.run("ALTER TABLE host_pool_new RENAME TO host_pool")
+
+ log_time()
+
+ ########################################################################
+ # Image
+ #
+ # IMAGE/RUNNING_VMS
+ # IMAGE/VMS/ID
+ ########################################################################
+
+ # Create a new empty table where we will store the new calculated values
+ @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.transaction do
+ @db[:image_pool].each do |row|
+ doc = Document.new(row[:body])
+
+ oid = row[:oid]
+
+ rvms = counters[:image][oid].size
+
+ # rewrite running_vms
+ doc.root.each_element("RUNNING_VMS") {|e|
+ if e.text != rvms.to_s
+ warn("Image #{oid} RUNNING_VMS has #{e.text} \tis\t#{rvms}")
+ e.text = rvms
+ end
+ }
+
+ # re-do list of VM IDs
+ vms_new_elem = doc.root.add_element("VMS")
+
+ counters[:image][oid].each do |id|
+ vms_new_elem.add_element("ID").text = id.to_s
+ end
+
+ row[:body] = doc.to_s
+
+ # commit
+ @db[:image_pool_new].insert(row)
+ end
+ end
+
+ # Rename table
+ @db.run("DROP TABLE image_pool")
+ @db.run("ALTER TABLE image_pool_new RENAME TO image_pool")
+
+ log_time()
+
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.8.1_to_3.8.2.rb b/src/onedb/shared/3.8.1_to_3.8.2.rb
new file mode 100644
index 0000000000..71d942e4de
--- /dev/null
+++ b/src/onedb/shared/3.8.1_to_3.8.2.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "3.8.2"
+ end
+
+ def one_version
+ "OpenNebula 3.8.2"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.8.2_to_3.8.3.rb b/src/onedb/shared/3.8.2_to_3.8.3.rb
new file mode 100644
index 0000000000..ed9cb927cb
--- /dev/null
+++ b/src/onedb/shared/3.8.2_to_3.8.3.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "3.8.3"
+ end
+
+ def one_version
+ "OpenNebula 3.8.3"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.8.3_to_3.8.4.rb b/src/onedb/shared/3.8.3_to_3.8.4.rb
new file mode 100644
index 0000000000..5b2e44a841
--- /dev/null
+++ b/src/onedb/shared/3.8.3_to_3.8.4.rb
@@ -0,0 +1,55 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "3.8.4"
+ end
+
+ def one_version
+ "OpenNebula 3.8.4"
+ end
+
+ def up
+
+ ########################################################################
+ # Bug #1813: change body column type from TEXT to MEDIUMTEXT
+ ########################################################################
+
+ # Sqlite does not support alter table modify column, but the TEXT column
+ # is enough in sqlite.
+
+ if !@sqlite_file
+ @db.run "ALTER TABLE cluster_pool MODIFY COLUMN body MEDIUMTEXT;"
+ @db.run "ALTER TABLE datastore_pool MODIFY COLUMN body MEDIUMTEXT;"
+ @db.run "ALTER TABLE document_pool MODIFY COLUMN body MEDIUMTEXT;"
+ @db.run "ALTER TABLE group_pool MODIFY COLUMN body MEDIUMTEXT;"
+ @db.run "ALTER TABLE history MODIFY COLUMN body MEDIUMTEXT;"
+ @db.run "ALTER TABLE host_monitoring MODIFY COLUMN body MEDIUMTEXT;"
+ @db.run "ALTER TABLE host_pool MODIFY COLUMN body MEDIUMTEXT;"
+ @db.run "ALTER TABLE image_pool MODIFY COLUMN body MEDIUMTEXT;"
+ @db.run "ALTER TABLE leases MODIFY COLUMN body MEDIUMTEXT;"
+ @db.run "ALTER TABLE network_pool MODIFY COLUMN body MEDIUMTEXT;"
+ @db.run "ALTER TABLE template_pool MODIFY COLUMN body MEDIUMTEXT;"
+ @db.run "ALTER TABLE user_pool MODIFY COLUMN body MEDIUMTEXT;"
+ @db.run "ALTER TABLE vm_monitoring MODIFY COLUMN body MEDIUMTEXT;"
+ @db.run "ALTER TABLE vm_pool MODIFY COLUMN body MEDIUMTEXT;"
+ end
+
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.8.4_to_3.8.5.rb b/src/onedb/shared/3.8.4_to_3.8.5.rb
new file mode 100644
index 0000000000..ba0ffc9d95
--- /dev/null
+++ b/src/onedb/shared/3.8.4_to_3.8.5.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "3.8.5"
+ end
+
+ def one_version
+ "OpenNebula 3.8.5"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/3.8.5_to_3.9.80.rb b/src/onedb/shared/3.8.5_to_3.9.80.rb
new file mode 100644
index 0000000000..4158cf81c8
--- /dev/null
+++ b/src/onedb/shared/3.8.5_to_3.9.80.rb
@@ -0,0 +1,655 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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
+
+require 'nokogiri'
+
+class String
+ def red
+ colorize(31)
+ end
+
+private
+
+ def colorize(color_code)
+ "\e[#{color_code}m#{self}\e[0m"
+ end
+end
+
+module Migrator
+ def db_version
+ "3.9.80"
+ end
+
+ def one_version
+ "OpenNebula 3.9.80"
+ end
+
+ def up
+
+ init_log_time()
+
+ ########################################################################
+ # 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
+
+ log_time()
+
+ ########################################################################
+ # Image
+ #
+ # IMAGE/CLONING_OPS
+ # IMAGE/CLONES/ID
+ ########################################################################
+
+ @db.run "CREATE TABLE image_pool_new (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name,uid) );"
+
+ @db.transaction do
+ @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
+ end
+
+ # Rename table
+ @db.run("DROP TABLE image_pool")
+ @db.run("ALTER TABLE image_pool_new RENAME TO image_pool")
+
+ log_time()
+
+ ########################################################################
+ # Feature #1565: New cid column in host, ds and vnet tables
+ ########################################################################
+
+ @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, UNIQUE(name));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_host_pool") do |row|
+ doc = Document.new(row[:body])
+
+ cluster_id = doc.root.get_text('CLUSTER_ID').to_s
+
+ @db[:host_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => row[:body],
+ :state => row[:state],
+ :last_mon_time => row[:last_mon_time],
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :cid => cluster_id)
+ end
+ end
+
+ @db.run "DROP TABLE old_host_pool;"
+
+ log_time()
+
+ ########################################################################
+ # Feature #1565: New cid column
+ # Feature #471: IPv6 addresses
+ ########################################################################
+
+ @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, cid INTEGER, UNIQUE(name,uid));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_network_pool") do |row|
+ doc = Document.new(row[:body])
+
+ cluster_id = doc.root.get_text('CLUSTER_ID').to_s
+
+ doc.root.add_element("GLOBAL_PREFIX")
+ doc.root.add_element("SITE_PREFIX")
+
+ @db[:network_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :cid => cluster_id)
+ end
+ end
+
+ @db.run "DROP TABLE old_network_pool;"
+
+ log_time()
+
+ ########################################################################
+ # Feature #1617
+ # New datastore, 2 "files"
+ # DATASTORE/SYSTEM is now DATASTORE/TYPE
+ #
+ # Feature #1565: New cid column in host, ds and vnet tables
+ ########################################################################
+
+ @db.run "ALTER TABLE datastore_pool RENAME TO old_datastore_pool;"
+ @db.run "CREATE TABLE datastore_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, cid INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_datastore_pool") do |row|
+ doc = Document.new(row[:body])
+
+ type = "0" # IMAGE_DS
+
+ system_elem = doc.root.delete_element("SYSTEM")
+
+ if ( !system_elem.nil? && system_elem.text == "1" )
+ type = "1" # SYSTEM_DS
+ end
+
+ doc.root.add_element("TYPE").text = type
+
+ doc.root.each_element("TEMPLATE") do |e|
+ e.delete_element("SYSTEM")
+ e.add_element("TYPE").text = type == "0" ? "IMAGE_DS" : "SYSTEM_DS"
+ end
+
+ cluster_id = doc.root.get_text('CLUSTER_ID').to_s
+
+ @db[:datastore_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :cid => cluster_id)
+ end
+ end
+
+ @db.run "DROP TABLE old_datastore_pool;"
+
+ log_time()
+
+ user_0_name = "oneadmin"
+
+ @db.fetch("SELECT name FROM user_pool WHERE oid=0") do |row|
+ user_0_name = row[:name]
+ end
+
+ group_0_name = "oneadmin"
+
+ @db.fetch("SELECT name FROM group_pool WHERE oid=0") do |row|
+ group_0_name = row[:name]
+ end
+
+ base_path = "/var/lib/one/datastores/2"
+
+ @db.fetch("SELECT body FROM datastore_pool WHERE oid=0") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.each_element("BASE_PATH") do |e|
+ base_path = e.text
+ base_path[-1] = "2"
+ end
+ end
+
+ @db.run "INSERT INTO datastore_pool VALUES(2,'files','200#{user_0_name}#{group_0_name}files110100100fsssh#{base_path}20-1',0,0,1,1,1,-1);"
+
+ log_time()
+
+ ########################################################################
+ # Feature #1611: Default quotas
+ ########################################################################
+
+ @db.run("CREATE TABLE IF NOT EXISTS system_attributes (name VARCHAR(128) PRIMARY KEY, body MEDIUMTEXT)")
+ @db.run("INSERT INTO system_attributes VALUES('DEFAULT_GROUP_QUOTAS','');")
+ @db.run("INSERT INTO system_attributes VALUES('DEFAULT_USER_QUOTAS','');")
+
+
+ @db.run "ALTER TABLE user_pool RENAME TO old_user_pool;"
+ @db.run "CREATE TABLE user_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ # oneadmin does not have quotas
+ @db.fetch("SELECT * FROM old_user_pool WHERE oid=0") do |row|
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => row[:body],
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.fetch("SELECT * FROM old_user_pool WHERE oid>0") do |row|
+ doc = nokogiri_doc(row[:body], 'old_user_pool')
+
+ set_default_quotas(doc)
+
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_user_pool;"
+
+ log_time()
+
+ @db.run "ALTER TABLE group_pool RENAME TO old_group_pool;"
+ @db.run "CREATE TABLE group_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ # oneadmin group does not have quotas
+ @db.fetch("SELECT * FROM old_group_pool WHERE oid=0") do |row|
+ @db[:group_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => row[:body],
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.fetch("SELECT * FROM old_group_pool WHERE oid>0") do |row|
+ doc = nokogiri_doc(row[:body], 'old_group_pool')
+
+ set_default_quotas(doc)
+
+ @db[:group_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_group_pool;"
+
+ log_time()
+
+ ########################################################################
+ # Bug #1694: SYSTEM_DS is now set with the method adddatastore
+ ########################################################################
+
+ @db.run "ALTER TABLE cluster_pool RENAME TO old_cluster_pool;"
+ @db.run "CREATE TABLE cluster_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_cluster_pool") do |row|
+ doc = Document.new(row[:body])
+
+ system_ds = 0
+
+ doc.root.each_element("TEMPLATE") do |e|
+ elem = e.delete_element("SYSTEM_DS")
+
+ if !elem.nil?
+ system_ds = elem.text.to_i
+ end
+ end
+
+ if system_ds != 0
+ updated_body = nil
+
+ @db.fetch("SELECT body FROM datastore_pool WHERE oid=#{system_ds}") do |ds_row|
+ ds_doc = Document.new(ds_row[:body])
+
+ type = "0" # IMAGE_DS
+
+ ds_doc.root.each_element("TYPE") do |e|
+ type = e.text
+ end
+
+ if type != "1"
+ puts " > Cluster #{row[:oid]} has the "<<
+ "System Datastore set to Datastore #{system_ds}, "<<
+ "but its type is not SYSTEM_DS. The System Datastore "<<
+ "for this Cluster will be set to 0"
+
+ system_ds = 0
+ else
+ cluster_id = "-1"
+
+ ds_doc.root.each_element("CLUSTER_ID") do |e|
+ cluster_id = e.text
+ end
+
+ if row[:oid] != cluster_id.to_i
+ puts " > Cluster #{row[:oid]} has the "<<
+ "System Datastore set to Datastore #{system_ds}, "<<
+ "but it is not part of the Cluster. It will be added now."
+
+ ds_doc.root.each_element("CLUSTER_ID") do |e|
+ e.text = row[:oid]
+ end
+
+ ds_doc.root.each_element("CLUSTER") do |e|
+ e.text = row[:name]
+ end
+
+ updated_body = ds_doc.root.to_s
+ end
+ end
+ end
+
+ if !updated_body.nil?
+ @db[:datastore_pool].where(:oid => system_ds).update(
+ :body => updated_body)
+ end
+ end
+
+ doc.root.add_element("SYSTEM_DS").text = system_ds.to_s
+
+ @db[:cluster_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_cluster_pool;"
+
+ log_time()
+
+ ########################################################################
+ # Feature #1556: New elem USER_TEMPLATE
+ #
+ # Feature #1483: Move scheduling attributes
+ # /VM/TEMPLATE/REQUIREMENTS -> USER_TEMPLATE/SCHED_REQUIREMENTS
+ # /VM/TEMPLATE/RANK -> USER_TEMPLATE/SCHED_RANK
+ ########################################################################
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE 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_doc(row[:body], 'old_vm_pool')
+ user_template = doc.create_element("USER_TEMPLATE")
+
+ e = doc.root.at_xpath("TEMPLATE")
+ elem = e.at_xpath("REQUIREMENTS")
+
+ if !elem.nil?
+ new_elem = doc.create_element("SCHED_REQUIREMENTS")
+ new_elem.content = elem.text
+ elem.remove
+
+ user_template.add_child(new_elem)
+ end
+
+ elem = e.at_xpath("RANK")
+
+ if !elem.nil?
+ new_elem = doc.create_element("SCHED_RANK")
+ new_elem.content = elem.text
+ elem.remove
+
+ user_template.add_child(new_elem)
+ end
+
+ doc.root << user_template
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+ log_time()
+
+ ########################################################################
+ # Feature #1483: Move scheduling attributes
+ # /VMTEMPLATE/TEMPLATE/REQUIREMENTS -> /VMTEMPLATE/TEMPLATE/SCHED_REQUIREMENTS
+ # /VMTEMPLATE/TEMPLATE/RANK -> /VMTEMPLATE/TEMPLATE/SCHED_RANK
+ ########################################################################
+
+ @db.run "ALTER TABLE template_pool RENAME TO old_template_pool;"
+ @db.run "CREATE TABLE template_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_template_pool") do |row|
+
+ doc = nokogiri_doc(row[:body], 'old_template_pool')
+
+ template = doc.root.at_xpath("TEMPLATE")
+
+ elem = template.at_xpath("REQUIREMENTS")
+
+ if !elem.nil?
+ new_elem = doc.create_element("SCHED_REQUIREMENTS")
+ new_elem.content = elem.text
+ elem.remove
+
+ template.add_child(new_elem)
+ end
+
+ elem = template.at_xpath("RANK")
+
+ if !elem.nil?
+ new_elem = doc.create_element("SCHED_RANK")
+ new_elem.content = elem.text
+ elem.remove
+
+ template.add_child(new_elem)
+ end
+
+ @db[:template_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_template_pool;"
+
+ log_time()
+
+ ########################################################################
+ # Feature #1691 Add new attribute NIC/NIC_ID
+ ########################################################################
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE 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|
+ if ( row[:state] != 6 ) # DONE
+ doc = nokogiri_doc(row[:body], 'old_vm_pool')
+
+ nic_id = 0
+
+ doc.root.xpath("TEMPLATE/NIC").each { |e|
+ e.xpath("NIC_ID").each {|n| n.remove}
+ e.add_child(doc.create_element("NIC_ID")).content =
+ (nic_id).to_s
+
+ nic_id += 1
+ }
+
+ row[:body] = doc.root.to_s
+ end
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => row[:body],
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+ log_time()
+
+ ########################################################################
+ #
+ # Banner for the new /var/lib/one/vms directory
+ #
+ ########################################################################
+
+ puts
+ puts "ATTENTION: manual intervention required".red
+ puts <<-END.gsub(/^ {8}/, '')
+ Virtual Machine deployment files have been moved from /var/lib/one to
+ /var/lib/one/vms. You need to move these files manually:
+
+ $ mv /var/lib/one/[0-9]* /var/lib/one/vms
+
+ END
+
+ return true
+ end
+
+
+ def set_default_quotas(doc)
+
+ # VM quotas
+
+ doc.root.xpath("VM_QUOTA/VM/CPU").each do |e|
+ e.content = "-1" if e.text.to_f == 0
+ end
+
+ doc.root.xpath("VM_QUOTA/VM/MEMORY").each do |e|
+ e.content = "-1" if e.text.to_i == 0
+ end
+
+ doc.root.xpath("VM_QUOTA/VM/VMS").each do |e|
+ e.content = "-1" if e.text.to_i == 0
+ end
+
+ # VNet quotas
+
+ doc.root.xpath("NETWORK_QUOTA/NETWORK/LEASES").each do |e|
+ e.content = "-1" if e.text.to_i == 0
+ end
+
+ # Image quotas
+
+ doc.root.xpath("IMAGE_QUOTA/IMAGE/RVMS").each do |e|
+ e.content = "-1" if e.text.to_i == 0
+ end
+
+ # Datastore quotas
+
+ doc.root.xpath("DATASTORE_QUOTA/DATASTORE/IMAGES").each do |e|
+ e.content = "-1" if e.text.to_i == 0
+ end
+
+ doc.root.xpath("DATASTORE_QUOTA/DATASTORE/SIZE").each do |e|
+ e.content = "-1" if e.text.to_i == 0
+ end
+ end
+end
diff --git a/src/onedb/shared/3.9.80_to_3.9.90.rb b/src/onedb/shared/3.9.80_to_3.9.90.rb
new file mode 100644
index 0000000000..59763c79ca
--- /dev/null
+++ b/src/onedb/shared/3.9.80_to_3.9.90.rb
@@ -0,0 +1,162 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 "nokogiri"
+
+class String
+ def red
+ colorize(31)
+ end
+
+private
+
+ def colorize(color_code)
+ "\e[#{color_code}m#{self}\e[0m"
+ end
+end
+
+module Migrator
+ def db_version
+ "3.9.90"
+ end
+
+ def one_version
+ "OpenNebula 3.9.90"
+ end
+
+ def up
+ init_log_time()
+
+ ########################################################################
+ # Feature #1631: Add ACTION to history entries
+ ########################################################################
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE 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_doc(row[:body], 'old_vm_pool')
+
+ doc.root.xpath("HISTORY_RECORDS/HISTORY").each do |e|
+ update_history(e)
+ end
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+ log_time()
+
+ @db.run "ALTER TABLE history RENAME TO old_history;"
+ @db.run "CREATE TABLE history (vid INTEGER, seq INTEGER, body MEDIUMTEXT, stime INTEGER, etime INTEGER,PRIMARY KEY(vid,seq));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_history") do |row|
+ doc = nokogiri_doc(row[:body], 'old_history')
+
+ doc.root.xpath("/HISTORY").each do |e|
+ update_history(e)
+ end
+
+ @db[:history].insert(
+ :vid => row[:vid],
+ :seq => row[:seq],
+ :body => doc.root.to_s,
+ :stime => row[:stime],
+ :etime => row[:etime])
+ end
+ end
+
+ @db.run "DROP TABLE old_history;"
+
+ log_time()
+
+ ########################################################################
+ # Banner for drivers renamed
+ ########################################################################
+
+ puts
+ puts "ATTENTION: manual intervention required".red
+ puts <<-END.gsub(/^ {8}/, '')
+ IM and VM MADS have been renamed in oned.conf. To keep your
+ existing hosts working, you need to duplicate the drivers with the
+ old names.
+
+ For example, for kvm you will have IM_MAD "kvm" and VM_MAD "kvm", so you
+ need to add IM_MAD "im_kvm" and VM_MAD "vmm_kvm"
+
+ IM_MAD = [
+ name = "kvm",
+ executable = "one_im_ssh",
+ arguments = "-r 0 -t 15 kvm" ]
+
+
+ IM_MAD = [
+ name = "im_kvm",
+ executable = "one_im_ssh",
+ arguments = "-r 0 -t 15 kvm" ]
+
+ VM_MAD = [
+ name = "kvm",
+ executable = "one_vmm_exec",
+ arguments = "-t 15 -r 0 kvm",
+ default = "vmm_exec/vmm_exec_kvm.conf",
+ type = "kvm" ]
+
+ VM_MAD = [
+ name = "vmm_kvm",
+ executable = "one_vmm_exec",
+ arguments = "-t 15 -r 0 kvm",
+ default = "vmm_exec/vmm_exec_kvm.conf",
+ type = "kvm" ]
+
+ END
+
+ return true
+ end
+
+ def update_history(history_elem)
+ # NONE_ACTION
+ history_elem.add_child(
+ history_elem.document.create_element("ACTION")).content = "0"
+
+ # History reason enum has changed from
+ # NONE, ERROR, STOP_RESUME, USER, CANCEL to
+ # NONE, ERROR, USER
+ history_elem.xpath("REASON").each do |reason_e|
+ reason = reason_e.text.to_i
+
+ if reason > 1 # STOP_RESUME, USER, CANCEL
+ reason_e.content = "2" # USER
+ end
+ end
+ end
+end
diff --git a/src/onedb/shared/3.9.90_to_4.0.0.rb b/src/onedb/shared/3.9.90_to_4.0.0.rb
new file mode 100644
index 0000000000..87d0315c02
--- /dev/null
+++ b/src/onedb/shared/3.9.90_to_4.0.0.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "4.0.0"
+ end
+
+ def one_version
+ "OpenNebula 4.0.0"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/4.0.0_to_4.0.1.rb b/src/onedb/shared/4.0.0_to_4.0.1.rb
new file mode 100644
index 0000000000..7e610e576e
--- /dev/null
+++ b/src/onedb/shared/4.0.0_to_4.0.1.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "4.0.1"
+ end
+
+ def one_version
+ "OpenNebula 4.0.1"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/4.0.1_to_4.1.80.rb b/src/onedb/shared/4.0.1_to_4.1.80.rb
new file mode 100644
index 0000000000..9395486937
--- /dev/null
+++ b/src/onedb/shared/4.0.1_to_4.1.80.rb
@@ -0,0 +1,109 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'fileutils'
+require 'openssl'
+
+require "nokogiri"
+
+module Migrator
+ def db_version
+ "4.1.80"
+ end
+
+ def one_version
+ "OpenNebula 4.1.80"
+ end
+
+ def up
+
+ begin
+ FileUtils.cp("#{VAR_LOCATION}/.one/sunstone_auth",
+ "#{VAR_LOCATION}/.one/onegate_auth", :preserve => true)
+
+ FileUtils.cp("#{VAR_LOCATION}/.one/sunstone_auth",
+ "#{VAR_LOCATION}/.one/oneflow_auth", :preserve => true)
+ rescue
+ puts "Error trying to copy #{VAR_LOCATION}/.one/sunstone_auth "<<
+ "to #{VAR_LOCATION}/.one/onegate_auth and #{VAR_LOCATION}/.one/oneflow_auth."
+ puts "Please copy the files manually."
+ end
+
+ init_log_time()
+
+ @db.run "ALTER TABLE user_pool RENAME TO old_user_pool;"
+ @db.run "CREATE TABLE user_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_user_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_user_pool')
+
+ doc.root.at_xpath("TEMPLATE").
+ add_child(doc.create_element("TOKEN_PASSWORD")).
+ content = OpenSSL::Digest::SHA1.hexdigest( rand().to_s )
+
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_user_pool;"
+
+ log_time()
+
+ ########################################################################
+ # Feature #1613
+ ########################################################################
+
+ @db.run "ALTER TABLE datastore_pool RENAME TO old_datastore_pool;"
+ @db.run "CREATE TABLE datastore_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, cid INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_datastore_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_datastore_pool')
+
+ doc.root.add_child(doc.create_element("TOTAL_MB")).content = "0"
+ doc.root.add_child(doc.create_element("FREE_MB")).content = "0"
+ doc.root.add_child(doc.create_element("USED_MB")).content = "0"
+
+ @db[:datastore_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :cid => row[:cid])
+ end
+ end
+
+ @db.run "DROP TABLE old_datastore_pool;"
+
+ log_time()
+
+ return true
+ end
+end
diff --git a/src/onedb/shared/4.1.80_to_4.2.0.rb b/src/onedb/shared/4.1.80_to_4.2.0.rb
new file mode 100644
index 0000000000..4cb6afb3b6
--- /dev/null
+++ b/src/onedb/shared/4.1.80_to_4.2.0.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "4.2.0"
+ end
+
+ def one_version
+ "OpenNebula 4.2.0"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/4.11.80_to_4.90.0.rb b/src/onedb/shared/4.11.80_to_4.90.0.rb
new file mode 100644
index 0000000000..527198b052
--- /dev/null
+++ b/src/onedb/shared/4.11.80_to_4.90.0.rb
@@ -0,0 +1,204 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'opennebula'
+
+include OpenNebula
+
+module Migrator
+ def db_version
+ "4.90.0"
+ end
+
+ def one_version
+ "OpenNebula 4.90.0"
+ end
+
+ USER_TRANSFORM_ATTRS = {
+ 'SUNSTONE_DISPLAY_NAME' => 'DISPLAY_NAME',
+ 'LANG' => 'LANG',
+ 'TABLE_DEFAULT_PAGE_LENGTH' => 'TABLE_DEFAULT_PAGE_LENGTH',
+ 'TABLE_ORDER' => 'TABLE_ORDER',
+ 'DEFAULT_VIEW' => 'DEFAULT_VIEW',
+ 'GROUP_ADMIN_DEFAULT_VIEW' => 'GROUP_ADMIN_DEFAULT_VIEW'
+ }
+
+ GROUP_TRANSFORM_ATTRS = {
+ "SUNSTONE_VIEWS" => "VIEWS",
+ "DEFAULT_VIEW" => "DEFAULT_VIEW",
+ "GROUP_ADMIN_VIEWS" => "GROUP_ADMIN_VIEWS",
+ "GROUP_ADMIN_DEFAULT_VIEW" => "GROUP_ADMIN_DEFAULT_VIEW"
+ }
+
+ def up
+ init_log_time()
+
+ # Feature #3671
+
+ @db.run "ALTER TABLE user_pool RENAME TO old_user_pool;"
+ @db.run "CREATE TABLE user_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_user_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_user_pool')
+
+ USER_TRANSFORM_ATTRS.each do |old_name, new_name|
+ elem = doc.at_xpath("/USER/TEMPLATE/#{old_name}")
+
+ if (!elem.nil?)
+ elem.remove
+
+ elem.name = new_name
+
+ if (doc.at_xpath("/USER/TEMPLATE/SUNSTONE").nil?)
+ doc.at_xpath("/USER/TEMPLATE").add_child(
+ doc.create_element("SUNSTONE"))
+ end
+
+ doc.at_xpath("/USER/TEMPLATE/SUNSTONE").add_child(elem)
+ end
+ end
+
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_user_pool;"
+
+ log_time()
+
+ @db.run "ALTER TABLE group_pool RENAME TO old_group_pool;"
+ @db.run "CREATE TABLE group_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_group_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_group_pool')
+
+ GROUP_TRANSFORM_ATTRS.each do |old_name, new_name|
+ elem = doc.at_xpath("/GROUP/TEMPLATE/#{old_name}")
+
+ if (!elem.nil?)
+ elem.remove
+
+ elem.name = new_name
+
+ if (doc.at_xpath("/GROUP/TEMPLATE/SUNSTONE").nil?)
+ doc.at_xpath("/GROUP/TEMPLATE").add_child(
+ doc.create_element("SUNSTONE"))
+ end
+
+ doc.at_xpath("/GROUP/TEMPLATE/SUNSTONE").add_child(elem)
+ end
+ end
+
+ @db[:group_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_group_pool;"
+
+ log_time()
+
+ # Feature #4215
+
+ @db.transaction do
+ @db.fetch("SELECT oid,body FROM group_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'group_pool')
+
+ doc.root.xpath("ADMINS/ID").each do |uid|
+ user = Acl::USERS["UID"] | uid.text.to_i
+ resource = 354936097341440 | Acl::USERS["GID"] | row[:oid]
+
+ @db[:acl].where({
+ :user=>user, # #
+ :resource=>resource, # VM+NET+IMAGE+TEMPLATE+DOCUMENT+SECGROUP/@
+ :rights=>3, # USE+MANAGE
+ :zone=>17179869184 # *
+ }).update(
+ # VM+NET+IMAGE+TEMPLATE+DOCUMENT+SECGROUP+VROUTER/@101
+ :resource => (1480836004184064 | Acl::USERS["GID"] | row[:oid]))
+ end
+ end
+ end
+
+ log_time()
+
+ # Feature #4217
+
+ oneadmin_uname = nil
+
+ @db.fetch("SELECT name FROM user_pool WHERE oid=0") do |row|
+ oneadmin_uname = row[:name]
+ end
+
+ if oneadmin_uname == nil
+ puts "Error trying to read oneadmin's user name ('SELECT name FROM user_pool WHERE oid=0')"
+ return false
+ end
+
+ oneadmin_gname = nil
+
+ @db.fetch("SELECT name FROM group_pool WHERE oid=0") do |row|
+ oneadmin_gname = row[:name]
+ end
+
+ if oneadmin_gname == nil
+ puts "Error trying to read oneadmin's group name ('SELECT name FROM group_pool WHERE oid=0')"
+ return false
+ end
+
+ @db.run "CREATE TABLE marketplace_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.run "INSERT INTO marketplace_pool VALUES(0,'OpenNebula Public','000#{oneadmin_uname}#{oneadmin_gname}OpenNebula Public000111100100',0,0,1,1,1);"
+
+ @db.run "INSERT INTO pool_control VALUES('marketplace_pool',99);"
+
+ @db.run "CREATE TABLE marketplaceapp_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name,uid));"
+
+ last_oid = -1
+
+ @db.fetch("SELECT last_oid FROM pool_control WHERE tablename='acl'") do |row|
+ last_oid = row[:last_oid].to_i
+ end
+
+ # * MARKETPLACE+MARKETPLACEAPP/* USE *
+ @db.run "INSERT INTO acl VALUES(#{last_oid+1},17179869184,6755416620924928,1,17179869184);"
+
+ @db.run "REPLACE INTO pool_control VALUES('acl', #{last_oid+1});"
+
+ log_time()
+
+ return true
+ end
+
+end
diff --git a/src/onedb/shared/4.2.0_to_4.3.80.rb b/src/onedb/shared/4.2.0_to_4.3.80.rb
new file mode 100644
index 0000000000..feee67d3f2
--- /dev/null
+++ b/src/onedb/shared/4.2.0_to_4.3.80.rb
@@ -0,0 +1,435 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'rexml/document'
+require 'nokogiri'
+
+TM_MAD_CONF = {
+ "dummy" => {
+ :ln_target => "NONE",
+ :clone_target => "SYSTEM"
+ },
+ "lvm" => {
+ :ln_target => "NONE",
+ :clone_target => "SELF"
+ },
+ "shared" => {
+ :ln_target => "NONE",
+ :clone_target => "SYSTEM"
+ },
+ "shared_lvm" => {
+ :ln_target => "SYSTEM",
+ :clone_target => "SYSTEM"
+ },
+ "qcow2" => {
+ :ln_target => "NONE",
+ :clone_target => "SYSTEM"
+ },
+ "ssh" => {
+ :ln_target => "SYSTEM",
+ :clone_target => "SYSTEM"
+ },
+ "vmfs" => {
+ :ln_target => "NONE",
+ :clone_target => "SYSTEM"
+ },
+ "iscsi" => {
+ :ln_target => "NONE",
+ :clone_target => "SELF"
+ },
+ "ceph" => {
+ :ln_target => "NONE",
+ :clone_target => "SELF"
+ }
+}
+
+class String
+ def red
+ colorize(31)
+ end
+
+private
+
+ def colorize(color_code)
+ "\e[#{color_code}m#{self}\e[0m"
+ end
+end
+
+module Migrator
+ def db_version
+ "4.3.80"
+ end
+
+ def one_version
+ "OpenNebula 4.3.80"
+ end
+
+ def up
+
+ init_log_time()
+
+ ########################################################################
+ # Feature #1742 & #1612
+ ########################################################################
+
+ @db.run "ALTER TABLE user_pool RENAME TO old_user_pool;"
+ @db.run "CREATE TABLE user_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_user_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_user_pool')
+
+ g_elem = doc.create_element("GROUPS")
+ g_elem.add_child(doc.create_element("ID")).content = row[:gid].to_s
+
+ doc.root.add_child(g_elem)
+
+ # oneadmin does not have quotas
+ if row[:oid] != 0
+ redo_vm_quotas(doc, "uid=#{row[:oid]}")
+ end
+
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_user_pool;"
+
+ log_time()
+
+ ########################################################################
+ # Feature #1612
+ ########################################################################
+
+ @db.run "ALTER TABLE group_pool RENAME TO old_group_pool;"
+ @db.run "CREATE TABLE group_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ # oneadmin group does not have quotas
+ @db.fetch("SELECT * FROM old_group_pool WHERE oid=0") do |row|
+ @db[:group_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => row[:body],
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.fetch("SELECT * FROM old_group_pool WHERE oid>0") do |row|
+ doc = nokogiri_doc(row[:body], 'old_group_pool')
+
+ redo_vm_quotas(doc, "gid=#{row[:oid]}")
+
+ @db[:group_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_group_pool;"
+
+ log_time()
+
+ ########################################################################
+ # Bug #2330 & Feature #1678
+ ########################################################################
+
+ @db.run "ALTER TABLE datastore_pool RENAME TO old_datastore_pool;"
+ @db.run "CREATE TABLE datastore_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, cid INTEGER, UNIQUE(name));"
+
+ #tm_mads = {}
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_datastore_pool") do |row|
+ doc = REXML::Document.new(row[:body])
+
+ doc.root.each_element("TEMPLATE/HOST") do |e|
+ e.name = "BRIDGE_LIST"
+ end
+
+ tm_mad = ""
+ doc.root.each_element("TM_MAD"){ |e| tm_mad = e.text }
+
+ type = 0
+ doc.root.each_element("TYPE"){ |e| type = e.text.to_i }
+
+ if (type == 1) # System DS
+ doc.root.each_element("TEMPLATE") do |e|
+ e.add_element("SHARED").text =
+ (tm_mad == "ssh" ? "NO" : "YES")
+ end
+ else
+ #tm_mads[row[:oid].to_i] = tm_mad
+
+ conf = TM_MAD_CONF[tm_mad]
+
+ if conf.nil?
+ puts
+ puts "ATTENTION: manual intervention required".red
+ puts <<-END
+The Datastore ##{row[:oid]} #{row[:name]} is using the
+custom TM MAD '#{tm_mad}'. You will need to define new
+configuration parameters in oned.conf for this driver, see
+http://opennebula.org/documentation:rel4.4:upgrade
+ END
+ else
+ doc.root.each_element("TEMPLATE") do |e|
+ e.add_element("LN_TARGET").text = conf[:ln_target]
+ e.add_element("CLONE_TARGET").text = conf[:clone_target]
+ end
+ end
+ end
+
+ @db[:datastore_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :cid => row[:cid])
+ end
+ end
+
+ @db.run "DROP TABLE old_datastore_pool;"
+
+ log_time()
+
+ ########################################################################
+ # Feature #2392
+ ########################################################################
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE 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_doc(row[:body], 'old_vm_pool')
+
+ doc.root.xpath("HISTORY_RECORDS/HISTORY").each do |e|
+ update_history(e)
+ end
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+ log_time()
+
+ @db.run "ALTER TABLE history RENAME TO old_history;"
+ @db.run "CREATE TABLE history (vid INTEGER, seq INTEGER, body MEDIUMTEXT, stime INTEGER, etime INTEGER,PRIMARY KEY(vid,seq));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_history") do |row|
+ doc = nokogiri_doc(row[:body], 'old_history')
+
+ doc.root.xpath("/HISTORY").each do |e|
+ update_history(e)
+ end
+
+ @db[:history].insert(
+ :vid => row[:vid],
+ :seq => row[:seq],
+ :body => doc.root.to_s,
+ :stime => row[:stime],
+ :etime => row[:etime])
+ end
+ end
+
+ @db.run "DROP TABLE old_history;"
+
+ log_time()
+
+ ########################################################################
+ # Feature #1678
+ ########################################################################
+
+ @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, UNIQUE(name));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_host_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_host_pool')
+
+ doc.root.at_xpath("HOST_SHARE").
+ add_child(doc.create_element("DATASTORES"))
+
+ @db[:host_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :state => row[:state],
+ :last_mon_time => row[:last_mon_time],
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :cid => row[:cid])
+ end
+ end
+
+ @db.run "DROP TABLE old_host_pool;"
+
+ log_time()
+
+ # TODO:
+ # For Feature #1678, VMs have new disk elements:
+ # VM/DISK/CLONE_TARGET
+ # VM/DISK/LN_TARGET
+ # VM/DISK/SIZE
+ #
+ # These elements are only used to schedule new deployments, so if we
+ # don't add them it will only affect automatic deployment of VMs
+ # recreated (onevm delete --recreate). Manual deployments will still
+ # work without problems.
+
+ return true
+ end
+
+ def redo_vm_quotas(doc, where_filter)
+ cpu_limit = "-1"
+ mem_limit = "-1"
+ vms_limit = "-1"
+ vol_limit = "-1"
+
+ doc.root.xpath("VM_QUOTA/VM/CPU").each { |e|
+ cpu_limit = e.text
+ }
+
+ doc.root.xpath("VM_QUOTA/VM/MEMORY").each { |e|
+ mem_limit = e.text
+ }
+
+ doc.root.xpath("VM_QUOTA/VM/VMS").each { |e|
+ vms_limit = e.text
+ }
+
+ doc.root.xpath("VM_QUOTA").each { |e|
+ e.remove
+ }
+
+ vm_quota = doc.root.add_child(doc.create_element("VM_QUOTA"))
+
+ # VM quotas
+ cpu_used = 0
+ mem_used = 0
+ vms_used = 0
+ vol_used = 0
+
+ @db.fetch("SELECT body FROM vm_pool WHERE #{where_filter} AND state<>6") do |vm_row|
+ vmdoc = nokogiri_doc(vm_row[:body], 'vm_pool')
+
+ # VM quotas
+ vmdoc.root.xpath("TEMPLATE/CPU").each { |e|
+ cpu_used += e.text.to_f
+ }
+
+ vmdoc.root.xpath("TEMPLATE/MEMORY").each { |e|
+ mem_used += e.text.to_i
+ }
+
+ vmdoc.root.xpath("TEMPLATE/DISK").each { |e|
+ type = ""
+
+ e.xpath("TYPE").each { |t_elem|
+ type = t_elem.text.upcase
+ }
+
+ if ( type == "SWAP" || type == "FS")
+ e.xpath("SIZE").each { |size_elem|
+ vol_used += size_elem.text.to_i
+ }
+ end
+ }
+
+ vms_used += 1
+ end
+
+ if (vms_used != 0 ||
+ cpu_limit != "-1" || mem_limit != "-1" || vms_limit != "-1" || vol_limit != "-1" )
+
+ # VM quotas
+ vm_elem = vm_quota.add_child(doc.create_element("VM"))
+
+ vm_elem.add_child(doc.create_element("CPU")).content = cpu_limit
+ vm_elem.add_child(doc.create_element("CPU_USED")).content = sprintf('%.2f', cpu_used)
+
+ vm_elem.add_child(doc.create_element("MEMORY")).content = mem_limit
+ vm_elem.add_child(doc.create_element("MEMORY_USED")).content = mem_used.to_s
+
+ vm_elem.add_child(doc.create_element("VMS")).content = vms_limit
+ vm_elem.add_child(doc.create_element("VMS_USED")).content = vms_used.to_s
+
+ vm_elem.add_child(doc.create_element("VOLATILE_SIZE")).content = vol_limit
+ vm_elem.add_child(doc.create_element("VOLATILE_SIZE_USED")).content = vol_used.to_s
+ end
+ end
+
+ def update_history(history_elem)
+ hid = nil
+
+ history_elem.xpath("HID").each do |e|
+ hid = e.text
+ end
+
+ new_elem = history_elem.add_child(
+ history_elem.document.create_element("CID"))
+
+ new_elem.content = "-1" # Cluster None
+
+ if hid.nil?
+ return
+ end
+
+ @db.fetch("SELECT cid FROM host_pool WHERE oid = #{hid}") do |row|
+ new_elem.content = row[:cid].to_s
+ end
+ end
+
+end
diff --git a/src/onedb/shared/4.3.80_to_4.3.85.rb b/src/onedb/shared/4.3.80_to_4.3.85.rb
new file mode 100644
index 0000000000..3e8988e2e9
--- /dev/null
+++ b/src/onedb/shared/4.3.80_to_4.3.85.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "4.3.85"
+ end
+
+ def one_version
+ "OpenNebula 4.3.85"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/4.3.85_to_4.3.90.rb b/src/onedb/shared/4.3.85_to_4.3.90.rb
new file mode 100644
index 0000000000..2888cbe7ee
--- /dev/null
+++ b/src/onedb/shared/4.3.85_to_4.3.90.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "4.3.90"
+ end
+
+ def one_version
+ "OpenNebula 4.3.90"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/4.3.90_to_4.4.0.rb b/src/onedb/shared/4.3.90_to_4.4.0.rb
new file mode 100644
index 0000000000..06b4f18539
--- /dev/null
+++ b/src/onedb/shared/4.3.90_to_4.4.0.rb
@@ -0,0 +1,31 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "4.4.0"
+ end
+
+ def one_version
+ "OpenNebula 4.4.0"
+ end
+
+ def up
+ @db.run "UPDATE host_pool SET last_mon_time=0 WHERE last_mon_time IS NULL;"
+ return true
+ end
+end
diff --git a/src/onedb/shared/4.4.0_to_4.4.1.rb b/src/onedb/shared/4.4.0_to_4.4.1.rb
new file mode 100644
index 0000000000..e1b577cc9a
--- /dev/null
+++ b/src/onedb/shared/4.4.0_to_4.4.1.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "4.4.1"
+ end
+
+ def one_version
+ "OpenNebula 4.4.1"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/4.4.1_to_4.5.80.rb b/src/onedb/shared/4.4.1_to_4.5.80.rb
new file mode 100644
index 0000000000..4af4f545c7
--- /dev/null
+++ b/src/onedb/shared/4.4.1_to_4.5.80.rb
@@ -0,0 +1,248 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'nokogiri'
+
+module Migrator
+ def db_version
+ "4.5.80"
+ end
+
+ def one_version
+ "OpenNebula 4.5.80"
+ end
+
+ def up
+
+ init_log_time()
+
+ @db.run "ALTER TABLE acl RENAME TO old_acl;"
+ @db.run "CREATE TABLE acl (oid INT PRIMARY KEY, user BIGINT, resource BIGINT, rights BIGINT, zone BIGINT, UNIQUE(user, resource, rights, zone));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_acl") do |row|
+ @db[:acl].insert(
+ :oid => row[:oid],
+ :user => row[:user],
+ :resource => row[:resource],
+ :rights => row[:rights],
+ :zone => 4294967296)
+ end
+ end
+
+ @db.run "DROP TABLE old_acl;"
+
+ log_time()
+
+ # Move USER/QUOTA to user_quotas table
+
+ @db.run "ALTER TABLE user_pool RENAME TO old_user_pool;"
+ @db.run "CREATE TABLE user_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.run "CREATE TABLE user_quotas (user_oid INTEGER PRIMARY KEY, body MEDIUMTEXT);"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_user_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_user_pool')
+
+ quotas_doc = extract_quotas(doc)
+
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+
+ @db[:user_quotas].insert(
+ :user_oid => row[:oid],
+ :body => quotas_doc.root.to_s)
+ end
+ end
+
+ @db.run "DROP TABLE old_user_pool;"
+
+ log_time()
+
+ # GROUP/RESOURCE_PROVIDER is not needed
+
+ # Move GROUP/QUOTA to group_quotas table
+ # Add GROUP/TEMPLATE
+
+ @db.run "ALTER TABLE group_pool RENAME TO old_group_pool;"
+ @db.run "CREATE TABLE group_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.run "CREATE TABLE group_quotas (group_oid INTEGER PRIMARY KEY, body MEDIUMTEXT);"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_group_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_group_pool')
+
+ quotas_doc = extract_quotas(doc)
+
+ doc.root.add_child(doc.create_element("TEMPLATE"))
+
+ @db[:group_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+
+ @db[:group_quotas].insert(
+ :group_oid => row[:oid],
+ :body => quotas_doc.root.to_s)
+ end
+ end
+
+ @db.run "DROP TABLE old_group_pool;"
+
+ log_time()
+
+ # Copy VNet config variables to the template
+
+ @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, cid INTEGER, UNIQUE(name,uid));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_network_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_network_pool')
+
+ template = doc.root.at_xpath("TEMPLATE")
+
+ ["PHYDEV", "VLAN_ID", "BRIDGE"].each do |elem_name|
+ elem = doc.root.at_xpath(elem_name)
+ txt = elem.nil? ? "" : elem.text
+
+ # The cleaner doc.create_cdata(txt) is not supported in
+ # old versions of nokogiri
+
+ template.add_child(doc.create_element(elem_name)).
+ add_child(Nokogiri::XML::CDATA.new(doc,txt))
+ end
+
+ vlan_text = doc.root.at_xpath("VLAN").text == "0" ? "NO" : "YES"
+
+ template.add_child(doc.create_element("VLAN")).
+ add_child(Nokogiri::XML::CDATA.new(doc,vlan_text))
+
+ @db[:network_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u],
+ :cid => row[:cid])
+ end
+ end
+
+ @db.run "DROP TABLE old_network_pool;"
+
+ log_time()
+
+ # Replace deprecated host attributes inside requirements/rank expressions
+
+ @db.run "ALTER TABLE template_pool RENAME TO old_template_pool;"
+ @db.run "CREATE TABLE template_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_template_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_template_pool')
+
+ atts = ["SCHED_REQUIREMENTS", "SCHED_RANK", "REQUIREMENTS", "RANK"]
+
+ atts.each do |att|
+ elem = doc.root.at_xpath("TEMPLATE/#{att}")
+
+ if !elem.nil?
+ elem.content = elem.text.
+ gsub("TOTALCPU", "MAX_CPU").
+ gsub("TOTALMEMORY","MAX_MEM").
+ gsub("FREECPU", "FREE_CPU").
+ gsub("FREEMEMORY", "FREE_MEM").
+ gsub("USEDCPU", "USED_CPU").
+ gsub("USEDMEMORY", "USED_MEM")
+ end
+ end
+
+ @db[:template_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_template_pool;"
+
+ log_time()
+
+ # Default ZONE
+ @db.run "CREATE TABLE zone_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+ @db.run "INSERT INTO zone_pool VALUES(0,'OpenNebula','0OpenNebula',0,0,1,0,0);"
+
+ @db.run "INSERT INTO pool_control VALUES('zone_pool',99);"
+
+ # New versioning table
+ @db.run "CREATE TABLE local_db_versioning (oid INTEGER PRIMARY KEY, version VARCHAR(256), timestamp INTEGER, comment VARCHAR(256), is_slave BOOLEAN);"
+ @db.run "INSERT INTO local_db_versioning VALUES(0,'#{db_version()}',#{Time.now.to_i},'Database migrated from 4.4.1 to 4.5.80 (OpenNebula 4.5.80) by onedb command.',0);"
+
+ return true
+ end
+
+ def extract_quotas(doc)
+ ds_quota = doc.root.at_xpath("DATASTORE_QUOTA")
+ net_quota = doc.root.at_xpath("NETWORK_QUOTA")
+ vm_quota = doc.root.at_xpath("VM_QUOTA")
+ img_quota = doc.root.at_xpath("IMAGE_QUOTA")
+
+ quotas_doc = Nokogiri::XML("",nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
+
+ ds_quota = quotas_doc.create_element("DATASTORE_QUOTA") if ds_quota.nil?
+ net_quota = quotas_doc.create_element("NETWORK_QUOTA") if net_quota.nil?
+ vm_quota = quotas_doc.create_element("VM_QUOTA") if vm_quota.nil?
+ img_quota = quotas_doc.create_element("IMAGE_QUOTA") if img_quota.nil?
+
+ ds_quota.remove
+ net_quota.remove
+ vm_quota.remove
+ img_quota.remove
+
+ quotas_doc.root.add_child(quotas_doc.create_element("ID")).
+ content = doc.root.at_xpath("ID").text
+
+ quotas_doc.root.add_child(ds_quota)
+ quotas_doc.root.add_child(net_quota)
+ quotas_doc.root.add_child(vm_quota)
+ quotas_doc.root.add_child(img_quota)
+
+ return quotas_doc
+ end
+end
diff --git a/src/onedb/shared/4.5.80_to_4.6.0.rb b/src/onedb/shared/4.5.80_to_4.6.0.rb
new file mode 100644
index 0000000000..57033eee41
--- /dev/null
+++ b/src/onedb/shared/4.5.80_to_4.6.0.rb
@@ -0,0 +1,52 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'nokogiri'
+
+module Migrator
+ def db_version
+ "4.6.0"
+ end
+
+ def one_version
+ "OpenNebula 4.6.0"
+ end
+
+ def up
+
+ found = false
+
+ @db.fetch("SELECT oid FROM acl WHERE user=17179869184 and resource=140754668224512 and rights=1 and zone=17179869184") do |row|
+ found = true
+ end
+
+ if !found
+ last_oid = -1
+
+ @db.fetch("SELECT last_oid FROM pool_control WHERE tablename='acl'") do |row|
+ last_oid = row[:last_oid].to_i
+ end
+
+ # * ZONE/* USE *
+ @db.run "INSERT INTO acl VALUES(#{last_oid+1},17179869184,140754668224512,1,17179869184);"
+
+ @db.run "REPLACE INTO pool_control VALUES('acl', #{last_oid+1});"
+ end
+
+ return true
+ end
+end
diff --git a/src/onedb/shared/4.6.0_to_4.11.80.rb b/src/onedb/shared/4.6.0_to_4.11.80.rb
new file mode 100644
index 0000000000..6eedb183e1
--- /dev/null
+++ b/src/onedb/shared/4.6.0_to_4.11.80.rb
@@ -0,0 +1,232 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'nokogiri'
+
+module Migrator
+ def db_version
+ "4.11.80"
+ end
+
+ def one_version
+ "OpenNebula 4.11.80"
+ end
+
+ CLUSTER_ALL = 10
+ VDC_ALL = -10
+
+ EMPTY_VDC = <
+
+
+
+
+
+
+
+
+
+
+
+EOT
+
+ def up
+
+ init_log_time()
+
+ ########################################################################
+ # VDC
+ ########################################################################
+
+ @db.run "CREATE TABLE vdc_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ # The defat vdc in a bootstrap contains the group users and cluster ALL.
+ # But this may have changed, so the default VDC is left empty and
+ # a new VDC 'users' is be created with the current resource providers
+ @db.run "INSERT INTO vdc_pool VALUES(0,'default','0default',0,0,1,0,0);"
+
+ vdc_last_oid = 99
+
+ @db.run "ALTER TABLE group_pool RENAME TO old_group_pool;"
+ @db.run "CREATE TABLE group_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_group_pool") do |row|
+ vdc_doc = nokogiri_doc(row[:body], 'old_group_pool')
+
+ doc = nokogiri_doc(row[:body], 'old_group_pool')
+
+ ["GROUP_ADMIN_VIEWS", "SUNSTONE_VIEWS", "DEFAULT_VIEW"].each do |elem_name|
+ elem = doc.at_xpath("/GROUP/TEMPLATE/#{elem_name}")
+
+ if (!elem.nil?)
+ elem.remove
+
+ newtext = (elem.text.split(",").map { |s|
+ s.strip.
+ gsub(/^vcenter$/, "admin_vcenter").
+ gsub(/^vdcadmin$/, "groupadmin")
+ }).join(",")
+
+ # The cleaner doc.create_cdata(txt) is not supported in
+ # old versions of nokogiri
+ doc.at_xpath("/GROUP/TEMPLATE").add_child(
+ doc.create_element(elem_name)).
+ add_child(Nokogiri::XML::CDATA.new(doc, newtext))
+ end
+ end
+
+ admin_v_elem = doc.at_xpath("/GROUP/TEMPLATE/GROUP_ADMIN_VIEWS")
+
+ if (!admin_v_elem.nil?)
+ aux_e = doc.at_xpath("/GROUP/TEMPLATE/GROUP_ADMIN_DEFAULT_VIEW")
+ aux_e.remove if !aux_e.nil?
+
+ doc.at_xpath("/GROUP/TEMPLATE").add_child(
+ doc.create_element("GROUP_ADMIN_DEFAULT_VIEW")).
+ add_child(Nokogiri::XML::CDATA.new(
+ doc,
+ admin_v_elem.text))
+ end
+
+ admins_elem = doc.root.add_child( doc.create_element("ADMINS") )
+
+ elem = doc.at_xpath("/GROUP/TEMPLATE/GROUP_ADMINS")
+
+ if (!elem.nil?)
+ elem.remove
+
+ elem.text.split(",").each do |uname|
+ @db.fetch("SELECT oid FROM user_pool \
+ WHERE name=\"#{uname.strip}\"") do |user_row|
+
+ # Check that user is part of this group first
+ if !doc.at_xpath("/GROUP/USERS/ID[.=#{user_row[:oid]}]").nil?
+ admins_elem.add_child(
+ doc.create_element("ID") ).content =
+ user_row[:oid]
+ end
+ end
+ end
+ end
+
+ res_providers = doc.xpath("/GROUP/RESOURCE_PROVIDER")
+
+ res_providers.each do |provider|
+ zone_id = provider.at_xpath("ZONE_ID").text
+ cluster_id = provider.at_xpath("CLUSTER_ID").text
+
+ if cluster_id == CLUSTER_ALL
+ cluster_id = VDC_ALL
+ end
+
+ cluster_elem = vdc_doc.create_element("CLUSTER")
+
+ cluster_elem.add_child(
+ vdc_doc.create_element("ZONE_ID")).content = zone_id
+
+ cluster_elem.add_child(
+ vdc_doc.create_element("CLUSTER_ID")).content = cluster_id
+
+ vdc_doc.at_xpath("/VDC/CLUSTERS").add_child(cluster_elem)
+ end
+
+ res_providers.remove
+
+ @db[:group_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+
+ # Do not create a VDC for the oneadmin group
+ if row[:oid] != 0
+ vdc_last_oid += 1
+
+ vdc_doc.at_xpath("/VDC/ID").content = vdc_last_oid.to_s
+ vdc_doc.at_xpath("/VDC/NAME").content = row[:name]
+
+ vdc_doc.at_xpath("/VDC/GROUPS").add_child(
+ vdc_doc.create_element("ID")).content = row[:oid]
+
+ @db[:vdc_pool].insert(
+ :oid => vdc_last_oid.to_s,
+ :name => row[:name],
+ :body => vdc_doc.root.to_s,
+ :uid => 0,
+ :gid => 0,
+ :owner_u => 1,
+ :group_u => 0,
+ :other_u => 0)
+ end
+ end
+ end
+
+ @db.run "DROP TABLE old_group_pool;"
+
+ # Update last_oid in pool control
+ @db.run "INSERT INTO pool_control VALUES('vdc_pool',#{vdc_last_oid});"
+
+ log_time()
+
+
+ @db.run "ALTER TABLE user_pool RENAME TO old_user_pool;"
+ @db.run "CREATE TABLE user_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_user_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_user_pool')
+
+ elem = doc.at_xpath("/USER/TEMPLATE/DEFAULT_VIEW")
+
+ if (!elem.nil?)
+ elem.remove
+
+ newtext = (elem.text.split(",").map { |s|
+ s.strip.
+ gsub(/^vcenter$/, "admin_vcenter").
+ gsub(/^vdcadmin$/, "groupadmin")
+ }).join(",")
+
+ doc.at_xpath("/USER/TEMPLATE").add_child(
+ doc.create_element("DEFAULT_VIEW")).
+ add_child(Nokogiri::XML::CDATA.new(doc,newtext))
+ end
+
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_user_pool;"
+
+ log_time()
+
+ return true
+ end
+end
diff --git a/src/onedb/shared/4.90.0_to_5.2.0.rb b/src/onedb/shared/4.90.0_to_5.2.0.rb
new file mode 100644
index 0000000000..6cae8a3e7f
--- /dev/null
+++ b/src/onedb/shared/4.90.0_to_5.2.0.rb
@@ -0,0 +1,71 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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 'opennebula'
+
+include OpenNebula
+
+module Migrator
+ def db_version
+ "5.2.0"
+ end
+
+ def one_version
+ "OpenNebula 5.2.0"
+ end
+
+ def up
+ init_log_time()
+
+ # Feature #4714
+
+ @db.run "ALTER TABLE user_pool RENAME TO old_user_pool;"
+ @db.run "CREATE TABLE user_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.transaction do
+ @db.fetch("SELECT * FROM old_user_pool") do |row|
+ doc = nokogiri_doc(row[:body], 'old_user_pool')
+
+ token_elem = doc.at_xpath("/USER/LOGIN_TOKEN")
+
+ if !token_elem.nil?
+ if token_elem.children.length == 0
+ token_elem.remove
+ else
+ token_elem.add_child(doc.create_element("EID")).content = "-1"
+ end
+ end
+
+ @db[:user_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+ end
+
+ @db.run "DROP TABLE old_user_pool;"
+
+ log_time()
+
+ return true
+ end
+end
diff --git a/src/onedb/shared/5.10.0_to_5.12.0.rb b/src/onedb/shared/5.10.0_to_5.12.0.rb
new file mode 100644
index 0000000000..b48e69b734
--- /dev/null
+++ b/src/onedb/shared/5.10.0_to_5.12.0.rb
@@ -0,0 +1,96 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+include OpenNebula
+
+module Migrator
+
+ def db_version
+ '5.12.0'
+ end
+
+ def one_version
+ 'OpenNebula 5.12.0'
+ end
+
+ def up
+ feature_3600
+ feature_4089
+ true
+ end
+
+ private
+
+ # Rename acl column name from user to userset to support postgresql
+ def feature_3600
+ @db.run 'DROP TABLE IF EXISTS old_acl;'
+ @db.run 'ALTER TABLE acl RENAME TO old_acl;'
+
+ create_table(:acl)
+
+ @db.transaction do
+ @db.fetch('SELECT * FROM old_acl') do |row|
+ row[:userset] = row.delete(:user)
+
+ @db[:acl].insert(row)
+ end
+ end
+
+ @db.run "DROP TABLE old_acl;"
+ end
+
+ # Add DockerHub marketplace
+ def feature_4089
+ @db.transaction do
+ @db.fetch('SELECT max(oid) as maxid FROM marketplace_pool') do |row|
+ next_oid = row[:maxid] + 1
+
+ body = "#{next_oid}00" \
+ 'oneadminoneadmin' \
+ 'DockerHub' \
+ '' \
+ '0' \
+ '00' \
+ '1' \
+ '11' \
+ '10' \
+ '01' \
+ '00' \
+ '' \
+ '' \
+ '' \
+ ''
+
+ new_row = {
+ :oid => next_oid,
+ :name => 'DockerHub',
+ :body => body,
+ :uid => 0,
+ :gid => 0,
+ :owner_u => 1,
+ :group_u => 1,
+ :other_u => 1
+ }
+
+ @db[:marketplace_pool].insert(new_row)
+ end
+ end
+ end
+
+end
diff --git a/src/onedb/shared/5.2.0_to_5.3.80.rb b/src/onedb/shared/5.2.0_to_5.3.80.rb
new file mode 100644
index 0000000000..6e29b75e83
--- /dev/null
+++ b/src/onedb/shared/5.2.0_to_5.3.80.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "5.3.80"
+ end
+
+ def one_version
+ "OpenNebula 5.3.80"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/5.3.80_to_5.4.0.rb b/src/onedb/shared/5.3.80_to_5.4.0.rb
new file mode 100644
index 0000000000..f2513f3fe9
--- /dev/null
+++ b/src/onedb/shared/5.3.80_to_5.4.0.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "5.4.0"
+ end
+
+ def one_version
+ "OpenNebula 5.4.0"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/5.4.0_to_5.4.1.rb b/src/onedb/shared/5.4.0_to_5.4.1.rb
new file mode 100644
index 0000000000..b948316122
--- /dev/null
+++ b/src/onedb/shared/5.4.0_to_5.4.1.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "5.4.1"
+ end
+
+ def one_version
+ "OpenNebula 5.4.1"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/5.4.1_to_5.5.80.rb b/src/onedb/shared/5.4.1_to_5.5.80.rb
new file mode 100644
index 0000000000..acac86ebdf
--- /dev/null
+++ b/src/onedb/shared/5.4.1_to_5.5.80.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "5.5.80"
+ end
+
+ def one_version
+ "OpenNebula 5.5.80"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/5.5.80_to_5.6.0.rb b/src/onedb/shared/5.5.80_to_5.6.0.rb
new file mode 100644
index 0000000000..b1d967eccd
--- /dev/null
+++ b/src/onedb/shared/5.5.80_to_5.6.0.rb
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "5.6.0"
+ end
+
+ def one_version
+ "OpenNebula 5.6.0"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/shared/5.6.0_to_5.10.0.rb b/src/onedb/shared/5.6.0_to_5.10.0.rb
new file mode 100644
index 0000000000..ac1f212790
--- /dev/null
+++ b/src/onedb/shared/5.6.0_to_5.10.0.rb
@@ -0,0 +1,34 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2019-2020, OpenNebula Systems S.L. #
+# #
+# Licensed under the OpenNebula Software License #
+# (the "License"); you may not use this file except in compliance with #
+# the License. You may obtain a copy of the License as part of the software #
+# distribution. #
+# #
+# See https://github.com/OpenNebula/one/blob/master/LICENSE.onsla #
+# (or copy bundled with OpenNebula in /usr/share/doc/one/). #
+# #
+# Unless 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. #
+# -------------------------------------------------------------------------- #
+
+include OpenNebula
+
+module Migrator
+
+ def db_version
+ '5.10.0'
+ end
+
+ def one_version
+ 'OpenNebula 5.9.80'
+ end
+
+ def up
+ true
+ end
+
+end