def agentFunctionReboot(functionParameterValues): # Put a file to indicate what is happening and start the reboot process with open(currentFunctionDir + '/doingReboot.json', 'w') as outfile: json.dump({'doingRebootAsPartOfFunction': True}, outfile, indent=4) comDavra.logInfo('Function: Reboot Device, starting') comDavra.runCommandWithTimeout('sudo reboot -h now', comDavra.conf["scriptMaxTime"])
def agentFunctionRunScriptBash(functionParameterValues): if "script" not in functionParameterValues: comDavra.upsertJsonEntry(currentFunctionJson, 'response', 'script missing') comDavra.upsertJsonEntry(currentFunctionJson, 'status', 'failed') comDavra.logError( 'Could not run script as function because no script to run') checkFunctionFinished() return # Put the script into the function dir scriptFile = open(currentFunctionDir + "/script.sh", "a") scriptFile.write(str(functionParameterValues["script"])) scriptFile.close() comDavra.logInfo('Running script ' + str(functionParameterValues["script"])) os.system("chmod 777 " + currentFunctionDir + "/script.sh") time.sleep(0.5) # Time for file flush to disk # Run the script with -x flag so it prints each command before ruuning it. # This allows the UI to show it formatted better for user on jobs page scriptResponse = comDavra.runCommandWithTimeout('cd ' + currentFunctionDir + \ ' && sudo bash -x ' + currentFunctionDir + "/script.sh", comDavra.conf["scriptMaxTime"]) # scriptResponse is a tuple of (exitStatusCode, stdout) . For exitStatusCode: 0 = success, 1 = failed ) comDavra.log("Script response: " + str(scriptResponse[1])) scriptStatus = 'completed' if (scriptResponse[0] == 0) else 'failed' comDavra.upsertJsonEntry(currentFunctionJson, 'response', str(scriptResponse[1])) comDavra.upsertJsonEntry(currentFunctionJson, 'status', scriptStatus) checkFunctionFinished()
def agentFunctionReportAgentConfig(functionParameterValues): comDavra.logInfo('Function: Reporting the agent config to server') comDavra.reportDeviceConfigurationToServer() comDavra.upsertJsonEntry(currentFunctionJson, 'response', comDavra.conf) comDavra.upsertJsonEntry(currentFunctionJson, 'status', 'completed') checkFunctionFinished() return
def sendHeartbeatMetricsToServer(): dataToSend = [{ "UUID": comDavra.conf['UUID'], "name": "uptime", "value": comDavra.getUptimeProcess(), "msg_type": "datum" }, { "UUID": comDavra.conf['UUID'], "name": "cpu", "value": comDavra.getUptime()[1], "msg_type": "datum", }, { "UUID": comDavra.conf['UUID'], "name": "ram", "value": comDavra.getRam()[1], "msg_type": "datum", }, { "UUID": comDavra.conf['UUID'], "name": "davra.agent.heartbeat", "value": { "davraAgentVersion": comDavra.davraAgentVersion, "heartbeatInterval": comDavra.conf['heartbeatInterval'] }, "msg_type": "event" }] comDavra.logInfo('Sending heartbeat data to: ' + comDavra.conf['server'] + ": " + comDavra.conf['UUID']) #print(json.dumps(dataToSend, indent=4)) statusCode = comDavra.sendDataToServer(dataToSend).status_code comDavra.log('Response after sending heartbeat data: ' + str(statusCode)) return
def runDavraJob(jobObject): # Catch situation where a job is already running if (os.path.isfile(currentJobJson) == True): comDavra.logWarning( 'A job is already running. Will not start another job. ' + jobObject["UUID"]) return comDavra.log('Start Run of job ' + jobObject["UUID"]) try: flagIsJobRunning = True # Write this job to disk as the current job jobObject['devices'][0][ 'startTime'] = comDavra.getMilliSecondsSinceEpoch() jobObject['devices'][0]['status'] = 'running' comDavra.provideFreshDirectory(currentJobDir) with open(currentJobJson, 'w') as outfile: json.dump(jobObject, outfile, indent=4) if (jobObject.has_key('jobConfig') and jobObject['jobConfig']['type'].lower() == 'runfunction'): comDavra.logInfo('Job Run: type is runFunction. ' + jobObject['jobConfig']['functionName']) runFunction(jobObject['jobConfig']['functionName'], jobObject['jobConfig']['functionParameterValues']) return # Reaching here means the job type was not recognised so that is a failed situation updateJobWithResult('failed', 'Unknown job type') checkCurrentJob() return except Exception as e: # Reaching here means the job type was not recognised so that is a failed situation comDavra.logError('Job Error ' + str(e)) updateJobWithResult('failed', 'Unknown job type') checkCurrentJob() return
def agentFunctionPushAppSnap(functionParameterValues): comDavra.logInfo( 'Function: Pushing Application onto device to run as a snap ' + str(functionParameterValues)) if (functionParameterValues["Snap File From Repo"]): comDavra.log('URL is ' + functionParameterValues["File URL"]) # TODO return
def agentFunctionUpdateAgentConfig(functionParameterValues): comDavra.logInfo('Function: Updating the agent config to server ' + str(functionParameterValues)) comDavra.upsertConfigurationItem(functionParameterValues["key"], functionParameterValues["value"]) comDavra.reportDeviceConfigurationToServer() comDavra.upsertJsonEntry(currentFunctionJson, 'response', comDavra.conf) comDavra.upsertJsonEntry(currentFunctionJson, 'status', 'completed') checkFunctionFinished() return
def reportAgentStarted(): eventToSend = { "UUID": comDavra.conf['UUID'], "name": "davra.agent.started", "msg_type": "event", "value": comDavra.conf } r = comDavra.sendDataToServer(eventToSend) if (r.status_code == 200): comDavra.logInfo("Sent event to server to indicate agent started") # Update the device labels to reflect this agent version comDavra.logInfo("Running davraAgentVersion:" + comDavra.davraAgentVersion) comDavra.updateDeviceLabelOnServer("davraAgentVersion", comDavra.davraAgentVersion) return
def agentFunctionPushAppWithInstaller(functionParameterValues): comDavra.logInfo( 'Function: Pushing Application onto device to run as a service ' + str(functionParameterValues)) if (functionParameterValues["Installation File"]): installationFile = functionParameterValues["Installation File"] # Download the app tarball try: tmpPath = '/tmp/' + str(comDavra.getMilliSecondsSinceEpoch()) comDavra.ensureDirectoryExists(tmpPath) comDavra.runCommandWithTimeout( 'cd ' + tmpPath + ' && /usr/bin/curl -LO ' + installationFile, 300) comDavra.runCommandWithTimeout( 'cd ' + tmpPath + ' && /bin/tar -xvf ./* ', 300) comDavra.runCommandWithTimeout( 'cd ' + tmpPath + ' && chmod 777 ./* ', 300) # Ensure the install.sh is unix format comDavra.runCommandWithTimeout( "cd " + tmpPath + " && sed -i $'s/\r$//' install.sh ", 30) installedAppPath = comDavra.installationDir + '/apps/' + str( comDavra.getMilliSecondsSinceEpoch()) comDavra.ensureDirectoryExists(installedAppPath) comDavra.runCommandWithTimeout( 'cd ' + tmpPath + ' && cp -r * ' + installedAppPath, 300) installResponse = comDavra.runCommandWithTimeout( 'cd ' + installedAppPath + ' && bash ./install.sh ', comDavra.conf["scriptMaxTime"]) comDavra.log('Installation response: ' + str(installResponse[1])) scriptStatus = 'completed' if (installResponse[0] == 0) else 'failed' comDavra.upsertJsonEntry(currentFunctionJson, 'response', str(installResponse[1])) comDavra.upsertJsonEntry(currentFunctionJson, 'status', scriptStatus) except Exception as e: comDavra.logError('Failed to download application:' + installationFile + " : Error: " + str(e)) comDavra.upsertJsonEntry(currentFunctionJson, 'status', 'failed') checkFunctionFinished() comDavra.log('Finished agentFunctionPushAppWithInstaller') checkFunctionFinished() else: comDavra.logWarning('Action parameters missing, nothing to do') # TODO return
def reportJobStatus(): comDavra.log('Current job is finished so reporting it to server now') jobObject = None with open(currentJobJson) as data_file: jobObject = json.load(data_file) deviceJobObject = jobObject['devices'][0] headers = comDavra.getHeadersForRequests() apiEndPoint = comDavra.conf['server'] + '/api/v1/jobs/' + jobObject[ 'UUID'] + '/' + deviceJobObject['UUID'] comDavra.logInfo('Reporting job update to server: ' + apiEndPoint + ' : ' + json.dumps(deviceJobObject)) r = comDavra.httpPut(apiEndPoint, deviceJobObject) if (r.status_code == 200): comDavra.log("Updated server after running job.") # The job has completed and been reflected at the server so delete the currentJobJson file os.remove(currentJobJson) else: comDavra.log("Issue while updating server after running job. " + str(r.status_code)) comDavra.log(r.content) # Report job event to server as an iotdata event eventToSend = { "UUID": deviceJobObject['UUID'], "name": "davra.job.finished", "msg_type": "event", "value": deviceJobObject, "tags": { "status": deviceJobObject["status"] } } apiEndPoint = comDavra.conf['server'] + '/api/v1/iotdata' r = comDavra.httpPut(apiEndPoint, eventToSend) if (r.status_code == 200): comDavra.log("Sent event to server after running job.") else: comDavra.logError( "Issue while sending event to server after running job. " + str(r.status_code)) comDavra.logError(r.content) comDavra.provideFreshDirectory( currentJobDir) # Remove the file and dir on disk flagIsJobRunning = False return
import time, requests, os.path from requests.auth import HTTPBasicAuth import json from pprint import pprint import datetime import paho.mqtt.client as mqtt import davra_lib as comDavra # If you add new libraries to the agent, update requirements.txt # sys.dont_write_bytecode = True # Confirm configuration available from within the config file if ('server' not in comDavra.conf or 'UUID' not in comDavra.conf): print("Configuration incomplete. Please run setup.py first.") sys.exit(1) comDavra.logInfo('Starting Davra Device Agent.') comDavra.logInfo('Server: ' + comDavra.conf['server'] + ". Device: " + comDavra.conf['UUID']) # The job details of currently running job for this device. # Files are used to track the currently running Job, script and function. # Each get a dirctory to themselves and a json for tracking. # The directory "currentJob" etc may be removed when job is finished. currentJobDir = comDavra.installationDir + '/currentJob' currentJobJson = currentJobDir + '/job.json' currentFunctionDir = comDavra.installationDir + "/currentFunction" currentFunctionJson = currentFunctionDir + "/currentFunction.json" # Some flags to cache in RAM whether a function/script/job is running # rather than checking the hard drive continuously flagIsFunctionRunning = False flagIsScriptRunning = False