blob: 1e23377c012fff8dec80fe36a2b4c6df9aa8f34d [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.upgrade.dao;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.log4j.Logger;
import com.cloud.utils.exception.CloudRuntimeException;
public class Upgrade224to225 implements DbUpgrade {
final static Logger s_logger = Logger.getLogger(Upgrade224to225.class);
@Override
public InputStream[] getPrepareScripts() {
final String scriptFile = "META-INF/db/schema-224to225.sql";
final InputStream script = Thread.currentThread().getContextClassLoader().getResourceAsStream(scriptFile);
if (script == null) {
throw new CloudRuntimeException("Unable to find " + scriptFile);
}
return new InputStream[] {script};
}
@Override
public void performDataMigration(Connection conn) {
// create security groups for existing accounts if not present
createSecurityGroups(conn);
dropKeysIfExist(conn);
dropTableColumnsIfExist(conn);
addMissingKeys(conn);
addMissingOvsAccount(conn);
}
@Override
public InputStream[] getCleanupScripts() {
final String scriptFile = "META-INF/db/schema-224to225-cleanup.sql";
final InputStream script = Thread.currentThread().getContextClassLoader().getResourceAsStream(scriptFile);
if (script == null) {
throw new CloudRuntimeException("Unable to find " + scriptFile);
}
return new InputStream[] {script};
}
@Override
public String[] getUpgradableVersionRange() {
return new String[] {"2.2.4", "2.2.4"};
}
@Override
public String getUpgradedVersion() {
return "2.2.5";
}
@Override
public boolean supportsRollingUpgrade() {
return false;
}
private void createSecurityGroups(Connection conn) {
s_logger.debug("Creating missing default security group as a part of 224-225 upgrade");
try {
List<Long> accounts = new ArrayList<Long>();
PreparedStatement pstmt = conn.prepareStatement("SELECT id FROM account WHERE removed IS NULL and id != 1");
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
accounts.add(rs.getLong(1));
}
for (Long accountId : accounts) {
// get default security group
pstmt = conn.prepareStatement("SELECT * FROM security_group WHERE name='default' and account_id=?");
pstmt.setLong(1, accountId);
rs = pstmt.executeQuery();
if (!rs.next()) {
s_logger.debug("Default security group is missing for account id=" + accountId + " so adding it");
// get accountName/domainId information
pstmt = conn.prepareStatement("SELECT account_name, domain_id FROM account WHERE id=?");
pstmt.setLong(1, accountId);
ResultSet rs1 = pstmt.executeQuery();
if (!rs1.next()) {
throw new CloudRuntimeException("Unable to create default security group for account id=" + accountId +
": unable to get accountName/domainId info");
}
String accountName = rs1.getString(1);
Long domainId = rs1.getLong(2);
pstmt =
conn.prepareStatement("INSERT INTO `cloud`.`security_group` (name, description, account_name, account_id, domain_id) VALUES ('default', 'Default Security Group', ?, ?, ?)");
pstmt.setString(1, accountName);
pstmt.setLong(2, accountId);
pstmt.setLong(3, domainId);
pstmt.executeUpdate();
}
rs.close();
pstmt.close();
}
} catch (SQLException e) {
throw new CloudRuntimeException("Unable to create default security groups for existing accounts due to", e);
}
}
private void dropTableColumnsIfExist(Connection conn) {
HashMap<String, List<String>> tablesToModify = new HashMap<String, List<String>>();
// account table
List<String> columns = new ArrayList<String>();
columns.add("network_domain");
tablesToModify.put("account", columns);
// console proxy table
columns = new ArrayList<String>();
columns.add("gateway");
columns.add("dns1");
columns.add("dns2");
columns.add("domain");
columns.add("guest_mac_address");
columns.add("guest_ip_address");
columns.add("guest_netmask");
columns.add("vlan_db_id");
columns.add("vlan_id");
columns.add("ram_size");
tablesToModify.put("console_proxy", columns);
// secondary storage table
columns = new ArrayList<String>();
columns.add("gateway");
columns.add("dns1");
columns.add("dns2");
columns.add("domain");
columns.add("guest_mac_address");
columns.add("guest_ip_address");
columns.add("guest_netmask");
columns.add("vlan_db_id");
columns.add("vlan_id");
columns.add("ram_size");
tablesToModify.put("secondary_storage_vm", columns);
// disk offering table
columns = new ArrayList<String>();
columns.add("mirrored");
tablesToModify.put("disk_offering", columns);
// domain router table
columns = new ArrayList<String>();
columns.add("gateway");
columns.add("ram_size");
columns.add("dns1");
columns.add("dns2");
columns.add("domain");
columns.add("guest_mac_address");
columns.add("guest_dc_mac_address");
columns.add("vnet");
columns.add("dc_vlan");
columns.add("vlan_db_id");
columns.add("vlan_id");
columns.add("dhcp_ip_address");
tablesToModify.put("domain_router", columns);
// volumes table
columns = new ArrayList<String>();
columns.add("mirror_state");
columns.add("mirror_vol");
columns.add("destroyed");
tablesToModify.put("volumes", columns);
// vm_instance table
columns = new ArrayList<String>();
columns.add("mirrored_vols");
tablesToModify.put("vm_instance", columns);
// user_vm table
columns = new ArrayList<String>();
columns.add("domain_router_id");
columns.add("vnet");
columns.add("dc_vlan");
columns.add("external_ip_address");
columns.add("external_mac_address");
columns.add("external_vlan_db_id");
tablesToModify.put("user_vm", columns);
// service_offerings table
columns = new ArrayList<String>();
columns.add("guest_ip_type");
tablesToModify.put("service_offering", columns);
s_logger.debug("Dropping columns that don't exist in 2.2.5 version of the DB...");
for (String tableName : tablesToModify.keySet()) {
DbUpgradeUtils.dropTableColumnsIfExist(conn, tableName, tablesToModify.get(tableName));
}
}
private void dropKeysIfExist(Connection conn) {
HashMap<String, List<String>> foreignKeys = new HashMap<String, List<String>>();
HashMap<String, List<String>> indexes = new HashMap<String, List<String>>();
// console proxy table
List<String> keys = new ArrayList<String>();
keys.add("fk_console_proxy__vlan_id");
foreignKeys.put("console_proxy", keys);
keys = new ArrayList<String>();
keys.add("i_console_proxy__vlan_id");
indexes.put("console_proxy", keys);
// mshost table
keys = new ArrayList<String>();
keys.add("msid_2");
indexes.put("mshost", keys);
// domain router table
keys = new ArrayList<String>();
keys.add("fk_domain_router__vlan_id");
keys.add("fk_domain_route__id");
foreignKeys.put("domain_router", keys);
keys = new ArrayList<String>();
keys.add("i_domain_router__public_ip_address");
keys.add("i_domain_router__vlan_id");
indexes.put("domain_router", keys);
// user_vm table
keys = new ArrayList<String>();
keys.add("i_user_vm__domain_router_id");
keys.add("i_user_vm__external_ip_address");
keys.add("i_user_vm__external_vlan_db_id");
indexes.put("user_vm", keys);
keys = new ArrayList<String>();
keys.add("fk_user_vm__domain_router_id");
keys.add("fk_user_vm__external_vlan_db_id");
keys.add("fk_user_vm__external_ip_address");
foreignKeys.put("user_vm", keys);
// user_vm_details table
keys = new ArrayList<String>();
keys.add("fk_user_vm_details__vm_id");
foreignKeys.put("user_vm_details", keys);
indexes.put("user_vm_details", keys);
// snapshots table
keys = new ArrayList<String>();
keys.add("id_2");
indexes.put("snapshots", keys);
// remote_access_vpn
keys = new ArrayList<String>();
keys.add("fk_remote_access_vpn__server_addr");
foreignKeys.put("remote_access_vpn", keys);
keys = new ArrayList<String>();
keys.add("fk_remote_access_vpn__server_addr_id");
indexes.put("remote_access_vpn", keys);
// drop all foreign keys first
s_logger.debug("Dropping keys that don't exist in 2.2.5 version of the DB...");
for (String tableName : foreignKeys.keySet()) {
DbUpgradeUtils.dropKeysIfExist(conn, tableName, foreignKeys.get(tableName), true);
}
// drop indexes now
for (String tableName : indexes.keySet()) {
DbUpgradeUtils.dropKeysIfExist(conn, tableName, indexes.get(tableName), false);
}
}
private void addMissingKeys(Connection conn) {
PreparedStatement pstmt = null;
try {
s_logger.debug("Adding missing foreign keys");
HashMap<String, String> keyToTableMap = new HashMap<String, String>();
keyToTableMap.put("fk_console_proxy__id", "console_proxy");
keyToTableMap.put("fk_secondary_storage_vm__id", "secondary_storage_vm");
keyToTableMap.put("fk_template_spool_ref__template_id", "template_spool_ref");
keyToTableMap.put("fk_template_spool_ref__pool_id", "template_spool_ref");
keyToTableMap.put("fk_user_vm_details__vm_id", "user_vm_details");
keyToTableMap.put("fk_op_ha_work__instance_id", "op_ha_work");
keyToTableMap.put("fk_op_ha_work__mgmt_server_id", "op_ha_work");
keyToTableMap.put("fk_op_ha_work__host_id", "op_ha_work");
HashMap<String, String> keyToStatementMap = new HashMap<String, String>();
keyToStatementMap.put("fk_console_proxy__id", "(`id`) REFERENCES `vm_instance` (`id`) ON DELETE CASCADE");
keyToStatementMap.put("fk_secondary_storage_vm__id", "(`id`) REFERENCES `vm_instance` (`id`) ON DELETE CASCADE");
keyToStatementMap.put("fk_template_spool_ref__template_id", "(`template_id`) REFERENCES `vm_template` (`id`)");
keyToStatementMap.put("fk_template_spool_ref__pool_id", "(`pool_id`) REFERENCES `storage_pool` (`id`) ON DELETE CASCADE");
keyToStatementMap.put("fk_user_vm_details__vm_id", "(`vm_id`) REFERENCES `user_vm` (`id`) ON DELETE CASCADE");
keyToStatementMap.put("fk_op_ha_work__instance_id", "(`instance_id`) REFERENCES `vm_instance` (`id`) ON DELETE CASCADE");
keyToStatementMap.put("fk_op_ha_work__mgmt_server_id", "(`mgmt_server_id`) REFERENCES `mshost`(`msid`)");
keyToStatementMap.put("fk_op_ha_work__host_id", "(`host_id`) REFERENCES `host` (`id`)");
for (String key : keyToTableMap.keySet()) {
String tableName = keyToTableMap.get(key);
pstmt =
conn.prepareStatement("SELECT * FROM information_schema.table_constraints a JOIN information_schema.key_column_usage b ON a.table_schema = b.table_schema AND a.constraint_name = b.constraint_name WHERE a.table_schema=database() AND a.constraint_type='FOREIGN KEY' and a.constraint_name=?");
pstmt.setString(1, key);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
continue;
}
pstmt = conn.prepareStatement("ALTER TABLE " + tableName + " ADD CONSTRAINT " + key + " FOREIGN KEY " + keyToStatementMap.get(key));
pstmt.executeUpdate();
s_logger.debug("Added missing key " + key + " to table " + tableName);
rs.close();
}
s_logger.debug("Missing keys were added successfully as a part of 224 to 225 upgrade");
pstmt.close();
} catch (SQLException e) {
s_logger.error("Unable to add missing foreign key; following statement was executed:" + pstmt);
throw new CloudRuntimeException("Unable to add missign keys due to exception", e);
}
}
private void addMissingOvsAccount(Connection conn) {
try {
PreparedStatement pstmt = conn.prepareStatement("SELECT * from ovs_tunnel_account");
ResultSet rs = pstmt.executeQuery();
if (!rs.next()) {
s_logger.debug("Adding missing ovs tunnel account");
pstmt =
conn.prepareStatement("INSERT INTO `cloud`.`ovs_tunnel_account` (`from`, `to`, `account`, `key`, `port_name`, `state`) VALUES (0, 0, 0, 0, 'lock', 'SUCCESS')");
pstmt.executeUpdate();
}
} catch (SQLException e) {
s_logger.error("Unable to add missing ovs tunnel account due to ", e);
throw new CloudRuntimeException("Unable to add missign ovs tunnel account due to ", e);
}
}
}