/* * Copyright (c) 2013 Big Switch Networks, Inc. * * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html * * 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 org.sdnplatform.ovsdb.internal; import java.util.ArrayList; import java.util.Iterator; import java.util.Map.Entry; import org.jboss.netty.buffer.ChannelBuffer; import org.openflow.util.HexString; /** * JSONDelPortMsg builds the JSON RPC message to request the deletion * of a port * * @author Saurav Das * */ public class JSONDelPortMsg extends JSONMsg { private String name; private String portHash; private OVSDBImpl tsw; private int id; private String completeString; private String dbuuid = ""; /** * Constructor * @param name name of tunnel-port to delete * @param portHash hash-value of tunnel-port used by ovsdb * @param tsw the tunnel-switch on which to delete port * @param messageId message-id for this RPC message * @throws OVSDBBridgeUnknown */ public JSONDelPortMsg(String name, String portHash, OVSDBImpl tsw, int messageId) throws OVSDBBridgeUnknown { this.name = name; this.portHash = portHash; this.tsw = tsw; this.id = messageId; buildDelPortMsg(); } private void buildDelPortMsg() throws OVSDBBridgeUnknown { completeString = "{\"method\":\"transact\",\"id\":"+id+",\"params\":["+ " \"Open_vSwitch\", "; completeString += rowsUntil() + update() + mutations() + comment(); } private String rowsUntil() { String rows = ""; //first the interfaces String start = "{\"rows\":[{\"interfaces\":[\"uuid\",\""; String mid = "\"]}],\"until\":\"==\",\"where\":[[\"_uuid\",\"==\"" + ",[\"uuid\",\""; String end = "\"]]],\"timeout\":0,\"op\":\"wait\",\"table\":\"Port\"" + ",\"columns\":[\"interfaces\"]},"; Iterator<Entry<String, OVSPort>> iter = tsw.port.entrySet().iterator(); while(iter.hasNext()) { Entry<String, OVSPort> e = iter.next(); String portuuid = e.getKey(); String intfuuid = e.getValue().getNew().getInterfaces().get(1); rows += start + intfuuid + mid + portuuid + end; } // then the bridges -- assumes there is a single db called Open_vSwitch int numbridges = getNumBridges(); if (numbridges > 1) { start = "{\"rows\":[{\"bridges\":[\"set\",[[\"uuid\",\""; String mid2 = "\"],[\"uuid\",\""; String mid3 = "\"]]]}],\"until\":\"==\",\"where\":[[\"_uuid\"," + "\"==\",[\"uuid\",\""; end = "\"]]],\"timeout\":0,\"op\":\"wait\",\"table\":\"Open_" + "vSwitch\"" + ",\"columns\":[\"bridges\"]},"; Iterator<Entry<String, OVSDatabase>> iter1 = tsw.open_vswitch.entrySet().iterator(); rows += start; Iterator<String> iter2 = tsw.bridge.keySet().iterator(); while (iter2.hasNext()) { String bridgeuuid = iter2.next(); rows += bridgeuuid; if (iter2.hasNext()) rows += mid2; else rows += mid3; } while (iter1.hasNext()) { Entry<String, OVSDatabase> e1 = iter1.next(); dbuuid = e1.getKey(); break; // only one database } rows += dbuuid + end; } else { start = "{\"rows\":[{\"bridges\":[\"uuid\",\""; end = "\"]]],\"timeout\":0,\"op\":\"wait\",\"table\":\"Open_" + "vSwitch\"" + ",\"columns\":[\"bridges\"]},"; Iterator<Entry<String, OVSDatabase>> iter1 = tsw.open_vswitch.entrySet().iterator(); while(iter1.hasNext()) { Entry<String, OVSDatabase> e1 = iter1.next(); dbuuid = e1.getKey(); String bridgeuuid = (String) e1.getValue().getNew() .getBridges().get(1); rows += start + bridgeuuid + mid + dbuuid + end; break; // just one database } } //finally the ports per bridge - a separate entry per bridge Iterator<Entry<String, OVSBridge>> iter5 = tsw.bridge.entrySet() .iterator(); while (iter5.hasNext()) { Entry<String, OVSBridge> e = iter5.next(); OVSBridge br = e.getValue(); String bridgeuuid = e.getKey(); start = "{\"rows\":[{\"ports\":[\"set\",["; rows += start; String porthdr = "[\"uuid\",\""; String porttlr = "\"]"; ArrayList<String> brportuuids = br.getNew().getPortUuids(); for (int i=0; i< brportuuids.size(); i++) { rows += porthdr + brportuuids.get(i) + porttlr; if (i+1 < brportuuids.size()) rows += ","; } end = "\"]]],\"timeout\":0,\"op\":\"wait\",\"table\":\"Bridge\"" + ",\"columns\":[\"ports\"]},"; rows += "]" + mid.substring(1) + bridgeuuid + end; } return rows; } private int getNumBridges() { // only a single database per ovs is expected for( OVSDatabase odb : tsw.open_vswitch.values()) { ArrayList<Object> brs = odb.getNew().getBridges(); return brs.size(); } return 0; } private String update() throws OVSDBBridgeUnknown { String bridgeuuid = getBridgeuuid(); String start1 = "{\"where\":[[\"_uuid\",\"==\",[\"uuid\",\"" + bridgeuuid + "\"]]],\"op\":\"update\",\"table\":\"Bridge\"," + "\"row\":{\"ports\":[\"set\",["; String ports = ""; String porthdr = "[\"uuid\",\""; String porttlr = "\"]"; OVSBridge br = tsw.bridge.get(bridgeuuid); if ( br == null ) { throw new RuntimeException("tsw.bridge.get("+ bridgeuuid + ") returned Null"); } ArrayList<String> pl = br.getNew().getPortUuids(); //for this bridge for (int i=0; i< pl.size(); i++) { String portkey = pl.get(i); if (portkey.equals(portHash)) { if (i+1 >= pl.size()) { ports = ports.substring(0, ports.length()-1); } continue; } ports += porthdr + portkey + porttlr; if (i+1 < pl.size()) ports += ","; } return start1 + ports + "]]}},"; } private String getBridgeuuid() throws OVSDBBridgeUnknown { long dpid = tsw.getDpid(); Iterator<Entry<String, OVSBridge>> iter = tsw.bridge.entrySet(). iterator(); while (iter.hasNext()) { Entry<String, OVSBridge> e = iter.next(); String bruuid = e.getKey(); OVSBridge br = e.getValue(); if (br.getNew().getReportedDpid() == dpid) { return bruuid; } } throw new OVSDBBridgeUnknown(tsw.getDpid()); } private String mutations() { return "{\"mutations\":[[\"next_cfg\",\"+=\",1]]," + "\"where\":[[\"_uuid\",\"==\",[\"uuid\",\"" + dbuuid + "\"]]]," + "\"op\":\"mutate\",\"table\":\"Open_vSwitch\"}," + "{\"where\":[[\"_uuid\",\"==\",[\"uuid\",\"" + dbuuid + "\"]]]," + "\"op\":\"select\",\"table\":\"Open_vSwitch\"," + "\"columns\":[\"next_cfg\"]},"; } private String comment() { return "{\"comment\":\"ovs-vsctl: ./ovs-vsctl --db=tcp:" + tsw.getMgmtIPAddr() + ":6635 del-port tunnelswitch " + name + "\",\"op\":\"comment\"}]}"; } @Override public void writeTo(ChannelBuffer buf) { if (log.isTraceEnabled()) { log.trace("sent del-port message to:" + name + " msg-id:"+ id + " @sw: {} ", HexString.toHexString(tsw.getDpid())); } buf.writeBytes(completeString.getBytes()); } @Override public int getLengthU() { return completeString.length(); } }