From b98099386474cc91a6684464748a8910de2478c4 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Mon, 26 Mar 2012 11:57:50 +0100 Subject: [PATCH] Adding DB support for interfaces OVS tunnel manager will use as GRE endpoints --- .../network/ovs/OvsFetchInterfaceAnswer.java | 59 ++++++++++ .../network/ovs/OvsFetchInterfaceCommand.java | 39 ++++++ .../xen/resource/CitrixResourceBase.java | 27 +++++ .../network/ovs/OvsTunnelManagerImpl.java | 84 ++++++++++++- .../ovs/dao/OvsTunnelInterfaceDao.java | 32 +++++ .../ovs/dao/OvsTunnelInterfaceDaoImpl.java | 65 ++++++++++ .../network/ovs/dao/OvsTunnelInterfaceVO.java | 111 ++++++++++++++++++ 7 files changed, 414 insertions(+), 3 deletions(-) create mode 100644 api/src/com/cloud/network/ovs/OvsFetchInterfaceAnswer.java create mode 100644 api/src/com/cloud/network/ovs/OvsFetchInterfaceCommand.java create mode 100644 server/src/com/cloud/network/ovs/dao/OvsTunnelInterfaceDao.java create mode 100644 server/src/com/cloud/network/ovs/dao/OvsTunnelInterfaceDaoImpl.java create mode 100644 server/src/com/cloud/network/ovs/dao/OvsTunnelInterfaceVO.java diff --git a/api/src/com/cloud/network/ovs/OvsFetchInterfaceAnswer.java b/api/src/com/cloud/network/ovs/OvsFetchInterfaceAnswer.java new file mode 100644 index 00000000000..53c0c13ee2f --- /dev/null +++ b/api/src/com/cloud/network/ovs/OvsFetchInterfaceAnswer.java @@ -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 . + * + */ + +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; + } +} diff --git a/api/src/com/cloud/network/ovs/OvsFetchInterfaceCommand.java b/api/src/com/cloud/network/ovs/OvsFetchInterfaceCommand.java new file mode 100644 index 00000000000..4e42506a4fd --- /dev/null +++ b/api/src/com/cloud/network/ovs/OvsFetchInterfaceCommand.java @@ -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 . + * + */ + +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; + } + +} diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index f762689ee82..8164b57a521 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -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; diff --git a/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java b/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java index 62826ec6d08..50a82427506 100644 --- a/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java +++ b/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java @@ -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( diff --git a/server/src/com/cloud/network/ovs/dao/OvsTunnelInterfaceDao.java b/server/src/com/cloud/network/ovs/dao/OvsTunnelInterfaceDao.java new file mode 100644 index 00000000000..3298ca686a9 --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/OvsTunnelInterfaceDao.java @@ -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 . + * + */ + +package com.cloud.network.ovs.dao; + +import java.util.List; + +import com.cloud.utils.db.GenericDao; + +public interface OvsTunnelInterfaceDao extends + GenericDao { + + OvsTunnelInterfaceVO getByHostAndLabel(long hostId, String label); + + List listByLabel(String label); + +} diff --git a/server/src/com/cloud/network/ovs/dao/OvsTunnelInterfaceDaoImpl.java b/server/src/com/cloud/network/ovs/dao/OvsTunnelInterfaceDaoImpl.java new file mode 100644 index 00000000000..5adf63d3362 --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/OvsTunnelInterfaceDaoImpl.java @@ -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 . + * + */ + +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 implements OvsTunnelInterfaceDao { + + protected final SearchBuilder hostAndLabelSearch; + protected final SearchBuilder 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 sc = hostAndLabelSearch.create(); + sc.setParameters("host_id", hostId); + sc.setParameters("label", label); + return findOneBy(sc); + } + + @Override + public List listByLabel(String label) { + SearchCriteria sc = labelSearch.create(); + sc.setParameters("label", label); + return listBy(sc); + } + + +} diff --git a/server/src/com/cloud/network/ovs/dao/OvsTunnelInterfaceVO.java b/server/src/com/cloud/network/ovs/dao/OvsTunnelInterfaceVO.java new file mode 100644 index 00000000000..0b2699dcf4c --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/OvsTunnelInterfaceVO.java @@ -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 . + * + */ + +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; + } + +}