Adding DB support for interfaces OVS tunnel manager will use as GRE endpoints

This commit is contained in:
Salvatore Orlando 2012-03-26 11:57:50 +01:00
parent 3513551ae3
commit b980993864
7 changed files with 414 additions and 3 deletions

View File

@ -0,0 +1,59 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.ovs;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
public class OvsFetchInterfaceAnswer extends Answer {
String ip;
String netmask;
String mac;
String label;
public OvsFetchInterfaceAnswer(Command cmd, boolean success, String details) {
super(cmd, success, details);
this.label = ((OvsFetchInterfaceCommand)cmd).getLabel();
}
public OvsFetchInterfaceAnswer(Command cmd, boolean success,
String details, String ip, String netmask, String mac) {
super(cmd, success, details);
this.ip = ip;
this.netmask = netmask;
this.mac = mac;
this.label = ((OvsFetchInterfaceCommand)cmd).getLabel();
}
public String getIp() {
return ip;
}
public String getNetmask() {
return netmask;
}
public String getMac() {
return mac;
}
public String getLabel() {
return label;
}
}

View File

@ -0,0 +1,39 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.ovs;
import com.cloud.agent.api.Command;
public class OvsFetchInterfaceCommand extends Command {
String label;
@Override
public boolean executeInSequence() {
return true;
}
public OvsFetchInterfaceCommand(String label) {
this.label = label;
}
public String getLabel() {
return label;
}
}

View File

@ -179,6 +179,8 @@ import com.cloud.network.ovs.OvsCreateTunnelCommand;
import com.cloud.network.ovs.OvsDeleteFlowCommand;
import com.cloud.network.ovs.OvsDestroyBridgeCommand;
import com.cloud.network.ovs.OvsDestroyTunnelCommand;
import com.cloud.network.ovs.OvsFetchInterfaceAnswer;
import com.cloud.network.ovs.OvsFetchInterfaceCommand;
import com.cloud.network.ovs.OvsSetTagAndFlowAnswer;
import com.cloud.network.ovs.OvsSetTagAndFlowCommand;
import com.cloud.network.ovs.OvsSetupBridgeCommand;
@ -210,6 +212,7 @@ import com.xensource.xenapi.HostMetrics;
import com.xensource.xenapi.Network;
import com.xensource.xenapi.PBD;
import com.xensource.xenapi.PIF;
import com.xensource.xenapi.PIF.Record;
import com.xensource.xenapi.Pool;
import com.xensource.xenapi.SR;
import com.xensource.xenapi.Session;
@ -478,6 +481,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
return execute((CheckSshCommand)cmd);
} else if (clazz == SecurityGroupRulesCmd.class) {
return execute((SecurityGroupRulesCmd) cmd);
} else if (clazz == OvsFetchInterfaceCommand.class) {
return execute((OvsFetchInterfaceCommand)cmd);
} else if (clazz == OvsCreateGreTunnelCommand.class) {
return execute((OvsCreateGreTunnelCommand)cmd);
} else if (clazz == OvsSetTagAndFlowCommand.class) {
@ -4940,6 +4945,28 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
}
private OvsFetchInterfaceAnswer execute(OvsFetchInterfaceCommand cmd) {
String label = cmd.getLabel();
s_logger.debug("### Will look for network with name-label:" + label + " on host " + _host.ip);
Connection conn = getConnection();
try {
XsLocalNetwork nw = this.getNetworkByName(conn, label);
s_logger.debug("### Network object:" + nw.getNetwork().getUuid(conn));
PIF pif = nw.getPif(conn);
Record pifRec = pif.getRecord(conn);
s_logger.debug("### PIF object:" + pifRec.uuid + "(" + pifRec.device + ")");
return new OvsFetchInterfaceAnswer(cmd, true, "Interface " + pifRec.device + " retrieved successfully",
pifRec.IP, pifRec.netmask, pifRec.MAC);
} catch (Exception e) {
e.printStackTrace();
return new OvsFetchInterfaceAnswer(cmd, false, "EXCEPTION:" + e.getMessage());
}
}
private OvsCreateGreTunnelAnswer execute(OvsCreateGreTunnelCommand cmd) {
_isOvs = true;

View File

@ -33,7 +33,15 @@ import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.PhysicalNetwork;
import com.cloud.network.PhysicalNetworkTrafficType;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
import com.cloud.network.ovs.dao.OvsTunnelInterfaceDao;
import com.cloud.network.ovs.dao.OvsTunnelInterfaceVO;
import com.cloud.network.ovs.dao.OvsTunnelNetworkDao;
import com.cloud.network.ovs.dao.OvsTunnelNetworkVO;
import com.cloud.utils.component.Inject;
@ -62,9 +70,11 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager {
@Inject ConfigurationDao _configDao;
@Inject NicDao _nicDao;
@Inject HostDao _hostDao;
@Inject PhysicalNetworkTrafficTypeDao _physNetTTDao;
@Inject UserVmDao _userVmDao;
@Inject DomainRouterDao _routerDao;
@Inject OvsTunnelNetworkDao _tunnelNetworkDao;
@Inject OvsTunnelInterfaceDao _tunnelInterfaceDao;
@Inject AgentManager _agentMgr;
@Override
@ -101,6 +111,40 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager {
return ta;
}
@DB
protected OvsTunnelInterfaceVO createInterfaceRecord(String ip, String netmask, String mac,
long hostId, String label) {
OvsTunnelInterfaceVO ti = null;
try {
ti = new OvsTunnelInterfaceVO(ip, netmask, mac, hostId, label);
//TODO: Is locking really necessary here?
OvsTunnelInterfaceVO lock = _tunnelInterfaceDao.acquireInLockTable(Long.valueOf(1));
if (lock == null) {
s_logger.warn("Cannot lock table ovs_tunnel_account");
return null;
}
_tunnelInterfaceDao.persist(ti);
_tunnelInterfaceDao.releaseFromLockTable(lock.getId());
} catch (EntityExistsException e) {
s_logger.debug("A record for the interface for network " + label +
" on host id " + hostId + " already exists");
}
return ti;
}
private String handleFetchInterfaceAnswer(Answer[] answers, Long hostId){
OvsFetchInterfaceAnswer ans = (OvsFetchInterfaceAnswer) answers[0];
String s = String.format(
"(ip:%1$s, netmask:%2$s, mac:%3$s, label:%4s, host:%5l)",
ans.getIp(), ans.getNetmask(), ans.getMac(), ans.getLabel(), hostId);
s_logger.debug("### About to add DB entry for:" + s);
OvsTunnelInterfaceVO ti = createInterfaceRecord(ans.getIp(), ans.getNetmask(), ans.getMac(),
hostId, ans.getLabel());
s_logger.debug("### Interface added to DB - id:" + ti.getId());
return ti.getIp();
}
private void handleCreateTunnelAnswer(Answer[] answers){
OvsCreateTunnelAnswer r = (OvsCreateTunnelAnswer) answers[0];
String s = String.format(
@ -203,9 +247,43 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager {
}
//FIXME: Why are we cancelling the exception here?
try {
//HACK HACK HACK - Should not use public IP
String myIp = dest.getHost().getPublicIpAddress();
boolean noHost = true;
String myIp = null;
// Fetch physical network and associated tags
// If no tag specified, look for this network
// TODO: Should we Make this a configuration option?
String physNetLabel = "cloud-public";
Long physNetId = nw.getPhysicalNetworkId();
PhysicalNetworkTrafficType physNetTT = _physNetTTDao.findBy(physNetId, TrafficType.Guest);
s_logger.debug("### Physical network:" + physNetId + " - traffic type:" + physNetTT.getUuid());
HypervisorType hvType = dest.getHost().getHypervisorType();
switch (hvType) {
case XenServer:
String label = physNetTT.getXenNetworkLabel();
if ((label!=null) && (!label.equals(""))) {
physNetLabel = label;
}
break;
default:
throw new CloudRuntimeException("Hypervisor " + hvType.toString() + " unsupported by OVS Tunnel Manager");
}
// Try to fetch GRE endpoint IP address for cloud db
// If not found, then find it on the hypervisor
OvsTunnelInterfaceVO tunnelIface = _tunnelInterfaceDao.getByHostAndLabel(hostId, physNetLabel);
if (tunnelIface == null) {
//Now find and fetch configuration for physical interface for network with label on target host
Commands fetchIfaceCmds = new Commands(new OvsFetchInterfaceCommand(physNetLabel));
s_logger.debug("Ask host " + hostId + " to retrieve interface for phy net with label:" + physNetLabel);
Answer[] fetchIfaceAnswers = _agentMgr.send(hostId, fetchIfaceCmds);
//And finally save it for future use
myIp = handleFetchInterfaceAnswer(fetchIfaceAnswers, hostId);
} else {
myIp = tunnelIface.getIp();
}
boolean noHost = true;
for (Long i : toHostIds) {
HostVO rHost = _hostDao.findById(i);
Commands cmds = new Commands(

View File

@ -0,0 +1,32 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.ovs.dao;
import java.util.List;
import com.cloud.utils.db.GenericDao;
public interface OvsTunnelInterfaceDao extends
GenericDao<OvsTunnelInterfaceVO, Long> {
OvsTunnelInterfaceVO getByHostAndLabel(long hostId, String label);
List<OvsTunnelInterfaceVO> listByLabel(String label);
}

View File

@ -0,0 +1,65 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.ovs.dao;
import java.util.List;
import javax.ejb.Local;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
@Local(value = { OvsTunnelInterfaceDao.class })
public class OvsTunnelInterfaceDaoImpl extends
GenericDaoBase<OvsTunnelInterfaceVO, Long> implements OvsTunnelInterfaceDao {
protected final SearchBuilder<OvsTunnelInterfaceVO> hostAndLabelSearch;
protected final SearchBuilder<OvsTunnelInterfaceVO> labelSearch;
public OvsTunnelInterfaceDaoImpl() {
hostAndLabelSearch = createSearchBuilder();
hostAndLabelSearch.and("host_id", hostAndLabelSearch.entity().getHostId(), Op.EQ);
hostAndLabelSearch.and("label", hostAndLabelSearch.entity().getLabel(), Op.EQ);
hostAndLabelSearch.done();
labelSearch = createSearchBuilder();
labelSearch.and("label", labelSearch.entity().getLabel(), Op.EQ);
labelSearch.done();
}
@Override
public OvsTunnelInterfaceVO getByHostAndLabel(long hostId, String label) {
SearchCriteria<OvsTunnelInterfaceVO> sc = hostAndLabelSearch.create();
sc.setParameters("host_id", hostId);
sc.setParameters("label", label);
return findOneBy(sc);
}
@Override
public List<OvsTunnelInterfaceVO> listByLabel(String label) {
SearchCriteria<OvsTunnelInterfaceVO> sc = labelSearch.create();
sc.setParameters("label", label);
return listBy(sc);
}
}

View File

@ -0,0 +1,111 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.ovs.dao;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name=("ovs_tunnel_interface"))
public class OvsTunnelInterfaceVO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "ip")
private String ip;
@Column(name = "netmask")
private String netmask;
@Column(name = "mac")
private String mac;
@Column(name = "host_id")
private long hostId;
@Column(name = "label")
private String label;
public OvsTunnelInterfaceVO() {
}
public OvsTunnelInterfaceVO(String ip, String netmask, String mac, long hostId, String label) {
this.ip = ip;
this.netmask = netmask;
this.mac = mac;
this.hostId = hostId;
this.label = label;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getNetmask() {
return netmask;
}
public void setNetmask(String netmask) {
this.netmask = netmask;
}
public String getMac() {
return mac;
}
public void setMac(String mac) {
this.mac = mac;
}
public long getHostId() {
return hostId;
}
public void setHostId(long hostId) {
this.hostId = hostId;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
}