blob: ee017d5522315383cfa8692d49d16d82209f98bb [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.test;
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 java.util.Vector;
import com.cloud.network.Networks.TrafficType;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.net.NetUtils;
public class PodZoneConfig {
public static void main(String[] args) {
PodZoneConfig config = ComponentContext.inject(PodZoneConfig.class);
//config.run(args);
System.exit(0);
}
public void savePod(boolean printOutput, long id, String name, long dcId, String gateway, String cidr, int vlanStart, int vlanEnd) {
// Check that the cidr was valid
if (!IPRangeConfig.validCIDR(cidr))
printError("Please enter a valid CIDR for pod: " + name);
// Get the individual cidrAddress and cidrSize values
String[] cidrPair = cidr.split("\\/");
String cidrAddress = cidrPair[0];
String cidrSize = cidrPair[1];
String sql = null;
if (id != -1)
sql =
"INSERT INTO `cloud`.`host_pod_ref` (id, name, data_center_id, gateway, cidr_address, cidr_size) " + "VALUES ('" + id + "','" + name + "','" + dcId +
"','" + gateway + "','" + cidrAddress + "','" + cidrSize + "')";
else
sql =
"INSERT INTO `cloud`.`host_pod_ref` (name, data_center_id, gateway, cidr_address, cidr_size) " + "VALUES ('" + name + "','" + dcId + "','" + gateway +
"','" + cidrAddress + "','" + cidrSize + "')";
DatabaseConfig.saveSQL(sql, "Failed to save pod due to exception. Please contact Cloud Support.");
if (printOutput)
System.out.println("Successfully saved pod.");
}
public void checkAllPodCidrSubnets() {
Vector<Long> allZoneIDs = getAllZoneIDs();
for (Long dcId : allZoneIDs) {
HashMap<Long, Vector<Object>> currentPodCidrSubnets = getCurrentPodCidrSubnets(dcId.longValue());
String result = checkPodCidrSubnets(dcId.longValue(), currentPodCidrSubnets);
if (!result.equals("success"))
printError(result);
}
}
private String checkPodCidrSubnets(long dcId, HashMap<Long, Vector<Object>> currentPodCidrSubnets) {
// DataCenterDao _dcDao = null;
// final ComponentLocator locator = ComponentLocator.getLocator("management-server");
// _dcDao = locator.getDao(DataCenterDao.class);
// For each pod, return an error if any of the following is true:
// 1. The pod's CIDR subnet conflicts with the guest network subnet
// 2. The pod's CIDR subnet conflicts with the CIDR subnet of any other pod
String zoneName = PodZoneConfig.getZoneName(dcId);
//get the guest network cidr and guest netmask from the zone
// DataCenterVO dcVo = _dcDao.findById(dcId);
String guestNetworkCidr = IPRangeConfig.getGuestNetworkCidr(dcId);
if (guestNetworkCidr == null || guestNetworkCidr.isEmpty())
return "Please specify a valid guest cidr";
String[] cidrTuple = guestNetworkCidr.split("\\/");
String guestIpNetwork = NetUtils.getIpRangeStartIpFromCidr(cidrTuple[0], Long.parseLong(cidrTuple[1]));
long guestCidrSize = Long.parseLong(cidrTuple[1]);
// Iterate through all pods in this zone
for (Long podId : currentPodCidrSubnets.keySet()) {
String podName;
if (podId.longValue() == -1)
podName = "newPod";
else
podName = PodZoneConfig.getPodName(podId.longValue(), dcId);
Vector<Object> cidrPair = currentPodCidrSubnets.get(podId);
String cidrAddress = (String)cidrPair.get(0);
long cidrSize = ((Long)cidrPair.get(1)).longValue();
long cidrSizeToUse = -1;
if (cidrSize < guestCidrSize)
cidrSizeToUse = cidrSize;
else
cidrSizeToUse = guestCidrSize;
String cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSizeToUse);
String guestSubnet = NetUtils.getCidrSubNet(guestIpNetwork, cidrSizeToUse);
// Check that cidrSubnet does not equal guestSubnet
if (cidrSubnet.equals(guestSubnet)) {
if (podName.equals("newPod")) {
return "The subnet of the pod you are adding conflicts with the subnet of the Guest IP Network. Please specify a different CIDR.";
} else {
return "Warning: The subnet of pod " + podName + " in zone " + zoneName +
" conflicts with the subnet of the Guest IP Network. Please change either the pod's CIDR or the Guest IP Network's subnet, and re-run install-vmops-management.";
}
}
// Iterate through the rest of the pods
for (Long otherPodId : currentPodCidrSubnets.keySet()) {
if (podId.equals(otherPodId))
continue;
// Check that cidrSubnet does not equal otherCidrSubnet
Vector<Object> otherCidrPair = currentPodCidrSubnets.get(otherPodId);
String otherCidrAddress = (String)otherCidrPair.get(0);
long otherCidrSize = ((Long)otherCidrPair.get(1)).longValue();
if (cidrSize < otherCidrSize)
cidrSizeToUse = cidrSize;
else
cidrSizeToUse = otherCidrSize;
cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSizeToUse);
String otherCidrSubnet = NetUtils.getCidrSubNet(otherCidrAddress, cidrSizeToUse);
if (cidrSubnet.equals(otherCidrSubnet)) {
String otherPodName = PodZoneConfig.getPodName(otherPodId.longValue(), dcId);
if (podName.equals("newPod")) {
return "The subnet of the pod you are adding conflicts with the subnet of pod " + otherPodName + " in zone " + zoneName +
". Please specify a different CIDR.";
} else {
return "Warning: The pods " + podName + " and " + otherPodName + " in zone " + zoneName +
" have conflicting CIDR subnets. Please change the CIDR of one of these pods.";
}
}
}
}
return "success";
}
@DB
protected HashMap<Long, Vector<Object>> getCurrentPodCidrSubnets(long dcId) {
HashMap<Long, Vector<Object>> currentPodCidrSubnets = new HashMap<Long, Vector<Object>>();
String selectSql = "SELECT id, cidr_address, cidr_size FROM host_pod_ref WHERE data_center_id=" + dcId;
TransactionLegacy txn = TransactionLegacy.currentTxn();
try {
PreparedStatement stmt = txn.prepareAutoCloseStatement(selectSql);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
Long podId = rs.getLong("id");
String cidrAddress = rs.getString("cidr_address");
long cidrSize = rs.getLong("cidr_size");
Vector<Object> cidrPair = new Vector<Object>();
cidrPair.add(0, cidrAddress);
cidrPair.add(1, new Long(cidrSize));
currentPodCidrSubnets.put(podId, cidrPair);
}
} catch (SQLException ex) {
System.out.println(ex.getMessage());
printError("There was an issue with reading currently saved pod CIDR subnets. Please contact Cloud Support.");
return null;
}
return currentPodCidrSubnets;
}
public void deletePod(String name, long dcId) {
String sql = "DELETE FROM `cloud`.`host_pod_ref` WHERE name=\"" + name + "\" AND data_center_id=\"" + dcId + "\"";
DatabaseConfig.saveSQL(sql, "Failed to delete pod due to exception. Please contact Cloud Support.");
}
public long getVlanDbId(String zone, String vlanId) {
long zoneId = getZoneId(zone);
return DatabaseConfig.getDatabaseValueLong("SELECT * FROM `cloud`.`vlan` WHERE data_center_id=\"" + zoneId + "\" AND vlan_id =\"" + vlanId + "\"", "id",
"Unable to start DB connection to read vlan DB id. Please contact Cloud Support.");
}
public List<String> modifyVlan(String zone, boolean add, String vlanId, String vlanGateway, String vlanNetmask, String pod, String vlanType, String ipRange,
long networkId, long physicalNetworkId) {
// Check if the zone is valid
long zoneId = getZoneId(zone);
if (zoneId == -1)
return genReturnList("false", "Please specify a valid zone.");
//check if physical network is valid
long physicalNetworkDbId = checkPhysicalNetwork(physicalNetworkId);
if (physicalNetworkId == -1)
return genReturnList("false", "Please specify a valid physical network.");
Long podId = pod != null ? getPodId(pod, zone) : null;
if (podId != null && podId == -1)
return genReturnList("false", "Please specify a valid pod.");
if (add) {
// Make sure the gateway is valid
if (!NetUtils.isValidIp4(vlanGateway))
return genReturnList("false", "Please specify a valid gateway.");
// Make sure the netmask is valid
if (!NetUtils.isValidIp4(vlanNetmask))
return genReturnList("false", "Please specify a valid netmask.");
// Check if a vlan with the same vlanId already exists in the specified zone
if (getVlanDbId(zone, vlanId) != -1)
return genReturnList("false", "A VLAN with the specified VLAN ID already exists in zone " + zone + ".");
/*
// Check if another vlan in the same zone has the same subnet
String newVlanSubnet = NetUtils.getSubNet(vlanGateway, vlanNetmask);
List<VlanVO> vlans = _vlanDao.findByZone(zoneId);
for (VlanVO vlan : vlans) {
String currentVlanSubnet = NetUtils.getSubNet(vlan.getVlanGateway(), vlan.getVlanNetmask());
if (newVlanSubnet.equals(currentVlanSubnet))
return genReturnList("false", "The VLAN with ID " + vlan.getVlanId() + " in zone " + zone + " has the same subnet. Please specify a different gateway/netmask.");
}
*/
// Everything was fine, so persist the VLAN
saveVlan(zoneId, podId, vlanId, vlanGateway, vlanNetmask, vlanType, ipRange, networkId, physicalNetworkDbId);
if (podId != null) {
long vlanDbId = getVlanDbId(zone, vlanId);
String sql = "INSERT INTO `cloud`.`pod_vlan_map` (pod_id, vlan_db_id) " + "VALUES (?,?)";
String errorMsg = "Failed to save pod_vlan_map due to exception vlanDbId=" + vlanDbId + ", podId=" + podId + ". Please contact Cloud Support.";
TransactionLegacy txn = TransactionLegacy.open("saveSQL");
try ( PreparedStatement stmt = txn.prepareAutoCloseStatement(sql); ) {
stmt.setString(1, podId.toString());
stmt.setString(2, String.valueOf(vlanDbId));
stmt.executeUpdate();
} catch (SQLException ex) {
System.out.println("SQL Exception: " + ex.getMessage());
printError(errorMsg);
}
}
return genReturnList("true", "Successfully added VLAN.");
} else {
return genReturnList("false", "That operation is not suppored.");
}
/*
else {
// Check if a VLAN actually exists in the specified zone
long vlanDbId = getVlanDbId(zone, vlanId);
if (vlanDbId == -1)
return genReturnList("false", "A VLAN with ID " + vlanId + " does not exist in zone " + zone);
// Check if there are any public IPs that are in the specified vlan.
List<IPAddressVO> ips = _publicIpAddressDao.listByVlanDbId(vlanDbId);
if (ips.size() != 0)
return genReturnList("false", "Please delete all IP addresses that are in VLAN " + vlanId + " before deleting the VLAN.");
// Delete the vlan
_vlanDao.delete(vlanDbId);
return genReturnList("true", "Successfully deleted VLAN.");
}
*/
}
@DB
public void saveZone(boolean printOutput, long id, String name, String dns1, String dns2, String dns3, String dns4, String guestNetworkCidr, String networkType) {
if (printOutput)
System.out.println("Saving zone, please wait...");
String columns = null;
String values = null;
if (id != -1) {
columns = "(id, name";
values = "('" + id + "','" + name + "'";
} else {
columns = "(name";
values = "('" + name + "'";
}
if (dns1 != null) {
columns += ", dns1";
values += ",'" + dns1 + "'";
}
if (dns2 != null) {
columns += ", dns2";
values += ",'" + dns2 + "'";
}
if (dns3 != null) {
columns += ", internal_dns1";
values += ",'" + dns3 + "'";
}
if (dns4 != null) {
columns += ", internal_dns2";
values += ",'" + dns4 + "'";
}
if (guestNetworkCidr != null) {
columns += ", guest_network_cidr";
values += ",'" + guestNetworkCidr + "'";
}
if (networkType != null) {
columns += ", networktype";
values += ",'" + networkType + "'";
}
columns += ", uuid";
values += ", UUID()";
columns += ")";
values += ")";
String sql = "INSERT INTO `cloud`.`data_center` " + columns + " VALUES " + values;
DatabaseConfig.saveSQL(sql, "Failed to save zone due to exception. Please contact Cloud Support.");
if (printOutput)
System.out.println("Successfully saved zone.");
}
@DB
public void savePhysicalNetwork(boolean printOutput, long id, long dcId, int vnetStart, int vnetEnd) {
if (printOutput)
System.out.println("Saving physical network, please wait...");
String columns = null;
String values = null;
columns = "(id ";
values = "('" + id + "'";
columns += ", name ";
values += ",'physical network'";
columns += ", data_center_id ";
values += ",'" + dcId + "'";
//save vnet information
columns += ", vnet";
values += ",'" + vnetStart + "-" + vnetEnd + "'";
columns += ", state";
values += ", 'Enabled'";
columns += ", uuid";
values += ", UUID()";
columns += ")";
values += ")";
String sql = "INSERT INTO `cloud`.`physical_network` " + columns + " VALUES " + values;
DatabaseConfig.saveSQL(sql, "Failed to save physical network due to exception. Please contact Cloud Support.");
// Hardcode the vnet range to be the full range
int begin = 0x64;
int end = 64000;
// If vnet arguments were passed in, use them
if (vnetStart != -1 && vnetEnd != -1) {
begin = vnetStart;
end = vnetEnd;
}
String insertVnet = "INSERT INTO `cloud`.`op_dc_vnet_alloc` (vnet, data_center_id, physical_network_id) VALUES ( ?, ?, ?)";
TransactionLegacy txn = TransactionLegacy.currentTxn();
try {
PreparedStatement stmt = txn.prepareAutoCloseStatement(insertVnet);
for (int i = begin; i <= end; i++) {
stmt.setString(1, Integer.toString(i));
stmt.setLong(2, dcId);
stmt.setLong(3, id);
stmt.addBatch();
}
stmt.executeBatch();
} catch (SQLException ex) {
printError("Error creating vnet for the physical network. Please contact Cloud Support.");
}
//add default traffic types
//get default Xen network labels
String defaultXenPrivateNetworkLabel = getDefaultXenNetworkLabel(TrafficType.Management);
String defaultXenPublicNetworkLabel = getDefaultXenNetworkLabel(TrafficType.Public);
String defaultXenStorageNetworkLabel = getDefaultXenNetworkLabel(TrafficType.Storage);
String defaultXenGuestNetworkLabel = getDefaultXenNetworkLabel(TrafficType.Guest);
String insertTraficType = "INSERT INTO `cloud`.`physical_network_traffic_types` " + "(physical_network_id, traffic_type, xenserver_network_label) VALUES ( ?, ?, ?)";
try {
PreparedStatement stmt = txn.prepareAutoCloseStatement(insertTraficType);
for (TrafficType traffic : TrafficType.values()) {
if (traffic.equals(TrafficType.Control) || traffic.equals(TrafficType.Vpn) || traffic.equals(TrafficType.None)) {
continue;
}
stmt.setLong(1, id);
stmt.setString(2, traffic.toString());
if (traffic.equals(TrafficType.Public)) {
stmt.setString(3, defaultXenPublicNetworkLabel);
} else if (traffic.equals(TrafficType.Management)) {
stmt.setString(3, defaultXenPrivateNetworkLabel);
} else if (traffic.equals(TrafficType.Storage)) {
stmt.setString(3, defaultXenStorageNetworkLabel);
} else if (traffic.equals(TrafficType.Guest)) {
stmt.setString(3, defaultXenGuestNetworkLabel);
}
stmt.addBatch();
}
stmt.executeBatch();
} catch (SQLException ex) {
printError("Error adding default traffic types for the physical network. Please contact Cloud Support.");
}
if (printOutput)
System.out.println("Successfully saved physical network.");
}
private String getDefaultXenNetworkLabel(TrafficType trafficType) {
String xenLabel = null;
String configName = null;
switch (trafficType) {
case Public:
configName = "xenserver.public.network.device";
break;
case Guest:
configName = "xenserver.guest.network.device";
break;
case Storage:
configName = "xenserver.storage.network.device1";
break;
case Management:
configName = "xenserver.private.network.device";
break;
}
if (configName != null) {
xenLabel = getConfiguredValue(configName);
}
return xenLabel;
}
public static String getConfiguredValue(String configName) {
return DatabaseConfig.getDatabaseValueString("SELECT value FROM `cloud`.`configuration` where name = \"" + configName + "\"", "value",
"Unable to start DB connection to read configuration. Please contact Cloud Support.");
}
public void deleteZone(String name) {
String sql = "DELETE FROM `cloud`.`data_center` WHERE name=\"" + name + "\"";
DatabaseConfig.saveSQL(sql, "Failed to delete zone due to exception. Please contact Cloud Support.");
}
public void saveVlan(long zoneId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String vlanType, String ipRange, long networkId,
long physicalNetworkId) {
String sql =
"INSERT INTO `cloud`.`vlan` (vlan_id, vlan_gateway, vlan_netmask, data_center_id, vlan_type, ip4_range, network_id, physical_network_id) " + "VALUES ('" +
vlanId + "','" + vlanGateway + "','" + vlanNetmask + "','" + zoneId + "','" + vlanType + "','" + ipRange + "','" + networkId + "','" + physicalNetworkId +
"')";
DatabaseConfig.saveSQL(sql, "Failed to save vlan due to exception. Please contact Cloud Support.");
}
public static long getPodId(String pod, String zone) {
long dcId = getZoneId(zone);
String selectSql = "SELECT * FROM `cloud`.`host_pod_ref` WHERE name = \"" + pod + "\" AND data_center_id = \"" + dcId + "\"";
String errorMsg = "Could not read pod ID fro mdatabase. Please contact Cloud Support.";
return DatabaseConfig.getDatabaseValueLong(selectSql, "id", errorMsg);
}
public static long getPodId(String pod, long dcId) {
String selectSql = "SELECT * FROM `cloud`.`host_pod_ref` WHERE name = \"" + pod + "\" AND data_center_id = \"" + dcId + "\"";
String errorMsg = "Could not read pod ID fro mdatabase. Please contact Cloud Support.";
return DatabaseConfig.getDatabaseValueLong(selectSql, "id", errorMsg);
}
public static long getZoneId(String zone) {
String selectSql = "SELECT * FROM `cloud`.`data_center` WHERE name = \"" + zone + "\"";
String errorMsg = "Could not read zone ID from database. Please contact Cloud Support.";
return DatabaseConfig.getDatabaseValueLong(selectSql, "id", errorMsg);
}
public static long checkPhysicalNetwork(long physicalNetworkId) {
String selectSql = "SELECT * FROM `cloud`.`physical_network` WHERE id = \"" + physicalNetworkId + "\"";
String errorMsg = "Could not read physicalNetwork ID from database. Please contact Cloud Support.";
return DatabaseConfig.getDatabaseValueLong(selectSql, "id", errorMsg);
}
@DB
public Vector<Long> getAllZoneIDs() {
Vector<Long> allZoneIDs = new Vector<Long>();
String selectSql = "SELECT id FROM data_center";
TransactionLegacy txn = TransactionLegacy.currentTxn();
try {
PreparedStatement stmt = txn.prepareAutoCloseStatement(selectSql);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
Long dcId = rs.getLong("id");
allZoneIDs.add(dcId);
}
} catch (SQLException ex) {
System.out.println(ex.getMessage());
printError("There was an issue with reading zone IDs. Please contact Cloud Support.");
return null;
}
return allZoneIDs;
}
public static boolean validPod(String pod, String zone) {
return (getPodId(pod, zone) != -1);
}
public static boolean validZone(String zone) {
return (getZoneId(zone) != -1);
}
public static String getPodName(long podId, long dcId) {
return DatabaseConfig.getDatabaseValueString("SELECT * FROM `cloud`.`host_pod_ref` WHERE id=" + podId + " AND data_center_id=" + dcId, "name",
"Unable to start DB connection to read pod name. Please contact Cloud Support.");
}
public static String getZoneName(long dcId) {
return DatabaseConfig.getDatabaseValueString("SELECT * FROM `cloud`.`data_center` WHERE id=" + dcId, "name",
"Unable to start DB connection to read zone name. Please contact Cloud Support.");
}
private static void printError(String message) {
DatabaseConfig.printError(message);
}
private List<String> genReturnList(String success, String message) {
List<String> returnList = new ArrayList<String>();
returnList.add(0, success);
returnList.add(1, message);
return returnList;
}
}