Commit eb172094 authored by Thierry Monteil's avatar Thierry Monteil
Browse files

Merge branch 'thierry.monteil-main-patch-71839' into 'main'

Thierry.monteil main patch 71839

See merge request !4
parents 27eaeb3d b51a3493
Loading
Loading
Loading
Loading

src/.gitkeep

0 → 100644
+0 −0

Empty file added.

+458 −0
Original line number Diff line number Diff line
#!/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 <AE>    ###
############################
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 <AE>    ###
############################
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 <Container>	###
###############################
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 <Container>    ###
###################################
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 <ContentInstance> 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 <ContentInstance>	###
#######################################
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 <ACP>     ###
##########################
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 <ACP>    ###
###################################
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 <SUB>    ###
###################################
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()

src/profiler.py

0 → 100644
+124 −0
Original line number Diff line number Diff line
#!/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()