def get(self, tenant_id): global engine global upPortByLvlPort global W abort_if_tenant_doesnt_exist(tenant_id) hosts = laas.VecInt() l1UpPorts = laas.VecPairInt() l2UpPorts = laas.VecPairInt() if not engine.getTenantAlloc(tenant_id, hosts, l1UpPorts, l2UpPorts): portNames = [] for i in range(0, l2UpPorts.size()): iNp = l2UpPorts[i] allocSwIdx = iNp[0] pn = iNp[1] for j in range(0, W[1]): swIdx = allocSwIdx * W[1] + j key = [2, swIdx, pn].__str__() name = upPortByLvlPort[key] if name is None: portNames.append("UNDEF") else: portNames.append(name) return portNames else: abort( 410, message="Fail to get L2 ports for tenant {}".format(tenant_id))
def get(self, tenant_id): global engine global dnPortByLvlPort global M abort_if_tenant_doesnt_exist(tenant_id) hosts = laas.VecInt() l1UpPorts = laas.VecPairInt() l2UpPorts = laas.VecPairInt() if not engine.getTenantAlloc(tenant_id, hosts, l1UpPorts, l2UpPorts): portNames = [] for i in range(0, hosts.size()): j = hosts[i] k = j / M[0] p = j % M[0] key = [1, k, p].__str__() name = dnPortByLvlPort[key] if name is None: portNames.append("UNDEF") else: portNames.append(name) return portNames else: abort( 408, message="Fail to get L0 ports for tenant {}".format(tenant_id))
def main(argv=None): global verbose csvFileName = None M = laas.VecInt(3) W = laas.VecInt(3) if argv is None: argv = sys.argv try: try: opts, args = getopt.getopt( argv[1:], "hvc:m:w:", ["help", "verbose", "csv=", "children=", "parents="]) except getopt.error, msg: raise Usage(msg) for opt, arg in opts: if opt in ('-h', "--help"): print 'sim.py -c|--csv <csvFile> -m|--children m1,m2,m3' \ '-w|--parents 1,w2,w3' sys.exit() elif opt in ("-c", "--csv"): csvFileName = arg elif opt in ("-v", "--verbose"): verbose = True elif opt in ("-m", "--children"): i = 0 for m in arg.split(','): M[i] = int(m) i += 1 elif opt in ("-w", "--parents"): i = 0 for w in arg.split(','): W[i] = int(w) i += 1 if csvFileName is None or W is None or M is None: raise Usage("missing mandatory args") sim = Sim(M, W, csvFileName) sim.run() sim.analyze()
def post(self): global W args = parser.parse_args() tenant_id = args['id'] abort_if_tenant_exist(tenant_id) g = laas.VecInt(1) g[0] = args['n'] if not engine.allocTenant(tenant_id, g): hosts = laas.VecInt() l1UpPorts = laas.VecPairInt() l2UpPorts = laas.VecPairInt() engine.getTenantAlloc(tenant_id, hosts, l1UpPorts, l2UpPorts) TENANTS[tenant_id] = { 'N': args['n'], 'hosts': hosts.size(), 'l1Ports': l1UpPorts.size(), 'l2Ports': W[1] * l2UpPorts.size() } updateSDNConf() addOpenStackTenent(tenant_id) return TENANTS[tenant_id], 201 else: abort(406, message="Fail to allocate tenant {}".format(tenant_id))
def addOpenStackTenent(id): global engine global osCmdId directory = 'OSCfg' if not os.path.exists(directory): os.makedirs(directory) osCmdId = osCmdId + 1 cmdName = "cmd-%d.sh" % osCmdId logName = "cmd-%d.log" % osCmdId fileName = os.path.join(directory, cmdName) F = open(fileName, 'w') if F is None: raise LaaSFailure("Cannot write OS cmd file: %s" % fileName) logFile = os.path.join(directory, logName) F.write("#!/bin/bash\n") F.write("#\n# Adding tenant %d to OpenStack\n#\n" % id) aggrName = "laas-aggr-%d" % id tenantName = "laas-tenant-%d" % id F.write("echo Adding tenant %d to OpenStack > %s\n" % (id, logFile)) F.write("keystone tenant-create --name %s --description \"LaaS Tenant %d\" >> %s\n" % \ (tenantName, id, logFile)) F.write("tenantId=`keystone tenant-get %s | awk '/ id /{print $4}'` >> %s\n" % \ (tenantName, logFile)) F.write("nova aggregate-create %s >> %s\n" % (aggrName, logFile)) # HACK for now we assume no need for key F.write( "nova aggregate-set-metadata %s filter_tenant_id=$tenantId >> %s\n" % (aggrName, logFile)) hosts = laas.VecInt() l1UpPorts = laas.VecPairInt() l2UpPorts = laas.VecPairInt() if engine.getTenantAlloc(id, hosts, l1UpPorts, l2UpPorts): raise LaaSFailure("Cannot get tenant %d information" % id) for i in range(0, hosts.size()): j = hosts[i] key = [0, j, 0].__str__() nameNPort = upPortByLvlPort[key] # = {'sName': sName, 'pNum': pNum} if nameNPort is not None: F.write("nova aggregate-add-host %s %s >> %s\n" % (aggrName, nameNPort['sName'], logName)) F.close() if callOpenStack: safeExecute(fileName) return 0
def delOpenStackTenant(id): global engine global osCmdId global callOpenStack hosts = laas.VecInt() l1UpPorts = laas.VecPairInt() l2UpPorts = laas.VecPairInt() if engine.getTenantAlloc(id, hosts, l1UpPorts, l2UpPorts): raise LaaSFailure("Cannot get tenant %d information" % id) directory = 'OSCfg' if not os.path.exists(directory): os.makedirs(directory) osCmdId = osCmdId + 1 cmdName = "cmd-%d.sh" % osCmdId logName = "cmd-%d.log" % osCmdId fileName = os.path.join(directory, cmdName) F = open(fileName, 'w') if F is None: raise LaaSFailure("Cannot write OS cmd file: %s" % fileName) logFile = os.path.join(directory, logName) F.write("#!/bin/bash\n") F.write("#\n# Removing tenant %d from OpenStack\n#\n" % id) aggrName = "laas-aggr-%d" % id tenantName = "laas-tenant-%d" % id for i in range(0, hosts.size()): j = hosts[i] key = [0, j, 0].__str__() nameNPort = upPortByLvlPort[key] # = {'sName': sName, 'pNum': pNum} if nameNPort is not None: F.write("nova aggregate-remove-host %s %s >> %s\n" % (aggrName, nameNPort['sName'], logName)) F.write("nova aggregate-delete %s >> %s\n" % (aggrName, logFile)) F.write("keystone tenant-delete %s >> %s\n" % (tenantName, logFile)) F.close() if callOpenStack: safeExecute(fileName) return 0
def get(self, tenant_id): global engine global nameByLevelIdx abort_if_tenant_doesnt_exist(tenant_id) hosts = laas.VecInt() l1UpPorts = laas.VecPairInt() l2UpPorts = laas.VecPairInt() if not engine.getTenantAlloc(tenant_id, hosts, l1UpPorts, l2UpPorts): hostNames = [] for i in range(0, hosts.size()): j = hosts[i] key = [0, j].__str__() name = nameByLevelIdx[key] if name is None: hostNames.append("UNDEF") else: hostNames.append(name) return hostNames else: abort(407, message="Fail to get hosts for tenant {}".format(tenant_id))
def get(self, tenant_id): global engine global upPortByLvlPort abort_if_tenant_doesnt_exist(tenant_id) hosts = laas.VecInt() l1UpPorts = laas.VecPairInt() l2UpPorts = laas.VecPairInt() if not engine.getTenantAlloc(tenant_id, hosts, l1UpPorts, l2UpPorts): portNames = [] for i in range(0, l1UpPorts.size()): iNp = l1UpPorts[i] key = [1, iNp[0], iNp[1]].__str__() name = upPortByLvlPort[key] if name is None: portNames.append("UNDEF") else: portNames.append(name) return portNames else: abort( 409, message="Fail to get L1 ports for tenant {}".format(tenant_id))
def run(self): # we need to loop until no pending jobs or fail to place # we have two sorted containers: # pending - by arrival time # running - by finish time (this is a heapq by time to list of jobs) # # Whenever we advance time t we need to first clear all ended jobs # then we need to try placing all pending jobs arriving before t # # We advance time when either: # 1. Some pending job can't be placed: advance to next ending job # 2. No pending jobs at the time: advance to next pending job time # t0 = time() t = 0 grps = laas.VecInt(1) while len(self.pending): if verbose: print "-I- At t=%d" % t # first clean all running jobs endT = self.running.minT() while endT != None and endT <= t: endT, endingJobs = self.running.pop() for j in endingJobs: # note the inverse in semantics... if not self.engine.deallocTenant(j.id): raise SimFailure(self.engine.getLastErrorMsg()) else: if verbose: print "-V- Remove %s" % j endT = self.running.minT() # now try placement of all jobs that already arrived j = self.pending[0] placeFailed = False while not placeFailed and j.arrival <= t: grps[0] = j.N # the engine returns 0 for success! placeFailed = self.engine.allocTenant(j.id, grps, j.isolation) if placeFailed: if not self.running.len(): err = "No job running but fail to place job %s" % j raise SimFailure(err) else: if self.firstJobWaiting < 0 and t > 0: self.firstJobWaiting = t if verbose: print "-V- Fail %s" % j else: # was placed: hosts = laas.VecInt() l1Up = laas.VecPairInt() l2Up = laas.VecPairInt() alloc = self.engine.getTenantAlloc(j.id, hosts, l1Up, l2Up) j.actNumHosts = hosts.size() j.numL1UpLinks = l1Up.size() j.numL2UpLinks = l2Up.size() * self.W[1] if verbose: print "-V- Place %s %d hosts %d L1 %d L2" % \ (j, j.actNumHosts, j.numL1UpLinks, j.numL2UpLinks) self.running.insert(t + j.length, j) j.start = t self.lastJobPlacement = t self.pending.pop(0) if len(self.pending): j = self.pending[0] else: placeFailed = True # we can reach here on two cases either no more ready jobs or # failure to place if placeFailed: # advance to next ending job time t = self.running.minT() else: t = self.pending[0].arrival t1 = time() self.runTime = t1 - t0 return 0
def main(argv=None): global verbose global engine global M global W global osCmdId global callOpenStack callOpenStack = False osCmdId = 0 csvFileName = None M = laas.VecInt(3) W = laas.VecInt(3) if argv is None: argv = sys.argv try: try: opts, args = getopt.getopt(argv[1:], "hvn:m:w:o", [ "help", "verbose", "names=", "children=", "parents=", "openstack" ]) except getopt.GetoptError as err: raise Usage(str(err)) for opt, arg in opts: if opt in ('-h', "--help"): print('sim.py -n|--names <nameMap.csv> -m|--children m1,m2,m3' \ '-w|--parents 1,w2,w3') sys.exit(0) elif opt in ("-n", "--names"): csvFileName = arg elif opt in ("-v", "--verbose"): verbose = True elif opt in ("-o", "--openstack"): callOpenStack = True elif opt in ("-m", "--children"): i = 0 for m in arg.split(','): M[i] = int(m) i += 1 elif opt in ("-w", "--parents"): i = 0 for w in arg.split(','): W[i] = int(w) i += 1 missingArgs = "" if csvFileName is None: missingArgs = "-n " if W is None: missingArgs = missingArgs + "-w " if M is None: missingArgs = missingArgs + "-m " if missingArgs != "": raise Usage("missing mandatory args %s" % missingArgs) # start the LaaS service with the given parameters engine = laas.LaaS(M, W, "logile") if not engine.good(): raise LaaSFailure(engine.getLastErrorMsg()) engine.setVerbose(verbose) if parseNameMap(csvFileName): raise LaaSFailure("Fail to parse name map file: %s", csvFileName) # start the server app.run(port=12345, debug=True) except Usage, err: print >> sys.stderr, err.msg print >> sys.stderr, "for help use --help" return 2
def updateSDNConf(): global engine global upPortByLvlPort # make sure dest dir exists directory = 'SDNCfg' if not os.path.exists(directory): os.makedirs(directory) # clear pervious settings deleteDirContent(directory) # now lets populate it again topoFileName = os.path.join(directory, 'topologies.conf') T = open(topoFileName, 'w') if T is None: raise LaaSFailure("Cannot write topologies file: %s" % topoFileName) groupsFileName = os.path.join(directory, 'groups.conf') G = open(groupsFileName, 'w') if G is None: raise LaaSFailure("Cannot write groups file: %s" % groupsFileName) chainsFileName = os.path.join(directory, 'chains.conf') C = open(chainsFileName, 'w') if C is None: raise LaaSFailure("Cannot write chains file: %s" % chainsFileName) link = 1 topo = 0 C.write( "unicast-step\nid: %d\ntopology: %d\nengine: updn\npath-bit: 0\nend-unicast-step\n\n" % (link, topo)) # now go over all tenants tenants = laas.SetInt() engine.getTenants(tenants) for id in tenants: link = link + 1 # topologies T.write("topology\n") T.write("id: %d\n" % id) T.write("sw-grp: T%d-switches\n" % id) T.write("hca-grp: T%d-hcas\n" % id) T.write("end-topology\n\n") # PQFT (?) pqftOpts = "T%d.opensm.conf" % id pqftOptsFileName = os.path.join(directory, pqftOpts) O = open(pqftOptsFileName, 'w') if C is None: raise LaaSFailure("Cannot write options file: %s" % pqftOptsFileName) pqftStr = getPQFTStr(id) if pqftStr is not None: O.write("pqft_structure %s\n" % pqftStr) O.close() # Chain link C.write("unicast-step\n") C.write("id: %d\n" % link) C.write("topology: %d\n" % id) if pqftStr is not None: C.write("engine: pqft\n") else: C.write("engine: updn\n") C.write("config: %s\n" % pqftOptsFileName) C.write("path-bit: 0\n") C.write("end-unicast-step\n\n") hosts = laas.VecInt() l1UpPorts = laas.VecPairInt() l2UpPorts = laas.VecPairInt() if engine.getTenantAlloc(id, hosts, l1UpPorts, l2UpPorts): raise LaaSFailure("Cannot get tenant %d information" % id) # PORT GROUPS G.write("port-group\n") G.write("name: T%d-hcas\n" % id) G.write("obj_list: ") for i in range(0, hosts.size()): j = hosts[i] key = [0, j, 0].__str__() nameNPort = upPortByLvlPort[ key] # = {'sName': sName, 'pNum': pNum} if nameNPort is not None: G.write("\n name=%s/U1:P%d" % (nameNPort['sName'], nameNPort['pNum'])) G.write(";\n") G.write("end-port-group\n\n") # collapse switch used ports to masks SW_PORTS = {} for i in range(0, l1UpPorts.size()): iNp = l1UpPorts[i] key = [1, iNp[0], iNp[1]].__str__() nameNPort = upPortByLvlPort[key] if nameNPort is not None: name = nameNPort['sName'] pn = nameNPort['pNum'] mask = 1 << pn if name not in SW_PORTS: SW_PORTS[name] = mask else: SW_PORTS[name] = SW_PORTS[name] | mask for i in range(0, l2UpPorts.size()): iNp = l1UpPorts[i] key = [1, iNp[0], iNp[1]].__str__() nameNPort = upPortByLvlPort[key] if nameNPort is not None: name = nameNPort['sName'] pn = nameNPort['pNum'] mask = 1 << pn if name not in SW_PORTS: SW_PORTS[name] = mask else: SW_PORTS[name] = SW_PORTS[name] | mask # now write the group G.write("port-group\n") G.write("name: T%d-switches\n" % id) if len(SW_PORTS) > 0: G.write("obj_list: ") for name in SW_PORTS: mask = SW_PORTS[name] G.write("\n name=%s/U1 pmask=0x%x" % (name, mask)) G.write(";\n") G.write("end-port-group\n\n") T.close() C.close() G.close() return 0