Source code for sts.snapshot

# Copyright 2011-2013 Colin Scott
# Copyright 2011-2013 Andreas Wundsam
# Copyright 2012-2013 Sam Whitlock
# Copyright 2012-2012 Kyriakos Zarifis
#
# Licensed 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.

import urllib2
import logging
import json
import string
import time
from pox.lib.graph.util import NOMDecoder
from pox.openflow.topology import OpenFlowSwitch
from pox.openflow.flow_table import FlowTable, TableEntry
from pox.openflow.libopenflow_01 import ofp_match, ofp_action_output
from sts.entities import POXController, BigSwitchController

log = logging.getLogger("Snapshot")

[docs]class Snapshot(object): """ A Snapshot object is a description of the controllers' view of the network in terms that are meaningful to the debugger. Any snaphsot grabbed from any controller should be transformed into a Snapshot object in order to be fed to HSA """ def __int__(self): self.time = None self.switches = [] # The debugger doesn't use the next two (for now anyway) self.hosts = [] self.links = [] def __repr__(self): return "<Snapshot object: (%i switches)>"%len(self.switches)
[docs]class SnapshotService(object): """ Controller-specific SnapshotServices take care of grabbing a snapshot from their controller in whatever format the controller exports it, and translating it into a Snaphot object that is meaningful to the debbuger """
[docs] def __init__(self): self.snapshot = Snapshot()
[docs] def fetchSnapshot(self, controller): pass
[docs]class FlexibleNOMDecoder:
[docs] def __init__(self): self.pox_nom_decoder = NOMDecoder()
[docs] def decode(self, json): if isinstance(json, (str, unicode)) and string.find(json, "__module__")>=0: return self.pox_nom_decoder.decode(json) else: return self.decode_switch(json)
[docs] def decode_switch(self, json): flow_table = self.decode_flow_table(json["flow_table"] if "flow_table" in json else json["flowTable"]) switch = OpenFlowSwitch(json["dpid"], flow_table=flow_table) return switch
[docs] def decode_flow_table(self, json): ft = FlowTable() for e in json["entries"]: ft.add_entry(self.decode_entry(e)) return ft
[docs] def decode_entry(self, json): e = TableEntry() for (k, v) in json.iteritems(): if k == "match": e.match = self.decode_match(v) elif k == "actions": e.actions = [ self.decode_action(a) for a in v ] else: setattr(e, k, v) return e
[docs] def decode_match(self, json): return ofp_match(**json)
[docs] def decode_action(self, json): a = ofp_action_output(port = json['port']) return a
[docs]class SyncProtoSnapshotService(SnapshotService):
[docs] def __init__(self): SnapshotService.__init__(self) self.myNOMDecoder = FlexibleNOMDecoder()
[docs] def fetchSnapshot(self, controller): jsonNOM = controller.sync_connection.get_nom_snapshot() # Update local Snapshot object self.snapshot.switches = [self.myNOMDecoder.decode(s) for s in jsonNOM["switches"]] self.snapshot.hosts = [self.myNOMDecoder.decode(h) for h in jsonNOM["hosts"]] self.snapshot.links = [self.myNOMDecoder.decode(l) for l in jsonNOM["links"]] self.snapshot.time = time.time() return self.snapshot
[docs]class PoxSnapshotService(SnapshotService):
[docs] def __init__(self): SnapshotService.__init__(self) self.port = 7790 self.myNOMDecoder = NOMDecoder()
[docs] def fetchSnapshot(self, controller): from pox.lib.util import connect_socket_with_backoff import socket snapshotSocket = connect_socket_with_backoff('127.0.0.1', self.port) log.debug("Sending Request") snapshotSocket.send("{\"hello\":\"nommessenger\"}") snapshotSocket.send("{\"getnom\":0}", socket.MSG_WAITALL) log.debug("Receiving Results") jsonstr = "" while True: data = snapshotSocket.recv(1024) log.debug("%d byte packet received" % len(data)) if not data: break jsonstr += data if len(data) != 1024: break snapshotSocket.close() jsonNOM = json.loads(jsonstr) # (json string with the NOM) # Update local Snapshot object self.snapshot.switches = [self.myNOMDecoder.decode(s) for s in jsonNOM["switches"]] self.snapshot.hosts = [self.myNOMDecoder.decode(h) for h in jsonNOM["hosts"]] self.snapshot.links = [self.myNOMDecoder.decode(l) for l in jsonNOM["links"]] self.snapshot.time = time.time() return self.snapshot
[docs]class BigSwitchSnapshotService(SnapshotService):
[docs] def __init__(self): SnapshotService.__init__(self)
[docs] def fetchSnapshot(self, controller): req = urllib2.Request('http://localhost:8080/wm/core/proact') response = urllib2.urlopen(req) json_data = response.read() l = json.loads(json_data) res = [] for m in l: res.append(Snapshot.from_json_map(m)) return res # Create local Snapshot object snapshot = Snapshot() self.snapshot = snapshot return self.snapshot
[docs]def get_snapshotservice(controller_configs): '''Return a SnapshotService object determined by the name of the first controller in the controller_configs. For now, we only support a homogenous controller environment.''' # Read from config what controller we are using # TODO(cs): allow for heterogenous controllers? if controller_configs != [] and controller_configs[0].sync: snapshotService = SyncProtoSnapshotService() elif controller_configs != [] and controller_configs[0].type == POXController: snapshotService = PoxSnapshotService() elif controller_configs != [] and controller_configs[0].type == BigSwitchController: snapshotService = BigSwitchSnapshotService() else: # We default snapshotService to POX snapshotService = PoxSnapshotService() return snapshotService