| // 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.File; |
| import java.sql.Connection; |
| import java.sql.PreparedStatement; |
| import java.sql.ResultSet; |
| import java.sql.SQLException; |
| |
| import org.apache.log4j.Logger; |
| |
| import com.cloud.hypervisor.Hypervisor; |
| import com.cloud.utils.exception.CloudRuntimeException; |
| import com.cloud.utils.script.Script; |
| |
| public class Upgrade420to421 implements DbUpgrade { |
| final static Logger s_logger = Logger.getLogger(Upgrade420to421.class); |
| |
| @Override |
| public String[] getUpgradableVersionRange() { |
| return new String[] {"4.2.0", "4.2.1"}; |
| } |
| |
| @Override |
| public String getUpgradedVersion() { |
| return "4.2.1"; |
| } |
| |
| @Override |
| public boolean supportsRollingUpgrade() { |
| return false; |
| } |
| |
| @Override |
| public File[] getPrepareScripts() { |
| String script = Script.findScript("", "db/schema-420to421.sql"); |
| if (script == null) { |
| throw new CloudRuntimeException("Unable to find db/schema-420to421.sql"); |
| } |
| |
| return new File[] {new File(script)}; |
| } |
| |
| @Override |
| public File[] getCleanupScripts() { |
| return null; |
| } |
| |
| @Override |
| public void performDataMigration(Connection conn) { |
| upgradeResourceCount(conn); |
| updateOverprovisioningPerVm(conn); |
| } |
| |
| |
| |
| private void updateOverprovisioningPerVm(Connection conn) { |
| PreparedStatement pstmt1 = null; |
| PreparedStatement pstmt2 = null; |
| PreparedStatement pstmt3 = null; |
| ResultSet result1 = null; |
| ResultSet result2 = null; |
| |
| // Get cpu overprovisioning factor from global setting and update user vm details table for all the vms if factor > 1 |
| |
| try { |
| pstmt1 = conn.prepareStatement("select value from `cloud`.`configuration` where name='cpu.overprovisioning.factor'"); |
| result1 = pstmt1.executeQuery(); |
| String cpuoverprov = "1"; |
| if(result1.next()){ |
| cpuoverprov = result1.getString(1); |
| } |
| result1.close(); |
| pstmt1.close(); |
| |
| pstmt1 = conn.prepareStatement("select value from `cloud`.`configuration` where name='mem.overprovisioning.factor'"); |
| result1 = pstmt1.executeQuery(); |
| String memoverprov = "1"; |
| if(result1.next()){ |
| memoverprov = result1.getString(1); |
| } |
| result1.close(); |
| pstmt1.close(); |
| |
| // Need to populate only when overprovisioning factor doesn't pre exist. |
| s_logger.debug("Starting updating user_vm_details with cpu/memory overprovisioning factors"); |
| pstmt2 = conn.prepareStatement("select id, hypervisor_type from `cloud`.`vm_instance` where removed is null and id not in (select vm_id from `cloud`.`user_vm_details` where name='cpuOvercommitRatio')"); |
| pstmt3 = conn.prepareStatement("INSERT IGNORE INTO cloud.user_vm_details (vm_id, name, value) VALUES (?, ?, ?)"); |
| result2 = pstmt2.executeQuery(); |
| while (result2.next()) { |
| String hypervisor_type = result2.getString(2); |
| if (hypervisor_type.equalsIgnoreCase(Hypervisor.HypervisorType.VMware.name())) { |
| //For cpu |
| pstmt3.setLong(1, result2.getLong(1)); |
| pstmt3.setString(2, "cpuOvercommitRatio"); |
| pstmt3.setString(3, cpuoverprov); |
| pstmt3.executeUpdate(); |
| |
| // For memory |
| pstmt3.setLong(1, result2.getLong(1)); |
| pstmt3.setString(2, "memoryOvercommitRatio"); |
| pstmt3.setString(3, memoverprov); // memory overprovisioning was used to reserve memory in case of VMware. |
| pstmt3.executeUpdate(); |
| } else { |
| //For cpu |
| pstmt3.setLong(1, result2.getLong(1)); |
| pstmt3.setString(2, "cpuOvercommitRatio"); |
| pstmt3.setString(3, cpuoverprov); |
| pstmt3.executeUpdate(); |
| |
| // For memory |
| pstmt3.setLong(1, result2.getLong(1)); |
| pstmt3.setString(2, "memoryOvercommitRatio"); |
| pstmt3.setString(3, "1"); // memory overprovisioning didn't exist earlier. |
| pstmt3.executeUpdate(); |
| } |
| } |
| s_logger.debug("Done updating user_vm_details with cpu/memory overprovisioning factors"); |
| |
| } catch (SQLException e) { |
| throw new CloudRuntimeException("Unable to update cpu/memory overprovisioning factors", e); |
| } finally { |
| try { |
| if (pstmt1 != null && !pstmt1.isClosed()) { |
| pstmt1.close(); |
| } |
| } catch (SQLException e) { |
| } |
| try { |
| if (pstmt2 != null && !pstmt2.isClosed()) { |
| pstmt2.close(); |
| } |
| } catch (SQLException e) { |
| } |
| try { |
| if (pstmt3 != null && !pstmt3.isClosed()) { |
| pstmt3.close(); |
| } |
| } catch (SQLException e) { |
| } |
| try { |
| if (result1 != null) { |
| result1.close(); |
| } |
| } catch (SQLException e) { |
| } |
| try { |
| if (result2 != null) { |
| result2.close(); |
| } |
| }catch (SQLException e){ |
| |
| } |
| } |
| |
| } |
| |
| private void upgradeResourceCount(Connection conn) { |
| s_logger.debug("upgradeResourceCount start"); |
| PreparedStatement pstmt1 = null; |
| PreparedStatement pstmt2 = null; |
| PreparedStatement pstmt3 = null; |
| PreparedStatement pstmt4 = null; |
| PreparedStatement pstmt5 = null; |
| ResultSet rsAccount = null; |
| ResultSet rsCount = null; |
| try { |
| pstmt1 = conn.prepareStatement("select id, domain_id FROM `cloud`.`account` where removed is NULL "); |
| rsAccount = pstmt1.executeQuery(); |
| while (rsAccount.next()) { |
| long account_id = rsAccount.getLong(1); |
| long domain_id = rsAccount.getLong(2); |
| // 1. update cpu,memory for all accounts |
| pstmt2 = |
| conn.prepareStatement("SELECT SUM(service_offering.cpu), SUM(service_offering.ram_size)" + " FROM `cloud`.`vm_instance`, `cloud`.`service_offering`" |
| + " WHERE vm_instance.service_offering_id = service_offering.id AND vm_instance.account_id = ?" + " AND vm_instance.removed is NULL" |
| + " AND vm_instance.vm_type='User' AND state not in ('Destroyed', 'Error', 'Expunging')"); |
| pstmt2.setLong(1, account_id); |
| rsCount = pstmt2.executeQuery(); |
| if (rsCount.next()) { |
| upgradeResourceCountforAccount(conn, account_id, domain_id, "cpu", rsCount.getLong(1)); |
| upgradeResourceCountforAccount(conn, account_id, domain_id, "memory", rsCount.getLong(2)); |
| } else { |
| upgradeResourceCountforAccount(conn, account_id, domain_id, "cpu", 0L); |
| upgradeResourceCountforAccount(conn, account_id, domain_id, "memory", 0L); |
| } |
| rsCount.close(); |
| |
| // 2. update primary_storage for all accounts |
| pstmt3 = |
| conn.prepareStatement("SELECT sum(size) FROM `cloud`.`volumes` WHERE account_id= ?" |
| + " AND (path is not NULL OR state in ('Allocated')) AND removed is NULL" |
| + " AND instance_id IN (SELECT id FROM `cloud`.`vm_instance` WHERE vm_type='User')"); |
| pstmt3.setLong(1, account_id); |
| rsCount = pstmt3.executeQuery(); |
| if (rsCount.next()) { |
| upgradeResourceCountforAccount(conn, account_id, domain_id, "primary_storage", rsCount.getLong(1)); |
| } else { |
| upgradeResourceCountforAccount(conn, account_id, domain_id, "primary_storage", 0L); |
| } |
| rsCount.close(); |
| |
| // 3. update secondary_storage for all accounts |
| long totalVolumesSize = 0; |
| long totalSnapshotsSize = 0; |
| long totalTemplatesSize = 0; |
| pstmt4 = |
| conn.prepareStatement("SELECT sum(size) FROM `cloud`.`volumes` WHERE account_id= ?" |
| + " AND path is NULL AND state not in ('Allocated') AND removed is NULL"); |
| pstmt4.setLong(1, account_id); |
| rsCount = pstmt4.executeQuery(); |
| if (rsCount.next()) { |
| totalVolumesSize = rsCount.getLong(1); |
| } |
| rsCount.close(); |
| pstmt4.close(); |
| |
| pstmt4 = conn.prepareStatement("SELECT sum(size) FROM `cloud`.`snapshots` WHERE account_id= ? AND removed is NULL"); |
| pstmt4.setLong(1, account_id); |
| rsCount = pstmt4.executeQuery(); |
| if (rsCount.next()) { |
| totalSnapshotsSize = rsCount.getLong(1); |
| } |
| rsCount.close(); |
| pstmt4.close(); |
| |
| pstmt4 = |
| conn.prepareStatement("SELECT sum(template_store_ref.size) FROM `cloud`.`template_store_ref`,`cloud`.`vm_template` WHERE account_id = ?" |
| + " AND template_store_ref.template_id = vm_template.id AND download_state = 'DOWNLOADED' AND destroyed = false AND removed is NULL"); |
| pstmt4.setLong(1, account_id); |
| rsCount = pstmt4.executeQuery(); |
| if (rsCount.next()) { |
| totalTemplatesSize = rsCount.getLong(1); |
| } |
| upgradeResourceCountforAccount(conn, account_id, domain_id, "secondary_storage", totalVolumesSize + totalSnapshotsSize + totalTemplatesSize); |
| } |
| rsAccount.close(); |
| |
| // 4. upgrade cpu,memory,primary_storage,secondary_storage for domains |
| String resource_types[] = {"cpu", "memory", "primary_storage", "secondary_storage"}; |
| pstmt5 = conn.prepareStatement("select id FROM `cloud`.`domain`"); |
| rsAccount = pstmt5.executeQuery(); |
| while (rsAccount.next()) { |
| long domain_id = rsAccount.getLong(1); |
| for (int count = 0; count < resource_types.length; count++) { |
| String resource_type = resource_types[count]; |
| upgradeResourceCountforDomain(conn, domain_id, resource_type, 0L); // reset value to 0 before statistics |
| } |
| } |
| for (int count = 0; count < resource_types.length; count++) { |
| String resource_type = resource_types[count]; |
| pstmt5 = |
| conn.prepareStatement("select account.domain_id,sum(resource_count.count) from `cloud`.`account` left join `cloud`.`resource_count` on account.id=resource_count.account_id " |
| + "where resource_count.type=? group by account.domain_id;"); |
| pstmt5.setString(1, resource_type); |
| rsCount = pstmt5.executeQuery(); |
| while (rsCount.next()) { |
| long domain_id = rsCount.getLong(1); |
| long resource_count = rsCount.getLong(2); |
| upgradeResourceCountforDomain(conn, domain_id, resource_type, resource_count); |
| } |
| } |
| s_logger.debug("upgradeResourceCount finish"); |
| } catch (SQLException e) { |
| throw new CloudRuntimeException("Unable to upgrade resource count (cpu,memory,primary_storage,secondary_storage) ", e); |
| } finally { |
| try { |
| if (rsAccount != null) { |
| rsAccount.close(); |
| } |
| if (rsCount != null) { |
| rsCount.close(); |
| } |
| if (pstmt1 != null) { |
| pstmt1.close(); |
| } |
| if (pstmt2 != null) { |
| pstmt2.close(); |
| } |
| if (pstmt3 != null) { |
| pstmt3.close(); |
| } |
| if (pstmt4 != null) { |
| pstmt4.close(); |
| } |
| if (pstmt5 != null) { |
| pstmt5.close(); |
| } |
| } catch (SQLException e) { |
| } |
| } |
| } |
| |
| private static void upgradeResourceCountforAccount(Connection conn, Long accountId, Long domainId, String type, Long resourceCount) throws SQLException { |
| //update or insert into resource_count table. |
| PreparedStatement pstmt = null; |
| pstmt = |
| conn.prepareStatement("INSERT INTO `cloud`.`resource_count` (account_id, type, count) VALUES (?,?,?) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), count=?"); |
| pstmt.setLong(1, accountId); |
| pstmt.setString(2, type); |
| pstmt.setLong(3, resourceCount); |
| pstmt.setLong(4, resourceCount); |
| pstmt.executeUpdate(); |
| pstmt.close(); |
| } |
| |
| private static void upgradeResourceCountforDomain(Connection conn, Long domainId, String type, Long resourceCount) throws SQLException { |
| //update or insert into resource_count table. |
| PreparedStatement pstmt = null; |
| pstmt = |
| conn.prepareStatement("INSERT INTO `cloud`.`resource_count` (domain_id, type, count) VALUES (?,?,?) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), count=?"); |
| pstmt.setLong(1, domainId); |
| pstmt.setString(2, type); |
| pstmt.setLong(3, resourceCount); |
| pstmt.setLong(4, resourceCount); |
| pstmt.executeUpdate(); |
| pstmt.close(); |
| } |
| } |