Statistics
| Branch: | Revision:

wcn_emulator / test_code / dummyrouting.py @ 29e07078

History | View | Annotate | Download (9.77 KB)

1

    
2
import sys
3
sys.path.append('../')
4
from network_builder import *
5
from os import kill, path, makedirs
6
from matplotlib.pyplot import ion
7
import random 
8
import time
9

    
10
import signal
11

    
12
from test_generic import *
13

    
14
class dummyRoutingTest(MininetTest):
15

    
16
    def __init__(self, mininet, duration=10):
17

    
18
        super(dummyRoutingTest, self).__init__(mininet, path, duration)
19

    
20

    
21
    def launchSniffer(self, host):
22

    
23
        cmd = "tcpdump -i any -n -X -e "
24

    
25
        logfile = self.prefix + host.name + "-dump.log"
26

    
27
        params = {}
28
        params['>'] = logfile
29
        params['2>'] = logfile
30

    
31

    
32
        return self.bgCmd(host, True, cmd,
33
            *reduce(lambda x, y: x + y, params.items()))
34

    
35

    
36
    def launchdummyRouting(self, host,  args):
37

    
38
        cmd = "../dummy_routing_protocol/routingdaemon.py " + \
39
                args
40

    
41
        logfile = self.prefix + host.name + ".log"
42

    
43
        params = {}
44
        params['>'] = logfile
45
        params['2>'] = logfile
46

    
47

    
48
        return self.bgCmd(host, True, cmd,
49
            *reduce(lambda x, y: x + y, params.items()))
50

    
51
    def runTest(self):
52

    
53
        info("*** Launching dummyRouting test\n")
54
        info("Data folder: "+self.prefix+"\n")
55

    
56
        if self.stopAllNodes:
57
            self.centList = self.getCentrality()
58
            self.numRuns = 3#len(self.centList)
59

    
60
        for runid in range(self.numRuns):
61
            info("\nStarting run " + str(runid) + "\n")
62
            self.runId = str(runid)
63
            if self.stopAllNodes:
64
                self.nodeCrashed = self.centList.pop()[0]
65

    
66
            self.startRun()
67

    
68
            eventDict = {
69
                    self.startLog:["Start logging", self.sendSignal,
70
                        {"sig":signal.SIGUSR1}],
71
                    self.stopNode:["Stopping node " + str(self.nodeCrashed),
72
                        self.sendSignal, {"sig":signal.SIGTSTP,
73
                        "hostName":self.nodeCrashed}],
74
                    self.stopLog:["Stop logging", self.sendSignal,
75
                        {"sig":signal.SIGUSR1}]}
76

    
77
            eventList = []
78
            relativeTime = 0
79
            for e in sorted(eventDict.keys()):
80
                if e > 0:
81
                    data = eventDict[e]
82
                    eventList.append([e - relativeTime] + data)
83
                    relativeTime += (e - relativeTime)
84

    
85
            waitTime = self.duration - relativeTime
86

    
87
            for event in eventList:
88
                sleep(event[0])
89
                event[2](**event[3])
90
                info(event[1] + str(time.time()) + "\n")
91
            sleep(waitTime)
92
            self.killAll(signal.SIGTERM)
93
            time.sleep(1)
94
            self.killAll()
95
            time.sleep(1)
96
            #sendSignal(signal.SIGUSR2)
97
            #if self.startLog > 0:
98
            #    duration -= self.startLog
99
            #    sleep(self.startLog)
100
            #    print "XX", self.startLog, duration, time.time()
101
            #    # this is interpreted by the daemons as 
102
            #    # "start (or stop) logging"
103
            #    self.sendSignal(signal.SIGUSR1)
104
            #    info("\nStart logging now!\n") 
105
            #if self.stopNode > 0:
106
            #    crashTime = self.stopNode - self.startLog
107
            #    duration -= crashTime
108
            #    sleep(crashTime)
109
            #    print "XX", self.stopNode, duration, time.time()
110
            #    # this is interpreted as "crash"
111
            #    self.sendSignal(signal.SIGTSTP, self.nodeCrashed)
112
            #    info("\nSent crash signal to node " + str(self.nodeCrashed))
113
            #if self.stopLog > 0:
114
            #    stopTime = self.stopLog - (self.startLog + self.stopNode)
115
            #    duration -= stopTime
116
            #    print "XX", stopTime, duration, time.time()
117
            #    sleep(stopTime)
118
            #    self.sendSignal(signal.SIGUSR1)
119
            #    info("\nStop logging now!\n") 
120
            #print "XX", time.time(), duration
121
            #sleep(duration)
122
            ## this is interpreted by the daemons as 
123
            ## "restart a new run"
124
            #self.sendSignal(signal.SIGUSR2)
125

    
126

    
127

    
128

    
129
    def getCentrality(self):
130
        """ return a list of nodes ordered by centrality. Return only nodes
131
        that can be removed from the network without partitioning the network """
132

    
133
        centList =  sorted(
134
                [n for n in nx.betweenness_centrality(self.graph).items() \
135
                        if n[1] > 0], key = lambda x: x[1])
136
        connected_centlist = []
137
        for idx, n in enumerate(centList):
138
            gg = self.graph.copy()
139
            gg.remove_node(n[0])
140
            conSize = len(nx.connected_components(gg)[0])
141
            if conSize == len(self.graph) - 1:
142
                connected_centlist.append(n)
143
        return connected_centlist
144

    
145
    def startRun(self):
146

    
147
        rNode = ""
148
        hostList = self.getAllHosts()
149
        if self.stopNode > 0 and self.stopCentralNode != -1:
150
            # unused
151

    
152
            # split the degree list in 5 parts ordered for their degree
153
            # the input value selects one of the parts, and one
154
            # random node in this part will be returned
155
            deg = sorted(
156
                    [n for n in self.graph.degree().items() if n[1] > 1],
157
                    key = lambda x: x[1])
158
            partLength = len(deg)/4
159
            rr = random.sample(range(self.stopCentralNode*partLength, 
160
                min((self.stopCentralNode+1)*partLength, len(deg))), 1)[0]
161
            nodeName = deg[rr][0]
162
            for h in hostList:
163
                if h.name == nodeName:
164
                    rNode = h.name
165
                    break
166

    
167
        # TODO this function must be refactored. I don't use 
168
        # command line to trigger failures anymore, so rNode 
169
        # makes no sense anymore, just use self.nodeCrashed
170
        #elif self.stopNode  > 0 and self.nodeCrashed == "":
171
        #    rNode = random.sample(hostList, 1)[0].name
172

    
173
        #elif self.stopNode > 0 and self.nodeCrashed != "":
174
        #    rNode = self.nodeCrashed
175

    
176
        if rNode:
177
            info("\nChosen node " + str(rNode) + " to fail\n")
178

    
179
        #if self.runId == 0:
180
        for h in hostList:
181
            args = " --runid=" + self.runId
182
            if self.logInterval != "":
183
                args += " " + self.logInterval
184
            if self.verbose != "":
185
                args += " " + self.verbose
186
            if self.centralityTuning != "":
187
                args += " " + self.centralityTuning
188

    
189
            self.launchdummyRouting(h, args)
190
            if self.dump:
191
                self.launchSniffer(h)
192

    
193
        if not self.nodeCrashed and rNode:
194
            self.nodeCrashed = rNode
195

    
196
    def sendSignal(self, sig, hostName=""):
197
        for pid, h in self.pendingProc.items():
198
            if hostName:
199
                if hostName == h.name:
200
                    print "sending signal to host:", hostName, ", pid", pid
201
                    self.sendSig(pid, sig)
202
                    break
203
                continue
204
            self.sendSig(pid, sig)
205

    
206

    
207
    def parseTime(self, timeString):
208

    
209
        retString = ""
210
        if timeString.endswith('s'):
211
            retString = timeString[:-1]
212
        elif timeString.endswith('m'):
213
            retString = int(timeString[:-1])*60
214
        else:
215
            retString = timeString
216
        return str(retString)
217

    
218
class dummyRoutingRandomTest(dummyRoutingTest):
219

    
220
    def __init__(self, mininet, name, args):
221

    
222
        self.graph = mininet.gg
223
        if "dumpWithTCPDump" in args.keys():
224
            self.dump = True
225
        else:
226
            self.dump = False
227
        # Doesn't work. If processes are started one after the other
228
        # there is misalignment in the relative log time. I use 
229
        # a signal instead.
230
        #if "startLog" in args.keys():
231
        #    self.startLog = "--startlog " + self.parseTime(args["startLog"])
232
        #else:
233
        #    self.startLog = ""
234

    
235
        if "startLog" in args.keys():
236
            self.startLog = float(self.parseTime(args["startLog"]))
237
        else:
238
            self.startLog = -1
239

    
240
        if "stopLog" in args.keys():
241
            self.stopLog = float(self.parseTime(args["stopLog"]))
242
        else:
243
            self.stopLog = -1
244

    
245
        if "logInterval" in args.keys():
246
            self.logInterval = "--loginterval " \
247
                    + self.parseTime(args["logInterval"])
248
        else:
249
            self.logInterval = ""
250

    
251
        if "verbose" in args.keys():
252
            self.verbose = "-v "
253
        else:
254
            self.verbose = ""
255

    
256
        if "centralityTuning" in args.keys():
257
            self.centralityTuning = "-c "
258
        else:
259
            self.centralityTuning = ""
260

    
261
        if "stopNode" in args.keys():
262
            self.stopNode = int(self.parseTime(args["stopNode"]))
263
        else:
264
            self.stopNode = -1
265

    
266
        if "nodeCrashed" in args.keys():
267
            self.nodeCrashed = args["nodeCrashed"]
268
        else:
269
            self.nodeCrashed = ""
270

    
271
        if "stopAllNodes" in args.keys():
272
            self.stopAllNodes = True
273
            self.nodeCrashed = ""
274
            info("Going to stop all the nodes in sequence")
275
        else:
276
            self.stopAllNodes = False
277

    
278
        if "stopCentralNode" in args.keys():
279
            self.stopCentralNode = int(args["stopCentralNode"])
280
            if self.stopCentralNode < 0 or self.stopCentralNode > 3:
281
                error("\nPlease stopCentralNode must be between 0 and 3\n")
282
                sys.exit(1)
283
        else:
284
            self.stopCentralNode = -1
285

    
286
        # stopAllNodes will confilct with numRuns!
287
        if "numRuns" in args.keys():
288
            if self.stopAllNodes == True:
289
                error("Cannot set stopAllNodes and numRuns in the same configuration")
290
                sys.exit(1)
291
            self.numRuns = int(args["numRuns"])
292
        else:
293
            self.numRuns = 1
294

    
295
        self.runId = 0
296

    
297
        duration = int(self.parseTime(args["duration"]))
298

    
299
        super(dummyRoutingRandomTest, self).__init__(mininet, duration)
300
        self.setPrefix(name)
301

    
302