diff --git a/src/.gitkeep b/src/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/oneM2M_Ressources.py b/src/oneM2M_Ressources.py new file mode 100644 index 0000000000000000000000000000000000000000..eea2cbc67879d7f92e57d61882a1228ebe866732 --- /dev/null +++ b/src/oneM2M_Ressources.py @@ -0,0 +1,458 @@ +#!/usr/bin/python +############################################################################## +# Goal: oneM2M requests burst for performance analysis +# contributor: +# Thierry Monteil (thierry.monteil@irit.fr) +# +# Based on simple_om2m.py created by: +# Ahmad Abbas (ahmad.abbas@eglobalmark.com) +# Thierry Monteil (thierry.monteil@irit.fr) +# +#BSD 3-Clause License +# +#Copyright (c) 2024, IoT / SmartM2M-oneM2M-performance-evaluation +#All rights reserved. +############################################################################# + +import sys +import requests +import json +import random +import time +import json +import socket + +#PROFILER +HOST = 'localhost' + +PORT = 9998 + + +#ACME +CSE_URL_ACME="http://192.168.1.54:8085/~/id-in/cse-in" + + +ORIGIN_ACME="CAdmin" + +#MOBIUS +CSE_URL_MOBIUS="http://192.168.1.28:7579/Mobius" +ORIGIN_MOBIUS="Torigin" + +#OM2M +CSE_URL_OM2M="http://192.168.1.54:8080/~/in-cse/in-name" +ORIGIN_OM2M="admin:admin" + +HTTP_SERVEUR="http://192.168.1.54:9999" +DEBUG_RESPONSE=0 +DEBUG_TEST=1 + + +def handleResponse(r): + if DEBUG_RESPONSE ==1 : + print (r.status_code) + print (r.headers) + print (r.text) + +############################ +### Create an ### +############################ +def createAE(origin,CSEurl, STACK,api_value,rn_value): + payload = '{ \ + "m2m:ae": { \ + "api": "'+api_value+'", \ + "srv":["3"],\ + "rr": true,\ + "rn": "'+rn_value+'"\ + } \ + }' + if (STACK == "OM2M"): + _headers = {'X-M2M-Origin': '','X-M2M-RI': 'req1','X-M2M-RVI': '3','Content-Type': 'application/json;ty=2','Accept': 'application/json'} + + else: + _headers = {'X-M2M-Origin': origin,'X-M2M-RI': 'req1','X-M2M-RVI': '3','Content-Type': 'application/json;ty=2','Accept': 'application/json'} + + json.dumps(json.loads(payload,strict=False), indent=4) + r = requests.post(CSEurl.strip(),data=payload,headers=_headers) + handleResponse(r) + return r; +############################ +### Delete an ### +############################ +def deleteAE(origin, CSEurl,api_value,rn_value): + payload = '' + _headers = {'X-M2M-Origin': origin ,'X-M2M-RI': 'req1', 'X-M2M-RVI': '3','Content-Type': 'application/json'} + r = requests.delete((CSEurl+'/'+rn_value).strip(),headers=_headers) + handleResponse(r) + return r; + +############################### +### Create a ### +############################### +def createContainer(origin,AEurl,rn_value): + payload = '{ \ + "m2m:cnt": { \ + "rn": "'+rn_value+'" \ + } \ + }' + _headers = {'X-M2M-Origin': origin,'X-M2M-RI': 'req1', 'X-M2M-RVI': '3','Content-Type': 'application/json;ty=3'} + json.dumps(json.loads(payload,strict=False), indent=4) + r = requests.post(AEurl.strip(),data=payload,headers=_headers) + handleResponse(r) + return r; + +################################### +### Delete an ### +################################### +def deleteContainer(origin,CSEurl,api_value,rn_value): + payload = '' + _headers = {'X-M2M-Origin': origin,'X-M2M-RI': 'req1', 'X-M2M-RVI': '3','Content-Type': 'application/json'} + r = requests.delete((CSEurl+'/'+rn_value).strip(),headers=_headers) + handleResponse(r) + return r; + +############################################################### +### Create a with mandatory attributes ### +############################################################### +def createContentInstance(origin,CONurl,con_value): + + payload = '{ \ + "m2m:cin": { \ + "con": "'+str(con_value)+'" \ + } \ + }' + _headers = {'X-M2M-Origin': origin,'X-M2M-RI': 'req1', 'X-M2M-RVI': '3','Content-Type': 'application/json;ty=4'} + json.dumps(json.loads(payload,strict=False), indent=4) + r = requests.post(CONurl.strip(),data=payload,headers=_headers) + handleResponse(r) + return r; + +####################################### +### Get latest ### +####################################### +def getContentInstanceLatest(origin,CONurl): + _headers = {'X-M2M-Origin': origin,'X-M2M-RI': 'req1', 'X-M2M-RVI': '3','Accept': 'application/json'} + r = requests.get(CONurl.strip(),headers=_headers) + handleResponse(r) + return r; + +########################## +## Create ### +########################## +def createACP(origin,url,rn_value,pv_acor_value,pv_acop_value): + payload = '{ "m2m:acp": {\ + "rn": "'+rn_value+'",\ + "pv": {\ + "acr": [ {\ + "acor": ["'+pv_acor_value+'"],\ + "acop": "'+pv_acop_value+'"\ + }]\ + },\ + "pvs": {\ + "acr": [ {\ + "acor": ["'+pv_acor_value+'"],\ + "acop": "'+pv_acop_value+'"\ + }]\ + }\ + }\ + }' + _headers = {'X-M2M-Origin': origin,'X-M2M-RI': 'req1', 'X-M2M-RVI': '3','Content-Type': 'application/json;ty=1'} + json.dumps(json.loads(payload,strict=False),indent=4) + r = requests.post(url.strip(),data=payload,headers=_headers) + handleResponse(r); + return r; + + +################################### +### Delete an ### +################################### +def deleteACP(origin,CSEurl,api_value,rn_value): + payload = '' + _headers = {'X-M2M-Origin': origin,'X-M2M-RI': 'req1', 'X-M2M-RVI': '3','Content-Type': 'application/json'} + r = requests.delete((CSEurl+'/'+rn_value).strip(),headers=_headers) + handleResponse(r) + return r; + + + +################################### +### Delete an ### +################################### +def deleteSUB(origin,CSEurl,api_value,rn_value): + payload = '' + _headers = {'X-M2M-Origin': origin,'X-M2M-RI': 'req1', 'X-M2M-RVI': '3','Content-Type': 'application/json'} + r = requests.delete((CSEurl+'/'+rn_value).strip(),headers=_headers) + handleResponse(r) + return r; + +################################## +### Create a subscritpion ### +################################## +def createSUB(origin,CONurl,rn_value,nu_value): + payload = '{ \ + "m2m:sub": { \ + "rn": "'+rn_value+'", \ + "enc": {\ + "net": [1,3] \ + } ,\ + "nu": ["'+nu_value+'"],\ + "su": "'+nu_value+'"\ + } \ + }' + _headers = {'X-M2M-Origin': origin,'X-M2M-RI': 'req1', 'X-M2M-RVI': '3','Content-Type': 'application/json;ty=23'} + json.dumps(json.loads(payload,strict=False),indent=4) + r = requests.post(CONurl.strip(),data=payload,headers=_headers) + handleResponse(r) + return r; + +####################### +### manage analyser ### +####################### + +def analyserOrder(sock,data): + print("communication to profiler: "+data) + sock.sendall(data.encode('utf-8')) + buff = sock.recv(512) + message = buff.decode('utf-8') + print("ack from profiler: "+message) + if message != "OK": + print("error on communicaton with profiler") + +################################################################################ +### burst of "val" creation of AE and Delete after a sleep of "dort" seconds ### +################################################################################ +def Test_AE(origin,CSE_URL,STACK,val, dort, sock): + print("Connection to remote analyser for AE analysis") + analyserOrder(sock, "START") + for i in range(val): + createAE(origin+str(i),CSE_URL, STACK, "NResource.company.com", "resource_AE"+str(i)) + analyserOrder(sock,"STOP "+str(val)+" AE Create") + print("end "+str(val)+" AE creation") + time.sleep(dort) + analyserOrder(sock,"START") + for i in range(val): + if (STACK == "OM2M"): + deleteAE(origin,CSE_URL, "NResource.company.com", "resource_AE"+str(i)) + else: + deleteAE(origin+str(i),CSE_URL, "NResource.company.com", "resource_AE"+str(i)) + analyserOrder(sock, "STOP "+str(val)+" AE Delete") + print("end AE delete") + print("end AE profiling") + +####################################################################################### +### burst of "val" creation of container and Delete after a sleep of "dort" seconds ### +####################################################################################### +def Test_CNT(origin,CSE_URL,STACK,val, dort, sock): + print("Connection to remote analyser for CNT analysis") + createAE(origin+"0",CSE_URL,STACK, "NResource.company.com", "resource_AE_testCNT") + analyserOrder(sock, "START") + for i in range(val): + createContainer(origin,CSE_URL+"/resource_AE_testCNT", "resource_CNT"+str(i)) + analyserOrder(sock,"STOP "+str(val)+" CNT Create") + print("end "+str(val)+ " CNT creation") + time.sleep(dort) + analyserOrder(sock,"START") + for i in range(val): + deleteContainer(origin,CSE_URL+"/resource_AE_testCNT", "NResource.company.com", "resource_CNT"+str(i)) + analyserOrder(sock, "STOP "+str(val)+" CNT Delete") + if (STACK == "OM2M"): + deleteAE(origin,CSE_URL, "NResource.company.com", "resource_AE_testCNT") + else: + deleteAE(origin+"0",CSE_URL, "NResource.company.com", "resource_AE_testCNT") + print("end CNT delete") + print("end CNT profiling") + + + ################################################################################ + ### burst of "val" creation of content instance and Delete after a sleep of "dort" seconds ### + ################################################################################ +def Test_CIN(origin,CSE_URL,STACK,val, dort, sock): + print("Connection to remote analyser for CIN analysis") + createAE(origin+"0",CSE_URL,STACK, "NResource.company.com", "resource_AE_testCIN") + createContainer(origin,CSE_URL+"/resource_AE_testCIN", "resource_CNT") + analyserOrder(sock, "START") + for i in range(val): + createContentInstance(origin,CSE_URL+"/resource_AE_testCIN/resource_CNT", i) + analyserOrder(sock,"STOP "+str(val)+" CIN Create") + time.sleep(dort) + deleteContainer(origin,CSE_URL+"/resource_AE_testCIN", "NResource.company.com", "resource_CNT") + if (STACK == "OM2M"): + deleteAE(origin,CSE_URL, "NResource.company.com", "resource_AE_testCIN") + else: + deleteAE(origin+"0",CSE_URL, "NResource.company.com", "resource_AE_testCIN") + print("end CIN profiling") + + +################################################################################ +### burst of "val" creation of content instance, get last value and Delete after a sleep of "dort" seconds ### +################################################################################ +def Test_LAST(origin,CSE_URL,STACK,val, dort, sock): + print("Connection to remote analyser for LAST CIN analysis") + createAE(origin+"0",CSE_URL,STACK, "NResource.company.com", "resource_AE_testCIN") + createContainer(origin,CSE_URL+"/resource_AE_testCIN", "resource_CNT") + createContentInstance(origin,CSE_URL+"/resource_AE_testCIN/resource_CNT", 0) + analyserOrder(sock, "START") + for i in range(val): + getContentInstanceLatest(origin,CSE_URL+"/resource_AE_testCIN/resource_CNT") + analyserOrder(sock,"STOP "+str(val)+" LASTCIN Read") + time.sleep(dort) + deleteContainer(origin,CSE_URL+"/resource_AE_testCIN", "NResource.company.com", "resource_CNT") + if (STACK == "OM2M"): + deleteAE(origin,CSE_URL, "NResource.company.com", "resource_AE_testCIN") + else: + deleteAE(origin+"0",CSE_URL, "NResource.company.com", "resource_AE_testCIN") + print("end LASTCIN profiling") + +################################################################################ +### burst of "val" creation of ACP Delete after a sleep of "dort" seconds ### +################################################################################ +def Test_ACP(origin,CSE_URL,STACK, val, dort, sock): + print("Connection to remote analyser for ACP analysis") + analyserOrder(sock, "START") + for i in range(val): + createACP(origin,CSE_URL,"TestACP"+str(i), origin, "63") + analyserOrder(sock,"STOP "+str(val)+" ACP Create") + print("end ACP creation") + time.sleep(dort) + analyserOrder(sock, "START") + for i in range(val): + deleteACP(origin,CSE_URL, "NResource.company.com", "TestACP"+str(i)) + analyserOrder(sock,"STOP "+str(val)+" ACP Delete") + print("end ACP delete") + print("end ACP profiling") + + +################################################################################ +### burst of "val" creation of subscription after a sleep of "dort" seconds ### +################################################################################ +def Test_SUB(origin,CSE_URL,STACK,val, dort, sock): + print("Connection to remote analyser for SUB analysis") + createAE(origin+"0",CSE_URL,STACK, "NResource.company.com", "resource_AE_testSUB") + createContainer(origin,CSE_URL+"/resource_AE_testSUB", "resource_CNT") + analyserOrder(sock, "START") + for i in range(val): + createSUB(origin,CSE_URL+"/resource_AE_testSUB"+"/resource_CNT","resource_SUB"+str(i),HTTP_SERVEUR) + analyserOrder(sock,"STOP "+str(val)+" SUB Create") + print("end SUB creation") + time.sleep(dort) + analyserOrder(sock, "START") + for i in range(val): + deleteSUB(origin,CSE_URL+"/resource_AE_testSUB"+"/resource_CNT", "NResource.company.com", "resource_SUB"+str(i)) + analyserOrder(sock,"STOP "+str(val)+" SUB Delete") + print("end SUB delete") + deleteContainer(origin,CSE_URL+"/resource_AE_testSUB", "NResource.company.com", "resource_CNT") + if (STACK == "OM2M"): + deleteAE(origin,CSE_URL, "NResource.company.com", "resource_AE_testSUB") + else: + deleteAE(origin+"0",CSE_URL, "NResource.company.com", "resource_AE_testSUB") + print("end SUB profiling") + +def setSTACK(thestack): + if thestack== "OM2M": + return CSE_URL_OM2M,ORIGIN_OM2M + elif thestack== "ACME": + return CSE_URL_ACME, ORIGIN_ACME + elif thestack== "MOBIUS": + return CSE_URL_MOBIUS, ORIGIN_MOBIUS + else : + print(" unknow stack") + exit(0) + +def callTest(res,ORIGIN,CSE_URL,STACK,iteration,dodo, sock): + if res=="AE": + Test_AE(ORIGIN,CSE_URL,STACK,iteration,dodo, sock) + elif res=="CNT": + Test_CNT(ORIGIN,CSE_URL,STACK,iteration,dodo, sock) + elif res=="CIN": + Test_CIN(ORIGIN,CSE_URL,STACK,iteration,dodo,sock) + elif res=="LAST": + Test_LAST(ORIGIN,CSE_URL,STACK,iteration,dodo, sock) + elif res=="ACP": + Test_ACP(ORIGIN,CSE_URL,STACK,iteration,dodo, sock) + elif res=="SUB": + Test_SUB(ORIGIN,CSE_URL,STACK,iteration,dodo, sock) + else : + print("unknown command") + + +######################################### +### run a test on a specific resource ### +######################################### +def main(): + # connection to the profiler + sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((HOST, PORT)) + + NUM_ARG=len(sys.argv) + print(NUM_ARG) + if ((NUM_ARG==2) and (sys.argv[1]=="manual")): + print("interactive mode") + print("choose a stack") + print("OM2M") + print("ACME") + print("MOBIUS") + thestack= input("your choice? ") + CSE_URL,ORIGIN=setSTACK(thestack) + print("---") + print("which resource (AE/CNT/CIN/LAST/ACP/SUB)") + resource=input("your choice? ") + print("---") + print("number of iterations") + iteration=int(input("your choice ? ")) + print("---") + print("time between test and reset") + dodo=int(input("your choice? ")) + print("---") + print("---") + analyserOrder(sock, "RUN "+thestack) + print("-- start the profiling") + time.sleep(15) + callTest(resource,ORIGIN,CSE_URL,thestack,iteration,dodo, sock) + print("-- end the profiling") + analyserOrder(sock, "END") + print("-- end the stack") + + elif (NUM_ARG==4) and (sys.argv[1]=="auto"): + dodo=5 + CSE_URL,ORIGIN=setSTACK(sys.argv[2]) + iteration=int(sys.argv[3]) + print("-- start the stack") + analyserOrder(sock, "RUN "+sys.argv[2]) + print("-- start the profiling") + time.sleep(15) + callTest("AE",ORIGIN,CSE_URL,sys.argv[2],iteration,dodo,sock) + time.sleep(dodo) + callTest("CNT",ORIGIN,CSE_URL,sys.argv[2],iteration,dodo,sock) + time.sleep(dodo) + callTest("CIN",ORIGIN,CSE_URL,sys.argv[2],iteration,dodo,sock) + time.sleep(dodo) + callTest("LAST",ORIGIN,CSE_URL,sys.argv[2],iteration,dodo,sock) + time.sleep(dodo) +### callTest("ACP",ORIGIN,CSE_URL,sys.argv[2],iteration,dodo,sock) + time.sleep(dodo) + callTest("SUB",ORIGIN,CSE_URL,sys.argv[2],iteration,dodo,sock) + print("-- end the profiling") + analyserOrder(sock, "END") + print("-- end the stack") + else: + print ("Usage: ") + print ("interactive mode: python3 oneM2M_Ressources.py manual") + print ("automatic mode: python3 oneM2M_Ressources.py auto [OM2M/ACME/MOBIUS] [number of iteration per test]") + print ("-- instruction for running the profiling part:--") + print("for ACME:") + print(" 1) copy the profiler code (profiler.py) in the same directory than acme.ini") + print(" 2) put the host and port number in profiler.py for with the IP of the host of ACME") + print(" 3) change to the directory of profiler.py and run the profiler with this instruction: python3 profiler.py") + print("for OM2M:") + print(" 1) copy the profiler code (profiler.py) in the same directory than in-cse start script") + print(" 2) put the host and port number in profiler.py for with the IP of the host of OM2M in-cse") + print(" 3) change to the directory of profiler.py and run the profiler with this instruction: python3 profiler.py") + print("-- to start the test on the remote test machine --") + print(" 1) in oneM2M_Ressources.py change the IP and port for the stack and for the HTTP server for oneM2M subscription") + print(" 2) start before the profiler depending of the oneM2M stack ") + print(" 3) start the HTTP server for notification if you test subscription") + print(" 4) run the oneM2M_ressources program with the correct parameters") + print(" 5) get the profiling results in the file STACK_NAME_Resources") + sock.close() + +if __name__ == "__main__": + main() diff --git a/src/profiler.py b/src/profiler.py new file mode 100644 index 0000000000000000000000000000000000000000..b2b9d0d053ddaed02d6ac852d28b70f9c8457e55 --- /dev/null +++ b/src/profiler.py @@ -0,0 +1,124 @@ +#!/usr/bin/python +############################################################################## +# profiler of oneM2M stacks +# creator: +# Thierry Monteil (thierry.monteil@irit.fr) +# +#BSD 3-Clause License +# +#Copyright (c) 2024, IoT / SmartM2M-oneM2M-performance-evaluation +#All rights reserved. + +import socket +import os +import time +import signal + +# port and host to receive order from client part +HOST = 'localhost' +PORT = 9998 + +# capacity of processor in term of mips +MIPS = 4589 + +def runoneM2MStack(STACK): + newpid = os.fork() + if newpid == -1: + print("Error creating stack") + exit(-1) + + elif newpid == 0: # should run +"stack + print("start stack: "+STACK) + if STACK=="ACME": + os.execv('/usr/bin/python3',['python3','-m','acme']) + print("error stack "+STACK+" has been stopped") + exit(-2) + + else: # shoud open process image + time.sleep(5) + print("pid of stack is"+str(newpid)) + fic_cpu=open('/proc/'+str(newpid)+'/stat','r') + fic_mem=open('/proc/'+str(newpid)+'/statm','r') + #fic_cpu=open('./stat.txt','r') + #fic_mem=open('./statm.txt','r') + print("stat files have been opened") + return fic_cpu, fic_mem, newpid + +def getResources(fic_res, fic_mem): + # tick per secodfor this processor + CLK_TCK=100 + linecpu=fic_res.read() + fic_res.seek(0) + # find the fields + fieldscpu = linecpu.strip().split(' ') + # analyse fields + cpu = (float(fieldscpu[13])+float(fieldscpu[14]))/CLK_TCK + linemem=fic_mem.read() + fic_mem.seek(0) + fieldsmem = linemem.strip().split(' ') + size_rss_pages = int(fieldsmem[1]) # size resident pages + size_shared_pages = int(fieldsmem[2]) # size shared pages + # convert in Bytes + size_page_Bytes = os.sysconf('SC_PAGESIZE') + memory=size_rss_pages * size_page_Bytes + size_shared_pages * size_page_Bytes + print("cpu: "+str(cpu)+" mem: "+str(memory)) + return cpu, memory + + +def main(): + global fic_cpu + global fic_mem + global fic_stat +# run server part + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind((HOST, PORT)) + s.listen(1) + runServer=True + print("-----------connect") + conn, address = s.accept() + with conn: + while runServer: + buff = conn.recv(512) + message = buff.decode('utf-8') + print("-----------receive "+message) + # runserver=False for stop + fieldsorder =message.strip().split(' ') + + if fieldsorder[0]=="RUN": + # run the stack + fic_cpu, fic_mem, pid= runoneM2MStack(fieldsorder[1]) + print("iot stack: "+fieldsorder[1]+" is running with pid:"+str(pid)) + # open json file + fic_stat=open(fieldsorder[1]+"_Resources",'w') + fic_stat.write("Mips "+str(MIPS)+"\n") + print("-----------send OK") + conn.sendall("OK".encode('utf-8')) + elif fieldsorder[0]=="START": + cpu_start, mem_start = getResources(fic_cpu, fic_mem) + print("-----------send OK") + conn.sendall("OK".encode('utf-8')) + elif fieldsorder[0]=="STOP": + cpu_end, mem_end = getResources(fic_cpu, fic_mem) + # write cpu and mem used per request + print("-----------write: "+fieldsorder[2]+", "+fieldsorder[3] + ", cpu, "+str((cpu_end-cpu_start)/int(fieldsorder[1]))+", mem, "+str((mem_end-mem_start)/int(fieldsorder[1]))) + fic_stat.write(fieldsorder[2]+", "+fieldsorder[3] + ", cpu, "+str((cpu_end-cpu_start)/int(fieldsorder[1]))+", mem, "+str((mem_end-mem_start)/int(fieldsorder[1]))+"\n") + print("-----------send OK") + conn.sendall("OK".encode('utf-8')) + elif fieldsorder[0]=="END": + time.sleep(2); + fic_stat.close() + fic_mem.close() + fic_cpu.close() + runServer=False + print("-----------send OK") + conn.sendall("OK".encode('utf-8')) + print("Stop IoT STACK") + os.kill(pid, signal.SIGKILL) + + + + + +if __name__ == "__main__": + main()