blob: 387e8bdf1547cb3b2098b49237c06ba9d8058776 [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.hypervisor.ovm3.resources.helpers;
import java.util.List;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckNetworkAnswer;
import com.cloud.agent.api.CheckNetworkCommand;
import com.cloud.agent.api.PingTestCommand;
import com.cloud.agent.api.to.NicTO;
import com.cloud.hypervisor.ovm3.objects.CloudstackPlugin;
import com.cloud.hypervisor.ovm3.objects.Connection;
import com.cloud.hypervisor.ovm3.objects.Network;
import com.cloud.hypervisor.ovm3.objects.Ovm3ResourceException;
import com.cloud.network.PhysicalNetworkSetupInfo;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.TrafficType;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
public class Ovm3HypervisorNetwork {
private static final Logger LOGGER = Logger
.getLogger(Ovm3HypervisorNetwork.class);
private Connection c;
private Ovm3Configuration config;
public Ovm3HypervisorNetwork(Connection conn, Ovm3Configuration ovm3config) {
c = conn;
config = ovm3config;
}
public void configureNetworking() throws ConfigurationException {
/* TODO: setup meta tags for the management interface (probably
* required with multiple interfaces)?
*/
try {
Network net = new Network(c);
String controlIface = config.getAgentControlNetworkName();
if (controlIface != null
&& net.getInterfaceByName(controlIface) == null) {
LOGGER.debug("starting " + controlIface);
net.startOvsLocalConfig(controlIface);
/* ovs replies too "fast" so the bridge can be "busy" */
int contCount = 0;
while (net.getInterfaceByName(controlIface) == null) {
LOGGER.debug("waiting for " + controlIface);
Thread.sleep(1 * 1000);
if (contCount > 9) {
throw new ConfigurationException("Unable to configure "
+ controlIface + " on host "
+ config.getAgentHostname());
}
contCount++;
}
} else {
LOGGER.debug("already have " + controlIface);
}
/*
* The bridge is remembered upon reboot, but not the IP or the
* config. Zeroconf also adds the route again by default.
*/
net.ovsIpConfig(controlIface, "static",
NetUtils.getLinkLocalGateway(),
NetUtils.getLinkLocalNetMask());
CloudstackPlugin cSp = new CloudstackPlugin(c);
cSp.ovsControlInterface(controlIface,
NetUtils.getLinkLocalCIDR());
} catch (InterruptedException e) {
LOGGER.error("interrupted?", e);
} catch (Ovm3ResourceException e) {
String msg = "Basic configuration failed on " + config.getAgentHostname();
LOGGER.error(msg, e);
throw new ConfigurationException(msg + ", " + e.getMessage());
}
}
/**/
private boolean isNetworkSetupByName(String nameTag) {
if (nameTag != null) {
LOGGER.debug("Looking for network setup by name " + nameTag);
try {
Network net = new Network(c);
net.getInterfaceList();
if (net.getBridgeByName(nameTag) != null) {
LOGGER.debug("Found bridge with name: " + nameTag);
return true;
}
} catch (Ovm3ResourceException e) {
LOGGER.debug("Unxpected error looking for name: " + nameTag, e);
return false;
}
}
LOGGER.debug("No bridge with name: " + nameTag);
return false;
}
/* this might have to change in the future, works for now... */
public CheckNetworkAnswer execute(CheckNetworkCommand cmd) {
LOGGER.debug("Checking if network name setup is done on "
+ config.getAgentHostname());
List<PhysicalNetworkSetupInfo> infoList = cmd
.getPhysicalNetworkInfoList();
/* here we assume all networks are set */
for (PhysicalNetworkSetupInfo info : infoList) {
if (info.getGuestNetworkName() == null) {
info.setGuestNetworkName(config.getAgentGuestNetworkName());
}
if (info.getPublicNetworkName() == null) {
info.setPublicNetworkName(config.getAgentPublicNetworkName());
}
if (info.getPrivateNetworkName() == null) {
info.setPrivateNetworkName(config.getAgentPrivateNetworkName());
}
if (info.getStorageNetworkName() == null) {
info.setStorageNetworkName(config.getAgentStorageNetworkName());
}
if (!isNetworkSetupByName(info.getGuestNetworkName())) {
String msg = "Guest Physical Network id:"
+ info.getPhysicalNetworkId()
+ ", Guest Network is not configured on the backend by name "
+ info.getGuestNetworkName();
LOGGER.error(msg);
return new CheckNetworkAnswer(cmd, false, msg);
}
if (!isNetworkSetupByName(info.getPrivateNetworkName())) {
String msg = "Private Physical Network id:"
+ info.getPhysicalNetworkId()
+ ", Private Network is not configured on the backend by name "
+ info.getPrivateNetworkName();
LOGGER.error(msg);
return new CheckNetworkAnswer(cmd, false, msg);
}
if (!isNetworkSetupByName(info.getPublicNetworkName())) {
String msg = "Public Physical Network id:"
+ info.getPhysicalNetworkId()
+ ", Public Network is not configured on the backend by name "
+ info.getPublicNetworkName();
LOGGER.error(msg);
return new CheckNetworkAnswer(cmd, false, msg);
}
/* Storage network is optional, will revert to private otherwise */
}
return new CheckNetworkAnswer(cmd, true,
"Network Setup check by names is done");
}
public Answer execute(PingTestCommand cmd) {
try {
if (cmd.getComputingHostIp() != null) {
CloudstackPlugin cSp = new CloudstackPlugin(c);
if (!cSp.ping(cmd.getComputingHostIp())) {
return new Answer(cmd, false, "ping failed");
}
} else {
return new Answer(cmd, false, "why asks me to ping a router???");
}
return new Answer(cmd, true, "success");
} catch (Ovm3ResourceException e) {
LOGGER.debug("Ping " + cmd.getComputingHostIp() + " failed", e);
return new Answer(cmd, false, e.getMessage());
}
}
private String createVlanBridge(String networkName, Integer vlanId)
throws Ovm3ResourceException {
if (vlanId < 1 || vlanId > 4094) {
String msg = "Incorrect vlan " + vlanId
+ ", needs to be between 1 and 4094";
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
Network net = new Network(c);
/* figure out if our bridged vlan exists, if not then create */
String brName = networkName + "." + vlanId.toString();
try {
String physInterface = net.getPhysicalByBridgeName(networkName);
if (net.getInterfaceByName(brName) == null) {
net.startOvsVlanBridge(brName, physInterface, vlanId);
} else {
LOGGER.debug("Interface " + brName + " already exists");
}
} catch (Ovm3ResourceException e) {
String msg = "Unable to create vlan " + vlanId.toString()
+ " bridge for " + networkName;
LOGGER.warn(msg + ": " + e);
throw new CloudRuntimeException(msg + ":" + e.getMessage());
}
return brName;
}
/* getNetwork needs to be split in pure retrieval versus creation */
public String getNetwork(NicTO nic) throws Ovm3ResourceException {
String vlanId = null;
String bridgeName = null;
if (nic.getBroadcastType() == BroadcastDomainType.Vlan) {
vlanId = BroadcastDomainType.getValue(nic.getBroadcastUri());
}
if (nic.getType() == TrafficType.Guest) {
if (nic.getBroadcastType() == BroadcastDomainType.Vlan
&& !"untagged".equalsIgnoreCase(vlanId)) {
/* This is completely the wrong place for this, we should NEVER
* create a network when we're just trying to figure out if it's there
* The name of this is misleading and wrong.
*/
bridgeName = createVlanBridge(config.getAgentGuestNetworkName(),
Integer.valueOf(vlanId));
} else {
bridgeName = config.getAgentGuestNetworkName();
}
/* VLANs for other mgmt traffic ? */
} else if (nic.getType() == TrafficType.Control) {
bridgeName = config.getAgentControlNetworkName();
} else if (nic.getType() == TrafficType.Public) {
bridgeName = config.getAgentPublicNetworkName();
} else if (nic.getType() == TrafficType.Management) {
bridgeName = config.getAgentPrivateNetworkName();
} else if (nic.getType() == TrafficType.Storage) {
bridgeName = config.getAgentStorageNetworkName();
} else {
throw new CloudRuntimeException("Unknown network traffic type:"
+ nic.getType());
}
return bridgeName;
}
}